Compare commits
85 Commits
1320865a2f
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 13d89b020d | |||
| 34735c3e0e | |||
| 866701b499 | |||
| f47e9cb306 | |||
| 8c4cd61081 | |||
| cfefd337b9 | |||
| af1a9e1859 | |||
| 6c7278a064 | |||
| 58c81f32e5 | |||
| 67623951ce | |||
| 8960406388 | |||
| 51bf1e5a6f | |||
| 0e75201906 | |||
| 8aa5351ccc | |||
| 1e80a8067b | |||
| df7b021ea0 | |||
| 86f1a339d0 | |||
| b8e653e57d | |||
| 9ec56ced34 | |||
| e949fdc3e5 | |||
| 7167780f0f | |||
| dd6a0f4018 | |||
| 64e5f9c6d9 | |||
| f16dd8cae1 | |||
| e358abc840 | |||
| 054d36b04d | |||
| 424ff95d2b | |||
| 8405b06e9a | |||
| 115626622b | |||
| 7a34565a64 | |||
| 9de27d332d | |||
| deb6e8fb4c | |||
| fc56cd8c54 | |||
| 7dc4eb24fd | |||
| 358c51a054 | |||
| db7b6cb54a | |||
| b1b381b7a6 | |||
| 7dd5c0d661 | |||
| 4b174c9f3e | |||
| 0892550341 | |||
| 1613f15825 | |||
| 0370063b48 | |||
| 239f2b1de4 | |||
| df79d971f4 | |||
| b1164af03a | |||
| c0a5ef2486 | |||
| 75d28434ee | |||
| aec778ff41 | |||
| 21aa528f08 | |||
| 29fc054c02 | |||
| 9e8761d7a4 | |||
| dd3e023690 | |||
| 64d25ac27d | |||
| 4cb52cd56e | |||
| 0226485c31 | |||
| 19333bc43a | |||
| e74d6554e9 | |||
| 528b0d8885 | |||
| 23640b607a | |||
| 649dd5ac89 | |||
| 27631b814a | |||
| c8b014e457 | |||
| b46444dea2 | |||
| 8fc63ad9c0 | |||
| 26622767e6 | |||
| 2311f5ad29 | |||
| 1c199de379 | |||
| c8e27de06b | |||
| 132bc23c8c | |||
| 0059733ffd | |||
| d8e7976afc | |||
| cf74259b5e | |||
| e0f14d46ea | |||
| 1d88394e2b | |||
| c0f2b7110c | |||
| 017ef1ef56 | |||
| e9c1de8fe5 | |||
| d251f3e86c | |||
| 7e54e08c90 | |||
| ff00478296 | |||
| 9d2464ee9e | |||
| ff05268d01 | |||
| a193b1b5b5 | |||
| ed28bf17af | |||
| f7792ad665 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,3 @@
|
||||
/venv 3.9/
|
||||
/venv 3.11/
|
||||
venv/Lib/site-packages/setuptools/gui-arm64.exe
|
||||
.idea/
|
||||
4
.idea/hook.iml
generated
4
.idea/hook.iml
generated
@@ -3,8 +3,10 @@
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv 3.11" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv 3.9" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.9 (hook) (2)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (hook)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (hook) (2)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,11 +0,0 @@
|
||||
//AppLogReaperServiceImpl类的LIZ方法
|
||||
Java.perform(function() {
|
||||
var AppLogReaperServiceImpl = Java.use("com.ss.android.ugc.aweme.lancet.AppLogReaperServiceImpl");
|
||||
|
||||
AppLogReaperServiceImpl.LIZ.overload('org.json.JSONObject').implementation = function(jsonObject) {
|
||||
console.log("Logged JSON: " + jsonObject.toString());
|
||||
|
||||
// Call the original function
|
||||
return this.LIZ(jsonObject);
|
||||
};
|
||||
});
|
||||
65
frida抓包.md
Normal file
65
frida抓包.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# frida抓包
|
||||
|
||||
## 环境和工具准备:
|
||||
|
||||
- python 3.x
|
||||
- r0capture
|
||||
- frida / frida-tools
|
||||
- apkshell
|
||||
|
||||
## r0capture
|
||||
|
||||
```shell
|
||||
git clone https://github.com/r0ysue/r0capture
|
||||
```
|
||||
|
||||
## frida
|
||||
|
||||
frida-server下载地址
|
||||
|
||||
```
|
||||
https://github.com/frida/frida/releases
|
||||
```
|
||||
|
||||
虚拟环境安装frida和frida- tools
|
||||
|
||||
```shell
|
||||
pip install frida
|
||||
```
|
||||
|
||||
```shell
|
||||
pip install frida-tools
|
||||
```
|
||||
|
||||
使用Frida查看包进程
|
||||
|
||||
```shell
|
||||
frida-ps -U | grep "包名"
|
||||
```
|
||||
|
||||
## 运行 r0capture.py
|
||||
|
||||
```bash
|
||||
python r0capture.py -U 前面记录的目标应用包名 -p xxx.pcap
|
||||
```
|
||||
|
||||
```
|
||||
python3 r0capture/r0capture.py -U com.vmall.client -p com.vmall.client.pcap
|
||||
```
|
||||
|
||||
|
||||
|
||||
其中 -p 参数用来保存抓包结果,.pcap 是数据报存储格式,包括 Wireshark 在内的很多主流抓包软件都可以生成或者导入 pcap 数据包并分析
|
||||
|
||||
如果中途提示 hexdump 名称错误,pip 安装一下即可
|
||||
|
||||
```bash
|
||||
pip install hexdump
|
||||
```
|
||||
|
||||
# hook appsflyer conversions
|
||||
|
||||
```
|
||||
frida -U -l <jshook代码> -f <packageName>
|
||||
```
|
||||
|
||||
76
main.py
Normal file
76
main.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import frida
|
||||
import modules.command
|
||||
import modules.files_utils
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
FIRST_WRITE = True # 全局变量,用于跟踪是否是首次写入
|
||||
|
||||
def on_message(message, data):
|
||||
print(message)
|
||||
# modules.files_utils.write_log(message)
|
||||
# print(message)
|
||||
# if message['type'] == 'send':
|
||||
# print(message['payload'])
|
||||
|
||||
def attach_method(is_spawn):
|
||||
if type(is_spawn) == bool:
|
||||
if is_spawn:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
print(f"is_spawn type error,please check is_spawn type.")
|
||||
|
||||
|
||||
def main(package_name,script_path,is_spawn):
|
||||
# 从Python发送数据到Frida的JavaScript脚本
|
||||
print(f"script_path: {script_path}")
|
||||
js_code = modules.files_utils.read_javascript(script_path)
|
||||
# print(js_code)
|
||||
modules.command.start_frida()
|
||||
# modules.command.clearCache(package_name)
|
||||
# 连接到USB设备
|
||||
device = frida.get_usb_device()
|
||||
print(device)
|
||||
if attach_method(is_spawn):
|
||||
pid = device.spawn(package_name)
|
||||
print(f"进程pid: {pid}")
|
||||
process = device.attach(pid)
|
||||
script = process.create_script(js_code)
|
||||
# script.on("message", on_message)
|
||||
script.load()
|
||||
# data_to_send = {'data': 'Hello from Python!'}
|
||||
# script.post({'type': 'input_data', 'payload': data_to_send})
|
||||
device.resume(pid) # 加载完脚本后, 恢复进程运行
|
||||
sys.stdin.read()
|
||||
else:
|
||||
# 列出设备上的所有进程
|
||||
pid = None
|
||||
processes = device.enumerate_processes()
|
||||
for process in processes:
|
||||
if process.name == attach_process_name:
|
||||
pid = process.pid
|
||||
print(f"pid: {process.pid},App Name: {process.name}")
|
||||
# 如果你想附加到一个特定的进程并注入一个脚本:
|
||||
if pid is not None:
|
||||
session = device.attach(pid)
|
||||
script = session.create_script(js_code)
|
||||
script.on('message', on_message)
|
||||
script.load()
|
||||
else:
|
||||
print(f"get process error")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 是否以spawn模式运行
|
||||
is_spawn = True
|
||||
# 目标进程名
|
||||
attach_process_name = "百度网盘"
|
||||
# 目标包名
|
||||
package_name = "com.baidu.netdisk"
|
||||
# 注入的脚本路径
|
||||
# script_path = "scripts/hook_conversions.js"
|
||||
script_path = "scripts/baidunetdisk.js"
|
||||
main(package_name,script_path, is_spawn)
|
||||
98
modules/command.py
Normal file
98
modules/command.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import subprocess
|
||||
import logging
|
||||
import time
|
||||
import json
|
||||
from modules.files_utils import get_path
|
||||
|
||||
|
||||
def run_adb_command(command_list):
|
||||
process = subprocess.Popen(command_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = process.communicate()
|
||||
output = stdout.decode().strip()
|
||||
status_code = process.returncode
|
||||
error = stderr.decode().strip()
|
||||
return output, status_code, error
|
||||
def start_frida():
|
||||
if is_frida_running():
|
||||
return
|
||||
else:
|
||||
output, status_code, error = run_adb_command(['adb', 'shell', 'su', '-c', '/data/local/tmp/frica'])
|
||||
if status_code == 0:
|
||||
print(output)
|
||||
logging.info(f"start frida output: {output}")
|
||||
return True
|
||||
else:
|
||||
print(error)
|
||||
logging.error(f"start error,error:{error}")
|
||||
return False
|
||||
|
||||
def is_frida_running():
|
||||
output, status_code, error = run_adb_command(['adb', 'shell', 'ps', '|', 'grep', 'frica'])
|
||||
print(output)
|
||||
return 'frica' in output
|
||||
|
||||
|
||||
def get_main_activity_for_package(package_name):
|
||||
output, status_code, error = run_adb_command(['adb', 'shell', 'dumpsys', 'package', package_name])
|
||||
if status_code != 0:
|
||||
print(f"Error getting main activity: {error}")
|
||||
return None
|
||||
else:
|
||||
# print(f"output: {output},output type: {type(output)}")
|
||||
return find_mainActivity(output,package_name)
|
||||
|
||||
|
||||
def find_mainActivity(output,package_name):
|
||||
activity = []
|
||||
start_append = False
|
||||
lines = [line.strip() for line in output.split("\n")]
|
||||
for line in lines:
|
||||
if "Activity Resolver Table:" in line:
|
||||
activity.append(line)
|
||||
if "Non-Data Actions:" in line:
|
||||
activity.append(line)
|
||||
start_append = True
|
||||
elif "android.intent.category.LAUNCHER" in line:
|
||||
activity.append(line)
|
||||
break
|
||||
elif start_append == True:
|
||||
activity.append(line)
|
||||
for main_ac in activity:
|
||||
if package_name in main_ac:
|
||||
tmp = main_ac.split()
|
||||
print(tmp[1])
|
||||
return tmp[1]
|
||||
# lines = output.split('\n')
|
||||
# print(f"lines: \n{lines},lines type: {type(lines)}")
|
||||
# last_line_indent = 0
|
||||
# for line in lines:
|
||||
# stripped = line.lstrip()
|
||||
# indent = len(line) - len(stripped)
|
||||
# print(indent)
|
||||
|
||||
|
||||
|
||||
def clearCache(package_name):
|
||||
if stopApp(package_name):
|
||||
output, status_code, error = run_adb_command(['adb', 'shell', 'pm', 'clear', package_name])
|
||||
if status_code == 0:
|
||||
print(f"clear cache status_code: {status_code}\noutput: {output}")
|
||||
return True
|
||||
else:
|
||||
print(error)
|
||||
print(f"clear cache error: {error}")
|
||||
return False
|
||||
else:
|
||||
print("stopApp error")
|
||||
|
||||
def stopApp(package_name):
|
||||
print(f"强行停止{package_name}")
|
||||
output, status_code, error = run_adb_command(['adb', 'shell', 'am', 'force-stop', package_name])
|
||||
if status_code == 0:
|
||||
print(f"status_code: {status_code}\noutput: {output}")
|
||||
return True
|
||||
else:
|
||||
print(error)
|
||||
logging.error(f"stop APP error: {error}")
|
||||
return False
|
||||
|
||||
23
modules/files_utils.py
Normal file
23
modules/files_utils.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import os
|
||||
|
||||
# 获取当前Python脚本的绝对路径
|
||||
def get_path(script_name):
|
||||
script_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_directory = os.path.dirname(script_directory)
|
||||
# 使用os.path.join构建hook_conversions.js的完整路径
|
||||
script_path = os.path.join(parent_directory,script_name)
|
||||
print(script_path)
|
||||
return script_path
|
||||
|
||||
def read_javascript(script_path):
|
||||
with open(script_path, "r") as file:
|
||||
script_code = file.read()
|
||||
return script_code
|
||||
def write_log(messages):
|
||||
global FIRST_WRITE
|
||||
print(f"FIRST_WRITE: {FIRST_WRITE}")
|
||||
with open("frida_log.log", "a") as log_file:
|
||||
if FIRST_WRITE: # 如果是首次写入
|
||||
log_file.write("\n\n\n") # 空出三行
|
||||
FIRST_WRITE = False # 更新状态,表明已经写过了
|
||||
log_file.write(str(messages) + "\n")
|
||||
479
r0capture/myhexdump.py
Normal file
479
r0capture/myhexdump.py
Normal file
@@ -0,0 +1,479 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# !/usr/bin/env python
|
||||
# -*- coding: latin-1 -*-
|
||||
|
||||
# <-- removing this magic comment breaks Python 3.4 on Windows
|
||||
"""
|
||||
1. Dump binary data to the following text format:
|
||||
|
||||
00000000: 00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump]....
|
||||
00000010: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........
|
||||
|
||||
It is similar to the one used by:
|
||||
Scapy
|
||||
00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump]....
|
||||
00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........
|
||||
|
||||
Far Manager
|
||||
000000000: 00 00 00 5B 68 65 78 64 ¦ 75 6D 70 5D 00 00 00 00 [hexdump]
|
||||
000000010: 00 11 22 33 44 55 66 77 ¦ 88 99 AA BB CC DD EE FF ?"3DUfwª»ÌÝîÿ
|
||||
|
||||
|
||||
2. Restore binary data from the formats above as well
|
||||
as from less exotic strings of raw hex
|
||||
|
||||
"""
|
||||
|
||||
__version__ = '3.3'
|
||||
__author__ = 'anatoly techtonik <techtonik@gmail.com>'
|
||||
__license__ = 'Public Domain'
|
||||
|
||||
__history__ = \
|
||||
"""
|
||||
3.3 (2015-01-22)
|
||||
* accept input from sys.stdin if "-" is specified
|
||||
for both dump and restore (issue #1)
|
||||
* new normalize_py() helper to set sys.stdout to
|
||||
binary mode on Windows
|
||||
|
||||
3.2 (2015-07-02)
|
||||
* hexdump is now packaged as .zip on all platforms
|
||||
(on Linux created archive was tar.gz)
|
||||
* .zip is executable! try `python hexdump-3.2.zip`
|
||||
* dump() now accepts configurable separator, patch
|
||||
by Ian Land (PR #3)
|
||||
|
||||
3.1 (2014-10-20)
|
||||
* implemented workaround against mysterious coding
|
||||
issue with Python 3 (see revision 51302cf)
|
||||
* fix Python 3 installs for systems where UTF-8 is
|
||||
not default (Windows), thanks to George Schizas
|
||||
(the problem was caused by reading of README.txt)
|
||||
|
||||
3.0 (2014-09-07)
|
||||
* remove unused int2byte() helper
|
||||
* add dehex(text) helper to convert hex string
|
||||
to binary data
|
||||
* add 'size' argument to dump() helper to specify
|
||||
length of chunks
|
||||
|
||||
2.0 (2014-02-02)
|
||||
* add --restore option to command line mode to get
|
||||
binary data back from hex dump
|
||||
* support saving test output with `--test logfile`
|
||||
* restore() from hex strings without spaces
|
||||
* restore() now raises TypeError if input data is
|
||||
not string
|
||||
* hexdump() and dumpgen() now don't return unicode
|
||||
strings in Python 2.x when generator is requested
|
||||
|
||||
1.0 (2013-12-30)
|
||||
* length of address is reduced from 10 to 8
|
||||
* hexdump() got new 'result' keyword argument, it
|
||||
can be either 'print', 'generator' or 'return'
|
||||
* actual dumping logic is now in new dumpgen()
|
||||
generator function
|
||||
* new dump(binary) function that takes binary data
|
||||
and returns string like "66 6F 72 6D 61 74"
|
||||
* new genchunks(mixed, size) function that chunks
|
||||
both sequences and file like objects
|
||||
|
||||
0.5 (2013-06-10)
|
||||
* hexdump is now also a command line utility (no
|
||||
restore yet)
|
||||
|
||||
0.4 (2013-06-09)
|
||||
* fix installation with Python 3 for non English
|
||||
versions of Windows, thanks to George Schizas
|
||||
|
||||
0.3 (2013-04-29)
|
||||
* fully Python 3 compatible
|
||||
|
||||
0.2 (2013-04-28)
|
||||
* restore() to recover binary data from a hex dump in
|
||||
native, Far Manager and Scapy text formats (others
|
||||
might work as well)
|
||||
* restore() is Python 3 compatible
|
||||
|
||||
0.1 (2013-04-28)
|
||||
* working hexdump() function for Python 2
|
||||
"""
|
||||
|
||||
import binascii # binascii is required for Python 3
|
||||
import sys
|
||||
|
||||
# --- constants
|
||||
PY3K = sys.version_info >= (3, 0)
|
||||
|
||||
|
||||
# --- workaround against Python consistency issues
|
||||
def normalize_py():
|
||||
''' Problem 001 - sys.stdout in Python is by default opened in
|
||||
text mode, and writes to this stdout produce corrupted binary
|
||||
data on Windows
|
||||
|
||||
python -c "import sys; sys.stdout.write('_\n_')" > file
|
||||
python -c "print(repr(open('file', 'rb').read()))"
|
||||
'''
|
||||
if sys.platform == "win32":
|
||||
# set sys.stdout to binary mode on Windows
|
||||
import os, msvcrt
|
||||
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
|
||||
|
||||
|
||||
# --- - chunking helpers
|
||||
def chunks(seq, size):
|
||||
'''Generator that cuts sequence (bytes, memoryview, etc.)
|
||||
into chunks of given size. If `seq` length is not multiply
|
||||
of `size`, the lengh of the last chunk returned will be
|
||||
less than requested.
|
||||
|
||||
>>> list( chunks([1,2,3,4,5,6,7], 3) )
|
||||
[[1, 2, 3], [4, 5, 6], [7]]
|
||||
'''
|
||||
d, m = divmod(len(seq), size)
|
||||
for i in range(d):
|
||||
yield seq[i * size:(i + 1) * size]
|
||||
if m:
|
||||
yield seq[d * size:]
|
||||
|
||||
|
||||
def chunkread(f, size):
|
||||
'''Generator that reads from file like object. May return less
|
||||
data than requested on the last read.'''
|
||||
c = f.read(size)
|
||||
while len(c):
|
||||
yield c
|
||||
c = f.read(size)
|
||||
|
||||
|
||||
def genchunks(mixed, size):
|
||||
'''Generator to chunk binary sequences or file like objects.
|
||||
The size of the last chunk returned may be less than
|
||||
requested.'''
|
||||
if hasattr(mixed, 'read'):
|
||||
return chunkread(mixed, size)
|
||||
else:
|
||||
return chunks(mixed, size)
|
||||
|
||||
|
||||
# --- - /chunking helpers
|
||||
|
||||
|
||||
def dehex(hextext):
|
||||
"""
|
||||
Convert from hex string to binary data stripping
|
||||
whitespaces from `hextext` if necessary.
|
||||
"""
|
||||
if PY3K:
|
||||
return bytes.fromhex(hextext)
|
||||
else:
|
||||
hextext = "".join(hextext.split())
|
||||
return hextext.decode('hex')
|
||||
|
||||
|
||||
def dump(binary, size=2, sep=' '):
|
||||
'''
|
||||
Convert binary data (bytes in Python 3 and str in
|
||||
Python 2) to hex string like '00 DE AD BE EF'.
|
||||
`size` argument specifies length of text chunks
|
||||
and `sep` sets chunk separator.
|
||||
'''
|
||||
hexstr = binascii.hexlify(binary)
|
||||
if PY3K:
|
||||
hexstr = hexstr.decode('ascii')
|
||||
return sep.join(chunks(hexstr.upper(), size))
|
||||
|
||||
|
||||
def dumpgen(data, only_str):
|
||||
'''
|
||||
Generator that produces strings:
|
||||
|
||||
'00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................'
|
||||
'''
|
||||
generator = genchunks(data, 16)
|
||||
for addr, d in enumerate(generator):
|
||||
line = ""
|
||||
if not only_str:
|
||||
# 00000000:
|
||||
line = '%08X: ' % (addr * 16)
|
||||
# 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
dumpstr = dump(d)
|
||||
line += dumpstr[:8 * 3]
|
||||
if len(d) > 8: # insert separator if needed
|
||||
line += ' ' + dumpstr[8 * 3:]
|
||||
# ................
|
||||
# calculate indentation, which may be different for the last line
|
||||
pad = 2
|
||||
if len(d) < 16:
|
||||
pad += 3 * (16 - len(d))
|
||||
if len(d) <= 8:
|
||||
pad += 1
|
||||
line += ' ' * pad
|
||||
|
||||
for byte in d:
|
||||
# printable ASCII range 0x20 to 0x7E
|
||||
if not PY3K:
|
||||
byte = ord(byte)
|
||||
if 0x20 <= byte <= 0x7E:
|
||||
line += chr(byte)
|
||||
else:
|
||||
line += '.'
|
||||
yield line
|
||||
|
||||
|
||||
def hexdump(data, result='print', only_str=False):
|
||||
'''
|
||||
Transform binary data to the hex dump text format:
|
||||
|
||||
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
|
||||
[x] data argument as a binary string
|
||||
[x] data argument as a file like object
|
||||
|
||||
Returns result depending on the `result` argument:
|
||||
'print' - prints line by line
|
||||
'return' - returns single string
|
||||
'generator' - returns generator that produces lines
|
||||
'''
|
||||
if PY3K and type(data) == str:
|
||||
raise TypeError('Abstract unicode data (expected bytes sequence)')
|
||||
|
||||
gen = dumpgen(data, only_str=only_str)
|
||||
if result == 'generator':
|
||||
return gen
|
||||
elif result == 'return':
|
||||
return '\n'.join(gen)
|
||||
elif result == 'print':
|
||||
for line in gen:
|
||||
print(line)
|
||||
else:
|
||||
raise ValueError('Unknown value of `result` argument')
|
||||
|
||||
|
||||
def restore(dump):
|
||||
'''
|
||||
Restore binary data from a hex dump.
|
||||
[x] dump argument as a string
|
||||
[ ] dump argument as a line iterator
|
||||
|
||||
Supported formats:
|
||||
[x] hexdump.hexdump
|
||||
[x] Scapy
|
||||
[x] Far Manager
|
||||
'''
|
||||
minhexwidth = 2 * 16 # minimal width of the hex part - 00000... style
|
||||
bytehexwidth = 3 * 16 - 1 # min width for a bytewise dump - 00 00 ... style
|
||||
|
||||
result = bytes() if PY3K else ''
|
||||
if type(dump) != str:
|
||||
raise TypeError('Invalid data for restore')
|
||||
|
||||
text = dump.strip() # ignore surrounding empty lines
|
||||
for line in text.split('\n'):
|
||||
# strip address part
|
||||
addrend = line.find(':')
|
||||
if 0 < addrend < minhexwidth: # : is not in ascii part
|
||||
line = line[addrend + 1:]
|
||||
line = line.lstrip()
|
||||
# check dump type
|
||||
if line[2] == ' ': # 00 00 00 ... type of dump
|
||||
# check separator
|
||||
sepstart = (2 + 1) * 7 + 2 # ('00'+' ')*7+'00'
|
||||
sep = line[sepstart:sepstart + 3]
|
||||
if sep[:2] == ' ' and sep[2:] != ' ': # ...00 00 00 00...
|
||||
hexdata = line[:bytehexwidth + 1]
|
||||
elif sep[2:] == ' ': # ...00 00 | 00 00... - Far Manager
|
||||
hexdata = line[:sepstart] + line[sepstart + 3:bytehexwidth + 2]
|
||||
else: # ...00 00 00 00... - Scapy, no separator
|
||||
hexdata = line[:bytehexwidth]
|
||||
line = hexdata
|
||||
result += dehex(line)
|
||||
return result
|
||||
|
||||
|
||||
def runtest(logfile=None):
|
||||
'''Run hexdump tests. Requires hexfile.bin to be in the same
|
||||
directory as hexdump.py itself'''
|
||||
|
||||
class TeeOutput(object):
|
||||
def __init__(self, stream1, stream2):
|
||||
self.outputs = [stream1, stream2]
|
||||
|
||||
# -- methods from sys.stdout / sys.stderr
|
||||
def write(self, data):
|
||||
for stream in self.outputs:
|
||||
if PY3K:
|
||||
if 'b' in stream.mode:
|
||||
data = data.encode('utf-8')
|
||||
stream.write(data)
|
||||
stream.flush()
|
||||
|
||||
def tell(self):
|
||||
raise IOError
|
||||
|
||||
def flush(self):
|
||||
for stream in self.outputs:
|
||||
stream.flush()
|
||||
# --/ sys.stdout
|
||||
|
||||
if logfile:
|
||||
openlog = open(logfile, 'wb')
|
||||
# copy stdout and stderr streams to log file
|
||||
savedstd = sys.stderr, sys.stdout
|
||||
sys.stderr = TeeOutput(sys.stderr, openlog)
|
||||
sys.stdout = TeeOutput(sys.stdout, openlog)
|
||||
|
||||
def echo(msg, linefeed=True):
|
||||
sys.stdout.write(msg)
|
||||
if linefeed:
|
||||
sys.stdout.write('\n')
|
||||
|
||||
expected = '''\
|
||||
00000000: 00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump]....
|
||||
00000010: 00 11 22 33 44 55 66 77 88 99 0A BB CC DD EE FF .."3DUfw........\
|
||||
'''
|
||||
|
||||
# get path to hexfile.bin
|
||||
# this doesn't work from .zip
|
||||
# import os.path as osp
|
||||
# hexfile = osp.dirname(osp.abspath(__file__)) + '/hexfile.bin'
|
||||
# this doesn't work either
|
||||
# hexfile = osp.dirname(sys.modules[__name__].__file__) + '/hexfile.bin'
|
||||
# this works
|
||||
import pkgutil
|
||||
bin = pkgutil.get_data('hexdump', 'data/hexfile.bin')
|
||||
|
||||
# varios length of input data
|
||||
hexdump(b'zzzz' * 12)
|
||||
hexdump(b'o' * 17)
|
||||
hexdump(b'p' * 24)
|
||||
hexdump(b'q' * 26)
|
||||
# allowable character set filter
|
||||
hexdump(b'line\nfeed\r\ntest')
|
||||
hexdump(b'\x00\x00\x00\x5B\x68\x65\x78\x64\x75\x6D\x70\x5D\x00\x00\x00\x00'
|
||||
b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\x0A\xBB\xCC\xDD\xEE\xFF')
|
||||
print('---')
|
||||
# dumping file-like binary object to screen (default behavior)
|
||||
hexdump(bin)
|
||||
print('return output')
|
||||
hexout = hexdump(bin, result='return')
|
||||
assert hexout == expected, 'returned hex didn\'t match'
|
||||
print('return generator')
|
||||
hexgen = hexdump(bin, result='generator')
|
||||
assert next(hexgen) == expected.split('\n')[0], 'hex generator 1 didn\'t match'
|
||||
assert next(hexgen) == expected.split('\n')[1], 'hex generator 2 didn\'t match'
|
||||
|
||||
# binary restore test
|
||||
bindata = restore(
|
||||
'''
|
||||
00000000: 00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump]....
|
||||
00000010: 00 11 22 33 44 55 66 77 88 99 0A BB CC DD EE FF .."3DUfw........
|
||||
''')
|
||||
echo('restore check ', linefeed=False)
|
||||
assert bin == bindata, 'restore check failed'
|
||||
echo('passed')
|
||||
|
||||
far = \
|
||||
'''
|
||||
000000000: 00 00 00 5B 68 65 78 64 ¦ 75 6D 70 5D 00 00 00 00 [hexdump]
|
||||
000000010: 00 11 22 33 44 55 66 77 ¦ 88 99 0A BB CC DD EE FF ?"3DUfwª»ÌÝîÿ
|
||||
'''
|
||||
echo('restore far format ', linefeed=False)
|
||||
assert bin == restore(far), 'far format check failed'
|
||||
echo('passed')
|
||||
|
||||
scapy = '''\
|
||||
00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump]....
|
||||
00 11 22 33 44 55 66 77 88 99 0A BB CC DD EE FF .."3DUfw........
|
||||
'''
|
||||
echo('restore scapy format ', linefeed=False)
|
||||
assert bin == restore(scapy), 'scapy format check failed'
|
||||
echo('passed')
|
||||
|
||||
if not PY3K:
|
||||
assert restore('5B68657864756D705D') == '[hexdump]', 'no space check failed'
|
||||
assert dump('\\\xa1\xab\x1e', sep='').lower() == '5ca1ab1e'
|
||||
else:
|
||||
assert restore('5B68657864756D705D') == b'[hexdump]', 'no space check failed'
|
||||
assert dump(b'\\\xa1\xab\x1e', sep='').lower() == '5ca1ab1e'
|
||||
|
||||
print('---[test file hexdumping]---')
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
hexfile = tempfile.NamedTemporaryFile(delete=False)
|
||||
try:
|
||||
hexfile.write(bin)
|
||||
hexfile.close()
|
||||
hexdump(open(hexfile.name, 'rb'))
|
||||
finally:
|
||||
os.remove(hexfile.name)
|
||||
if logfile:
|
||||
sys.stderr, sys.stdout = savedstd
|
||||
openlog.close()
|
||||
|
||||
|
||||
def main():
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser(usage='''
|
||||
%prog [binfile|-]
|
||||
%prog -r hexfile
|
||||
%prog --test [logfile]''', version=__version__)
|
||||
parser.add_option('-r', '--restore', action='store_true',
|
||||
help='restore binary from hex dump')
|
||||
parser.add_option('--test', action='store_true', help='run hexdump sanity checks')
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if options.test:
|
||||
if args:
|
||||
runtest(logfile=args[0])
|
||||
else:
|
||||
runtest()
|
||||
elif not args or len(args) > 1:
|
||||
parser.print_help()
|
||||
sys.exit(-1)
|
||||
else:
|
||||
## dump file
|
||||
if not options.restore:
|
||||
# [x] memory effective dump
|
||||
if args[0] == '-':
|
||||
if not PY3K:
|
||||
hexdump(sys.stdin)
|
||||
else:
|
||||
hexdump(sys.stdin.buffer)
|
||||
else:
|
||||
hexdump(open(args[0], 'rb'))
|
||||
|
||||
## restore file
|
||||
else:
|
||||
# prepare input stream
|
||||
if args[0] == '-':
|
||||
instream = sys.stdin
|
||||
else:
|
||||
if PY3K:
|
||||
instream = open(args[0])
|
||||
else:
|
||||
instream = open(args[0], 'rb')
|
||||
|
||||
# output stream
|
||||
# [ ] memory efficient restore
|
||||
if PY3K:
|
||||
sys.stdout.buffer.write(restore(instream.read()))
|
||||
else:
|
||||
# Windows - binary mode for sys.stdout to prevent data corruption
|
||||
normalize_py()
|
||||
sys.stdout.write(restore(instream.read()))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# [x] file restore from command line utility
|
||||
# [ ] write dump with LF on Windows for consistency
|
||||
# [ ] encoding param for hexdump()ing Python 3 str if anybody requests that
|
||||
|
||||
# [ ] document chunking API
|
||||
# [ ] document hexdump API
|
||||
# [ ] blog about sys.stdout text mode problem on Windows
|
||||
374
r0capture/r0capture.py
Normal file
374
r0capture/r0capture.py
Normal file
@@ -0,0 +1,374 @@
|
||||
# Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Decrypts and logs a process's SSL traffic.
|
||||
Hooks the functions SSL_read() and SSL_write() in a given process and logs the
|
||||
decrypted data to the console and/or to a pcap file.
|
||||
Typical usage example:
|
||||
ssl_log("wget", "log.pcap", True)
|
||||
Dependencies:
|
||||
frida (https://www.frida.re/):
|
||||
sudo pip install frida
|
||||
hexdump (https://bitbucket.org/techtonik/hexdump/) if using verbose output:
|
||||
sudo pip install hexdump
|
||||
"""
|
||||
|
||||
__author__ = "geffner@google.com (Jason Geffner)"
|
||||
__version__ = "2.0"
|
||||
|
||||
"""
|
||||
# r0capture
|
||||
|
||||
ID: r0ysue
|
||||
|
||||
安卓应用层抓包通杀脚本
|
||||
|
||||
https://github.com/r0ysue/r0capture
|
||||
|
||||
## 简介
|
||||
|
||||
- 仅限安卓平台,测试安卓7、8、9、10 可用 ;
|
||||
- 无视所有证书校验或绑定,无视任何证书;
|
||||
- 通杀TCP/IP四层模型中的应用层中的全部协议;
|
||||
- 通杀协议包括:Http,WebSocket,Ftp,Xmpp,Imap,Smtp,Protobuf等等、以及它们的SSL版本;
|
||||
- 通杀所有应用层框架,包括HttpUrlConnection、Okhttp1/3/4、Retrofit/Volley等等;
|
||||
"""
|
||||
|
||||
# Windows版本需要安装库:
|
||||
# pip install 'win_inet_pton'
|
||||
# pip install hexdump
|
||||
import argparse
|
||||
import os
|
||||
import pprint
|
||||
import random
|
||||
import signal
|
||||
import socket
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import frida
|
||||
from loguru import logger
|
||||
|
||||
try:
|
||||
if os.name == 'nt':
|
||||
import win_inet_pton
|
||||
except ImportError:
|
||||
# win_inet_pton import error
|
||||
pass
|
||||
|
||||
try:
|
||||
import myhexdump as hexdump # pylint: disable=g-import-not-at-top
|
||||
except ImportError:
|
||||
pass
|
||||
try:
|
||||
from shutil import get_terminal_size as get_terminal_size
|
||||
except:
|
||||
try:
|
||||
from backports.shutil_get_terminal_size import get_terminal_size as get_terminal_size
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
import click
|
||||
except:
|
||||
class click:
|
||||
@staticmethod
|
||||
def secho(message=None, **kwargs):
|
||||
print(message)
|
||||
|
||||
@staticmethod
|
||||
def style(**kwargs):
|
||||
raise Exception("unsupported style")
|
||||
banner = """
|
||||
--------------------------------------------------------------------------------------------
|
||||
.oooo. .
|
||||
d8P'`Y8b .o8
|
||||
oooo d8b 888 888 .ooooo. .oooo. oo.ooooo. .o888oo oooo oooo oooo d8b .ooooo.
|
||||
`888""8P 888 888 d88' `"Y8 `P )88b 888' `88b 888 `888 `888 `888""8P d88' `88b
|
||||
888 888 888 888 .oP"888 888 888 888 888 888 888 888ooo888
|
||||
888 `88b d88' 888 .o8 d8( 888 888 888 888 . 888 888 888 888 .o
|
||||
d888b `Y8bd8P' `Y8bod8P' `Y888""8o 888bod8P' "888" `V88V"V8P' d888b `Y8bod8P'
|
||||
888
|
||||
o888o
|
||||
https://github.com/r0ysue/r0capture
|
||||
--------------------------------------------------------------------------------------------\n
|
||||
"""
|
||||
|
||||
|
||||
def show_banner():
|
||||
colors = ['bright_red', 'bright_green', 'bright_blue', 'cyan', 'magenta']
|
||||
try:
|
||||
click.style('color test', fg='bright_red')
|
||||
except:
|
||||
colors = ['red', 'green', 'blue', 'cyan', 'magenta']
|
||||
try:
|
||||
columns = get_terminal_size().columns
|
||||
if columns >= len(banner.splitlines()[1]):
|
||||
for line in banner.splitlines():
|
||||
click.secho(line, fg=random.choice(colors))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# ssl_session[<SSL_SESSION id>] = (<bytes sent by client>,
|
||||
# <bytes sent by server>)
|
||||
ssl_sessions = {}
|
||||
|
||||
|
||||
def ssl_log(process, pcap=None, host=False, verbose=False, isUsb=False, ssllib="", isSpawn=True, wait=0):
|
||||
"""Decrypts and logs a process's SSL traffic.
|
||||
Hooks the functions SSL_read() and SSL_write() in a given process and logs
|
||||
the decrypted data to the console and/or to a pcap file.
|
||||
Args:
|
||||
process: The target process's name (as a string) or process ID (as an int).
|
||||
pcap: The file path to which the pcap file should be written.
|
||||
verbose: If True, log the decrypted traffic to the console.
|
||||
Raises:
|
||||
NotImplementedError: Not running on a Linux or macOS system.
|
||||
"""
|
||||
|
||||
# if platform.system() not in ("Darwin", "Linux"):
|
||||
# raise NotImplementedError("This function is only implemented for Linux and "
|
||||
# "macOS systems.")
|
||||
|
||||
def log_pcap(pcap_file, ssl_session_id, function, src_addr, src_port,
|
||||
dst_addr, dst_port, data):
|
||||
"""Writes the captured data to a pcap file.
|
||||
Args:
|
||||
pcap_file: The opened pcap file.
|
||||
ssl_session_id: The SSL session ID for the communication.
|
||||
function: The function that was intercepted ("SSL_read" or "SSL_write").
|
||||
src_addr: The source address of the logged packet.
|
||||
src_port: The source port of the logged packet.
|
||||
dst_addr: The destination address of the logged packet.
|
||||
dst_port: The destination port of the logged packet.
|
||||
data: The decrypted packet data.
|
||||
"""
|
||||
t = time.time()
|
||||
|
||||
if ssl_session_id not in ssl_sessions:
|
||||
ssl_sessions[ssl_session_id] = (random.randint(0, 0xFFFFFFFF),
|
||||
random.randint(0, 0xFFFFFFFF))
|
||||
client_sent, server_sent = ssl_sessions[ssl_session_id]
|
||||
|
||||
if function == "SSL_read":
|
||||
seq, ack = (server_sent, client_sent)
|
||||
else:
|
||||
seq, ack = (client_sent, server_sent)
|
||||
|
||||
for writes in (
|
||||
# PCAP record (packet) header
|
||||
("=I", int(t)), # Timestamp seconds
|
||||
("=I", int((t * 1000000) % 1000000)), # Timestamp microseconds
|
||||
("=I", 40 + len(data)), # Number of octets saved
|
||||
("=i", 40 + len(data)), # Actual length of packet
|
||||
# IPv4 header
|
||||
(">B", 0x45), # Version and Header Length
|
||||
(">B", 0), # Type of Service
|
||||
(">H", 40 + len(data)), # Total Length
|
||||
(">H", 0), # Identification
|
||||
(">H", 0x4000), # Flags and Fragment Offset
|
||||
(">B", 0xFF), # Time to Live
|
||||
(">B", 6), # Protocol
|
||||
(">H", 0), # Header Checksum
|
||||
(">I", src_addr), # Source Address
|
||||
(">I", dst_addr), # Destination Address
|
||||
# TCP header
|
||||
(">H", src_port), # Source Port
|
||||
(">H", dst_port), # Destination Port
|
||||
(">I", seq), # Sequence Number
|
||||
(">I", ack), # Acknowledgment Number
|
||||
(">H", 0x5018), # Header Length and Flags
|
||||
(">H", 0xFFFF), # Window Size
|
||||
(">H", 0), # Checksum
|
||||
(">H", 0)): # Urgent Pointer
|
||||
pcap_file.write(struct.pack(writes[0], writes[1]))
|
||||
pcap_file.write(data)
|
||||
|
||||
if function == "SSL_read":
|
||||
server_sent += len(data)
|
||||
else:
|
||||
client_sent += len(data)
|
||||
ssl_sessions[ssl_session_id] = (client_sent, server_sent)
|
||||
|
||||
def on_message(message, data):
|
||||
"""Callback for errors and messages sent from Frida-injected JavaScript.
|
||||
Logs captured packet data received from JavaScript to the console and/or a
|
||||
pcap file. See https://www.frida.re/docs/messages/ for more detail on
|
||||
Frida's messages.
|
||||
Args:
|
||||
message: A dictionary containing the message "type" and other fields
|
||||
dependent on message type.
|
||||
data: The string of captured decrypted data.
|
||||
"""
|
||||
if message["type"] == "error":
|
||||
logger.info(f"{message}")
|
||||
os.kill(os.getpid(), signal.SIGTERM)
|
||||
return
|
||||
if len(data) == 1:
|
||||
logger.info(f'{message["payload"]["function"]}')
|
||||
logger.info(f'{message["payload"]["stack"]}')
|
||||
return
|
||||
p = message["payload"]
|
||||
if verbose:
|
||||
src_addr = socket.inet_ntop(socket.AF_INET,
|
||||
struct.pack(">I", p["src_addr"]))
|
||||
dst_addr = socket.inet_ntop(socket.AF_INET,
|
||||
struct.pack(">I", p["dst_addr"]))
|
||||
session_id = p['ssl_session_id']
|
||||
logger.info(f"SSL Session: {session_id}")
|
||||
logger.info("[%s] %s:%d --> %s:%d" % (
|
||||
p["function"],
|
||||
src_addr,
|
||||
p["src_port"],
|
||||
dst_addr,
|
||||
p["dst_port"]))
|
||||
gen = hexdump.hexdump(data, result="generator",only_str=True)
|
||||
str_gen = ''.join(gen)
|
||||
logger.info(f"{str_gen}")
|
||||
logger.info(f"{p['stack']}")
|
||||
if pcap:
|
||||
log_pcap(pcap_file, p["ssl_session_id"], p["function"], p["src_addr"],
|
||||
p["src_port"], p["dst_addr"], p["dst_port"], data)
|
||||
|
||||
if isUsb:
|
||||
try:
|
||||
device = frida.get_usb_device()
|
||||
except:
|
||||
device = frida.get_remote_device()
|
||||
else:
|
||||
if host:
|
||||
manager = frida.get_device_manager()
|
||||
device = manager.add_remote_device(host)
|
||||
else:
|
||||
device = frida.get_local_device()
|
||||
|
||||
if isSpawn:
|
||||
pid = device.spawn([process])
|
||||
time.sleep(1)
|
||||
session = device.attach(pid)
|
||||
time.sleep(1)
|
||||
device.resume(pid)
|
||||
else:
|
||||
print("attach")
|
||||
session = device.attach(process)
|
||||
if wait > 0:
|
||||
print(f"wait for {wait} seconds")
|
||||
time.sleep(wait)
|
||||
|
||||
# session = frida.attach(process)
|
||||
|
||||
# pid = device.spawn([process])
|
||||
# pid = process
|
||||
# session = device.attach(pid)
|
||||
# device.resume(pid)
|
||||
if pcap:
|
||||
pcap_file = open(pcap, "wb", 0)
|
||||
for writes in (
|
||||
("=I", 0xa1b2c3d4), # Magic number
|
||||
("=H", 2), # Major version number
|
||||
("=H", 4), # Minor version number
|
||||
("=i", time.timezone), # GMT to local correction
|
||||
("=I", 0), # Accuracy of timestamps
|
||||
("=I", 65535), # Max length of captured packets
|
||||
("=I", 228)): # Data link type (LINKTYPE_IPV4)
|
||||
pcap_file.write(struct.pack(writes[0], writes[1]))
|
||||
|
||||
with open(Path(__file__).resolve().parent.joinpath("./script.js"), encoding="utf-8") as f:
|
||||
_FRIDA_SCRIPT = f.read()
|
||||
# _FRIDA_SCRIPT = session.create_script(content)
|
||||
# print(_FRIDA_SCRIPT)
|
||||
script = session.create_script(_FRIDA_SCRIPT)
|
||||
script.on("message", on_message)
|
||||
script.load()
|
||||
|
||||
if ssllib != "":
|
||||
script.exports.setssllib(ssllib)
|
||||
|
||||
print("Press Ctrl+C to stop logging.")
|
||||
|
||||
def stoplog(signum, frame):
|
||||
print('You have stoped logging.')
|
||||
session.detach()
|
||||
if pcap:
|
||||
pcap_file.flush()
|
||||
pcap_file.close()
|
||||
exit()
|
||||
|
||||
signal.signal(signal.SIGINT, stoplog)
|
||||
signal.signal(signal.SIGTERM, stoplog)
|
||||
sys.stdin.read()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
show_banner()
|
||||
|
||||
|
||||
class ArgParser(argparse.ArgumentParser):
|
||||
|
||||
def error(self, message):
|
||||
print("ssl_logger v" + __version__)
|
||||
print("by " + __author__)
|
||||
print("Modified by BigFaceCat")
|
||||
print("Error: " + message)
|
||||
print()
|
||||
print(self.format_help().replace("usage:", "Usage:"))
|
||||
self.exit(0)
|
||||
|
||||
|
||||
parser = ArgParser(
|
||||
add_help=False,
|
||||
description="Decrypts and logs a process's SSL traffic.",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=r"""
|
||||
Examples:
|
||||
%(prog)s -pcap ssl.pcap openssl
|
||||
%(prog)s -verbose 31337
|
||||
%(prog)s -pcap log.pcap -verbose wget
|
||||
%(prog)s -pcap log.pcap -ssl "*libssl.so*" com.bigfacecat.testdemo
|
||||
""")
|
||||
|
||||
args = parser.add_argument_group("Arguments")
|
||||
args.add_argument("-pcap", '-p', metavar="<path>", required=False,
|
||||
help="Name of PCAP file to write")
|
||||
args.add_argument("-host", '-H', metavar="<192.168.1.1:27042>", required=False,
|
||||
help="connect to remote frida-server on HOST")
|
||||
args.add_argument("-verbose", "-v", required=False, action="store_const", default=True,
|
||||
const=True, help="Show verbose output")
|
||||
args.add_argument("process", metavar="<process name | process id>",
|
||||
help="Process whose SSL calls to log")
|
||||
args.add_argument("-ssl", default="", metavar="<lib>",
|
||||
help="SSL library to hook")
|
||||
args.add_argument("--isUsb", "-U", default=False, action="store_true",
|
||||
help="connect to USB device")
|
||||
args.add_argument("--isSpawn", "-f", default=False, action="store_true",
|
||||
help="if spawned app")
|
||||
args.add_argument("-wait", "-w", type=int, metavar="<seconds>", default=0,
|
||||
help="Time to wait for the process")
|
||||
|
||||
parsed = parser.parse_args()
|
||||
logger.add(f"{parsed.process.replace('.','_')}-{int(time.time())}.log", rotation="500MB", encoding="utf-8", enqueue=True, retention="10 days")
|
||||
|
||||
ssl_log(
|
||||
int(parsed.process) if parsed.process.isdigit() else parsed.process,
|
||||
parsed.pcap,
|
||||
parsed.host,
|
||||
parsed.verbose,
|
||||
isUsb=parsed.isUsb,
|
||||
isSpawn=parsed.isSpawn,
|
||||
ssllib=parsed.ssl,
|
||||
wait=parsed.wait
|
||||
)
|
||||
339
r0capture/script.js
Normal file
339
r0capture/script.js
Normal file
@@ -0,0 +1,339 @@
|
||||
/**
|
||||
* Initializes 'addresses' dictionary and NativeFunctions.
|
||||
*/
|
||||
"use strict";
|
||||
rpc.exports = {
|
||||
setssllib: function (name) {
|
||||
console.log("setSSLLib => " + name);
|
||||
libname = name;
|
||||
initializeGlobals();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
var addresses = {};
|
||||
var SSL_get_fd = null;
|
||||
var SSL_get_session = null;
|
||||
var SSL_SESSION_get_id = null;
|
||||
var getpeername = null;
|
||||
var getsockname = null;
|
||||
var ntohs = null;
|
||||
var ntohl = null;
|
||||
var SSLstackwrite = null;
|
||||
var SSLstackread = null;
|
||||
|
||||
var libname = "*libssl*";
|
||||
|
||||
function uuid(len, radix) {
|
||||
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
|
||||
var uuid = [], i;
|
||||
radix = radix || chars.length;
|
||||
|
||||
if (len) {
|
||||
// Compact form
|
||||
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
|
||||
} else {
|
||||
// rfc4122, version 4 form
|
||||
var r;
|
||||
|
||||
// rfc4122 requires these characters
|
||||
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
|
||||
uuid[14] = '4';
|
||||
|
||||
// Fill in random data. At i==19 set the high bits of clock sequence as
|
||||
// per rfc4122, sec. 4.1.5
|
||||
for (i = 0; i < 36; i++) {
|
||||
if (!uuid[i]) {
|
||||
r = 0 | Math.random() * 16;
|
||||
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uuid.join('');
|
||||
}
|
||||
function return_zero(args) {
|
||||
return 0;
|
||||
}
|
||||
function initializeGlobals() {
|
||||
var resolver = new ApiResolver("module");
|
||||
var exps = [
|
||||
[Process.platform == "darwin" ? "*libboringssl*" : "*libssl*", ["SSL_read", "SSL_write", "SSL_get_fd", "SSL_get_session", "SSL_SESSION_get_id"]], // for ios and Android
|
||||
[Process.platform == "darwin" ? "*libsystem*" : "*libc*", ["getpeername", "getsockname", "ntohs", "ntohl"]]
|
||||
];
|
||||
// console.log(exps)
|
||||
for (var i = 0; i < exps.length; i++) {
|
||||
var lib = exps[i][0];
|
||||
var names = exps[i][1];
|
||||
for (var j = 0; j < names.length; j++) {
|
||||
var name = names[j];
|
||||
// console.log("exports:" + lib + "!" + name)
|
||||
var matches = resolver.enumerateMatchesSync("exports:" + lib + "!" + name);
|
||||
if (matches.length == 0) {
|
||||
if (name == "SSL_get_fd") {
|
||||
addresses["SSL_get_fd"] = 0;
|
||||
continue;
|
||||
}
|
||||
throw "Could not find " + lib + "!" + name;
|
||||
}
|
||||
else if (matches.length != 1) {
|
||||
// Sometimes Frida returns duplicates.
|
||||
var address = 0;
|
||||
var s = "";
|
||||
var duplicates_only = true;
|
||||
for (var k = 0; k < matches.length; k++) {
|
||||
if (s.length != 0) {
|
||||
s += ", ";
|
||||
}
|
||||
s += matches[k].name + "@" + matches[k].address;
|
||||
if (address == 0) {
|
||||
address = matches[k].address;
|
||||
}
|
||||
else if (!address.equals(matches[k].address)) {
|
||||
duplicates_only = false;
|
||||
}
|
||||
}
|
||||
if (!duplicates_only) {
|
||||
throw "More than one match found for " + lib + "!" + name + ": " + s;
|
||||
}
|
||||
}
|
||||
addresses[name] = matches[0].address;
|
||||
}
|
||||
}
|
||||
if (addresses["SSL_get_fd"] == 0) {
|
||||
SSL_get_fd = return_zero;
|
||||
} else {
|
||||
SSL_get_fd = new NativeFunction(addresses["SSL_get_fd"], "int", ["pointer"]);
|
||||
}
|
||||
SSL_get_session = new NativeFunction(addresses["SSL_get_session"], "pointer", ["pointer"]);
|
||||
SSL_SESSION_get_id = new NativeFunction(addresses["SSL_SESSION_get_id"], "pointer", ["pointer", "pointer"]);
|
||||
getpeername = new NativeFunction(addresses["getpeername"], "int", ["int", "pointer", "pointer"]);
|
||||
getsockname = new NativeFunction(addresses["getsockname"], "int", ["int", "pointer", "pointer"]);
|
||||
ntohs = new NativeFunction(addresses["ntohs"], "uint16", ["uint16"]);
|
||||
ntohl = new NativeFunction(addresses["ntohl"], "uint32", ["uint32"]);
|
||||
}
|
||||
initializeGlobals();
|
||||
|
||||
function ipToNumber(ip) {
|
||||
var num = 0;
|
||||
if (ip == "") {
|
||||
return num;
|
||||
}
|
||||
var aNum = ip.split(".");
|
||||
if (aNum.length != 4) {
|
||||
return num;
|
||||
}
|
||||
num += parseInt(aNum[0]) << 0;
|
||||
num += parseInt(aNum[1]) << 8;
|
||||
num += parseInt(aNum[2]) << 16;
|
||||
num += parseInt(aNum[3]) << 24;
|
||||
num = num >>> 0;//这个很关键,不然可能会出现负数的情况
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a dictionary of a sockfd's "src_addr", "src_port", "dst_addr", and
|
||||
* "dst_port".
|
||||
* @param {int} sockfd The file descriptor of the socket to inspect.
|
||||
* @param {boolean} isRead If true, the context is an SSL_read call. If
|
||||
* false, the context is an SSL_write call.
|
||||
* @return {dict} Dictionary of sockfd's "src_addr", "src_port", "dst_addr",
|
||||
* and "dst_port".
|
||||
*/
|
||||
function getPortsAndAddresses(sockfd, isRead) {
|
||||
var message = {};
|
||||
var src_dst = ["src", "dst"];
|
||||
for (var i = 0; i < src_dst.length; i++) {
|
||||
if ((src_dst[i] == "src") ^ isRead) {
|
||||
var sockAddr = Socket.localAddress(sockfd)
|
||||
}
|
||||
else {
|
||||
var sockAddr = Socket.peerAddress(sockfd)
|
||||
}
|
||||
if (sockAddr == null) {
|
||||
// 网络超时or其他原因可能导致socket被关闭
|
||||
message[src_dst[i] + "_port"] = 0
|
||||
message[src_dst[i] + "_addr"] = 0
|
||||
} else {
|
||||
message[src_dst[i] + "_port"] = (sockAddr.port & 0xFFFF)
|
||||
message[src_dst[i] + "_addr"] = ntohl(ipToNumber(sockAddr.ip.split(":").pop()))
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
/**
|
||||
* Get the session_id of SSL object and return it as a hex string.
|
||||
* @param {!NativePointer} ssl A pointer to an SSL object.
|
||||
* @return {dict} A string representing the session_id of the SSL object's
|
||||
* SSL_SESSION. For example,
|
||||
* "59FD71B7B90202F359D89E66AE4E61247954E28431F6C6AC46625D472FF76336".
|
||||
*/
|
||||
function getSslSessionId(ssl) {
|
||||
var session = SSL_get_session(ssl);
|
||||
if (session == 0) {
|
||||
return 0;
|
||||
}
|
||||
var len = Memory.alloc(4);
|
||||
var p = SSL_SESSION_get_id(session, len);
|
||||
len = Memory.readU32(len);
|
||||
var session_id = "";
|
||||
for (var i = 0; i < len; i++) {
|
||||
// Read a byte, convert it to a hex string (0xAB ==> "AB"), and append
|
||||
// it to session_id.
|
||||
session_id +=
|
||||
("0" + Memory.readU8(p.add(i)).toString(16).toUpperCase()).substr(-2);
|
||||
}
|
||||
return session_id;
|
||||
}
|
||||
|
||||
Interceptor.attach(addresses["SSL_read"],
|
||||
{
|
||||
onEnter: function (args) {
|
||||
var message = getPortsAndAddresses(SSL_get_fd(args[0]), true);
|
||||
message["ssl_session_id"] = getSslSessionId(args[0]);
|
||||
message["function"] = "SSL_read";
|
||||
message["stack"] = SSLstackread;
|
||||
this.message = message;
|
||||
this.buf = args[1];
|
||||
},
|
||||
onLeave: function (retval) {
|
||||
retval |= 0; // Cast retval to 32-bit integer.
|
||||
if (retval <= 0) {
|
||||
return;
|
||||
}
|
||||
send(this.message, Memory.readByteArray(this.buf, retval));
|
||||
}
|
||||
});
|
||||
|
||||
Interceptor.attach(addresses["SSL_write"],
|
||||
{
|
||||
onEnter: function (args) {
|
||||
var message = getPortsAndAddresses(SSL_get_fd(args[0]), false);
|
||||
message["ssl_session_id"] = getSslSessionId(args[0]);
|
||||
message["function"] = "SSL_write";
|
||||
message["stack"] = SSLstackwrite;
|
||||
send(message, Memory.readByteArray(args[1], parseInt(args[2])));
|
||||
},
|
||||
onLeave: function (retval) {
|
||||
}
|
||||
});
|
||||
|
||||
if (Java.available) {
|
||||
Java.perform(function () {
|
||||
function storeP12(pri, p7, p12Path, p12Password) {
|
||||
var X509Certificate = Java.use("java.security.cert.X509Certificate")
|
||||
var p7X509 = Java.cast(p7, X509Certificate);
|
||||
var chain = Java.array("java.security.cert.X509Certificate", [p7X509])
|
||||
var ks = Java.use("java.security.KeyStore").getInstance("PKCS12", "BC");
|
||||
ks.load(null, null);
|
||||
ks.setKeyEntry("client", pri, Java.use('java.lang.String').$new(p12Password).toCharArray(), chain);
|
||||
try {
|
||||
var out = Java.use("java.io.FileOutputStream").$new(p12Path);
|
||||
ks.store(out, Java.use('java.lang.String').$new(p12Password).toCharArray())
|
||||
} catch (exp) {
|
||||
console.log(exp)
|
||||
}
|
||||
}
|
||||
//在服务器校验客户端的情形下,帮助dump客户端证书,并保存为p12的格式,证书密码为r0ysue
|
||||
Java.use("java.security.KeyStore$PrivateKeyEntry").getPrivateKey.implementation = function () {
|
||||
var result = this.getPrivateKey()
|
||||
var packageName = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext().getPackageName();
|
||||
storeP12(this.getPrivateKey(), this.getCertificate(), '/sdcard/Download/' + packageName + uuid(10, 16) + '.p12', 'r0ysue');
|
||||
var message = {};
|
||||
message["function"] = "dumpClinetCertificate=>" + '/sdcard/Download/' + packageName + uuid(10, 16) + '.p12' + ' pwd: r0ysue';
|
||||
message["stack"] = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new());
|
||||
var data = Memory.alloc(1);
|
||||
send(message, Memory.readByteArray(data, 1))
|
||||
return result;
|
||||
}
|
||||
Java.use("java.security.KeyStore$PrivateKeyEntry").getCertificateChain.implementation = function () {
|
||||
var result = this.getCertificateChain()
|
||||
var packageName = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext().getPackageName();
|
||||
storeP12(this.getPrivateKey(), this.getCertificate(), '/sdcard/Download/' + packageName + uuid(10, 16) + '.p12', 'r0ysue');
|
||||
var message = {};
|
||||
message["function"] = "dumpClinetCertificate=>" + '/sdcard/Download/' + packageName + uuid(10, 16) + '.p12' + ' pwd: r0ysue';
|
||||
message["stack"] = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new());
|
||||
var data = Memory.alloc(1);
|
||||
send(message, Memory.readByteArray(data, 1))
|
||||
return result;
|
||||
}
|
||||
|
||||
//SSLpinning helper 帮助定位证书绑定的关键代码a
|
||||
Java.use("java.io.File").$init.overload('java.io.File', 'java.lang.String').implementation = function (file, cert) {
|
||||
var result = this.$init(file, cert)
|
||||
var stack = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new());
|
||||
if (file.getPath().indexOf("cacert") >= 0 && stack.indexOf("X509TrustManagerExtensions.checkServerTrusted") >= 0) {
|
||||
var message = {};
|
||||
message["function"] = "SSLpinning position locator => " + file.getPath() + " " + cert;
|
||||
message["stack"] = stack;
|
||||
var data = Memory.alloc(1);
|
||||
send(message, Memory.readByteArray(data, 1))
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Java.use("java.net.SocketOutputStream").socketWrite0.overload('java.io.FileDescriptor', '[B', 'int', 'int').implementation = function (fd, bytearry, offset, byteCount) {
|
||||
var result = this.socketWrite0(fd, bytearry, offset, byteCount);
|
||||
var message = {};
|
||||
message["function"] = "HTTP_send";
|
||||
message["ssl_session_id"] = "";
|
||||
message["src_addr"] = ntohl(ipToNumber((this.socket.value.getLocalAddress().toString().split(":")[0]).split("/").pop()));
|
||||
message["src_port"] = parseInt(this.socket.value.getLocalPort().toString());
|
||||
message["dst_addr"] = ntohl(ipToNumber((this.socket.value.getRemoteSocketAddress().toString().split(":")[0]).split("/").pop()));
|
||||
message["dst_port"] = parseInt(this.socket.value.getRemoteSocketAddress().toString().split(":").pop());
|
||||
message["stack"] = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()).toString();
|
||||
var ptr = Memory.alloc(byteCount);
|
||||
for (var i = 0; i < byteCount; ++i)
|
||||
Memory.writeS8(ptr.add(i), bytearry[offset + i]);
|
||||
send(message, Memory.readByteArray(ptr, byteCount))
|
||||
return result;
|
||||
}
|
||||
Java.use("java.net.SocketInputStream").socketRead0.overload('java.io.FileDescriptor', '[B', 'int', 'int', 'int').implementation = function (fd, bytearry, offset, byteCount, timeout) {
|
||||
var result = this.socketRead0(fd, bytearry, offset, byteCount, timeout);
|
||||
var message = {};
|
||||
message["function"] = "HTTP_recv";
|
||||
message["ssl_session_id"] = "";
|
||||
message["src_addr"] = ntohl(ipToNumber((this.socket.value.getRemoteSocketAddress().toString().split(":")[0]).split("/").pop()));
|
||||
message["src_port"] = parseInt(this.socket.value.getRemoteSocketAddress().toString().split(":").pop());
|
||||
message["dst_addr"] = ntohl(ipToNumber((this.socket.value.getLocalAddress().toString().split(":")[0]).split("/").pop()));
|
||||
message["dst_port"] = parseInt(this.socket.value.getLocalPort());
|
||||
message["stack"] = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()).toString();
|
||||
if (result > 0) {
|
||||
var ptr = Memory.alloc(result);
|
||||
for (var i = 0; i < result; ++i)
|
||||
Memory.writeS8(ptr.add(i), bytearry[offset + i]);
|
||||
send(message, Memory.readByteArray(ptr, result))
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (parseFloat(Java.androidVersion) > 8) {
|
||||
Java.use("com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLOutputStream").write.overload('[B', 'int', 'int').implementation = function (bytearry, int1, int2) {
|
||||
var result = this.write(bytearry, int1, int2);
|
||||
SSLstackwrite = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()).toString();
|
||||
return result;
|
||||
}
|
||||
Java.use("com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream").read.overload('[B', 'int', 'int').implementation = function (bytearry, int1, int2) {
|
||||
var result = this.read(bytearry, int1, int2);
|
||||
SSLstackread = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()).toString();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Java.use("com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream").write.overload('[B', 'int', 'int').implementation = function (bytearry, int1, int2) {
|
||||
var result = this.write(bytearry, int1, int2);
|
||||
SSLstackwrite = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()).toString();
|
||||
return result;
|
||||
}
|
||||
Java.use("com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream").read.overload('[B', 'int', 'int').implementation = function (bytearry, int1, int2) {
|
||||
var result = this.read(bytearry, int1, int2);
|
||||
SSLstackread = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()).toString();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
8
requirements.txt
Normal file
8
requirements.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
colorama==0.4.6
|
||||
frida==16.0.19
|
||||
frida-tools==12.2.1
|
||||
loguru==0.7.2
|
||||
prompt-toolkit==3.0.38
|
||||
Pygments==2.15.1
|
||||
typing_extensions==4.6.3
|
||||
wcwidth==0.2.6
|
||||
21
scripts/baidunetdisk.js
Normal file
21
scripts/baidunetdisk.js
Normal file
@@ -0,0 +1,21 @@
|
||||
console.log("Script loaded successfully");
|
||||
|
||||
Java.perform(function () {
|
||||
var Request = Java.use("okhttp3.Request");
|
||||
|
||||
// Hook Request的toString方法
|
||||
Request.toString.implementation = function () {
|
||||
// 调用原始的toString方法并保存结果
|
||||
var result = this.toString();
|
||||
|
||||
// 打印结果
|
||||
console.log("Request.toString result: " + result);
|
||||
|
||||
// 返回原始方法调用的结果
|
||||
return result;
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
197
scripts/hook_conversions.js
Normal file
197
scripts/hook_conversions.js
Normal file
@@ -0,0 +1,197 @@
|
||||
log_info("Script loaded successfully");
|
||||
// hook_okhttp_client()
|
||||
if (Java.available) {
|
||||
hook_json()
|
||||
let class_name = "okhttp3.OkHttpClient"
|
||||
if (check_class(class_name)){
|
||||
hook_okhttp_client()
|
||||
}
|
||||
Java.perform(function () {
|
||||
log_info("start hook java.net.URL");
|
||||
var URL = Java.use('java.net.URL');
|
||||
URL.$init.overload('java.lang.String').implementation = function (spec) {
|
||||
// console.log("URL request:" + spec)
|
||||
log_info("URL request: " + spec)
|
||||
if (spec.includes("appsflyer")) {
|
||||
// console.log("URL request: " + spec);
|
||||
if (spec.includes("conversions")) {
|
||||
var stackTrace = Java.use('java.lang.Exception').$new().getStackTrace().toString();
|
||||
// console.log(stackTrace);
|
||||
}
|
||||
}
|
||||
return this.$init(spec);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function printMethods(className) {
|
||||
log_info("start print methods.")
|
||||
var jclass = Java.use(className);
|
||||
var methods = jclass.class.getDeclaredMethods();
|
||||
console.log("Printing methods of " + className + ":\n");
|
||||
methods.forEach(function (method) {
|
||||
// console.log(method);
|
||||
log_info("The methods under the class" + className + " are: " + method);
|
||||
});
|
||||
}
|
||||
|
||||
function hook_okhttp_client() {
|
||||
if (Java.available) {
|
||||
Java.perform(function () {
|
||||
log_info("start hook_okhttp_client.")
|
||||
try {
|
||||
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
|
||||
OkHttpClient.newCall.overload('okhttp3.Request').implementation = function (request) {
|
||||
var requestUrl = request.url();
|
||||
if (requestUrl) {
|
||||
console.log("OkHttp Request URL: " + requestUrl.toString());
|
||||
} else {
|
||||
console.log("OkHttp Request URL is not available");
|
||||
}
|
||||
console.log("OkHttp Request Headers: " + request.headers().toString());
|
||||
|
||||
if (request.method() == "POST") {
|
||||
console.log("OkHttp Request Body: " + request.body().contentType().toString());
|
||||
}
|
||||
var call = this.newCall(request);
|
||||
var response = call.execute();
|
||||
console.log("OkHttp Response: " + response.body().string());
|
||||
return call;
|
||||
};
|
||||
|
||||
} catch (e) {
|
||||
console.log("Error hooking OkHttp: " + e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function hook_HttpURLConnection_stream() {
|
||||
console.log("start hook_HttpURLConnection_stream")
|
||||
if (Java.available) {
|
||||
Java.perform(function () {
|
||||
var HttpURLConnection = Java.use("java.net.HttpURLConnection");
|
||||
|
||||
HttpURLConnection.getOutputStream.implementation = function () {
|
||||
var outputStream = this.getOutputStream();
|
||||
var OutputStreamWrapper = Java.use("java.io.OutputStream");
|
||||
|
||||
var newOutputStream = Java.registerClass({
|
||||
name: "CustomOutputStream",
|
||||
superClass: OutputStreamWrapper,
|
||||
methods: {
|
||||
write: function (buffer, byteOffset, byteCount) {
|
||||
var data = Array.prototype.slice.call(buffer.slice(byteOffset, byteOffset + byteCount));
|
||||
console.log("Request data: " + String.fromCharCode.apply(null, data));
|
||||
outputStream.write(buffer, byteOffset, byteCount);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return newOutputStream.$new(outputStream);
|
||||
};
|
||||
|
||||
HttpURLConnection.getInputStream.implementation = function () {
|
||||
var inputStream = this.getInputStream();
|
||||
var InputStreamWrapper = Java.use("java.io.InputStream");
|
||||
|
||||
var newInputStream = Java.registerClass({
|
||||
name: "CustomInputStream",
|
||||
superClass: InputStreamWrapper,
|
||||
methods: {
|
||||
read: function (buffer, byteOffset, byteCount) {
|
||||
var bytesRead = inputStream.read(buffer, byteOffset, byteCount);
|
||||
if (bytesRead != -1) {
|
||||
var data = Array.prototype.slice.call(buffer.slice(byteOffset, byteOffset + bytesRead));
|
||||
console.log("Response data: " + String.fromCharCode.apply(null, data));
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return newInputStream.$new(inputStream);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function hook_retrofit() {
|
||||
Java.perform(function () {
|
||||
var retrofitBuilder = Java.use("retrofit2.Retrofit$Builder");
|
||||
retrofitBuilder.build.implementation = function () {
|
||||
var retrofit = this.build();
|
||||
var httpClient = retrofit.callFactory().clone();
|
||||
httpClient.interceptors().add(new Java.use('okhttp3.Interceptor')({
|
||||
intercept: function (chain) {
|
||||
console.log("HTTP Request -> " + chain.request().toString())
|
||||
var response = chain.proceed(chain.request());
|
||||
console.log("HTTP Response -> " + response.toString());
|
||||
return response;
|
||||
}
|
||||
}))
|
||||
return retrofit.newBuilder()
|
||||
.callFactory(httpClient)
|
||||
.build();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function hook_json() {
|
||||
Java.perform(function () {
|
||||
var JSONObject = Java.use('org.json.JSONObject');
|
||||
JSONObject.toString.overload().implementation = function () {
|
||||
var result = this.toString.call(this);
|
||||
// get_conversions(result)
|
||||
// log_info("Serialized JSONObject: " + result)
|
||||
return result;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function log_info(messages) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-based
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
const milliseconds = String(now.getMilliseconds()).padStart(3, '0');
|
||||
|
||||
const timestamp = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}:${milliseconds}`;
|
||||
|
||||
console.log(`${timestamp} - ${messages}`);
|
||||
send(`${timestamp} - ${messages}`);
|
||||
}
|
||||
|
||||
function check_class(class_name) {
|
||||
var classFound = false; // 默认为未找到
|
||||
Java.enumerateLoadedClasses({
|
||||
onMatch: function(currentClassName) {
|
||||
if (currentClassName === class_name) {
|
||||
classFound = true; // 如果找到了类,则设置为true
|
||||
}
|
||||
},
|
||||
onComplete: function() {
|
||||
if (classFound) {
|
||||
log_info(class_name + " has been loaded!");
|
||||
} else {
|
||||
log_info(class_name + " has not been loaded yet.");
|
||||
}
|
||||
}
|
||||
});
|
||||
return classFound;
|
||||
}
|
||||
|
||||
recv('input_data', function(payload) {
|
||||
console.log(typeof(payload))
|
||||
|
||||
console.log(JSON.stringify(payload))
|
||||
console.log('Received data from Python: ' + payload.payload.data);
|
||||
});
|
||||
|
||||
40
scripts/hook_qqmusic.js
Normal file
40
scripts/hook_qqmusic.js
Normal file
@@ -0,0 +1,40 @@
|
||||
log_info("Script loaded successfully");
|
||||
if (Java.available) {
|
||||
hook_json()
|
||||
Java.perform(function () {
|
||||
log_info("start hook java.net.URL");
|
||||
var URL = Java.use('java.net.URL');
|
||||
URL.$init.overload('java.lang.String').implementation = function (spec) {
|
||||
log_info("URL request: " + spec)
|
||||
return this.$init(spec);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function log_info(messages) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-based
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
const milliseconds = String(now.getMilliseconds()).padStart(3, '0');
|
||||
|
||||
const timestamp = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}:${milliseconds}`;
|
||||
|
||||
console.log(`${timestamp} - ${messages}`);
|
||||
send(`${timestamp} - ${messages}`);
|
||||
}
|
||||
|
||||
function hook_json() {
|
||||
Java.perform(function () {
|
||||
var JSONObject = Java.use('org.json.JSONObject');
|
||||
JSONObject.toString.overload().implementation = function () {
|
||||
var result = this.toString.call(this);
|
||||
// get_conversions(result)
|
||||
log_info("Serialized JSONObject: " + result)
|
||||
return result;
|
||||
};
|
||||
});
|
||||
}
|
||||
362
scripts/hookssl.js
Normal file
362
scripts/hookssl.js
Normal file
@@ -0,0 +1,362 @@
|
||||
console.log("Script loaded successfully");
|
||||
Java.perform(function() {
|
||||
|
||||
/*
|
||||
hook list:
|
||||
1.SSLcontext
|
||||
2.okhttp
|
||||
3.webview
|
||||
4.XUtils
|
||||
5.httpclientandroidlib
|
||||
6.JSSE
|
||||
7.network\_security\_config (android 7.0+)
|
||||
8.Apache Http client (support partly)
|
||||
9.OpenSSLSocketImpl
|
||||
10.TrustKit
|
||||
11.Cronet
|
||||
*/
|
||||
|
||||
// Attempts to bypass SSL pinning implementations in a number of
|
||||
// ways. These include implementing a new TrustManager that will
|
||||
// accept any SSL certificate, overriding OkHTTP v3 check()
|
||||
// method etc.
|
||||
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
|
||||
var HostnameVerifier = Java.use('javax.net.ssl.HostnameVerifier');
|
||||
var SSLContext = Java.use('javax.net.ssl.SSLContext');
|
||||
var quiet_output = false;
|
||||
|
||||
// Helper method to honor the quiet flag.
|
||||
|
||||
function quiet_send(data) {
|
||||
|
||||
if (quiet_output) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
send(data)
|
||||
}
|
||||
|
||||
|
||||
// Implement a new TrustManager
|
||||
// ref: https://gist.github.com/oleavr/3ca67a173ff7d207c6b8c3b0ca65a9d8
|
||||
// Java.registerClass() is only supported on ART for now(201803). 所以android 4.4以下不兼容,4.4要切换成ART使用.
|
||||
/*
|
||||
06-07 16:15:38.541 27021-27073/mi.sslpinningdemo W/System.err: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
|
||||
06-07 16:15:38.542 27021-27073/mi.sslpinningdemo W/System.err: at android.net.http.X509TrustManagerExtensions.<init>(X509TrustManagerExtensions.java:73)
|
||||
at mi.ssl.MiPinningTrustManger.<init>(MiPinningTrustManger.java:61)
|
||||
06-07 16:15:38.543 27021-27073/mi.sslpinningdemo W/System.err: at mi.sslpinningdemo.OkHttpUtil.getSecPinningClient(OkHttpUtil.java:112)
|
||||
at mi.sslpinningdemo.OkHttpUtil.get(OkHttpUtil.java:62)
|
||||
at mi.sslpinningdemo.MainActivity$1$1.run(MainActivity.java:36)
|
||||
*/
|
||||
var X509Certificate = Java.use("java.security.cert.X509Certificate");
|
||||
var TrustManager;
|
||||
try {
|
||||
TrustManager = Java.registerClass({
|
||||
name: 'org.wooyun.TrustManager',
|
||||
implements: [X509TrustManager],
|
||||
methods: {
|
||||
checkClientTrusted: function(chain, authType) {},
|
||||
checkServerTrusted: function(chain, authType) {},
|
||||
getAcceptedIssuers: function() {
|
||||
// var certs = [X509Certificate.$new()];
|
||||
// return certs;
|
||||
return [];
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
quiet_send("registerClass from X509TrustManager >>>>>>>> " + e.message);
|
||||
}
|
||||
// Prepare the TrustManagers array to pass to SSLContext.init()
|
||||
var TrustManagers = [TrustManager.$new()];
|
||||
|
||||
try {
|
||||
// Prepare a Empty SSLFactory
|
||||
var TLS_SSLContext = SSLContext.getInstance("TLS");
|
||||
TLS_SSLContext.init(null, TrustManagers, null);
|
||||
var EmptySSLFactory = TLS_SSLContext.getSocketFactory();
|
||||
} catch (e) {
|
||||
quiet_send(e.message);
|
||||
}
|
||||
|
||||
send('Custom, Empty TrustManager ready');
|
||||
|
||||
// Get a handle on the init() on the SSLContext class
|
||||
var SSLContext_init = SSLContext.init.overload(
|
||||
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');
|
||||
|
||||
// Override the init method, specifying our new TrustManager
|
||||
SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {
|
||||
|
||||
quiet_send('Overriding SSLContext.init() with the custom TrustManager');
|
||||
|
||||
SSLContext_init.call(this, null, TrustManagers, null);
|
||||
};
|
||||
|
||||
/*** okhttp3.x unpinning ***/
|
||||
|
||||
|
||||
// Wrap the logic in a try/catch as not all applications will have
|
||||
// okhttp as part of the app.
|
||||
try {
|
||||
|
||||
var CertificatePinner = Java.use('okhttp3.CertificatePinner');
|
||||
|
||||
quiet_send('OkHTTP 3.x Found');
|
||||
|
||||
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
|
||||
|
||||
quiet_send('OkHTTP 3.x check() called. Not throwing an exception.');
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
// If we dont have a ClassNotFoundException exception, raise the
|
||||
// problem encountered.
|
||||
if (err.message.indexOf('ClassNotFoundException') === 0) {
|
||||
|
||||
throw new Error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Appcelerator Titanium PinningTrustManager
|
||||
|
||||
// Wrap the logic in a try/catch as not all applications will have
|
||||
// appcelerator as part of the app.
|
||||
try {
|
||||
|
||||
var PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager');
|
||||
|
||||
send('Appcelerator Titanium Found');
|
||||
|
||||
PinningTrustManager.checkServerTrusted.implementation = function() {
|
||||
|
||||
quiet_send('Appcelerator checkServerTrusted() called. Not throwing an exception.');
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
// If we dont have a ClassNotFoundException exception, raise the
|
||||
// problem encountered.
|
||||
if (err.message.indexOf('ClassNotFoundException') === 0) {
|
||||
|
||||
throw new Error(err);
|
||||
}
|
||||
}
|
||||
|
||||
/*** okhttp unpinning ***/
|
||||
|
||||
|
||||
try {
|
||||
var OkHttpClient = Java.use("com.squareup.okhttp.OkHttpClient");
|
||||
OkHttpClient.setCertificatePinner.implementation = function(certificatePinner) {
|
||||
// do nothing
|
||||
quiet_send("OkHttpClient.setCertificatePinner Called!");
|
||||
return this;
|
||||
};
|
||||
|
||||
// Invalidate the certificate pinnet checks (if "setCertificatePinner" was called before the previous invalidation)
|
||||
var CertificatePinner = Java.use("com.squareup.okhttp.CertificatePinner");
|
||||
CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(p0, p1) {
|
||||
// do nothing
|
||||
quiet_send("okhttp Called! [Certificate]");
|
||||
return;
|
||||
};
|
||||
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(p0, p1) {
|
||||
// do nothing
|
||||
quiet_send("okhttp Called! [List]");
|
||||
return;
|
||||
};
|
||||
} catch (e) {
|
||||
quiet_send("com.squareup.okhttp not found");
|
||||
}
|
||||
|
||||
/*** WebView Hooks ***/
|
||||
|
||||
/* frameworks/base/core/java/android/webkit/WebViewClient.java */
|
||||
/* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */
|
||||
var WebViewClient = Java.use("android.webkit.WebViewClient");
|
||||
|
||||
WebViewClient.onReceivedSslError.implementation = function(webView, sslErrorHandler, sslError) {
|
||||
quiet_send("WebViewClient onReceivedSslError invoke");
|
||||
//执行proceed方法
|
||||
sslErrorHandler.proceed();
|
||||
return;
|
||||
};
|
||||
|
||||
WebViewClient.onReceivedError.overload('android.webkit.WebView', 'int', 'java.lang.String', 'java.lang.String').implementation = function(a, b, c, d) {
|
||||
quiet_send("WebViewClient onReceivedError invoked");
|
||||
return;
|
||||
};
|
||||
|
||||
WebViewClient.onReceivedError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function() {
|
||||
quiet_send("WebViewClient onReceivedError invoked");
|
||||
return;
|
||||
};
|
||||
|
||||
/*** JSSE Hooks ***/
|
||||
|
||||
/* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */
|
||||
/* public final TrustManager[] getTrustManager() */
|
||||
/* TrustManagerFactory.getTrustManagers maybe cause X509TrustManagerExtensions error */
|
||||
// var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
|
||||
// TrustManagerFactory.getTrustManagers.implementation = function(){
|
||||
// quiet_send("TrustManagerFactory getTrustManagers invoked");
|
||||
// return TrustManagers;
|
||||
// }
|
||||
|
||||
var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");
|
||||
/* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
|
||||
/* public void setDefaultHostnameVerifier(HostnameVerifier) */
|
||||
HttpsURLConnection.setDefaultHostnameVerifier.implementation = function(hostnameVerifier) {
|
||||
quiet_send("HttpsURLConnection.setDefaultHostnameVerifier invoked");
|
||||
return null;
|
||||
};
|
||||
/* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
|
||||
/* public void setSSLSocketFactory(SSLSocketFactory) */
|
||||
HttpsURLConnection.setSSLSocketFactory.implementation = function(SSLSocketFactory) {
|
||||
quiet_send("HttpsURLConnection.setSSLSocketFactory invoked");
|
||||
return null;
|
||||
};
|
||||
/* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
|
||||
/* public void setHostnameVerifier(HostnameVerifier) */
|
||||
HttpsURLConnection.setHostnameVerifier.implementation = function(hostnameVerifier) {
|
||||
quiet_send("HttpsURLConnection.setHostnameVerifier invoked");
|
||||
return null;
|
||||
};
|
||||
|
||||
/*** Xutils3.x hooks ***/
|
||||
//Implement a new HostnameVerifier
|
||||
var TrustHostnameVerifier;
|
||||
try {
|
||||
TrustHostnameVerifier = Java.registerClass({
|
||||
name: 'org.wooyun.TrustHostnameVerifier',
|
||||
implements: [HostnameVerifier],
|
||||
method: {
|
||||
verify: function(hostname, session) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
//java.lang.ClassNotFoundException: Didn't find class "org.wooyun.TrustHostnameVerifier"
|
||||
quiet_send("registerClass from hostnameVerifier >>>>>>>> " + e.message);
|
||||
}
|
||||
|
||||
try {
|
||||
var RequestParams = Java.use('org.xutils.http.RequestParams');
|
||||
RequestParams.setSslSocketFactory.implementation = function(sslSocketFactory) {
|
||||
sslSocketFactory = EmptySSLFactory;
|
||||
return null;
|
||||
}
|
||||
|
||||
RequestParams.setHostnameVerifier.implementation = function(hostnameVerifier) {
|
||||
hostnameVerifier = TrustHostnameVerifier.$new();
|
||||
return null;
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
quiet_send("Xutils hooks not Found");
|
||||
}
|
||||
|
||||
/*** httpclientandroidlib Hooks ***/
|
||||
try {
|
||||
var AbstractVerifier = Java.use("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier");
|
||||
AbstractVerifier.verify.overload('java.lang.String', '[Ljava.lang.String', '[Ljava.lang.String', 'boolean').implementation = function() {
|
||||
quiet_send("httpclientandroidlib Hooks");
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
quiet_send("httpclientandroidlib Hooks not found");
|
||||
}
|
||||
|
||||
/***
|
||||
android 7.0+ network_security_config TrustManagerImpl hook
|
||||
apache httpclient partly
|
||||
***/
|
||||
var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");
|
||||
// try {
|
||||
// var Arrays = Java.use("java.util.Arrays");
|
||||
// //apache http client pinning maybe baypass
|
||||
// //https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#471
|
||||
// TrustManagerImpl.checkTrusted.implementation = function (chain, authType, session, parameters, authType) {
|
||||
// quiet_send("TrustManagerImpl checkTrusted called");
|
||||
// //Generics currently result in java.lang.Object
|
||||
// return Arrays.asList(chain);
|
||||
// }
|
||||
//
|
||||
// } catch (e) {
|
||||
// quiet_send("TrustManagerImpl checkTrusted nout found");
|
||||
// }
|
||||
|
||||
try {
|
||||
// Android 7+ TrustManagerImpl
|
||||
TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
|
||||
quiet_send("TrustManagerImpl verifyChain called");
|
||||
// Skip all the logic and just return the chain again :P
|
||||
//https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2017/november/bypassing-androids-network-security-configuration/
|
||||
// https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#L650
|
||||
return untrustedChain;
|
||||
}
|
||||
} catch (e) {
|
||||
quiet_send("TrustManagerImpl verifyChain nout found below 7.0");
|
||||
}
|
||||
// OpenSSLSocketImpl
|
||||
try {
|
||||
var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
|
||||
OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, authMethod) {
|
||||
quiet_send('OpenSSLSocketImpl.verifyCertificateChain');
|
||||
}
|
||||
|
||||
quiet_send('OpenSSLSocketImpl pinning')
|
||||
} catch (err) {
|
||||
quiet_send('OpenSSLSocketImpl pinner not found');
|
||||
}
|
||||
// Trustkit
|
||||
try {
|
||||
var Activity = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier");
|
||||
Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(str) {
|
||||
quiet_send('Trustkit.verify1: ' + str);
|
||||
return true;
|
||||
};
|
||||
Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(str) {
|
||||
quiet_send('Trustkit.verify2: ' + str);
|
||||
return true;
|
||||
};
|
||||
|
||||
quiet_send('Trustkit pinning')
|
||||
} catch (err) {
|
||||
quiet_send('Trustkit pinner not found')
|
||||
}
|
||||
|
||||
try {
|
||||
//cronet pinner hook
|
||||
//weibo don't invoke
|
||||
|
||||
var netBuilder = Java.use("org.chromium.net.CronetEngine$Builder");
|
||||
|
||||
//https://developer.android.com/guide/topics/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder.html#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean)
|
||||
netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.implementation = function(arg) {
|
||||
|
||||
//weibo not invoke
|
||||
console.log("Enables or disables public key pinning bypass for local trust anchors = " + arg);
|
||||
|
||||
//true to enable the bypass, false to disable.
|
||||
var ret = netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true);
|
||||
return ret;
|
||||
};
|
||||
|
||||
netBuilder.addPublicKeyPins.implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) {
|
||||
console.log("cronet addPublicKeyPins hostName = " + hostName);
|
||||
|
||||
//var ret = netBuilder.addPublicKeyPins.call(this,hostName, pinsSha256,includeSubdomains, expirationDate);
|
||||
//this 是调用 addPublicKeyPins 前的对象吗? Yes,CronetEngine.Builder
|
||||
return this;
|
||||
};
|
||||
|
||||
} catch (err) {
|
||||
console.log('[-] Cronet pinner not found')
|
||||
}
|
||||
});
|
||||
32
scripts/monitor_request.js
Normal file
32
scripts/monitor_request.js
Normal file
@@ -0,0 +1,32 @@
|
||||
log_info("Script loaded successfully");
|
||||
Java.perform(function () {
|
||||
var OkHttpClient = Java.use('okhttp3.OkHttpClient');
|
||||
var Request = Java.use('okhttp3.Request');
|
||||
|
||||
OkHttpClient.newCall.implementation = function (request) {
|
||||
var url = request.url().toString();
|
||||
var method = request.method();
|
||||
var body = request.body();
|
||||
var size = body != null ? body.contentLength() / 1024 : 0;
|
||||
console.log("Method: " + method + "\nURL: " + url + "\nSize: " + size + " kb");
|
||||
|
||||
return this.newCall(request);
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
function log_info(messages) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-based
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
const milliseconds = String(now.getMilliseconds()).padStart(3, '0');
|
||||
|
||||
const timestamp = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}:${milliseconds}`;
|
||||
|
||||
console.log(`${timestamp} - ${messages}`);
|
||||
send(`${timestamp} - ${messages}`);
|
||||
}
|
||||
20
scripts/test.js
Normal file
20
scripts/test.js
Normal file
@@ -0,0 +1,20 @@
|
||||
Java.perform(function() {
|
||||
var ByteArrayOutputStream = Java.use('java.io.ByteArrayOutputStream');
|
||||
var HttpsURLConnection = Java.use('javax.net.ssl.HttpsURLConnection');
|
||||
|
||||
HttpsURLConnection.getOutputStream.implementation = function() {
|
||||
var outputStream = this.getOutputStream();
|
||||
|
||||
// 创建一个新的 ByteArrayOutputStream 实例,以便于我们读取数据。
|
||||
var byteArrayOutputStream = ByteArrayOutputStream.$new();
|
||||
|
||||
outputStream.write.overload('[B').implementation = function(buffer) {
|
||||
byteArrayOutputStream.write(buffer);
|
||||
console.log("[*] Data written to URL:", this.getURL().toString());
|
||||
console.log("[*] Data:", byteArrayOutputStream.toString('UTF-8'));
|
||||
return outputStream.write(buffer);
|
||||
};
|
||||
|
||||
return outputStream;
|
||||
};
|
||||
});
|
||||
82
scripts/url_request.js
Normal file
82
scripts/url_request.js
Normal file
@@ -0,0 +1,82 @@
|
||||
Java.perform(function() {
|
||||
var URL = Java.use("java.net.URL");
|
||||
var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");
|
||||
var HttpURLConnection = Java.use("java.net.HttpURLConnection");
|
||||
var OutputStreamWriter = Java.use("java.io.OutputStreamWriter");
|
||||
var BufferedReader = Java.use("java.io.BufferedReader");
|
||||
var InputStreamReader = Java.use("java.io.InputStreamReader");
|
||||
var OutputStream = Java.use('java.io.OutputStream');
|
||||
var OkHttpClient = Java.use('okhttp3.OkHttpClient');
|
||||
|
||||
URL.$init.overload('java.lang.String').implementation = function(url) {
|
||||
console.log("[*] URL init:", url.toString());
|
||||
return this.$init(url);
|
||||
};
|
||||
|
||||
HttpsURLConnection.setDoOutput.implementation = function(value) {
|
||||
console.log("[*]HttpsURLConnection setDoOutput:", value);
|
||||
return this.setDoOutput(value);
|
||||
};
|
||||
|
||||
HttpsURLConnection.setRequestProperty.implementation = function(key, value) {
|
||||
console.log("[*] setRequestProperty:", key, value);
|
||||
return this.setRequestProperty(key, value);
|
||||
};
|
||||
|
||||
|
||||
HttpsURLConnection.getOutputStream.implementation = function() {
|
||||
console.log("[*] getOutputStream");
|
||||
return this.getOutputStream();
|
||||
};
|
||||
|
||||
|
||||
|
||||
HttpURLConnection.setRequestProperty.implementation = function(key, value) {
|
||||
console.log("[*] setRequestProperty:", key, value);
|
||||
return this.setRequestProperty(key, value);
|
||||
};
|
||||
|
||||
HttpURLConnection.setDoOutput.implementation = function(value) {
|
||||
console.log("[*]HttpURLConnection setDoOutput:", value);
|
||||
return this.setDoOutput(value);
|
||||
};
|
||||
|
||||
// HttpURLConnection.getOutputStream.implementation = function() {
|
||||
// console.log("[*] getOutputStream");
|
||||
// var outputStream = this.getOutputStream();
|
||||
//
|
||||
// outputStream.write.overload('[B').implementation = function(buffer) {
|
||||
// console.log("[*] Data written:", Java.array('byte', buffer).toString());
|
||||
// return this.write(buffer);
|
||||
// };
|
||||
// return outputStream;
|
||||
// };
|
||||
|
||||
// OutputStream.write.overload('[B').implementation = function(buffer) {
|
||||
// console.log("[*] Data written:", Java.array('byte', buffer).toString());
|
||||
// return this.write(buffer);
|
||||
// };
|
||||
|
||||
BufferedReader.readLine.overload().implementation = function() {
|
||||
var line = this.readLine();
|
||||
// console.log("[*] BufferedReader.readLine:", line);
|
||||
return line;
|
||||
};
|
||||
|
||||
InputStreamReader.$init.overload('java.io.InputStream').implementation = function(stream) {
|
||||
console.log("[*] InputStreamReader.init:", stream);
|
||||
return this.$init(stream);
|
||||
};
|
||||
|
||||
OkHttpClient.newCall.overload('okhttp3.Request').implementation = function(request) {
|
||||
console.log("[*] Request URL:", request.url().toString());
|
||||
console.log("[*] Request Headers:", request.headers().toString());
|
||||
|
||||
if (request.method() == "POST") {
|
||||
console.log("[*] Request Body:", request.body().toString());
|
||||
}
|
||||
|
||||
return this.newCall(request);
|
||||
};
|
||||
});
|
||||
|
||||
33
test.py
33
test.py
@@ -1,24 +1,11 @@
|
||||
import frida
|
||||
import frida,sys
|
||||
import modules.files_utils
|
||||
|
||||
|
||||
def is_frida_running(device):
|
||||
try:
|
||||
# 获取设备上的所有进程
|
||||
processes = device.enumerate_processes()
|
||||
|
||||
# 检查是否存在名为 'frida-server' 的进程
|
||||
for process in processes:
|
||||
print(process)
|
||||
if process.name == 'frida':
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
device = frida.get_usb_device(timeout=3)
|
||||
if is_frida_running(device):
|
||||
print("Frida is running on the device.")
|
||||
else:
|
||||
print("Frida is not running on the device.")
|
||||
js_code = modules.files_utils.read_javascript("scripts/hook_conversions.js")
|
||||
device = frida.get_usb_device()
|
||||
pid = device.spawn(["com.naviapp"]) # 以挂起方式创建进程
|
||||
process = device.attach(pid)
|
||||
script = process.create_script(js_code)
|
||||
script.load()
|
||||
device.resume(pid) # 加载完脚本, 恢复进程运行
|
||||
sys.stdin.read()
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
Pygments is written and maintained by Georg Brandl <georg@python.org>.
|
||||
|
||||
Major developers are Tim Hatch <tim@timhatch.com> and Armin Ronacher
|
||||
<armin.ronacher@active-4.com>.
|
||||
|
||||
Other contributors, listed alphabetically, are:
|
||||
|
||||
* Sam Aaron -- Ioke lexer
|
||||
* Jean Abou Samra -- LilyPond lexer
|
||||
* João Abecasis -- JSLT lexer
|
||||
* Ali Afshar -- image formatter
|
||||
* Thomas Aglassinger -- Easytrieve, JCL, Rexx, Transact-SQL and VBScript
|
||||
lexers
|
||||
* Maxence Ahlouche -- PostgreSQL Explain lexer
|
||||
* Muthiah Annamalai -- Ezhil lexer
|
||||
* Nikolay Antipov -- OpenSCAD lexer
|
||||
* Kumar Appaiah -- Debian control lexer
|
||||
* Andreas Amann -- AppleScript lexer
|
||||
* Timothy Armstrong -- Dart lexer fixes
|
||||
* Jeffrey Arnold -- R/S, Rd, BUGS, Jags, and Stan lexers
|
||||
* Eiríkr Åsheim -- Uxntal lexer
|
||||
* Jeremy Ashkenas -- CoffeeScript lexer
|
||||
* José Joaquín Atria -- Praat lexer
|
||||
* Stefan Matthias Aust -- Smalltalk lexer
|
||||
* Lucas Bajolet -- Nit lexer
|
||||
* Ben Bangert -- Mako lexers
|
||||
* Max Battcher -- Darcs patch lexer
|
||||
* Thomas Baruchel -- APL lexer
|
||||
* Tim Baumann -- (Literate) Agda lexer
|
||||
* Paul Baumgart, 280 North, Inc. -- Objective-J lexer
|
||||
* Michael Bayer -- Myghty lexers
|
||||
* Thomas Beale -- Archetype lexers
|
||||
* John Benediktsson -- Factor lexer
|
||||
* David Benjamin, Google LLC -- TLS lexer
|
||||
* Trevor Bergeron -- mIRC formatter
|
||||
* Vincent Bernat -- LessCSS lexer
|
||||
* Christopher Bertels -- Fancy lexer
|
||||
* Sébastien Bigaret -- QVT Operational lexer
|
||||
* Jarrett Billingsley -- MiniD lexer
|
||||
* Adam Blinkinsop -- Haskell, Redcode lexers
|
||||
* Stéphane Blondon -- Procfile, SGF and Sieve lexers
|
||||
* Frits van Bommel -- assembler lexers
|
||||
* Pierre Bourdon -- bugfixes
|
||||
* Martijn Braam -- Kernel log lexer, BARE lexer
|
||||
* Matthias Bussonnier -- ANSI style handling for terminal-256 formatter
|
||||
* chebee7i -- Python traceback lexer improvements
|
||||
* Hiram Chirino -- Scaml and Jade lexers
|
||||
* Mauricio Caceres -- SAS and Stata lexers.
|
||||
* Ian Cooper -- VGL lexer
|
||||
* David Corbett -- Inform, Jasmin, JSGF, Snowball, and TADS 3 lexers
|
||||
* Leaf Corcoran -- MoonScript lexer
|
||||
* Gabriel Corona -- ASN.1 lexer
|
||||
* Christopher Creutzig -- MuPAD lexer
|
||||
* Daniël W. Crompton -- Pike lexer
|
||||
* Pete Curry -- bugfixes
|
||||
* Bryan Davis -- EBNF lexer
|
||||
* Bruno Deferrari -- Shen lexer
|
||||
* Walter Dörwald -- UL4 lexer
|
||||
* Luke Drummond -- Meson lexer
|
||||
* Giedrius Dubinskas -- HTML formatter improvements
|
||||
* Owen Durni -- Haxe lexer
|
||||
* Alexander Dutton, Oxford University Computing Services -- SPARQL lexer
|
||||
* James Edwards -- Terraform lexer
|
||||
* Nick Efford -- Python 3 lexer
|
||||
* Sven Efftinge -- Xtend lexer
|
||||
* Artem Egorkine -- terminal256 formatter
|
||||
* Matthew Fernandez -- CAmkES lexer
|
||||
* Paweł Fertyk -- GDScript lexer, HTML formatter improvements
|
||||
* Michael Ficarra -- CPSA lexer
|
||||
* James H. Fisher -- PostScript lexer
|
||||
* William S. Fulton -- SWIG lexer
|
||||
* Carlos Galdino -- Elixir and Elixir Console lexers
|
||||
* Michael Galloy -- IDL lexer
|
||||
* Naveen Garg -- Autohotkey lexer
|
||||
* Simon Garnotel -- FreeFem++ lexer
|
||||
* Laurent Gautier -- R/S lexer
|
||||
* Alex Gaynor -- PyPy log lexer
|
||||
* Richard Gerkin -- Igor Pro lexer
|
||||
* Alain Gilbert -- TypeScript lexer
|
||||
* Alex Gilding -- BlitzBasic lexer
|
||||
* GitHub, Inc -- DASM16, Augeas, TOML, and Slash lexers
|
||||
* Bertrand Goetzmann -- Groovy lexer
|
||||
* Krzysiek Goj -- Scala lexer
|
||||
* Rostyslav Golda -- FloScript lexer
|
||||
* Andrey Golovizin -- BibTeX lexers
|
||||
* Matt Good -- Genshi, Cheetah lexers
|
||||
* Michał Górny -- vim modeline support
|
||||
* Alex Gosse -- TrafficScript lexer
|
||||
* Patrick Gotthardt -- PHP namespaces support
|
||||
* Hubert Gruniaux -- C and C++ lexer improvements
|
||||
* Olivier Guibe -- Asymptote lexer
|
||||
* Phil Hagelberg -- Fennel lexer
|
||||
* Florian Hahn -- Boogie lexer
|
||||
* Martin Harriman -- SNOBOL lexer
|
||||
* Matthew Harrison -- SVG formatter
|
||||
* Steven Hazel -- Tcl lexer
|
||||
* Dan Michael Heggø -- Turtle lexer
|
||||
* Aslak Hellesøy -- Gherkin lexer
|
||||
* Greg Hendershott -- Racket lexer
|
||||
* Justin Hendrick -- ParaSail lexer
|
||||
* Jordi Gutiérrez Hermoso -- Octave lexer
|
||||
* David Hess, Fish Software, Inc. -- Objective-J lexer
|
||||
* Ken Hilton -- Typographic Number Theory and Arrow lexers
|
||||
* Varun Hiremath -- Debian control lexer
|
||||
* Rob Hoelz -- Perl 6 lexer
|
||||
* Doug Hogan -- Mscgen lexer
|
||||
* Ben Hollis -- Mason lexer
|
||||
* Max Horn -- GAP lexer
|
||||
* Fred Hornsey -- OMG IDL Lexer
|
||||
* Alastair Houghton -- Lexer inheritance facility
|
||||
* Tim Howard -- BlitzMax lexer
|
||||
* Dustin Howett -- Logos lexer
|
||||
* Ivan Inozemtsev -- Fantom lexer
|
||||
* Hiroaki Itoh -- Shell console rewrite, Lexers for PowerShell session,
|
||||
MSDOS session, BC, WDiff
|
||||
* Brian R. Jackson -- Tea lexer
|
||||
* Christian Jann -- ShellSession lexer
|
||||
* Dennis Kaarsemaker -- sources.list lexer
|
||||
* Dmitri Kabak -- Inferno Limbo lexer
|
||||
* Igor Kalnitsky -- vhdl lexer
|
||||
* Colin Kennedy - USD lexer
|
||||
* Alexander Kit -- MaskJS lexer
|
||||
* Pekka Klärck -- Robot Framework lexer
|
||||
* Gerwin Klein -- Isabelle lexer
|
||||
* Eric Knibbe -- Lasso lexer
|
||||
* Stepan Koltsov -- Clay lexer
|
||||
* Oliver Kopp - Friendly grayscale style
|
||||
* Adam Koprowski -- Opa lexer
|
||||
* Benjamin Kowarsch -- Modula-2 lexer
|
||||
* Domen Kožar -- Nix lexer
|
||||
* Oleh Krekel -- Emacs Lisp lexer
|
||||
* Alexander Kriegisch -- Kconfig and AspectJ lexers
|
||||
* Marek Kubica -- Scheme lexer
|
||||
* Jochen Kupperschmidt -- Markdown processor
|
||||
* Gerd Kurzbach -- Modelica lexer
|
||||
* Jon Larimer, Google Inc. -- Smali lexer
|
||||
* Olov Lassus -- Dart lexer
|
||||
* Matt Layman -- TAP lexer
|
||||
* Kristian Lyngstøl -- Varnish lexers
|
||||
* Sylvestre Ledru -- Scilab lexer
|
||||
* Chee Sing Lee -- Flatline lexer
|
||||
* Mark Lee -- Vala lexer
|
||||
* Pete Lomax -- Phix lexer
|
||||
* Valentin Lorentz -- C++ lexer improvements
|
||||
* Ben Mabey -- Gherkin lexer
|
||||
* Angus MacArthur -- QML lexer
|
||||
* Louis Mandel -- X10 lexer
|
||||
* Louis Marchand -- Eiffel lexer
|
||||
* Simone Margaritelli -- Hybris lexer
|
||||
* Tim Martin - World of Warcraft TOC lexer
|
||||
* Kirk McDonald -- D lexer
|
||||
* Gordon McGregor -- SystemVerilog lexer
|
||||
* Stephen McKamey -- Duel/JBST lexer
|
||||
* Brian McKenna -- F# lexer
|
||||
* Charles McLaughlin -- Puppet lexer
|
||||
* Kurt McKee -- Tera Term macro lexer, PostgreSQL updates, MySQL overhaul, JSON lexer
|
||||
* Joe Eli McIlvain -- Savi lexer
|
||||
* Lukas Meuser -- BBCode formatter, Lua lexer
|
||||
* Cat Miller -- Pig lexer
|
||||
* Paul Miller -- LiveScript lexer
|
||||
* Hong Minhee -- HTTP lexer
|
||||
* Michael Mior -- Awk lexer
|
||||
* Bruce Mitchener -- Dylan lexer rewrite
|
||||
* Reuben Morais -- SourcePawn lexer
|
||||
* Jon Morton -- Rust lexer
|
||||
* Paulo Moura -- Logtalk lexer
|
||||
* Mher Movsisyan -- DTD lexer
|
||||
* Dejan Muhamedagic -- Crmsh lexer
|
||||
* Adrien Nayrat -- PostgreSQL Explain lexer
|
||||
* Ana Nelson -- Ragel, ANTLR, R console lexers
|
||||
* David Neto, Google LLC -- WebGPU Shading Language lexer
|
||||
* Kurt Neufeld -- Markdown lexer
|
||||
* Nam T. Nguyen -- Monokai style
|
||||
* Jesper Noehr -- HTML formatter "anchorlinenos"
|
||||
* Mike Nolta -- Julia lexer
|
||||
* Avery Nortonsmith -- Pointless lexer
|
||||
* Jonas Obrist -- BBCode lexer
|
||||
* Edward O'Callaghan -- Cryptol lexer
|
||||
* David Oliva -- Rebol lexer
|
||||
* Pat Pannuto -- nesC lexer
|
||||
* Jon Parise -- Protocol buffers and Thrift lexers
|
||||
* Benjamin Peterson -- Test suite refactoring
|
||||
* Ronny Pfannschmidt -- BBCode lexer
|
||||
* Dominik Picheta -- Nimrod lexer
|
||||
* Andrew Pinkham -- RTF Formatter Refactoring
|
||||
* Clément Prévost -- UrbiScript lexer
|
||||
* Tanner Prynn -- cmdline -x option and loading lexers from files
|
||||
* Oleh Prypin -- Crystal lexer (based on Ruby lexer)
|
||||
* Nick Psaris -- K and Q lexers
|
||||
* Xidorn Quan -- Web IDL lexer
|
||||
* Elias Rabel -- Fortran fixed form lexer
|
||||
* raichoo -- Idris lexer
|
||||
* Daniel Ramirez -- GDScript lexer
|
||||
* Kashif Rasul -- CUDA lexer
|
||||
* Nathan Reed -- HLSL lexer
|
||||
* Justin Reidy -- MXML lexer
|
||||
* Norman Richards -- JSON lexer
|
||||
* Corey Richardson -- Rust lexer updates
|
||||
* Fabrizio Riguzzi -- cplint leder
|
||||
* Lubomir Rintel -- GoodData MAQL and CL lexers
|
||||
* Andre Roberge -- Tango style
|
||||
* Georg Rollinger -- HSAIL lexer
|
||||
* Michiel Roos -- TypoScript lexer
|
||||
* Konrad Rudolph -- LaTeX formatter enhancements
|
||||
* Mario Ruggier -- Evoque lexers
|
||||
* Miikka Salminen -- Lovelace style, Hexdump lexer, lexer enhancements
|
||||
* Stou Sandalski -- NumPy, FORTRAN, tcsh and XSLT lexers
|
||||
* Matteo Sasso -- Common Lisp lexer
|
||||
* Joe Schafer -- Ada lexer
|
||||
* Max Schillinger -- TiddlyWiki5 lexer
|
||||
* Andrew Schmidt -- X++ lexer
|
||||
* Ken Schutte -- Matlab lexers
|
||||
* René Schwaiger -- Rainbow Dash style
|
||||
* Sebastian Schweizer -- Whiley lexer
|
||||
* Tassilo Schweyer -- Io, MOOCode lexers
|
||||
* Pablo Seminario -- PromQL lexer
|
||||
* Ted Shaw -- AutoIt lexer
|
||||
* Joerg Sieker -- ABAP lexer
|
||||
* Robert Simmons -- Standard ML lexer
|
||||
* Kirill Simonov -- YAML lexer
|
||||
* Corbin Simpson -- Monte lexer
|
||||
* Ville Skyttä -- ASCII armored lexer
|
||||
* Alexander Smishlajev -- Visual FoxPro lexer
|
||||
* Steve Spigarelli -- XQuery lexer
|
||||
* Jerome St-Louis -- eC lexer
|
||||
* Camil Staps -- Clean and NuSMV lexers; Solarized style
|
||||
* James Strachan -- Kotlin lexer
|
||||
* Tom Stuart -- Treetop lexer
|
||||
* Colin Sullivan -- SuperCollider lexer
|
||||
* Ben Swift -- Extempore lexer
|
||||
* tatt61880 -- Kuin lexer
|
||||
* Edoardo Tenani -- Arduino lexer
|
||||
* Tiberius Teng -- default style overhaul
|
||||
* Jeremy Thurgood -- Erlang, Squid config lexers
|
||||
* Brian Tiffin -- OpenCOBOL lexer
|
||||
* Bob Tolbert -- Hy lexer
|
||||
* Doug Torrance -- Macaulay2 lexer
|
||||
* Matthias Trute -- Forth lexer
|
||||
* Tuoa Spi T4 -- Bdd lexer
|
||||
* Erick Tryzelaar -- Felix lexer
|
||||
* Alexander Udalov -- Kotlin lexer improvements
|
||||
* Thomas Van Doren -- Chapel lexer
|
||||
* Dave Van Ee -- Uxntal lexer updates
|
||||
* Daniele Varrazzo -- PostgreSQL lexers
|
||||
* Abe Voelker -- OpenEdge ABL lexer
|
||||
* Pepijn de Vos -- HTML formatter CTags support
|
||||
* Matthias Vallentin -- Bro lexer
|
||||
* Benoît Vinot -- AMPL lexer
|
||||
* Linh Vu Hong -- RSL lexer
|
||||
* Immanuel Washington -- Smithy lexer
|
||||
* Nathan Weizenbaum -- Haml and Sass lexers
|
||||
* Nathan Whetsell -- Csound lexers
|
||||
* Dietmar Winkler -- Modelica lexer
|
||||
* Nils Winter -- Smalltalk lexer
|
||||
* Davy Wybiral -- Clojure lexer
|
||||
* Whitney Young -- ObjectiveC lexer
|
||||
* Diego Zamboni -- CFengine3 lexer
|
||||
* Enrique Zamudio -- Ceylon lexer
|
||||
* Alex Zimin -- Nemerle lexer
|
||||
* Rob Zimmerman -- Kal lexer
|
||||
* Vincent Zurczak -- Roboconf lexer
|
||||
* Hubert Gruniaux -- C and C++ lexer improvements
|
||||
* Thomas Symalla -- AMDGPU Lexer
|
||||
* 15b3 -- Image Formatter improvements
|
||||
* Fabian Neumann -- CDDL lexer
|
||||
* Thomas Duboucher -- CDDL lexer
|
||||
* Philipp Imhof -- Pango Markup formatter
|
||||
* Thomas Voss -- Sed lexer
|
||||
* Martin Fischer -- WCAG contrast testing
|
||||
* Marc Auberer -- Spice lexer
|
||||
* Amr Hesham -- Carbon lexer
|
||||
* diskdance -- Wikitext lexer
|
||||
* Nikolay Antipov -- OpenSCAD lexer
|
||||
* Markus Meyer, Nextron Systems -- YARA lexer
|
||||
|
||||
|
||||
Many thanks for all contributions!
|
||||
@@ -1 +0,0 @@
|
||||
pip
|
||||
@@ -1,25 +0,0 @@
|
||||
Copyright (c) 2006-2022 by the respective authors (see AUTHORS file).
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,56 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Pygments
|
||||
Version: 2.16.1
|
||||
Summary: Pygments is a syntax highlighting package written in Python.
|
||||
Author-email: Georg Brandl <georg@python.org>
|
||||
Maintainer: Matthäus G. Chajdas
|
||||
Maintainer-email: Georg Brandl <georg@python.org>, Jean Abou Samra <jean@abou-samra.fr>
|
||||
License: BSD-2-Clause
|
||||
Project-URL: Homepage, https://pygments.org
|
||||
Project-URL: Documentation, https://pygments.org/docs
|
||||
Project-URL: Source, https://github.com/pygments/pygments
|
||||
Project-URL: Bug Tracker, https://github.com/pygments/pygments/issues
|
||||
Project-URL: Changelog, https://github.com/pygments/pygments/blob/master/CHANGES
|
||||
Keywords: syntax highlighting
|
||||
Classifier: Development Status :: 6 - Mature
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: End Users/Desktop
|
||||
Classifier: Intended Audience :: System Administrators
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Text Processing :: Filters
|
||||
Classifier: Topic :: Utilities
|
||||
Requires-Python: >=3.7
|
||||
Description-Content-Type: text/x-rst
|
||||
License-File: LICENSE
|
||||
License-File: AUTHORS
|
||||
Provides-Extra: plugins
|
||||
Requires-Dist: importlib-metadata ; (python_version < "3.8") and extra == 'plugins'
|
||||
|
||||
Pygments
|
||||
~~~~~~~~
|
||||
|
||||
Pygments is a syntax highlighting package written in Python.
|
||||
|
||||
It is a generic syntax highlighter suitable for use in code hosting, forums,
|
||||
wikis or other applications that need to prettify source code. Highlights
|
||||
are:
|
||||
|
||||
* a wide range of over 500 languages and other text formats is supported
|
||||
* special attention is paid to details, increasing quality by a fair amount
|
||||
* support for new languages and formats are added easily
|
||||
* a number of output formats, presently HTML, LaTeX, RTF, SVG, all image
|
||||
formats that PIL supports and ANSI sequences
|
||||
* it is usable as a command-line tool and as a library
|
||||
|
||||
Copyright 2006-2023 by the Pygments team, see ``AUTHORS``.
|
||||
Licensed under the BSD, see ``LICENSE`` for details.
|
||||
@@ -1,635 +0,0 @@
|
||||
../../Scripts/pygmentize.exe,sha256=bfWrzukXg_T53yeLdio_fnE06eFnA_EVTvcZbG2Qi5Q,108408
|
||||
Pygments-2.16.1.dist-info/AUTHORS,sha256=dK80VJCrS-ONy4SVzPGhUP1zA_Jb1xbVKkNJbq8jEOw,10205
|
||||
Pygments-2.16.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Pygments-2.16.1.dist-info/LICENSE,sha256=qdZvHVJt8C4p3Oc0NtNOVuhjL0bCdbvf_HBWnogvnxc,1331
|
||||
Pygments-2.16.1.dist-info/METADATA,sha256=wFAnrrHdwCa6JYSly_Yu2scYO9YiPrq2yJCE09UHPB8,2451
|
||||
Pygments-2.16.1.dist-info/RECORD,,
|
||||
Pygments-2.16.1.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
|
||||
Pygments-2.16.1.dist-info/entry_points.txt,sha256=uUXw-XhMKBEX4pWcCtpuTTnPhL3h7OEE2jWi51VQsa8,53
|
||||
Pygments-2.16.1.dist-info/top_level.txt,sha256=RjKKqrVIStoebLHdbs0yZ2Lk4rS7cxGguXsLCYvZ2Ak,9
|
||||
pygments/__init__.py,sha256=Xox2DbZtfZilsOp0WSDuB5ymdevX5Q09WGI4yrxM8hI,2959
|
||||
pygments/__main__.py,sha256=xVzk7wG94kskOfLT6ORXWRPRZZ0IAavOeRCtGXn2yEM,348
|
||||
pygments/__pycache__/__init__.cpython-311.pyc,,
|
||||
pygments/__pycache__/__main__.cpython-311.pyc,,
|
||||
pygments/__pycache__/cmdline.cpython-311.pyc,,
|
||||
pygments/__pycache__/console.cpython-311.pyc,,
|
||||
pygments/__pycache__/filter.cpython-311.pyc,,
|
||||
pygments/__pycache__/formatter.cpython-311.pyc,,
|
||||
pygments/__pycache__/lexer.cpython-311.pyc,,
|
||||
pygments/__pycache__/modeline.cpython-311.pyc,,
|
||||
pygments/__pycache__/plugin.cpython-311.pyc,,
|
||||
pygments/__pycache__/regexopt.cpython-311.pyc,,
|
||||
pygments/__pycache__/scanner.cpython-311.pyc,,
|
||||
pygments/__pycache__/sphinxext.cpython-311.pyc,,
|
||||
pygments/__pycache__/style.cpython-311.pyc,,
|
||||
pygments/__pycache__/token.cpython-311.pyc,,
|
||||
pygments/__pycache__/unistring.cpython-311.pyc,,
|
||||
pygments/__pycache__/util.cpython-311.pyc,,
|
||||
pygments/cmdline.py,sha256=5BDrKb_cOcvzp0Ps8rr4rFIO8kYb15JDlEiRKpoTwWE,23530
|
||||
pygments/console.py,sha256=2wZ5W-U6TudJD1_NLUwjclMpbomFM91lNv11_60sfGY,1697
|
||||
pygments/filter.py,sha256=j5aLM9a9wSx6eH1oy473oSkJ02hGWNptBlVo4s1g_30,1938
|
||||
pygments/filters/__init__.py,sha256=q8r8GfK3dO021TSHJdpwNwh6RHKbAL7ceCzohavWaN0,40338
|
||||
pygments/filters/__pycache__/__init__.cpython-311.pyc,,
|
||||
pygments/formatter.py,sha256=Yz01yT1NSQXTF8GvsLxJSmez7ErTVOsxm3M6GVPuH-w,4154
|
||||
pygments/formatters/__init__.py,sha256=iRJiIk5375wDS08XLtJgTYEHzLd1_uvDGG0C85zQsfs,5388
|
||||
pygments/formatters/__pycache__/__init__.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/_mapping.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/bbcode.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/groff.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/html.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/img.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/irc.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/latex.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/other.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/pangomarkup.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/rtf.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/svg.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/terminal.cpython-311.pyc,,
|
||||
pygments/formatters/__pycache__/terminal256.cpython-311.pyc,,
|
||||
pygments/formatters/_mapping.py,sha256=1Cw37FuQlNacnxRKmtlPX4nyLoX9_ttko5ZwscNUZZ4,4176
|
||||
pygments/formatters/bbcode.py,sha256=7zcNcnoNj-dCyJlrHnmtq0V2o8ZGD14N5anFV4FQ5PE,3290
|
||||
pygments/formatters/groff.py,sha256=va2xlSCN-e_i0c_Dz0dg3HV9Ajt9G45PXaCi7CEsLdg,5070
|
||||
pygments/formatters/html.py,sha256=C0BdFXcODAHHHHVRiE5G6G3dUG_BHk938w90w-og1ZI,35574
|
||||
pygments/formatters/img.py,sha256=h0_7rBECMiz5Ylu3mc84C59NqQiycsZanBPgh_jJujo,23116
|
||||
pygments/formatters/irc.py,sha256=Jkze75ztayIkhNijfnFIsqOUR-Yz5fwEQM_oeWdOnRU,4945
|
||||
pygments/formatters/latex.py,sha256=48gMb8ziYgyQVJ4Ofx8x3Ka2l0RBomgYgn5zjeQK_vM,19303
|
||||
pygments/formatters/other.py,sha256=RzJhlXeYHyLxiC5vESy41WUK0FOqJPxvMiR6Von0z5Q,5025
|
||||
pygments/formatters/pangomarkup.py,sha256=0i4H7NLsxcxzFCJU5ONDJmhlLvsSLCnaFn-FXA5SMQk,2200
|
||||
pygments/formatters/rtf.py,sha256=8xghaGMBBXq2XNj-ZWNzYAeX_GqIDMqUBiJLDCulzNI,4990
|
||||
pygments/formatters/svg.py,sha256=VxjE-iqarQXJEFRissuLbsooXUCVXWgObQ7c4ub-5zg,7299
|
||||
pygments/formatters/terminal.py,sha256=P_dr7GLyRTIKg8LEceCOr5B5eGzGQBELA3JQOMvZ8VA,4626
|
||||
pygments/formatters/terminal256.py,sha256=_xYtNUUTAie5Bh7S98nrt7XIlLUURzDykosP7tT7044,11717
|
||||
pygments/lexer.py,sha256=mwt-oERb42u6R5qWdcujh9-xEv83QAVF5NwNnK5J6Fo,34825
|
||||
pygments/lexers/__init__.py,sha256=zIVAQGUmmzrjrNGeOEn0j178RNUqIb6bN8dnqIihfSA,12082
|
||||
pygments/lexers/__pycache__/__init__.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_ada_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_asy_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_cl_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_cocoa_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_csound_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_css_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_julia_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_lasso_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_lilypond_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_lua_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_mapping.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_mql_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_mysql_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_openedge_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_php_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_postgres_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_qlik_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_scheme_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_scilab_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_sourcemod_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_stan_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_stata_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_tsql_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_usd_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_vbscript_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/_vim_builtins.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/actionscript.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ada.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/agile.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/algebra.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ambient.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/amdgpu.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ampl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/apdlexer.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/apl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/archetype.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/arrow.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/arturo.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/asc.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/asm.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/asn1.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/automation.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/bare.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/basic.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/bdd.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/berry.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/bibtex.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/blueprint.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/boa.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/bqn.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/business.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/c_cpp.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/c_like.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/capnproto.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/carbon.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/cddl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/chapel.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/clean.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/comal.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/compiled.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/configs.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/console.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/cplint.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/crystal.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/csound.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/css.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/d.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/dalvik.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/data.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/dax.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/devicetree.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/diff.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/dns.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/dotnet.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/dsls.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/dylan.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ecl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/eiffel.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/elm.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/elpi.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/email.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/erlang.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/esoteric.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ezhil.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/factor.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/fantom.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/felix.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/fift.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/floscript.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/forth.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/fortran.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/foxpro.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/freefem.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/func.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/functional.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/futhark.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/gcodelexer.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/gdscript.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/go.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/grammar_notation.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/graph.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/graphics.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/graphql.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/graphviz.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/gsql.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/haskell.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/haxe.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/hdl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/hexdump.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/html.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/idl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/igor.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/inferno.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/installers.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/int_fiction.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/iolang.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/j.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/javascript.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/jmespath.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/jslt.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/jsonnet.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/julia.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/jvm.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/kuin.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/lilypond.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/lisp.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/macaulay2.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/make.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/markup.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/math.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/matlab.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/maxima.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/meson.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/mime.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/minecraft.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/mips.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ml.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/modeling.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/modula2.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/monte.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/mosel.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ncl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/nimrod.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/nit.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/nix.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/oberon.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/objective.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ooc.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/openscad.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/other.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/parasail.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/parsers.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/pascal.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/pawn.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/perl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/phix.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/php.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/pointless.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/pony.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/praat.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/procfile.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/prolog.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/promql.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ptx.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/python.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/q.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/qlik.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/qvt.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/r.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/rdf.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/rebol.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/resource.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ride.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/rita.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/rnc.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/roboconf.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/robotframework.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ruby.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/rust.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/sas.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/savi.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/scdoc.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/scripting.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/sgf.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/shell.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/sieve.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/slash.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/smalltalk.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/smithy.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/smv.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/snobol.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/solidity.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/sophia.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/special.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/spice.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/sql.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/srcinfo.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/stata.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/supercollider.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/tal.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/tcl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/teal.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/templates.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/teraterm.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/testing.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/text.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/textedit.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/textfmts.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/theorem.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/thingsdb.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/tlb.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/tls.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/tnt.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/trafficscript.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/typoscript.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/ul4.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/unicon.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/urbi.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/usd.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/varnish.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/verification.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/verifpal.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/web.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/webassembly.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/webidl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/webmisc.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/wgsl.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/whiley.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/wowtoc.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/wren.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/x10.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/xorg.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/yang.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/yara.cpython-311.pyc,,
|
||||
pygments/lexers/__pycache__/zig.cpython-311.pyc,,
|
||||
pygments/lexers/_ada_builtins.py,sha256=Z5IiSpdugeKU4H-SEczWPYG6EO0e-R7lwP7thfORooU,1543
|
||||
pygments/lexers/_asy_builtins.py,sha256=qn1PmuijZ0P5Mkd1hWmH1arUt03wGWR7QNZf7ACBcCQ,27287
|
||||
pygments/lexers/_cl_builtins.py,sha256=n0Y1jei9ssrZ58Ev4GMxDTspYXU58TyAhLJzBApLttE,13994
|
||||
pygments/lexers/_cocoa_builtins.py,sha256=LvaPwfjM2r73yJwTMNu1SiDKzWWqzhJBjN_kivnYsyo,105182
|
||||
pygments/lexers/_csound_builtins.py,sha256=IY2H0Eg8iBFdmWwecXGwDC41Glrw_bWLenQCtp6DHzg,18414
|
||||
pygments/lexers/_css_builtins.py,sha256=IuSVV88A8b37-XsXGF4_6P6XF5Wv3wd3SxYOS1fOGyU,12446
|
||||
pygments/lexers/_julia_builtins.py,sha256=evrvUJjAKN8bCeBooXqAeGnWRc0qBqG_W2TMRPWq7Q4,11883
|
||||
pygments/lexers/_lasso_builtins.py,sha256=9Ld87CsxAB9UTV77I9W6s_bv4p-kc2grOnc8Ew7cy3s,134510
|
||||
pygments/lexers/_lilypond_builtins.py,sha256=rVmINQYq3iQ9-5W_jGrwW4Q9OX_zEX37I-pn5i8Ya1c,108094
|
||||
pygments/lexers/_lua_builtins.py,sha256=x8gSOJzBlwMFH9XFxwgF0-3kMn066YRQTLJyM_fl22s,8116
|
||||
pygments/lexers/_mapping.py,sha256=Z6VVQHLwcfRbYBqdNYEmQJ_yiLmZZe_Mg7PuIRHlZbQ,66934
|
||||
pygments/lexers/_mql_builtins.py,sha256=j2K4s3Ye_tYEfJEyUKxvqR3ns_ZOLHGaiPDhkGRk40k,24713
|
||||
pygments/lexers/_mysql_builtins.py,sha256=8LqPsM38R2Et1U8sg-oy09aedb-jO1DgVGmssDUw6kg,25842
|
||||
pygments/lexers/_openedge_builtins.py,sha256=ZK0Vwj0PfCtg5WpOXCvI0OUnozrNbQxY_HNB_JhAXQc,49398
|
||||
pygments/lexers/_php_builtins.py,sha256=ns_E12wFe4Ce3EP38B0DRhAnhHTrdh7WfhjnDWgnJJ4,107930
|
||||
pygments/lexers/_postgres_builtins.py,sha256=LQbzTa5ICPqTspfBk7_4JV6bkjB5lz7uuWAUNRj6W4E,13355
|
||||
pygments/lexers/_qlik_builtins.py,sha256=zc-fq_8mXsR_XVzTEXFRjGbuwdACJ3O9QrMiEGfuKxQ,12595
|
||||
pygments/lexers/_scheme_builtins.py,sha256=ZdZg6-MK7Zt2qqOSBUS5D9YzULtlJIuUxvk39r-HTNc,32564
|
||||
pygments/lexers/_scilab_builtins.py,sha256=ib-wZROxsKBi-csMVlGBFHpzDzkT0FPn2wZZN29_9Rw,52413
|
||||
pygments/lexers/_sourcemod_builtins.py,sha256=nV2ZcNTvMY7x4oQ2niSNV1XTH9bkXbcAt2-A6ODs55k,26781
|
||||
pygments/lexers/_stan_builtins.py,sha256=gl_po01tnvV_tGj31jKHqaSnybhow9ElvFjYU4vWdIs,13445
|
||||
pygments/lexers/_stata_builtins.py,sha256=hIGKIkcalQetIwOoN30uflOYgYIOlG3mJ6H6f82edro,27227
|
||||
pygments/lexers/_tsql_builtins.py,sha256=wDKfDkftAUjPQW1RPjAwsaLE6VZeTCyCy21z44Uz7Vc,15460
|
||||
pygments/lexers/_usd_builtins.py,sha256=H7AYHzkaizd4mFrMtjvI913cX9YdK4qs9JrOlIdcl7c,1658
|
||||
pygments/lexers/_vbscript_builtins.py,sha256=EhzEYIk-DBIuU0sMg_davSSL1w-o3enlT1S9uzljZfM,4225
|
||||
pygments/lexers/_vim_builtins.py,sha256=BG929NCy6g3LHhpj8R_ueUWqLbuIt0kyCJhxR1Q5SJo,57066
|
||||
pygments/lexers/actionscript.py,sha256=lVrwbX2OYnN-KMGd4j3y0z-bWHdNxDDcf8peFMo9x2E,11676
|
||||
pygments/lexers/ada.py,sha256=3PAvDXPLpvlpLCSSVl3k1RcBPm7M2LzI3ZU1MJDPqD4,5320
|
||||
pygments/lexers/agile.py,sha256=C5m07vIsCir2Amrv0QK0Ah1HbTcjBOBwMdF-x2r__6E,876
|
||||
pygments/lexers/algebra.py,sha256=ns54jf39mw-oh8gFZ0mj9Z2zYK98Rq5XJfA99-EjmTE,9873
|
||||
pygments/lexers/ambient.py,sha256=u333k5mScy3cUUDQEJdxMQvOEX16aqpTd1DiJeTYzqE,2606
|
||||
pygments/lexers/amdgpu.py,sha256=f46YvzV1sD3eEfcdkRYIjkS1YTtHyVJT5T2awL48dlo,1670
|
||||
pygments/lexers/ampl.py,sha256=lfHAA0ZG4Dv38l5wTYi6InlXXXJ65FaXLjZU0tR_sWw,4177
|
||||
pygments/lexers/apdlexer.py,sha256=EbgslrWGNFYOa8a-fN-PMv4_pCv3Kbdo7TIHN_DCXAg,30766
|
||||
pygments/lexers/apl.py,sha256=f4QwKpfzMiUPRXCzmcBfN99TV2YVKyNzZ09Ey0bubYc,3405
|
||||
pygments/lexers/archetype.py,sha256=pps0tkPaK1VPJePJg0HyaGfTTwEpApgJ-qg9MJ9a6yE,11469
|
||||
pygments/lexers/arrow.py,sha256=wnI3F9Zo9HaYImF2pgksdosy3hkztFyA5GGycbtQoIM,3565
|
||||
pygments/lexers/arturo.py,sha256=wIFytTnZAkKVtHVjKK5FK2XLRie_hcv8YSs1Z2UAFlA,11417
|
||||
pygments/lexers/asc.py,sha256=Nb2PHQZW1351-vrLctIRX_70znhx8CgGk75y7b4fhEA,1658
|
||||
pygments/lexers/asm.py,sha256=2sSPg4tLOPzUTQoTAh8pL5tWbdS_KmqQSr9BTQLVRt0,41243
|
||||
pygments/lexers/asn1.py,sha256=z01NTnFPFgV0KQydmXvFArjcl-bLDf8TRjm3EQXy-kU,4263
|
||||
pygments/lexers/automation.py,sha256=Zgal7cKSlj0SaHAXx98gHjNM1tvCVIO2UykseFquNy4,19815
|
||||
pygments/lexers/bare.py,sha256=0WEBxv-FSgow1RFZzaXGFo00iwklIF5FpjJZDOOWbDo,3021
|
||||
pygments/lexers/basic.py,sha256=cxZ7oKq924j8_gDolL_IDV4CSN2vXKk6S7DIw2WlTc8,27923
|
||||
pygments/lexers/bdd.py,sha256=JsA-W_-oICZKrZS1i7NNYrRmDRVf3iuI1PufUdMkQhU,1652
|
||||
pygments/lexers/berry.py,sha256=swc0EY-bEf0wNFUhfvdkgWmP-PXV8PGvhNagqtsUqmA,3211
|
||||
pygments/lexers/bibtex.py,sha256=jzuo9lEZHPKzAAMpIeIWkNTr5I1LO-TMn1V9SdyHT1o,4723
|
||||
pygments/lexers/blueprint.py,sha256=iVyI00gQ72PIbgq2WknVxNOeCbRcIycm24AHiLE5Fg0,6189
|
||||
pygments/lexers/boa.py,sha256=bi5ZlPV61Xehq8bmSdFyqt3BN1jC03pB4t5Foa4vKPw,3915
|
||||
pygments/lexers/bqn.py,sha256=fJORpq60UhtW0N38GnmYqAskQ_O6QZtc_tw4XcZ4D5I,3338
|
||||
pygments/lexers/business.py,sha256=-QHRTWCdabWV8SIbKZ1oLH5NQ3-blSPES8jjIbEvD_I,28112
|
||||
pygments/lexers/c_cpp.py,sha256=17O7tZfnDIQqjnFEajHVcqoWf3CpP8LoWlB2x8avwGE,17946
|
||||
pygments/lexers/c_like.py,sha256=uWObWqxC4d-ZyyzEG2yajKZgpq4iINyAcqw7LMnnxZU,29206
|
||||
pygments/lexers/capnproto.py,sha256=fE3wK-3ZBzPsDaFf9EkE1dnGDRhJbcCqjyBXRm8GlD4,2175
|
||||
pygments/lexers/carbon.py,sha256=JaO3sPeH8yKZwj38tCUuirz1fSF70S0koSqu1_MH8VY,3222
|
||||
pygments/lexers/cddl.py,sha256=PZS6611__hY36NZj8n9Q__JMXNLSm_aMWLpC51axc-M,5182
|
||||
pygments/lexers/chapel.py,sha256=1oFt0h0Rh7JnF2qw1QtT0XzkUanV-Xb9Xi9B9ZcHaIA,5157
|
||||
pygments/lexers/clean.py,sha256=afJe0orU7Ux_pmmrbSNYPLrTCkY_z0MJTmhUBqPtyJU,6395
|
||||
pygments/lexers/comal.py,sha256=9IwxfxVBVMn7Uj2xo-WCr7RhLRDrDe6wjTdAi5hWT2g,3156
|
||||
pygments/lexers/compiled.py,sha256=xv8krgoDgd07QDXVPaa5uip1kl9tBprkGT1K5-DwiWE,1407
|
||||
pygments/lexers/configs.py,sha256=W0OJCYAjs45YhPTp_ovKMkeNbS02S8-o2xu3BgroeGs,46414
|
||||
pygments/lexers/console.py,sha256=17k4Ngrs0EsaJg90ud6dle-I1SvjoOiYJ-xuGpLesTI,4148
|
||||
pygments/lexers/cplint.py,sha256=HrKuhRKjK-atw1FKT_zu4FJjlHOM5BppRzoxisXbpZM,1390
|
||||
pygments/lexers/crystal.py,sha256=W7v6oZtbm-aqiM9IOqIypKkudxQICWRdoy-ZyWUdt6s,15756
|
||||
pygments/lexers/csound.py,sha256=yuzpCdZuHDmr2eaNodglDrCgX1W62xtQvjitnHlXC6s,16994
|
||||
pygments/lexers/css.py,sha256=lZKXESVwZRYTjjRkyB4cYpXk9CHcVxU_embzFRtPhhY,25322
|
||||
pygments/lexers/d.py,sha256=f1dFv2mAXqLKSJQ59m66u1Mj9us3fDskxltlrJ8EBmM,9875
|
||||
pygments/lexers/dalvik.py,sha256=0Ii9KIUWT5FkJkLKuUcHoHPhav4eEHqsWZL2_ikP1ZU,4607
|
||||
pygments/lexers/data.py,sha256=86RLrfLKYxNhjE_1eTjiz0HJxY-393QyyEC37lN98bk,26940
|
||||
pygments/lexers/dax.py,sha256=od3D5zfaryI5MO93E_OA-TUpekAcjXv73l6kNit57oI,8099
|
||||
pygments/lexers/devicetree.py,sha256=4GKiuZC5bYwG_gIl30fZH8VV2zo4cqwdemQrQgWH7ZQ,4020
|
||||
pygments/lexers/diff.py,sha256=VAyAFRFmyMH865rEJ37I3TpyrpLUoEMU95durw6HLRc,5278
|
||||
pygments/lexers/dns.py,sha256=-l1X7-R3AKDif65JIvL_Tc_dJdIjaOBq38-hQf17ZWg,3781
|
||||
pygments/lexers/dotnet.py,sha256=VjJWh7vslMNIoQdPFNUlAZI0ExuLFV6EdrywYaIjqQU,37623
|
||||
pygments/lexers/dsls.py,sha256=iSiDn_HsIeiYx8PFUTai5KHzISWLbClz2hwQudFrgmg,36774
|
||||
pygments/lexers/dylan.py,sha256=PbrnXZc9paqmkOVJjsoAxfs5-s0MA080Vzoiu3nZum8,10319
|
||||
pygments/lexers/ecl.py,sha256=Cezl6tWf-a8hMEEUfJqYI3EPf6sSS3kRz0GiOuFIQ4Y,6372
|
||||
pygments/lexers/eiffel.py,sha256=jt_49tqubN-gLnobCJn10oWxkCW5MosbUBtm5XjnaI4,2690
|
||||
pygments/lexers/elm.py,sha256=OpKdJV4nlVGBv8G8lDeeLdQPbDzaJWtn-TJmS8N9N5w,3152
|
||||
pygments/lexers/elpi.py,sha256=Lid861rWNCGfv839gD8E2JEP8HkhO0gCWGWKuc0so3I,6710
|
||||
pygments/lexers/email.py,sha256=EB3YvRDEP6_B6B1wzq0vS4_zrBX52zdyXxiNI3KHgxs,4742
|
||||
pygments/lexers/erlang.py,sha256=EhFx_0D9w85DCJR9FyUprFPiaDvJps3xy-Kn4whWcjs,19170
|
||||
pygments/lexers/esoteric.py,sha256=V--w2W-Jyl4yB8A00f4GikVeZXe_5lWHE0RMnfuoLTY,10396
|
||||
pygments/lexers/ezhil.py,sha256=xu9wMEESVWCLgNitSS0IS855TSJ3Yb2KXBrxmYqHKSo,3273
|
||||
pygments/lexers/factor.py,sha256=iVSIZaT7-qAI41wP__p2XjTSyREBSyAErPLVGP4bMeU,19531
|
||||
pygments/lexers/fantom.py,sha256=0DylUHKCeBMfQK4QczavL5ugyPTV0u5H0Lk0YTv6_mU,10197
|
||||
pygments/lexers/felix.py,sha256=fJsd0mNaSwkjU32-103-9XDzzz2lj-ONPiW8JkZAqxM,9646
|
||||
pygments/lexers/fift.py,sha256=ISH11Bvz15ZsMjTMdLDsHFx2HYgpGyDUlvi1CN8MC8Q,1621
|
||||
pygments/lexers/floscript.py,sha256=UYPHl2Ygez7RfBPTU00hUMXrU10mB996vz6rFisAmTs,2668
|
||||
pygments/lexers/forth.py,sha256=PzfXkhpusFIGVwrzVsqLgljlybN92OeU0_E3rHup2m0,7194
|
||||
pygments/lexers/fortran.py,sha256=i7xVuZEQnYruMo4xfvGI0izozI1qJvcPO8Dr7KRU0Vg,10336
|
||||
pygments/lexers/foxpro.py,sha256=XmVcWgw70vh31gri3LhfrB2YQ-RhkUkBKly0xHt8VQs,26212
|
||||
pygments/lexers/freefem.py,sha256=e_YjjHZu8PzQBykLzhpY2RJHjCnLxnlmoGj-5RinP6c,26914
|
||||
pygments/lexers/func.py,sha256=h6IHCdydWKpQcamC1XAGJjaGK-UDvh9iM0ZuWQK05dQ,3622
|
||||
pygments/lexers/functional.py,sha256=IpvPKomRGDqGs_MZZjkX5niMGZO9s5X1Dk0HDyO9zWM,674
|
||||
pygments/lexers/futhark.py,sha256=NwNYLxQ1feJwtPjG54VmSmo_ZtcTqtlzr0QQppmxWUM,3732
|
||||
pygments/lexers/gcodelexer.py,sha256=H754t2DKkgJYF-mzm4uI9dqc0qE02fjlZZfXM0eg6Lc,826
|
||||
pygments/lexers/gdscript.py,sha256=DFvf9eJgJic5DUHt2lrJksSu5X6eXRfrh30t5yAVSzY,7543
|
||||
pygments/lexers/go.py,sha256=8DSgsTlGjQ1QkGw0k1FY8Hzur9B1QOWTIA642qb9RHY,3784
|
||||
pygments/lexers/grammar_notation.py,sha256=SNQNggmjYCC0yRN2m2r_33X2pa8bw0AxLJsG1G5FjdQ,7980
|
||||
pygments/lexers/graph.py,sha256=AHtLRCnQdeY5fQdMJItngN67PBVlxWn2Eq_0ua4VlJI,3861
|
||||
pygments/lexers/graphics.py,sha256=AqhzeSjpQwk1Vrj_OT5jKDJMonB90Sr01mM3q90WGVg,39026
|
||||
pygments/lexers/graphql.py,sha256=swH3nnESkgFynenBJDjzzKaSKkOGQ9rbm-kFs2-AvIM,5602
|
||||
pygments/lexers/graphviz.py,sha256=_yJaR2CW--2ljvnPdNjsVOvosPoUJw0pb3Of33nWBtk,1935
|
||||
pygments/lexers/gsql.py,sha256=7GDWo1Wvt5UmJhAC8HQND1kbdONBRE1YhdawBzgGrHA,3991
|
||||
pygments/lexers/haskell.py,sha256=RkYEh9-amHeRS0-dU5Nyz4RL4KKJz27PsWhNpf-C7NA,32898
|
||||
pygments/lexers/haxe.py,sha256=W4ILlVNk1D6USMa2Kkr00IFaoqtUIxd5cO8_xWzo23k,30976
|
||||
pygments/lexers/hdl.py,sha256=xA5YnwhgaOTzvLpE1VIP8j7l5LM2FjkpssZyMe3sPtY,22520
|
||||
pygments/lexers/hexdump.py,sha256=QLvXzWmo2_xqHMy55OTXUB15CokyQLMzHvmXuwMj6z8,3603
|
||||
pygments/lexers/html.py,sha256=IvmbMYuuHsOdkOOBv7DVZL7ouONLfd9fVtjRFICAYD0,20260
|
||||
pygments/lexers/idl.py,sha256=bhS43u_ycIVN-dxlL0rkVDW0Kunuv4nCgMiw4CrEVTk,15450
|
||||
pygments/lexers/igor.py,sha256=YFdGLAgqoSnp6wpk23bwbgj7uVSRbyqG4r3Xr7ht8xQ,31658
|
||||
pygments/lexers/inferno.py,sha256=0pRpoR7W1Kp8q_9mxY43rYw_RYef3ruJ6xV1LwYbz3A,3136
|
||||
pygments/lexers/installers.py,sha256=5_jhlzWYi_6LMEr8BnpbjgiScZ_G3Q7AH6fTG4WrPRc,13178
|
||||
pygments/lexers/int_fiction.py,sha256=CkGFrMPiZZ6aQ607E4yfZDTcYpz1pdrbd4azyx7XVX8,57119
|
||||
pygments/lexers/iolang.py,sha256=ieom-sc8xdXbHi4g5LDofvLduKZdVBSOEwXocKmQU2g,1906
|
||||
pygments/lexers/j.py,sha256=Kd0Rga_1uwU_YhfXebvGuHKpOXM2SVH0_x_CqkCJVCk,4854
|
||||
pygments/lexers/javascript.py,sha256=y4ve9s2jq4UaTr9PhkNERIlu2DpbP_l64N_r2JJOBV0,62859
|
||||
pygments/lexers/jmespath.py,sha256=3P4_YQXh4IoohDQhoh0pquyFuUHVd88g7KYmVYg3NoM,2059
|
||||
pygments/lexers/jslt.py,sha256=cvH2LIuUnkhaqhfWvkIjS7sSx2FpXSEvl3rOF47d6Y0,3701
|
||||
pygments/lexers/jsonnet.py,sha256=CiJT00Tp0lBg9j_1EW-d6_poumtHoP2TmEQVDlf3cTs,5635
|
||||
pygments/lexers/julia.py,sha256=F5zuRm7OSZQeV1na7lasypEDGreLAzOdfaKmH1HIxgE,11646
|
||||
pygments/lexers/jvm.py,sha256=nyRvIF12oTZRmU0qDhgOQx8AsUgoZj1zMU8tDGyOP8U,72929
|
||||
pygments/lexers/kuin.py,sha256=AVUDd6JAy1jClIYeQDPcV-O7xGfb7x7fojN7hb7ANHU,11406
|
||||
pygments/lexers/lilypond.py,sha256=_A5P7PaITP8COXG8dy9nS7CzfdKY2UOe1XLGtucuip4,9753
|
||||
pygments/lexers/lisp.py,sha256=lIeqd1varBR8dCUi3MNr60Ikxf4W9sFsF7KW6n0lrR4,144039
|
||||
pygments/lexers/macaulay2.py,sha256=kEZghkvq-KLdUyL_A3SYgAwMLrg3OA3HN62Lq84qyFI,32193
|
||||
pygments/lexers/make.py,sha256=Pif0_6zvfwAYd3cm2oKMDJHdySP2T7CzHZPFnGMmboI,7618
|
||||
pygments/lexers/markup.py,sha256=KJ1rs9Kp8hrlaHMQxTDtGgkEUkROq1lw0ysKqLqo1G0,59263
|
||||
pygments/lexers/math.py,sha256=Wl6lU1VWevtQXymt6jdDeuz9LEMiPKl1On3Zm3QXQ8M,676
|
||||
pygments/lexers/matlab.py,sha256=WplG578_mB6sHlDDfgY83SMadCcqD_sN5Jb593rSr6w,132852
|
||||
pygments/lexers/maxima.py,sha256=tLSjeDIBZKHRoMludgF7oBdz1xTAHyvIEG6BshyBXyM,2716
|
||||
pygments/lexers/meson.py,sha256=ij0CgbEULfqLMcY_BQ7PxmCwWOYLc9XZwtrALFSinEA,4337
|
||||
pygments/lexers/mime.py,sha256=-wj3pvAQzNTC8fTZk9AV4Q-LIQhMUocet-j2kqGj5gs,7538
|
||||
pygments/lexers/minecraft.py,sha256=-Tb9aNbNM8gXgq69uaCxfmyTQlJ9dYYTK9UaFbSE2CI,13846
|
||||
pygments/lexers/mips.py,sha256=JBfvOPp5HTGp6b0kynkjzuJOTRAdTsJJdjPWLAtu1fo,4604
|
||||
pygments/lexers/ml.py,sha256=WlIdrpHCP8Z8OB5nkDXA6NyTvxPuc0tOueobOc8V840,35324
|
||||
pygments/lexers/modeling.py,sha256=3KxuIs1-lb_FN921kCCgjq84R69ATEp6K1EQyWaxp7M,13524
|
||||
pygments/lexers/modula2.py,sha256=z-4QbG4Bgjd-0ONC9SadglqCW2QmIMl-60b_n35V-70,53073
|
||||
pygments/lexers/monte.py,sha256=pKPKOkwxcGzJLVisA-H7xJJW9JUh2SsXyDi32mF5nSQ,6290
|
||||
pygments/lexers/mosel.py,sha256=_JeaaK5Jn0r7JcuLl62u1sl6uInkrP9g4EosCf9Z-IQ,9187
|
||||
pygments/lexers/ncl.py,sha256=O6CckyU8yABKmx8xmj4q6E2isWORmvNO7Xl1JX5NwVQ,63962
|
||||
pygments/lexers/nimrod.py,sha256=O_8dxk9x3vlYFPYjpe8iqQcCrcZmNnBE_Ld1lzO7xVI,6416
|
||||
pygments/lexers/nit.py,sha256=Ghja_AX8DIg_KA-rmvgmL76kZI-lq3pARMiebYi9Nqw,2726
|
||||
pygments/lexers/nix.py,sha256=qeKFMOSHa627SlkPsbpIOfzLu2ej-JdgGkDAqt4isP4,4015
|
||||
pygments/lexers/oberon.py,sha256=LgYgzGPus7w1lJLUAu2cmIRQGEgQiid34QH5Upa7Uro,4169
|
||||
pygments/lexers/objective.py,sha256=VoUeZYa1aO5rU69dDpv4Ob5FOYyr3nm-eJ3m0kuti0U,22961
|
||||
pygments/lexers/ooc.py,sha256=BEj7kfOimF_Qi62R-B8bmYGy_5QIE1jS20NfrnNE9Ss,2982
|
||||
pygments/lexers/openscad.py,sha256=JF4cUk6rAsH9BlXDdkdXMSlKajpghtOm0Ny-QikoiZ0,3701
|
||||
pygments/lexers/other.py,sha256=oXVtTELCPFxwuJxN5j_iYrt0Q9Aonq-GkotncUFPpeE,1744
|
||||
pygments/lexers/parasail.py,sha256=MxO40OTg_5z_EnMyb6weQHjhtzL1WgSwfjCXc0zl82Y,2720
|
||||
pygments/lexers/parsers.py,sha256=JiQT3IMsf2f0JLbiDpupZNSsHnMUH57OoAr0D_3AvbY,25904
|
||||
pygments/lexers/pascal.py,sha256=EHZi_mh4V7LuGXtcbTQnrrfqDDXcGyVwDvJmN8XRcps,30880
|
||||
pygments/lexers/pawn.py,sha256=fNq73VwQoXeKiRFKYIKzzOClcUb2eLPJIhymlnxKZlg,8146
|
||||
pygments/lexers/perl.py,sha256=82_7saaR3qBFlSnWYyEtkir7uvXTeUZqFUhjdkdTTXs,39170
|
||||
pygments/lexers/phix.py,sha256=48JEQK_0ijjipwDl1F-ik0B_CGUMsZOvXlvXzIqHVmk,23252
|
||||
pygments/lexers/php.py,sha256=b4sVWZTMq0t2GMlaFmzYWJna9WuDQFIm-vdqXkb89xo,13040
|
||||
pygments/lexers/pointless.py,sha256=dUATlYVUZkbggQ6PUymDKhB0UKqDo-KCf0Fp_EjWsTM,1975
|
||||
pygments/lexers/pony.py,sha256=k03DAhS-_G8SZsfXZOjF5YkQaMQ28_uy68_CMaxuUC4,3244
|
||||
pygments/lexers/praat.py,sha256=rTl5GSoJ58LQxRf_Ek0A1H4iCm2IVQFxEwSvbMki7tw,12677
|
||||
pygments/lexers/procfile.py,sha256=naQZcdvxVUjT56R0U6_YpgNCgfmNE9Xjzx9uQesl-Cg,1156
|
||||
pygments/lexers/prolog.py,sha256=d010T34HBjbf8I1PoCiU2mDPQlMLhBG8-eFbAILqy7Q,12351
|
||||
pygments/lexers/promql.py,sha256=Qw0VXIJGRkw6ZiSzvtR0KFiWmPuyI9xxXgDl_l3cHmc,4715
|
||||
pygments/lexers/ptx.py,sha256=ws5ghGmtTLaJ2zamWUixCbdkzbjnxdwZyI4t3mgrdSg,4502
|
||||
pygments/lexers/python.py,sha256=Dxdo6Pej2cdLI-LdR7jw18NQegVp3_YQIgVNV2jbOWU,53376
|
||||
pygments/lexers/q.py,sha256=Vw36x6rIp2U1b8GUtUbMlcD0MVqW3unCZEMBEt-PflQ,6932
|
||||
pygments/lexers/qlik.py,sha256=gCAQCe1Tuy_cMI4n51Sb8fG50L73AgmUMEWMmZRHeJg,3665
|
||||
pygments/lexers/qvt.py,sha256=IjHyopkDochlQt_fIf7Mrxw84pIg-gj4BkDHtEiKb_U,6072
|
||||
pygments/lexers/r.py,sha256=xMSNpNN3Hm0W51-TEfvzPeOGtobM2nIjGVmIoVydlfU,6185
|
||||
pygments/lexers/rdf.py,sha256=9aVmpa5FSE3rZwekkSRYp-qxi4Yg_SlFbX5kIPjgQdU,15790
|
||||
pygments/lexers/rebol.py,sha256=TMT3JlXoWvJbZwZdLuekwgv584HEP1mfsD2g9Oqj0IU,18248
|
||||
pygments/lexers/resource.py,sha256=KxxQJi9NPmghpa1mekxUFBd8eaiSB9pV_F4Eds4kK0k,2902
|
||||
pygments/lexers/ride.py,sha256=0mT89oluoz5lUT8ar6uPiSwTIBwyMc6oHYnrM5QY7Vo,5056
|
||||
pygments/lexers/rita.py,sha256=gPbMhlCyS_ekzXIKboXGEmtGZlSSUx0k6qcuWEHuM6s,1128
|
||||
pygments/lexers/rnc.py,sha256=SjXKJWNifTTWQC9NlcWNmdhkln0REEpEvaY6nVy6n4w,1973
|
||||
pygments/lexers/roboconf.py,sha256=HY0dSPJxg7knQ-cM6YotX8EoVjuQi-LeKYKeWpQyF94,1962
|
||||
pygments/lexers/robotframework.py,sha256=MJ4cnUDZWDrXCpYi-kJLqe1HpzJ24DMtNswDeuSnVCc,18449
|
||||
pygments/lexers/ruby.py,sha256=9Oext9bqwC7E4SE3fAB4Ldd9_9Tbq7D4D94RQA-8bcc,22672
|
||||
pygments/lexers/rust.py,sha256=Oq5bFgf_hcOLxiBLhzPArUFXgg3Ude_xpeKPC3g-HDI,8216
|
||||
pygments/lexers/sas.py,sha256=u0vkPLehX7UERsKIkooC4IFJdTf44L2_Qqdpx1De7wk,9400
|
||||
pygments/lexers/savi.py,sha256=3A563B-Wzp5AGZG0ruSQiPbe-c3uYGwCPUmnPJSEKOk,4645
|
||||
pygments/lexers/scdoc.py,sha256=_UKS5VZZ4eaVpxmSr6L_P8Or8gAt9mImX4HWuw1TGlo,2525
|
||||
pygments/lexers/scripting.py,sha256=EkXKzWLg-jpsV8rep2YW6fDsCDz-d3fY1qv1QVE7MI8,70014
|
||||
pygments/lexers/sgf.py,sha256=Oa3SNL31wN8rhY0gby61kbPxttvRQJTRN38CSMUiMJE,1986
|
||||
pygments/lexers/shell.py,sha256=oC115DNmEzPYPdKN5jNUz-gV44c_qVb2Y5OfGO3gQ_U,36466
|
||||
pygments/lexers/sieve.py,sha256=lLcCLdvj-AeudiG2xq2zTN16v0zSEXK5vcr1keg0TxA,2441
|
||||
pygments/lexers/slash.py,sha256=_soPrmF1ylAw7IWfRHTMMUdifwy4oNV5FpYMBQsVSyM,8482
|
||||
pygments/lexers/smalltalk.py,sha256=9UNqjCWOay3nb5BVqN2Muw-Ci63WnscW6xJcGnNWVq4,7206
|
||||
pygments/lexers/smithy.py,sha256=FMvWXKvjF_hUNqI7BmZYbVRrPg5_AnnzORHPp3skcXs,2660
|
||||
pygments/lexers/smv.py,sha256=VyWuTjtAhaZmu6oZG3Om_kU3NhorVz9ivzeu_mfRjwo,2773
|
||||
pygments/lexers/snobol.py,sha256=Wp7ViMnddy79tWJjsgSB9kIPFh_OhaM4Y2tZjWDuvMI,2732
|
||||
pygments/lexers/solidity.py,sha256=Mhmypb5WzxGdBaQpySae9NbiFJllkEezditjHajd7RA,3127
|
||||
pygments/lexers/sophia.py,sha256=0gARv0DbMi7DWUc793pd4f7IKxSeOlkjk_eez8tLihs,3330
|
||||
pygments/lexers/special.py,sha256=SDWqBKmWmKyvi8VNfPpW1V4g7ergad4RfUumDh6bNrk,3414
|
||||
pygments/lexers/spice.py,sha256=FIOtqds0pPFPE5DiA32H0SL4F2ou7ZKTXdpuOuUgEqs,2723
|
||||
pygments/lexers/sql.py,sha256=IirBrDuksw3Osvexob90XCmH7HRIcaBBgDyK1ay6BuA,42107
|
||||
pygments/lexers/srcinfo.py,sha256=x_6DsZ0mKVbI_v_G5bLBQl0WyFwj3tXmOqfHIB6zve4,1693
|
||||
pygments/lexers/stata.py,sha256=-IRfLl_rpuOiKs0Vnpc6OEKuA6AXbklW6RBGc7xzGEM,6416
|
||||
pygments/lexers/supercollider.py,sha256=Ua4RbmCRYPz7PcT1uyloAbfKc9kZim7nAKr55E26scY,3698
|
||||
pygments/lexers/tal.py,sha256=fXEJmSU74ImOyCVnEIW1Qa7rWKIiDHKmDlpIW3OUp-w,2898
|
||||
pygments/lexers/tcl.py,sha256=STjHSlVeWo-Eg4tKqn_7m3_3efcmHP0WCoL1_PK5tt0,5513
|
||||
pygments/lexers/teal.py,sha256=t8eOzrIiImVuUtkBlSPl9Y4olrCAZ21SQB-T67WZasQ,3523
|
||||
pygments/lexers/templates.py,sha256=Eawt5MXOe1V2RB_vhp6097GQMjoKHPSEWHKifhdMazw,72610
|
||||
pygments/lexers/teraterm.py,sha256=71NiLefy40L6R4B-qy-ho8Uy4kAQqsi7iLxexCDS5rU,9719
|
||||
pygments/lexers/testing.py,sha256=Ue93uh36l7JKc0cUDnLmk-E221b5y7qt6xXHvaJRxt4,10767
|
||||
pygments/lexers/text.py,sha256=ntF8QwsuhsqyQdxMB6H7MYP7o8A7xSxHe0UMTZLKSK8,1029
|
||||
pygments/lexers/textedit.py,sha256=xVU-3K5-0KEkb0pJ4hJjrjpnz9hJaIuLQOxfk9nLWjM,7609
|
||||
pygments/lexers/textfmts.py,sha256=d5g8AWDK5_MXMnPhj6t7T7SOLsk6wPptRmgnAdbAnUc,15310
|
||||
pygments/lexers/theorem.py,sha256=SVsdjX2YFbwlmuao2TvptbfASjSSbvgPL0VWekERXw8,20386
|
||||
pygments/lexers/thingsdb.py,sha256=FwelchVBXKf3nc78UgA9SyJbHta3EMdrLnQizIxS5SE,4228
|
||||
pygments/lexers/tlb.py,sha256=sQCsK3j8zqGVI_KCuursmOr4JIs3sfpqF_wPpQpyKM0,1377
|
||||
pygments/lexers/tls.py,sha256=KfI8y7abYZzC_jRwvti_foAAUrWSmpjdQ3RGPcP8yps,1541
|
||||
pygments/lexers/tnt.py,sha256=uvdcsw5NRZjbFouXBET3-w8I7LG9hqzMXiK6s_GK2ZY,10457
|
||||
pygments/lexers/trafficscript.py,sha256=GDl_7cSFit1anVH7KNH0qVts1eHcp_GGxpzIYWZabeg,1474
|
||||
pygments/lexers/typoscript.py,sha256=nIAUIlbL5sVqpTEt34YdUGDNmu60a7itBYaaUMuzAIs,8207
|
||||
pygments/lexers/ul4.py,sha256=XOm5dWiWtWN3RQMpA5VHvl1J1jg014SK27aJnVjq1C0,8956
|
||||
pygments/lexers/unicon.py,sha256=4MDnwsgXzLlm0zaDqYr9uHFNspgCzQRNzyxClVQ-RMI,18512
|
||||
pygments/lexers/urbi.py,sha256=3CkxfMOqpSVZpOq7_4YrWcmjq4B3CF_IDGIxAsedWQ0,6037
|
||||
pygments/lexers/usd.py,sha256=7FiS_KV1Q9Cvf51fAHmMqr5QDz1OtjqTkp1S-8VyQTw,3513
|
||||
pygments/lexers/varnish.py,sha256=LYL6rhIw-ApJRT4qkxFaxG71OPbHsiFv4mtfr0m1OPY,7273
|
||||
pygments/lexers/verification.py,sha256=1C1ntqvZmrCtzHV9eDIga1LtQ4jpAlb6GnWkNucEJXQ,3885
|
||||
pygments/lexers/verifpal.py,sha256=DF0nQlrw_Xt23OOFpOC8_LRpYWXlon1S7yxj6egbtDY,2662
|
||||
pygments/lexers/web.py,sha256=lscit_NgXsHDL8sjvNvAFriPBe24cz0b2rBGFFpYlv8,894
|
||||
pygments/lexers/webassembly.py,sha256=HGFp4qMAK0ejx0omrThEtIvl_ArKOeS7b4yZkipqmIo,5699
|
||||
pygments/lexers/webidl.py,sha256=VeqO7i3Y-e0ObtLxn1sniGmL_CvOWekaP2XyUFzDlLQ,10517
|
||||
pygments/lexers/webmisc.py,sha256=veICtUXL33effcYDX8_FU1F0Q5FfZfzcC2Tyu5SYT9A,40549
|
||||
pygments/lexers/wgsl.py,sha256=Mffgj3x5tFwsKWihw2kbhSmhvGNEgQc_pJi6C3mEQxc,11920
|
||||
pygments/lexers/whiley.py,sha256=SbbftaItSgIdczzT8qOV8mH1m6dD3aM2EvRk4ila6Co,4018
|
||||
pygments/lexers/wowtoc.py,sha256=o_01SGTJ3jecVHEpkhqHdwI66XQVi8wNeajVYPbd4Bo,4021
|
||||
pygments/lexers/wren.py,sha256=I3LaIzy3aa0aDXJd9PJp-SiJtgJHktISHdQ_zQuMHLY,3239
|
||||
pygments/lexers/x10.py,sha256=p3VwQg70e8ZR2iwR2kY-yojTyD_s3xVJMLTCWrpz6Hc,1920
|
||||
pygments/lexers/xorg.py,sha256=rXKVNQiiniNoaM4VTkLFj106NLddCBo1BV45BTxT1HE,902
|
||||
pygments/lexers/yang.py,sha256=rx08okYvJgWMe6jMRkt-ysEuaTi85X5DE0Q5EHb-Ehg,4500
|
||||
pygments/lexers/yara.py,sha256=nFwPtmuAhe5qrm_PKldVnWAiFZaLeipgi5q3-r1VGwE,2428
|
||||
pygments/lexers/zig.py,sha256=B5QZGfEoNkoAG5EZxHk28MZ1n2Q1Gvx11kcvTQ6N5X8,3953
|
||||
pygments/modeline.py,sha256=eF2vO4LpOGoPvIKKkbPfnyut8hT4UiebZPpb-BYGQdI,986
|
||||
pygments/plugin.py,sha256=k_gtJHBriDDWiNinQ-h_qnDUm7EnPLuXaTGH3Cd5pZw,2579
|
||||
pygments/regexopt.py,sha256=jg1ALogcYGU96TQS9isBl6dCrvw5y5--BP_K-uFk_8s,3072
|
||||
pygments/scanner.py,sha256=b_nu5_f3HCgSdp5S_aNRBQ1MSCm4ZjDwec2OmTRickw,3092
|
||||
pygments/sphinxext.py,sha256=lGw97r5LQrBvectMNzL03wRECrjs1HRXm8K_l7T-Ink,7687
|
||||
pygments/style.py,sha256=ePJAMWuctRHvKhdIFkZT9CAGEdHBZxx-Bv7PURa8NB4,6245
|
||||
pygments/styles/__init__.py,sha256=PjaODazvTXv2sRdQ3ULT9NBFl31hED77Kdilk0krHKQ,3638
|
||||
pygments/styles/__pycache__/__init__.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/abap.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/algol.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/algol_nu.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/arduino.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/autumn.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/borland.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/bw.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/colorful.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/default.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/dracula.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/emacs.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/friendly.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/friendly_grayscale.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/fruity.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/gh_dark.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/gruvbox.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/igor.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/inkpot.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/lightbulb.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/lilypond.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/lovelace.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/manni.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/material.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/monokai.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/murphy.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/native.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/nord.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/onedark.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/paraiso_dark.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/paraiso_light.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/pastie.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/perldoc.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/rainbow_dash.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/rrt.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/sas.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/solarized.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/staroffice.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/stata_dark.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/stata_light.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/tango.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/trac.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/vim.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/vs.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/xcode.cpython-311.pyc,,
|
||||
pygments/styles/__pycache__/zenburn.cpython-311.pyc,,
|
||||
pygments/styles/abap.py,sha256=pvsya8aKMVAkVeAsOumTamTsbnpTSaGNn3AUrYkbN_o,705
|
||||
pygments/styles/algol.py,sha256=Zpxg6alN3GogkpUWcp_EJlnqD_CBC9oxsvYkCOHLDHk,2216
|
||||
pygments/styles/algol_nu.py,sha256=JyBOI8tzg27aOr5Ua8JNPLi6d4BYTixFdkPBbKqEiAw,2231
|
||||
pygments/styles/arduino.py,sha256=Vsg-NzWKZZb4qMxgzE_Y2TX9lSx3FoUppRGUt8CSilk,4443
|
||||
pygments/styles/autumn.py,sha256=T2I-eQwlKN8qhIncILbPfVhfbcZREXMiDHFXmNd8y9Y,2147
|
||||
pygments/styles/borland.py,sha256=_euPVC2jAy1l3WXUp6WBI6I-eQxR7yPoqiVrsLRdPyU,1561
|
||||
pygments/styles/bw.py,sha256=RK_GBCAkMyRdTG5adFlnM7R2tOAE8keWadnzaAINd_U,1358
|
||||
pygments/styles/colorful.py,sha256=gAXphclisUFubl_ctL6YJLVQyuIdOKWLQ9r_p-FGIOg,2780
|
||||
pygments/styles/default.py,sha256=_eiTrKMS0c5Wc5n9AiHhwOMxOyqIS02CGk8tde216-g,2538
|
||||
pygments/styles/dracula.py,sha256=SuJcIUk7C5Mql2KzRQc3arevvnkWiIcSgHX3jn6cnNk,3363
|
||||
pygments/styles/emacs.py,sha256=aAHVY9nUFsW38rXCqzfte6-szwBCEjUW7B75kTY-7iM,2489
|
||||
pygments/styles/friendly.py,sha256=FosohyAspajzIBNNObCsq62ERNt0IWDyvywZeH29nlc,2552
|
||||
pygments/styles/friendly_grayscale.py,sha256=vjKdUsX3ZCYN8S7FcGS2e-VNvEq007UxFroCZ-jQbWI,2757
|
||||
pygments/styles/fruity.py,sha256=RHODyvBNzfoMsCXpo73rVE2P861U5Sp4y4Yeh5S5qA0,1274
|
||||
pygments/styles/gh_dark.py,sha256=qRXgt6xoQyOWGBLQ6X9d9U0_UJ8mk3SVt2nwQuExagQ,3532
|
||||
pygments/styles/gruvbox.py,sha256=cidyPwSrQZk1kHGi-tJLYI-fz2SOL8obkrpB4h_A4VY,3273
|
||||
pygments/styles/igor.py,sha256=WLVI14RraRiyO570MBPMTboieVvUyCxvToymTW33tec,692
|
||||
pygments/styles/inkpot.py,sha256=r0CQyZtTRTSxaIoaVETumFRZxv6e701EEdEg_0-dtJo,2352
|
||||
pygments/styles/lightbulb.py,sha256=HbB0I8Vn0Ig9H2U6874ewMSx1TYL9gR-fJEVHUnQXKY,3116
|
||||
pygments/styles/lilypond.py,sha256=wh-ip2qKgUTxdh82QKYCPdueDXhnCj-yatftcgWCljo,2016
|
||||
pygments/styles/lovelace.py,sha256=sQED5_nNpDp-ecFr6lnCcBOKRXhJubV4fUn8Y8IXY-U,3161
|
||||
pygments/styles/manni.py,sha256=B2e0b0e0j5rVm7QrqDSKzx0XeMZJbWDTy3Whs7pfzMo,2393
|
||||
pygments/styles/material.py,sha256=zvFojvLUybhLffnnyOFAKI5vVs8Kk9kMuiCogae_oPI,4130
|
||||
pygments/styles/monokai.py,sha256=ivCbyoiD_Sqe8ffrNHNKT21-scBmWPAzn2K9qcG8T6M,5129
|
||||
pygments/styles/murphy.py,sha256=0esYLra1PvVqZK0io1ocnZL_heGM7DCh-2yOdEVhnNU,2753
|
||||
pygments/styles/native.py,sha256=0ebrijg0lPvyIJPSlyYrxmda2yQDDYYyh04QH3tsNcU,1991
|
||||
pygments/styles/nord.py,sha256=0QAus-G-3WwHEjMmqa034IzLu2fU1HI1dqcE1lmZcOs,5295
|
||||
pygments/styles/onedark.py,sha256=BgsmXfNk_A4NUpNZYtl0C-Cj368DiLrlrBRlop8CixQ,1664
|
||||
pygments/styles/paraiso_dark.py,sha256=TsgjpRTfknZphgro0rvRGRFRMjY41sNUej8D-3z_3lU,5599
|
||||
pygments/styles/paraiso_light.py,sha256=PTqvKHkTZ-9KobiwRyXO1HGDz6Eziub57D3VPHgpjtk,5603
|
||||
pygments/styles/pastie.py,sha256=efRWlz5tmZ7kY8dTE4uce6tSZUGh-AqxS6wVAbZBWso,2472
|
||||
pygments/styles/perldoc.py,sha256=gCDIepYiVuh4FnNXjDfbZ5PW624Ljp31mR6vDHiv9TU,2175
|
||||
pygments/styles/rainbow_dash.py,sha256=sC9PCf8r7hZerAts52lOwBir7j61aAUM0I5uNOehXwc,2475
|
||||
pygments/styles/rrt.py,sha256=PyyasbLgJEGP_P9sMWMSKM2cVhk0yF6p0vGvtMEytG8,874
|
||||
pygments/styles/sas.py,sha256=D2HCwKU2ojWy-NPJsjiUKSDKNeMfJ7e04K_Hqki-dWo,1393
|
||||
pygments/styles/solarized.py,sha256=iMJSKxcMFKo4BhhCV8lFHX415xw6vDt2bdbecZMIsrg,4122
|
||||
pygments/styles/staroffice.py,sha256=SQb2dU8N5iVDK6z7NnYF-0XQL-s2mcu47vcbeImZ2mc,770
|
||||
pygments/styles/stata_dark.py,sha256=uKZsvGdSMxfKPlmKvPLWa48C1jXwuxlYVb44Kp2t2ik,1198
|
||||
pygments/styles/stata_light.py,sha256=l5V1Sdz31jEkzO7CdSSBXrKWfoGgOShjarO5WtqX4DE,1227
|
||||
pygments/styles/tango.py,sha256=VfnoaQIAVclCowWJQX1oV7TwcsuPytgpEIzIwUJtZmw,7113
|
||||
pygments/styles/trac.py,sha256=Y4Yf7YtquSFma3qs3OyvdUIMUw2zDaAb7eCzZOvGMHw,1932
|
||||
pygments/styles/vim.py,sha256=zJ6EIRuh4kwwPgiEnmn3QmyzBBpY7VV_OOCMHjXmqzw,1972
|
||||
pygments/styles/vs.py,sha256=lNFG1rVi1U1jSntoB6ZNxzimdNxIi1rDkOaOJndnCU4,1076
|
||||
pygments/styles/xcode.py,sha256=8nrGsI4FXIPx3DrGoqhLz_U0jZgpgKfW1FA2oV2iJ4A,1453
|
||||
pygments/styles/zenburn.py,sha256=RWniXYptEN65ip_FZGHnd25RvujfHSmhSZSWioH0xY8,2148
|
||||
pygments/token.py,sha256=DXVQcLULVn05LG63bagiqJd2FH3UzheVUBmdQeXn1U8,6226
|
||||
pygments/unistring.py,sha256=FaUfG14NBJEKLQoY9qj6JYeXrpYcLmKulghdxOGFaOc,63223
|
||||
pygments/util.py,sha256=AEVY0qonyyEMgv4Do2dINrrqUAwUk2XYSqHM650uzek,10230
|
||||
@@ -1,5 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.41.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[console_scripts]
|
||||
pygmentize = pygments.cmdline:main
|
||||
@@ -1 +0,0 @@
|
||||
pygments
|
||||
@@ -1,222 +0,0 @@
|
||||
# don't import any costly modules
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
is_pypy = '__pypy__' in sys.builtin_module_names
|
||||
|
||||
|
||||
def warn_distutils_present():
|
||||
if 'distutils' not in sys.modules:
|
||||
return
|
||||
if is_pypy and sys.version_info < (3, 7):
|
||||
# PyPy for 3.6 unconditionally imports distutils, so bypass the warning
|
||||
# https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
|
||||
return
|
||||
import warnings
|
||||
|
||||
warnings.warn(
|
||||
"Distutils was imported before Setuptools, but importing Setuptools "
|
||||
"also replaces the `distutils` module in `sys.modules`. This may lead "
|
||||
"to undesirable behaviors or errors. To avoid these issues, avoid "
|
||||
"using distutils directly, ensure that setuptools is installed in the "
|
||||
"traditional way (e.g. not an editable install), and/or make sure "
|
||||
"that setuptools is always imported before distutils."
|
||||
)
|
||||
|
||||
|
||||
def clear_distutils():
|
||||
if 'distutils' not in sys.modules:
|
||||
return
|
||||
import warnings
|
||||
|
||||
warnings.warn("Setuptools is replacing distutils.")
|
||||
mods = [
|
||||
name
|
||||
for name in sys.modules
|
||||
if name == "distutils" or name.startswith("distutils.")
|
||||
]
|
||||
for name in mods:
|
||||
del sys.modules[name]
|
||||
|
||||
|
||||
def enabled():
|
||||
"""
|
||||
Allow selection of distutils by environment variable.
|
||||
"""
|
||||
which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local')
|
||||
return which == 'local'
|
||||
|
||||
|
||||
def ensure_local_distutils():
|
||||
import importlib
|
||||
|
||||
clear_distutils()
|
||||
|
||||
# With the DistutilsMetaFinder in place,
|
||||
# perform an import to cause distutils to be
|
||||
# loaded from setuptools._distutils. Ref #2906.
|
||||
with shim():
|
||||
importlib.import_module('distutils')
|
||||
|
||||
# check that submodules load as expected
|
||||
core = importlib.import_module('distutils.core')
|
||||
assert '_distutils' in core.__file__, core.__file__
|
||||
assert 'setuptools._distutils.log' not in sys.modules
|
||||
|
||||
|
||||
def do_override():
|
||||
"""
|
||||
Ensure that the local copy of distutils is preferred over stdlib.
|
||||
|
||||
See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401
|
||||
for more motivation.
|
||||
"""
|
||||
if enabled():
|
||||
warn_distutils_present()
|
||||
ensure_local_distutils()
|
||||
|
||||
|
||||
class _TrivialRe:
|
||||
def __init__(self, *patterns):
|
||||
self._patterns = patterns
|
||||
|
||||
def match(self, string):
|
||||
return all(pat in string for pat in self._patterns)
|
||||
|
||||
|
||||
class DistutilsMetaFinder:
|
||||
def find_spec(self, fullname, path, target=None):
|
||||
# optimization: only consider top level modules and those
|
||||
# found in the CPython test suite.
|
||||
if path is not None and not fullname.startswith('test.'):
|
||||
return
|
||||
|
||||
method_name = 'spec_for_{fullname}'.format(**locals())
|
||||
method = getattr(self, method_name, lambda: None)
|
||||
return method()
|
||||
|
||||
def spec_for_distutils(self):
|
||||
if self.is_cpython():
|
||||
return
|
||||
|
||||
import importlib
|
||||
import importlib.abc
|
||||
import importlib.util
|
||||
|
||||
try:
|
||||
mod = importlib.import_module('setuptools._distutils')
|
||||
except Exception:
|
||||
# There are a couple of cases where setuptools._distutils
|
||||
# may not be present:
|
||||
# - An older Setuptools without a local distutils is
|
||||
# taking precedence. Ref #2957.
|
||||
# - Path manipulation during sitecustomize removes
|
||||
# setuptools from the path but only after the hook
|
||||
# has been loaded. Ref #2980.
|
||||
# In either case, fall back to stdlib behavior.
|
||||
return
|
||||
|
||||
class DistutilsLoader(importlib.abc.Loader):
|
||||
def create_module(self, spec):
|
||||
mod.__name__ = 'distutils'
|
||||
return mod
|
||||
|
||||
def exec_module(self, module):
|
||||
pass
|
||||
|
||||
return importlib.util.spec_from_loader(
|
||||
'distutils', DistutilsLoader(), origin=mod.__file__
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def is_cpython():
|
||||
"""
|
||||
Suppress supplying distutils for CPython (build and tests).
|
||||
Ref #2965 and #3007.
|
||||
"""
|
||||
return os.path.isfile('pybuilddir.txt')
|
||||
|
||||
def spec_for_pip(self):
|
||||
"""
|
||||
Ensure stdlib distutils when running under pip.
|
||||
See pypa/pip#8761 for rationale.
|
||||
"""
|
||||
if self.pip_imported_during_build():
|
||||
return
|
||||
clear_distutils()
|
||||
self.spec_for_distutils = lambda: None
|
||||
|
||||
@classmethod
|
||||
def pip_imported_during_build(cls):
|
||||
"""
|
||||
Detect if pip is being imported in a build script. Ref #2355.
|
||||
"""
|
||||
import traceback
|
||||
|
||||
return any(
|
||||
cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def frame_file_is_setup(frame):
|
||||
"""
|
||||
Return True if the indicated frame suggests a setup.py file.
|
||||
"""
|
||||
# some frames may not have __file__ (#2940)
|
||||
return frame.f_globals.get('__file__', '').endswith('setup.py')
|
||||
|
||||
def spec_for_sensitive_tests(self):
|
||||
"""
|
||||
Ensure stdlib distutils when running select tests under CPython.
|
||||
|
||||
python/cpython#91169
|
||||
"""
|
||||
clear_distutils()
|
||||
self.spec_for_distutils = lambda: None
|
||||
|
||||
sensitive_tests = (
|
||||
[
|
||||
'test.test_distutils',
|
||||
'test.test_peg_generator',
|
||||
'test.test_importlib',
|
||||
]
|
||||
if sys.version_info < (3, 10)
|
||||
else [
|
||||
'test.test_distutils',
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
for name in DistutilsMetaFinder.sensitive_tests:
|
||||
setattr(
|
||||
DistutilsMetaFinder,
|
||||
f'spec_for_{name}',
|
||||
DistutilsMetaFinder.spec_for_sensitive_tests,
|
||||
)
|
||||
|
||||
|
||||
DISTUTILS_FINDER = DistutilsMetaFinder()
|
||||
|
||||
|
||||
def add_shim():
|
||||
DISTUTILS_FINDER in sys.meta_path or insert_shim()
|
||||
|
||||
|
||||
class shim:
|
||||
def __enter__(self):
|
||||
insert_shim()
|
||||
|
||||
def __exit__(self, exc, value, tb):
|
||||
remove_shim()
|
||||
|
||||
|
||||
def insert_shim():
|
||||
sys.meta_path.insert(0, DISTUTILS_FINDER)
|
||||
|
||||
|
||||
def remove_shim():
|
||||
try:
|
||||
sys.meta_path.remove(DISTUTILS_FINDER)
|
||||
except ValueError:
|
||||
pass
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
__import__('_distutils_hack').do_override()
|
||||
Binary file not shown.
@@ -1,658 +0,0 @@
|
||||
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
|
||||
|
||||
# Exceptions
|
||||
class AddressInUseError(Exception): ...
|
||||
class ExecutableNotFoundError(Exception): ...
|
||||
class ExecutableNotSupportedError(Exception): ...
|
||||
class ServerNotRunningError(Exception): ...
|
||||
class TimedOutError(Exception): ...
|
||||
class TransportError(Exception): ...
|
||||
class ProcessNotFoundError(Exception): ...
|
||||
class ProcessNotRespondingError(Exception): ...
|
||||
class ProtocolError(Exception): ...
|
||||
class InvalidArgumentError(Exception): ...
|
||||
class InvalidOperationError(Exception): ...
|
||||
class NotSupportedError(Exception): ...
|
||||
class OperationCancelledError(Exception): ...
|
||||
class PermissionDeniedError(Exception): ...
|
||||
|
||||
class Object:
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
|
||||
def on(self, signal: str, callback: Callable[..., Any]) -> None:
|
||||
"""
|
||||
Add a signal handler.
|
||||
"""
|
||||
...
|
||||
def off(self, signal: str, callback: Callable[..., Any]) -> None:
|
||||
"""
|
||||
Remove a signal handler.
|
||||
"""
|
||||
...
|
||||
|
||||
class Application(Object):
|
||||
@property
|
||||
def identifier(self) -> str:
|
||||
"""
|
||||
Application identifier.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
Human-readable application name.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def parameters(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Parameters.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def pid(self) -> int:
|
||||
"""
|
||||
Process ID, or 0 if not running.
|
||||
"""
|
||||
...
|
||||
|
||||
class Bus(Object):
|
||||
def attach(self) -> None:
|
||||
"""
|
||||
Attach to the bus.
|
||||
"""
|
||||
...
|
||||
def post(self, message: str, data: Optional[Union[bytes, str]]) -> None:
|
||||
"""
|
||||
Post a JSON-encoded message to the bus.
|
||||
"""
|
||||
...
|
||||
|
||||
class Cancellable(Object):
|
||||
def cancel(self) -> None:
|
||||
"""
|
||||
Set cancellable to cancelled.
|
||||
"""
|
||||
...
|
||||
def connect(self, callback: Callable[..., Any]) -> int:
|
||||
"""
|
||||
Register notification callback.
|
||||
"""
|
||||
...
|
||||
def disconnect(self, handler_id: int) -> None:
|
||||
"""
|
||||
Unregister notification callback.
|
||||
"""
|
||||
...
|
||||
@classmethod
|
||||
def get_current(cls) -> "Cancellable":
|
||||
"""
|
||||
Get the top cancellable from the stack.
|
||||
"""
|
||||
...
|
||||
def get_fd(self) -> int:
|
||||
"""
|
||||
Get file descriptor for integrating with an event loop.
|
||||
"""
|
||||
...
|
||||
def is_cancelled(self) -> bool:
|
||||
"""
|
||||
Query whether cancellable has been cancelled.
|
||||
"""
|
||||
...
|
||||
def pop_current(self) -> None:
|
||||
"""
|
||||
Pop cancellable off the cancellable stack.
|
||||
"""
|
||||
...
|
||||
def push_current(self) -> None:
|
||||
"""
|
||||
Push cancellable onto the cancellable stack.
|
||||
"""
|
||||
...
|
||||
def raise_if_cancelled(self) -> None:
|
||||
"""
|
||||
Raise an exception if cancelled.
|
||||
"""
|
||||
...
|
||||
def release_fd(self) -> None:
|
||||
"""
|
||||
Release a resource previously allocated by get_fd().
|
||||
"""
|
||||
...
|
||||
|
||||
class Child(Object):
|
||||
@property
|
||||
def argv(self) -> List[str]:
|
||||
"""
|
||||
Argument vector.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def envp(self) -> Dict[str, str]:
|
||||
"""
|
||||
Environment vector.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def identifier(self) -> str:
|
||||
"""
|
||||
Application identifier.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def origin(self) -> str:
|
||||
"""
|
||||
Origin.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def parent_pid(self) -> int:
|
||||
"""
|
||||
Parent Process ID.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def path(self) -> str:
|
||||
"""
|
||||
Path of executable.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def pid(self) -> int:
|
||||
"""
|
||||
Process ID.
|
||||
"""
|
||||
...
|
||||
|
||||
class Crash(Object):
|
||||
@property
|
||||
def parameters(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Parameters.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def pid(self) -> int:
|
||||
"""
|
||||
Process ID.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def process_name(self) -> str:
|
||||
"""
|
||||
Process name.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def report(self) -> str:
|
||||
"""
|
||||
Human-readable crash report.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def summary(self) -> str:
|
||||
"""
|
||||
Human-readable crash summary.
|
||||
"""
|
||||
...
|
||||
|
||||
class Device(Object):
|
||||
@property
|
||||
def id(self) -> Optional[str]:
|
||||
"""
|
||||
Device ID.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def name(self) -> Optional[str]:
|
||||
"""
|
||||
Human-readable device name.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def icon(self) -> Optional[Any]:
|
||||
"""
|
||||
Icon.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def type(self) -> Optional[str]:
|
||||
"""
|
||||
Device type. One of: local, remote, usb.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def bus(self) -> Optional[Bus]:
|
||||
"""
|
||||
Message bus.
|
||||
"""
|
||||
...
|
||||
def attach(self, pid: int, realm: Optional[str] = None, persist_timeout: Optional[int] = None) -> "Session":
|
||||
"""
|
||||
Attach to a PID.
|
||||
"""
|
||||
...
|
||||
def disable_spawn_gating(self) -> None:
|
||||
"""
|
||||
Disable spawn gating.
|
||||
"""
|
||||
...
|
||||
def enable_spawn_gating(self) -> None:
|
||||
"""
|
||||
Enable spawn gating.
|
||||
"""
|
||||
...
|
||||
def enumerate_applications(
|
||||
self, identifiers: Optional[Sequence[str]] = None, scope: Optional[str] = None
|
||||
) -> List[Application]:
|
||||
"""
|
||||
Enumerate applications.
|
||||
"""
|
||||
...
|
||||
def enumerate_pending_children(self) -> List[Child]:
|
||||
"""
|
||||
Enumerate pending children.
|
||||
"""
|
||||
...
|
||||
def enumerate_pending_spawn(self) -> List["Spawn"]:
|
||||
"""
|
||||
Enumerate pending spawn.
|
||||
"""
|
||||
...
|
||||
def enumerate_processes(self, pids: Optional[Sequence[int]] = None, scope: Optional[str] = None) -> List[Process]:
|
||||
"""
|
||||
Enumerate processes.
|
||||
"""
|
||||
...
|
||||
def get_frontmost_application(self, scope: Optional[str] = None) -> Optional[Application]:
|
||||
"""
|
||||
Get details about the frontmost application.
|
||||
"""
|
||||
...
|
||||
def inject_library_blob(self, pid: int, blob_buffer: bytes, entrypoint: str, data: str) -> int:
|
||||
"""
|
||||
Inject a library blob to a PID.
|
||||
"""
|
||||
...
|
||||
def inject_library_file(self, pid: int, path: str, entrypoint: str, data: str) -> int:
|
||||
"""
|
||||
Inject a library file to a PID.
|
||||
"""
|
||||
...
|
||||
def input(self, pid: int, data: bytes) -> None:
|
||||
"""
|
||||
Input data on stdin of a spawned process.
|
||||
"""
|
||||
...
|
||||
def is_lost(self) -> bool:
|
||||
"""
|
||||
Query whether the device has been lost.
|
||||
"""
|
||||
...
|
||||
def kill(self, pid: int) -> None:
|
||||
"""
|
||||
Kill a PID.
|
||||
"""
|
||||
...
|
||||
def open_channel(self, address: str) -> "IOStream":
|
||||
"""
|
||||
Open a device-specific communication channel.
|
||||
"""
|
||||
...
|
||||
def query_system_parameters(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Returns a dictionary of information about the host system.
|
||||
"""
|
||||
...
|
||||
def resume(self, pid: int) -> None:
|
||||
"""
|
||||
Resume a process from the attachable state.
|
||||
"""
|
||||
...
|
||||
def spawn(
|
||||
self,
|
||||
program: str,
|
||||
argv: Union[None, List[Union[str, bytes]], Tuple[Union[str, bytes]]] = None,
|
||||
envp: Optional[Dict[str, str]] = None,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
cwd: Optional[str] = None,
|
||||
stdio: Optional[str] = None,
|
||||
**kwargs: Any,
|
||||
) -> int:
|
||||
"""
|
||||
Spawn a process into an attachable state.
|
||||
"""
|
||||
...
|
||||
|
||||
class DeviceManager(Object):
|
||||
def add_remote_device(
|
||||
self,
|
||||
address: str,
|
||||
certificate: Optional[str] = None,
|
||||
origin: Optional[str] = None,
|
||||
token: Optional[str] = None,
|
||||
keepalive_interval: Optional[int] = None,
|
||||
) -> Device:
|
||||
"""
|
||||
Add a remote device.
|
||||
"""
|
||||
...
|
||||
def close(self) -> None:
|
||||
"""
|
||||
Close the device manager.
|
||||
"""
|
||||
...
|
||||
def enumerate_devices(self) -> List[Device]:
|
||||
"""
|
||||
Enumerate devices.
|
||||
"""
|
||||
...
|
||||
def get_device_matching(self, predicate: Callable[[Device], bool], timeout: int) -> Device:
|
||||
"""
|
||||
Get device matching predicate.
|
||||
"""
|
||||
...
|
||||
def remove_remote_device(self, address: str) -> None:
|
||||
"""
|
||||
Remove a remote device.
|
||||
"""
|
||||
...
|
||||
|
||||
class EndpointParameters(Object): ...
|
||||
|
||||
class FileMonitor(Object):
|
||||
def disable(self) -> None:
|
||||
"""
|
||||
Disable the file monitor.
|
||||
"""
|
||||
...
|
||||
def enable(self) -> None:
|
||||
"""
|
||||
Enable the file monitor.
|
||||
"""
|
||||
...
|
||||
|
||||
class IOStream(Object):
|
||||
def close(self) -> None:
|
||||
"""
|
||||
Close the stream.
|
||||
"""
|
||||
...
|
||||
def is_closed(self) -> bool:
|
||||
"""
|
||||
Query whether the stream is closed.
|
||||
"""
|
||||
...
|
||||
def read(self, size: int) -> bytes:
|
||||
"""
|
||||
Read up to the specified number of bytes from the stream.
|
||||
"""
|
||||
...
|
||||
def read_all(self, size: int) -> bytes:
|
||||
"""
|
||||
Read exactly the specified number of bytes from the stream.
|
||||
"""
|
||||
...
|
||||
def write(self, data: bytes) -> int:
|
||||
"""
|
||||
Write as much as possible of the provided data to the stream.
|
||||
"""
|
||||
...
|
||||
def write_all(self, data: bytes) -> None:
|
||||
"""
|
||||
Write all of the provided data to the stream.
|
||||
"""
|
||||
...
|
||||
|
||||
class PortalMembership(Object):
|
||||
def terminate(self) -> None:
|
||||
"""
|
||||
Terminate the membership.
|
||||
"""
|
||||
...
|
||||
|
||||
class PortalService(Object):
|
||||
@property
|
||||
def device(self) -> Device:
|
||||
"""
|
||||
Device for in-process control.
|
||||
"""
|
||||
...
|
||||
def broadcast(self, message: str, data: Optional[Union[str, bytes]] = None) -> None:
|
||||
"""
|
||||
Broadcast a message to all control channels.
|
||||
"""
|
||||
...
|
||||
def enumerate_tags(self, connection_id: int) -> List[str]:
|
||||
"""
|
||||
Enumerate tags of a specific connection.
|
||||
"""
|
||||
...
|
||||
def kick(self, connection_id: int) -> None:
|
||||
"""
|
||||
Kick out a specific connection.
|
||||
"""
|
||||
...
|
||||
def narrowcast(self, tag: str, message: str, data: Optional[Union[str, bytes]] = None) -> None:
|
||||
"""
|
||||
Post a message to control channels with a specific tag.
|
||||
"""
|
||||
...
|
||||
def post(self, connection_id: int, message: str, data: Optional[Union[str, bytes]] = None) -> None:
|
||||
"""
|
||||
Post a message to a specific control channel.
|
||||
"""
|
||||
...
|
||||
def start(self) -> None:
|
||||
"""
|
||||
Start listening for incoming connections.
|
||||
"""
|
||||
...
|
||||
def stop(self) -> None:
|
||||
"""
|
||||
Stop listening for incoming connections, and kick any connected clients.
|
||||
"""
|
||||
...
|
||||
def tag(self, connection_id: int, tag: str) -> None:
|
||||
"""
|
||||
Tag a specific control channel.
|
||||
"""
|
||||
...
|
||||
def untag(self, connection_id: int, tag: str) -> None:
|
||||
"""
|
||||
Untag a specific control channel.
|
||||
"""
|
||||
...
|
||||
|
||||
class Process(Object):
|
||||
@property
|
||||
def pid(self) -> int:
|
||||
"""
|
||||
Process ID.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
Human-readable process name.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def parameters(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Parameters.
|
||||
"""
|
||||
...
|
||||
|
||||
class Relay(Object):
|
||||
def __init__(self, address: str, username: str, password: str, kind: str) -> None: ...
|
||||
@property
|
||||
def address(self) -> str:
|
||||
"""
|
||||
Network address or address:port of the TURN server.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def kind(self) -> str:
|
||||
"""
|
||||
Relay kind. One of: turn-udp, turn-tcp, turn-tls.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def password(self) -> str:
|
||||
"""
|
||||
The TURN password to use for the allocate request.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def username(self) -> str:
|
||||
"""
|
||||
The TURN username to use for the allocate request.
|
||||
"""
|
||||
...
|
||||
|
||||
class Script(Object):
|
||||
def eternalize(self) -> None:
|
||||
"""
|
||||
Eternalize the script.
|
||||
"""
|
||||
...
|
||||
def is_destroyed(self) -> bool:
|
||||
"""
|
||||
Query whether the script has been destroyed.
|
||||
"""
|
||||
...
|
||||
def load(self) -> None:
|
||||
"""
|
||||
Load the script.
|
||||
"""
|
||||
...
|
||||
def post(self, message: str, data: Optional[Union[str, bytes]] = None) -> None:
|
||||
"""
|
||||
Post a JSON-encoded message to the script.
|
||||
"""
|
||||
...
|
||||
def unload(self) -> None:
|
||||
"""
|
||||
Unload the script.
|
||||
"""
|
||||
...
|
||||
def enable_debugger(self, port: Optional[int]) -> None:
|
||||
"""
|
||||
Enable the Node.js compatible script debugger
|
||||
"""
|
||||
...
|
||||
def disable_debugger(self) -> None:
|
||||
"""
|
||||
Disable the Node.js compatible script debugger
|
||||
"""
|
||||
...
|
||||
|
||||
class Session(Object):
|
||||
@property
|
||||
def pid(self) -> int:
|
||||
"""
|
||||
Process ID.
|
||||
"""
|
||||
...
|
||||
def compile_script(self, source: str, name: Optional[str] = None, runtime: Optional[str] = None) -> bytes:
|
||||
"""
|
||||
Compile script source code to bytecode.
|
||||
"""
|
||||
...
|
||||
def create_script(self, source: str, name: Optional[str] = None, runtime: Optional[str] = None) -> Script:
|
||||
"""
|
||||
Create a new script.
|
||||
"""
|
||||
...
|
||||
def create_script_from_bytes(
|
||||
self, data: bytes, name: Optional[str] = None, runtime: Optional[str] = None
|
||||
) -> Script:
|
||||
"""
|
||||
Create a new script from bytecode.
|
||||
"""
|
||||
...
|
||||
def snapshot_script(self, embed_script: str, warmup_script: Optional[str], runtime: Optional[str] = None) -> bytes:
|
||||
"""
|
||||
Evaluate script and snapshot the resulting VM state
|
||||
"""
|
||||
...
|
||||
def detach(self) -> None:
|
||||
"""
|
||||
Detach session from the process.
|
||||
"""
|
||||
...
|
||||
def disable_child_gating(self) -> None:
|
||||
"""
|
||||
Disable child gating.
|
||||
"""
|
||||
...
|
||||
def enable_child_gating(self) -> None:
|
||||
"""
|
||||
Enable child gating.
|
||||
"""
|
||||
...
|
||||
def is_detached(self) -> bool:
|
||||
"""
|
||||
Query whether the session is detached.
|
||||
"""
|
||||
...
|
||||
def join_portal(
|
||||
self, address: str, certificate: Optional[str] = None, token: Optional[str] = None, acl: Optional[Any] = None
|
||||
) -> PortalMembership:
|
||||
"""
|
||||
Join a portal.
|
||||
"""
|
||||
...
|
||||
def resume(self) -> None:
|
||||
"""
|
||||
Resume session after network error.
|
||||
"""
|
||||
...
|
||||
def setup_peer_connection(
|
||||
self, stun_server: Optional[str] = None, relays: Optional[Sequence[Relay]] = None
|
||||
) -> None:
|
||||
"""
|
||||
Set up a peer connection with the target process.
|
||||
"""
|
||||
...
|
||||
|
||||
class Spawn(Object):
|
||||
@property
|
||||
def identifier(self) -> str:
|
||||
"""
|
||||
Application identifier.
|
||||
"""
|
||||
...
|
||||
@property
|
||||
def pid(self) -> int:
|
||||
"""
|
||||
Process ID.
|
||||
"""
|
||||
...
|
||||
|
||||
class Compiler(Object):
|
||||
def build(
|
||||
self,
|
||||
entrypoint: str,
|
||||
project_root: Optional[str] = None,
|
||||
source_maps: Optional[str] = None,
|
||||
compression: Optional[str] = None,
|
||||
) -> str:
|
||||
"""
|
||||
Build an agent.
|
||||
"""
|
||||
...
|
||||
def watch(
|
||||
self,
|
||||
entrypoint: str,
|
||||
project_root: Optional[str] = None,
|
||||
source_maps: Optional[str] = None,
|
||||
compression: Optional[str] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Continuously build an agent.
|
||||
"""
|
||||
...
|
||||
|
||||
__version__: str
|
||||
@@ -1 +0,0 @@
|
||||
pip
|
||||
@@ -1,441 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: colorama
|
||||
Version: 0.4.6
|
||||
Summary: Cross-platform colored terminal text.
|
||||
Project-URL: Homepage, https://github.com/tartley/colorama
|
||||
Author-email: Jonathan Hartley <tartley@tartley.com>
|
||||
License-File: LICENSE.txt
|
||||
Keywords: ansi,color,colour,crossplatform,terminal,text,windows,xplatform
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Terminals
|
||||
Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7
|
||||
Description-Content-Type: text/x-rst
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/colorama.svg
|
||||
:target: https://pypi.org/project/colorama/
|
||||
:alt: Latest Version
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/colorama.svg
|
||||
:target: https://pypi.org/project/colorama/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://github.com/tartley/colorama/actions/workflows/test.yml/badge.svg
|
||||
:target: https://github.com/tartley/colorama/actions/workflows/test.yml
|
||||
:alt: Build Status
|
||||
|
||||
Colorama
|
||||
========
|
||||
|
||||
Makes ANSI escape character sequences (for producing colored terminal text and
|
||||
cursor positioning) work under MS Windows.
|
||||
|
||||
.. |donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif
|
||||
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2MZ9D2GMLYCUJ&item_name=Colorama¤cy_code=USD
|
||||
:alt: Donate with Paypal
|
||||
|
||||
`PyPI for releases <https://pypi.org/project/colorama/>`_ |
|
||||
`Github for source <https://github.com/tartley/colorama>`_ |
|
||||
`Colorama for enterprise on Tidelift <https://github.com/tartley/colorama/blob/master/ENTERPRISE.md>`_
|
||||
|
||||
If you find Colorama useful, please |donate| to the authors. Thank you!
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Tested on CPython 2.7, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.8.
|
||||
|
||||
No requirements other than the standard library.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install colorama
|
||||
# or
|
||||
conda install -c anaconda colorama
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
ANSI escape character sequences have long been used to produce colored terminal
|
||||
text and cursor positioning on Unix and Macs. Colorama makes this work on
|
||||
Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which
|
||||
would appear as gobbledygook in the output), and converting them into the
|
||||
appropriate win32 calls to modify the state of the terminal. On other platforms,
|
||||
Colorama does nothing.
|
||||
|
||||
This has the upshot of providing a simple cross-platform API for printing
|
||||
colored terminal text from Python, and has the happy side-effect that existing
|
||||
applications or libraries which use ANSI sequences to produce colored output on
|
||||
Linux or Macs can now also work on Windows, simply by calling
|
||||
``colorama.just_fix_windows_console()`` (since v0.4.6) or ``colorama.init()``
|
||||
(all versions, but may have other side-effects – see below).
|
||||
|
||||
An alternative approach is to install ``ansi.sys`` on Windows machines, which
|
||||
provides the same behaviour for all applications running in terminals. Colorama
|
||||
is intended for situations where that isn't easy (e.g., maybe your app doesn't
|
||||
have an installer.)
|
||||
|
||||
Demo scripts in the source code repository print some colored text using
|
||||
ANSI sequences. Compare their output under Gnome-terminal's built in ANSI
|
||||
handling, versus on Windows Command-Prompt using Colorama:
|
||||
|
||||
.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png
|
||||
:width: 661
|
||||
:height: 357
|
||||
:alt: ANSI sequences on Ubuntu under gnome-terminal.
|
||||
|
||||
.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png
|
||||
:width: 668
|
||||
:height: 325
|
||||
:alt: Same ANSI sequences on Windows, using Colorama.
|
||||
|
||||
These screenshots show that, on Windows, Colorama does not support ANSI 'dim
|
||||
text'; it looks the same as 'normal text'.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Initialisation
|
||||
..............
|
||||
|
||||
If the only thing you want from Colorama is to get ANSI escapes to work on
|
||||
Windows, then run:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import just_fix_windows_console
|
||||
just_fix_windows_console()
|
||||
|
||||
If you're on a recent version of Windows 10 or better, and your stdout/stderr
|
||||
are pointing to a Windows console, then this will flip the magic configuration
|
||||
switch to enable Windows' built-in ANSI support.
|
||||
|
||||
If you're on an older version of Windows, and your stdout/stderr are pointing to
|
||||
a Windows console, then this will wrap ``sys.stdout`` and/or ``sys.stderr`` in a
|
||||
magic file object that intercepts ANSI escape sequences and issues the
|
||||
appropriate Win32 calls to emulate them.
|
||||
|
||||
In all other circumstances, it does nothing whatsoever. Basically the idea is
|
||||
that this makes Windows act like Unix with respect to ANSI escape handling.
|
||||
|
||||
It's safe to call this function multiple times. It's safe to call this function
|
||||
on non-Windows platforms, but it won't do anything. It's safe to call this
|
||||
function when one or both of your stdout/stderr are redirected to a file – it
|
||||
won't do anything to those streams.
|
||||
|
||||
Alternatively, you can use the older interface with more features (but also more
|
||||
potential footguns):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import init
|
||||
init()
|
||||
|
||||
This does the same thing as ``just_fix_windows_console``, except for the
|
||||
following differences:
|
||||
|
||||
- It's not safe to call ``init`` multiple times; you can end up with multiple
|
||||
layers of wrapping and broken ANSI support.
|
||||
|
||||
- Colorama will apply a heuristic to guess whether stdout/stderr support ANSI,
|
||||
and if it thinks they don't, then it will wrap ``sys.stdout`` and
|
||||
``sys.stderr`` in a magic file object that strips out ANSI escape sequences
|
||||
before printing them. This happens on all platforms, and can be convenient if
|
||||
you want to write your code to emit ANSI escape sequences unconditionally, and
|
||||
let Colorama decide whether they should actually be output. But note that
|
||||
Colorama's heuristic is not particularly clever.
|
||||
|
||||
- ``init`` also accepts explicit keyword args to enable/disable various
|
||||
functionality – see below.
|
||||
|
||||
To stop using Colorama before your program exits, simply call ``deinit()``.
|
||||
This will restore ``stdout`` and ``stderr`` to their original values, so that
|
||||
Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is
|
||||
cheaper than calling ``init()`` again (but does the same thing).
|
||||
|
||||
Most users should depend on ``colorama >= 0.4.6``, and use
|
||||
``just_fix_windows_console``. The old ``init`` interface will be supported
|
||||
indefinitely for backwards compatibility, but we don't plan to fix any issues
|
||||
with it, also for backwards compatibility.
|
||||
|
||||
Colored Output
|
||||
..............
|
||||
|
||||
Cross-platform printing of colored text can then be done using Colorama's
|
||||
constant shorthand for ANSI escape sequences. These are deliberately
|
||||
rudimentary, see below.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import Fore, Back, Style
|
||||
print(Fore.RED + 'some red text')
|
||||
print(Back.GREEN + 'and with a green background')
|
||||
print(Style.DIM + 'and in dim text')
|
||||
print(Style.RESET_ALL)
|
||||
print('back to normal now')
|
||||
|
||||
...or simply by manually printing ANSI sequences from your own code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print('\033[31m' + 'some red text')
|
||||
print('\033[39m') # and reset to default color
|
||||
|
||||
...or, Colorama can be used in conjunction with existing ANSI libraries
|
||||
such as the venerable `Termcolor <https://pypi.org/project/termcolor/>`_
|
||||
the fabulous `Blessings <https://pypi.org/project/blessings/>`_,
|
||||
or the incredible `_Rich <https://pypi.org/project/rich/>`_.
|
||||
|
||||
If you wish Colorama's Fore, Back and Style constants were more capable,
|
||||
then consider using one of the above highly capable libraries to generate
|
||||
colors, etc, and use Colorama just for its primary purpose: to convert
|
||||
those ANSI sequences to also work on Windows:
|
||||
|
||||
SIMILARLY, do not send PRs adding the generation of new ANSI types to Colorama.
|
||||
We are only interested in converting ANSI codes to win32 API calls, not
|
||||
shortcuts like the above to generate ANSI characters.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import just_fix_windows_console
|
||||
from termcolor import colored
|
||||
|
||||
# use Colorama to make Termcolor work on Windows too
|
||||
just_fix_windows_console()
|
||||
|
||||
# then use Termcolor for all colored text output
|
||||
print(colored('Hello, World!', 'green', 'on_red'))
|
||||
|
||||
Available formatting constants are::
|
||||
|
||||
Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
|
||||
Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
|
||||
Style: DIM, NORMAL, BRIGHT, RESET_ALL
|
||||
|
||||
``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will
|
||||
perform this reset automatically on program exit.
|
||||
|
||||
These are fairly well supported, but not part of the standard::
|
||||
|
||||
Fore: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX
|
||||
Back: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX
|
||||
|
||||
Cursor Positioning
|
||||
..................
|
||||
|
||||
ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for
|
||||
an example of how to generate them.
|
||||
|
||||
Init Keyword Args
|
||||
.................
|
||||
|
||||
``init()`` accepts some ``**kwargs`` to override default behaviour.
|
||||
|
||||
init(autoreset=False):
|
||||
If you find yourself repeatedly sending reset sequences to turn off color
|
||||
changes at the end of every print, then ``init(autoreset=True)`` will
|
||||
automate that:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from colorama import init
|
||||
init(autoreset=True)
|
||||
print(Fore.RED + 'some red text')
|
||||
print('automatically back to default color again')
|
||||
|
||||
init(strip=None):
|
||||
Pass ``True`` or ``False`` to override whether ANSI codes should be
|
||||
stripped from the output. The default behaviour is to strip if on Windows
|
||||
or if output is redirected (not a tty).
|
||||
|
||||
init(convert=None):
|
||||
Pass ``True`` or ``False`` to override whether to convert ANSI codes in the
|
||||
output into win32 calls. The default behaviour is to convert if on Windows
|
||||
and output is to a tty (terminal).
|
||||
|
||||
init(wrap=True):
|
||||
On Windows, Colorama works by replacing ``sys.stdout`` and ``sys.stderr``
|
||||
with proxy objects, which override the ``.write()`` method to do their work.
|
||||
If this wrapping causes you problems, then this can be disabled by passing
|
||||
``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or
|
||||
``strip`` or ``convert`` are True.
|
||||
|
||||
When wrapping is disabled, colored printing on non-Windows platforms will
|
||||
continue to work as normal. To do cross-platform colored output, you can
|
||||
use Colorama's ``AnsiToWin32`` proxy directly:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
from colorama import init, AnsiToWin32
|
||||
init(wrap=False)
|
||||
stream = AnsiToWin32(sys.stderr).stream
|
||||
|
||||
# Python 2
|
||||
print >>stream, Fore.BLUE + 'blue text on stderr'
|
||||
|
||||
# Python 3
|
||||
print(Fore.BLUE + 'blue text on stderr', file=stream)
|
||||
|
||||
Recognised ANSI Sequences
|
||||
.........................
|
||||
|
||||
ANSI sequences generally take the form::
|
||||
|
||||
ESC [ <param> ; <param> ... <command>
|
||||
|
||||
Where ``<param>`` is an integer, and ``<command>`` is a single letter. Zero or
|
||||
more params are passed to a ``<command>``. If no params are passed, it is
|
||||
generally synonymous with passing a single zero. No spaces exist in the
|
||||
sequence; they have been inserted here simply to read more easily.
|
||||
|
||||
The only ANSI sequences that Colorama converts into win32 calls are::
|
||||
|
||||
ESC [ 0 m # reset all (colors and brightness)
|
||||
ESC [ 1 m # bright
|
||||
ESC [ 2 m # dim (looks same as normal brightness)
|
||||
ESC [ 22 m # normal brightness
|
||||
|
||||
# FOREGROUND:
|
||||
ESC [ 30 m # black
|
||||
ESC [ 31 m # red
|
||||
ESC [ 32 m # green
|
||||
ESC [ 33 m # yellow
|
||||
ESC [ 34 m # blue
|
||||
ESC [ 35 m # magenta
|
||||
ESC [ 36 m # cyan
|
||||
ESC [ 37 m # white
|
||||
ESC [ 39 m # reset
|
||||
|
||||
# BACKGROUND
|
||||
ESC [ 40 m # black
|
||||
ESC [ 41 m # red
|
||||
ESC [ 42 m # green
|
||||
ESC [ 43 m # yellow
|
||||
ESC [ 44 m # blue
|
||||
ESC [ 45 m # magenta
|
||||
ESC [ 46 m # cyan
|
||||
ESC [ 47 m # white
|
||||
ESC [ 49 m # reset
|
||||
|
||||
# cursor positioning
|
||||
ESC [ y;x H # position cursor at x across, y down
|
||||
ESC [ y;x f # position cursor at x across, y down
|
||||
ESC [ n A # move cursor n lines up
|
||||
ESC [ n B # move cursor n lines down
|
||||
ESC [ n C # move cursor n characters forward
|
||||
ESC [ n D # move cursor n characters backward
|
||||
|
||||
# clear the screen
|
||||
ESC [ mode J # clear the screen
|
||||
|
||||
# clear the line
|
||||
ESC [ mode K # clear the line
|
||||
|
||||
Multiple numeric params to the ``'m'`` command can be combined into a single
|
||||
sequence::
|
||||
|
||||
ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background
|
||||
|
||||
All other ANSI sequences of the form ``ESC [ <param> ; <param> ... <command>``
|
||||
are silently stripped from the output on Windows.
|
||||
|
||||
Any other form of ANSI sequence, such as single-character codes or alternative
|
||||
initial characters, are not recognised or stripped. It would be cool to add
|
||||
them though. Let me know if it would be useful for you, via the Issues on
|
||||
GitHub.
|
||||
|
||||
Status & Known Problems
|
||||
-----------------------
|
||||
|
||||
I've personally only tested it on Windows XP (CMD, Console2), Ubuntu
|
||||
(gnome-terminal, xterm), and OS X.
|
||||
|
||||
Some valid ANSI sequences aren't recognised.
|
||||
|
||||
If you're hacking on the code, see `README-hacking.md`_. ESPECIALLY, see the
|
||||
explanation there of why we do not want PRs that allow Colorama to generate new
|
||||
types of ANSI codes.
|
||||
|
||||
See outstanding issues and wish-list:
|
||||
https://github.com/tartley/colorama/issues
|
||||
|
||||
If anything doesn't work for you, or doesn't do what you expected or hoped for,
|
||||
I'd love to hear about it on that issues list, would be delighted by patches,
|
||||
and would be happy to grant commit access to anyone who submits a working patch
|
||||
or two.
|
||||
|
||||
.. _README-hacking.md: README-hacking.md
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright Jonathan Hartley & Arnon Yaari, 2013-2020. BSD 3-Clause license; see
|
||||
LICENSE file.
|
||||
|
||||
Professional support
|
||||
--------------------
|
||||
|
||||
.. |tideliftlogo| image:: https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png
|
||||
:alt: Tidelift
|
||||
:target: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme
|
||||
|
||||
.. list-table::
|
||||
:widths: 10 100
|
||||
|
||||
* - |tideliftlogo|
|
||||
- Professional support for colorama is available as part of the
|
||||
`Tidelift Subscription`_.
|
||||
Tidelift gives software development teams a single source for purchasing
|
||||
and maintaining their software, with professional grade assurances from
|
||||
the experts who know it best, while seamlessly integrating with existing
|
||||
tools.
|
||||
|
||||
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
See the CHANGELOG for more thanks!
|
||||
|
||||
* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5.
|
||||
* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``,
|
||||
providing a solution to issue #7's setuptools/distutils debate,
|
||||
and other fixes.
|
||||
* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``.
|
||||
* Matthew McCormick for politely pointing out a longstanding crash on non-Win.
|
||||
* Ben Hoyt, for a magnificent fix under 64-bit Windows.
|
||||
* Jesse at Empty Square for submitting a fix for examples in the README.
|
||||
* User 'jamessp', an observant documentation fix for cursor positioning.
|
||||
* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7
|
||||
fix.
|
||||
* Julien Stuyck, for wisely suggesting Python3 compatible updates to README.
|
||||
* Daniel Griffith for multiple fabulous patches.
|
||||
* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty
|
||||
output.
|
||||
* Roger Binns, for many suggestions, valuable feedback, & bug reports.
|
||||
* Tim Golden for thought and much appreciated feedback on the initial idea.
|
||||
* User 'Zearin' for updates to the README file.
|
||||
* John Szakmeister for adding support for light colors
|
||||
* Charles Merriam for adding documentation to demos
|
||||
* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes
|
||||
* Florian Bruhin for a fix when stdout or stderr are None
|
||||
* Thomas Weininger for fixing ValueError on Windows
|
||||
* Remi Rampin for better Github integration and fixes to the README file
|
||||
* Simeon Visser for closing a file handle using 'with' and updating classifiers
|
||||
to include Python 3.3 and 3.4
|
||||
* Andy Neff for fixing RESET of LIGHT_EX colors.
|
||||
* Jonathan Hartley for the initial idea and implementation.
|
||||
@@ -1,31 +0,0 @@
|
||||
colorama-0.4.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
colorama-0.4.6.dist-info/METADATA,sha256=e67SnrUMOym9sz_4TjF3vxvAV4T3aF7NyqRHHH3YEMw,17158
|
||||
colorama-0.4.6.dist-info/RECORD,,
|
||||
colorama-0.4.6.dist-info/WHEEL,sha256=cdcF4Fbd0FPtw2EMIOwH-3rSOTUdTCeOSXRMD1iLUb8,105
|
||||
colorama-0.4.6.dist-info/licenses/LICENSE.txt,sha256=ysNcAmhuXQSlpxQL-zs25zrtSWZW6JEQLkKIhteTAxg,1491
|
||||
colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266
|
||||
colorama/__pycache__/__init__.cpython-311.pyc,,
|
||||
colorama/__pycache__/ansi.cpython-311.pyc,,
|
||||
colorama/__pycache__/ansitowin32.cpython-311.pyc,,
|
||||
colorama/__pycache__/initialise.cpython-311.pyc,,
|
||||
colorama/__pycache__/win32.cpython-311.pyc,,
|
||||
colorama/__pycache__/winterm.cpython-311.pyc,,
|
||||
colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522
|
||||
colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128
|
||||
colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325
|
||||
colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75
|
||||
colorama/tests/__pycache__/__init__.cpython-311.pyc,,
|
||||
colorama/tests/__pycache__/ansi_test.cpython-311.pyc,,
|
||||
colorama/tests/__pycache__/ansitowin32_test.cpython-311.pyc,,
|
||||
colorama/tests/__pycache__/initialise_test.cpython-311.pyc,,
|
||||
colorama/tests/__pycache__/isatty_test.cpython-311.pyc,,
|
||||
colorama/tests/__pycache__/utils.cpython-311.pyc,,
|
||||
colorama/tests/__pycache__/winterm_test.cpython-311.pyc,,
|
||||
colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839
|
||||
colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678
|
||||
colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741
|
||||
colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866
|
||||
colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079
|
||||
colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709
|
||||
colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181
|
||||
colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134
|
||||
@@ -1,5 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: hatchling 1.11.1
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
@@ -1,27 +0,0 @@
|
||||
Copyright (c) 2010 Jonathan Hartley
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holders, nor those of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,7 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
from .initialise import init, deinit, reinit, colorama_text, just_fix_windows_console
|
||||
from .ansi import Fore, Back, Style, Cursor
|
||||
from .ansitowin32 import AnsiToWin32
|
||||
|
||||
__version__ = '0.4.6'
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,102 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
'''
|
||||
This module generates ANSI character codes to printing colors to terminals.
|
||||
See: http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
'''
|
||||
|
||||
CSI = '\033['
|
||||
OSC = '\033]'
|
||||
BEL = '\a'
|
||||
|
||||
|
||||
def code_to_chars(code):
|
||||
return CSI + str(code) + 'm'
|
||||
|
||||
def set_title(title):
|
||||
return OSC + '2;' + title + BEL
|
||||
|
||||
def clear_screen(mode=2):
|
||||
return CSI + str(mode) + 'J'
|
||||
|
||||
def clear_line(mode=2):
|
||||
return CSI + str(mode) + 'K'
|
||||
|
||||
|
||||
class AnsiCodes(object):
|
||||
def __init__(self):
|
||||
# the subclasses declare class attributes which are numbers.
|
||||
# Upon instantiation we define instance attributes, which are the same
|
||||
# as the class attributes but wrapped with the ANSI escape sequence
|
||||
for name in dir(self):
|
||||
if not name.startswith('_'):
|
||||
value = getattr(self, name)
|
||||
setattr(self, name, code_to_chars(value))
|
||||
|
||||
|
||||
class AnsiCursor(object):
|
||||
def UP(self, n=1):
|
||||
return CSI + str(n) + 'A'
|
||||
def DOWN(self, n=1):
|
||||
return CSI + str(n) + 'B'
|
||||
def FORWARD(self, n=1):
|
||||
return CSI + str(n) + 'C'
|
||||
def BACK(self, n=1):
|
||||
return CSI + str(n) + 'D'
|
||||
def POS(self, x=1, y=1):
|
||||
return CSI + str(y) + ';' + str(x) + 'H'
|
||||
|
||||
|
||||
class AnsiFore(AnsiCodes):
|
||||
BLACK = 30
|
||||
RED = 31
|
||||
GREEN = 32
|
||||
YELLOW = 33
|
||||
BLUE = 34
|
||||
MAGENTA = 35
|
||||
CYAN = 36
|
||||
WHITE = 37
|
||||
RESET = 39
|
||||
|
||||
# These are fairly well supported, but not part of the standard.
|
||||
LIGHTBLACK_EX = 90
|
||||
LIGHTRED_EX = 91
|
||||
LIGHTGREEN_EX = 92
|
||||
LIGHTYELLOW_EX = 93
|
||||
LIGHTBLUE_EX = 94
|
||||
LIGHTMAGENTA_EX = 95
|
||||
LIGHTCYAN_EX = 96
|
||||
LIGHTWHITE_EX = 97
|
||||
|
||||
|
||||
class AnsiBack(AnsiCodes):
|
||||
BLACK = 40
|
||||
RED = 41
|
||||
GREEN = 42
|
||||
YELLOW = 43
|
||||
BLUE = 44
|
||||
MAGENTA = 45
|
||||
CYAN = 46
|
||||
WHITE = 47
|
||||
RESET = 49
|
||||
|
||||
# These are fairly well supported, but not part of the standard.
|
||||
LIGHTBLACK_EX = 100
|
||||
LIGHTRED_EX = 101
|
||||
LIGHTGREEN_EX = 102
|
||||
LIGHTYELLOW_EX = 103
|
||||
LIGHTBLUE_EX = 104
|
||||
LIGHTMAGENTA_EX = 105
|
||||
LIGHTCYAN_EX = 106
|
||||
LIGHTWHITE_EX = 107
|
||||
|
||||
|
||||
class AnsiStyle(AnsiCodes):
|
||||
BRIGHT = 1
|
||||
DIM = 2
|
||||
NORMAL = 22
|
||||
RESET_ALL = 0
|
||||
|
||||
Fore = AnsiFore()
|
||||
Back = AnsiBack()
|
||||
Style = AnsiStyle()
|
||||
Cursor = AnsiCursor()
|
||||
@@ -1,277 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
|
||||
from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL
|
||||
from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle
|
||||
from .win32 import windll, winapi_test
|
||||
|
||||
|
||||
winterm = None
|
||||
if windll is not None:
|
||||
winterm = WinTerm()
|
||||
|
||||
|
||||
class StreamWrapper(object):
|
||||
'''
|
||||
Wraps a stream (such as stdout), acting as a transparent proxy for all
|
||||
attribute access apart from method 'write()', which is delegated to our
|
||||
Converter instance.
|
||||
'''
|
||||
def __init__(self, wrapped, converter):
|
||||
# double-underscore everything to prevent clashes with names of
|
||||
# attributes on the wrapped stream object.
|
||||
self.__wrapped = wrapped
|
||||
self.__convertor = converter
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.__wrapped, name)
|
||||
|
||||
def __enter__(self, *args, **kwargs):
|
||||
# special method lookup bypasses __getattr__/__getattribute__, see
|
||||
# https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit
|
||||
# thus, contextlib magic methods are not proxied via __getattr__
|
||||
return self.__wrapped.__enter__(*args, **kwargs)
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
return self.__wrapped.__exit__(*args, **kwargs)
|
||||
|
||||
def __setstate__(self, state):
|
||||
self.__dict__ = state
|
||||
|
||||
def __getstate__(self):
|
||||
return self.__dict__
|
||||
|
||||
def write(self, text):
|
||||
self.__convertor.write(text)
|
||||
|
||||
def isatty(self):
|
||||
stream = self.__wrapped
|
||||
if 'PYCHARM_HOSTED' in os.environ:
|
||||
if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__):
|
||||
return True
|
||||
try:
|
||||
stream_isatty = stream.isatty
|
||||
except AttributeError:
|
||||
return False
|
||||
else:
|
||||
return stream_isatty()
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
stream = self.__wrapped
|
||||
try:
|
||||
return stream.closed
|
||||
# AttributeError in the case that the stream doesn't support being closed
|
||||
# ValueError for the case that the stream has already been detached when atexit runs
|
||||
except (AttributeError, ValueError):
|
||||
return True
|
||||
|
||||
|
||||
class AnsiToWin32(object):
|
||||
'''
|
||||
Implements a 'write()' method which, on Windows, will strip ANSI character
|
||||
sequences from the text, and if outputting to a tty, will convert them into
|
||||
win32 function calls.
|
||||
'''
|
||||
ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer
|
||||
ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command
|
||||
|
||||
def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
|
||||
# The wrapped stream (normally sys.stdout or sys.stderr)
|
||||
self.wrapped = wrapped
|
||||
|
||||
# should we reset colors to defaults after every .write()
|
||||
self.autoreset = autoreset
|
||||
|
||||
# create the proxy wrapping our output stream
|
||||
self.stream = StreamWrapper(wrapped, self)
|
||||
|
||||
on_windows = os.name == 'nt'
|
||||
# We test if the WinAPI works, because even if we are on Windows
|
||||
# we may be using a terminal that doesn't support the WinAPI
|
||||
# (e.g. Cygwin Terminal). In this case it's up to the terminal
|
||||
# to support the ANSI codes.
|
||||
conversion_supported = on_windows and winapi_test()
|
||||
try:
|
||||
fd = wrapped.fileno()
|
||||
except Exception:
|
||||
fd = -1
|
||||
system_has_native_ansi = not on_windows or enable_vt_processing(fd)
|
||||
have_tty = not self.stream.closed and self.stream.isatty()
|
||||
need_conversion = conversion_supported and not system_has_native_ansi
|
||||
|
||||
# should we strip ANSI sequences from our output?
|
||||
if strip is None:
|
||||
strip = need_conversion or not have_tty
|
||||
self.strip = strip
|
||||
|
||||
# should we should convert ANSI sequences into win32 calls?
|
||||
if convert is None:
|
||||
convert = need_conversion and have_tty
|
||||
self.convert = convert
|
||||
|
||||
# dict of ansi codes to win32 functions and parameters
|
||||
self.win32_calls = self.get_win32_calls()
|
||||
|
||||
# are we wrapping stderr?
|
||||
self.on_stderr = self.wrapped is sys.stderr
|
||||
|
||||
def should_wrap(self):
|
||||
'''
|
||||
True if this class is actually needed. If false, then the output
|
||||
stream will not be affected, nor will win32 calls be issued, so
|
||||
wrapping stdout is not actually required. This will generally be
|
||||
False on non-Windows platforms, unless optional functionality like
|
||||
autoreset has been requested using kwargs to init()
|
||||
'''
|
||||
return self.convert or self.strip or self.autoreset
|
||||
|
||||
def get_win32_calls(self):
|
||||
if self.convert and winterm:
|
||||
return {
|
||||
AnsiStyle.RESET_ALL: (winterm.reset_all, ),
|
||||
AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
|
||||
AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
|
||||
AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
|
||||
AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
|
||||
AnsiFore.RED: (winterm.fore, WinColor.RED),
|
||||
AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
|
||||
AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
|
||||
AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
|
||||
AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
|
||||
AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
|
||||
AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
|
||||
AnsiFore.RESET: (winterm.fore, ),
|
||||
AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
|
||||
AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
|
||||
AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
|
||||
AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
|
||||
AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
|
||||
AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
|
||||
AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
|
||||
AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
|
||||
AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
|
||||
AnsiBack.RED: (winterm.back, WinColor.RED),
|
||||
AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
|
||||
AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
|
||||
AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
|
||||
AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
|
||||
AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
|
||||
AnsiBack.WHITE: (winterm.back, WinColor.GREY),
|
||||
AnsiBack.RESET: (winterm.back, ),
|
||||
AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
|
||||
AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
|
||||
AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
|
||||
AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
|
||||
AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
|
||||
AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
|
||||
AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
|
||||
AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
|
||||
}
|
||||
return dict()
|
||||
|
||||
def write(self, text):
|
||||
if self.strip or self.convert:
|
||||
self.write_and_convert(text)
|
||||
else:
|
||||
self.wrapped.write(text)
|
||||
self.wrapped.flush()
|
||||
if self.autoreset:
|
||||
self.reset_all()
|
||||
|
||||
|
||||
def reset_all(self):
|
||||
if self.convert:
|
||||
self.call_win32('m', (0,))
|
||||
elif not self.strip and not self.stream.closed:
|
||||
self.wrapped.write(Style.RESET_ALL)
|
||||
|
||||
|
||||
def write_and_convert(self, text):
|
||||
'''
|
||||
Write the given text to our wrapped stream, stripping any ANSI
|
||||
sequences from the text, and optionally converting them into win32
|
||||
calls.
|
||||
'''
|
||||
cursor = 0
|
||||
text = self.convert_osc(text)
|
||||
for match in self.ANSI_CSI_RE.finditer(text):
|
||||
start, end = match.span()
|
||||
self.write_plain_text(text, cursor, start)
|
||||
self.convert_ansi(*match.groups())
|
||||
cursor = end
|
||||
self.write_plain_text(text, cursor, len(text))
|
||||
|
||||
|
||||
def write_plain_text(self, text, start, end):
|
||||
if start < end:
|
||||
self.wrapped.write(text[start:end])
|
||||
self.wrapped.flush()
|
||||
|
||||
|
||||
def convert_ansi(self, paramstring, command):
|
||||
if self.convert:
|
||||
params = self.extract_params(command, paramstring)
|
||||
self.call_win32(command, params)
|
||||
|
||||
|
||||
def extract_params(self, command, paramstring):
|
||||
if command in 'Hf':
|
||||
params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
|
||||
while len(params) < 2:
|
||||
# defaults:
|
||||
params = params + (1,)
|
||||
else:
|
||||
params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
|
||||
if len(params) == 0:
|
||||
# defaults:
|
||||
if command in 'JKm':
|
||||
params = (0,)
|
||||
elif command in 'ABCD':
|
||||
params = (1,)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def call_win32(self, command, params):
|
||||
if command == 'm':
|
||||
for param in params:
|
||||
if param in self.win32_calls:
|
||||
func_args = self.win32_calls[param]
|
||||
func = func_args[0]
|
||||
args = func_args[1:]
|
||||
kwargs = dict(on_stderr=self.on_stderr)
|
||||
func(*args, **kwargs)
|
||||
elif command in 'J':
|
||||
winterm.erase_screen(params[0], on_stderr=self.on_stderr)
|
||||
elif command in 'K':
|
||||
winterm.erase_line(params[0], on_stderr=self.on_stderr)
|
||||
elif command in 'Hf': # cursor position - absolute
|
||||
winterm.set_cursor_position(params, on_stderr=self.on_stderr)
|
||||
elif command in 'ABCD': # cursor position - relative
|
||||
n = params[0]
|
||||
# A - up, B - down, C - forward, D - back
|
||||
x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
|
||||
winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)
|
||||
|
||||
|
||||
def convert_osc(self, text):
|
||||
for match in self.ANSI_OSC_RE.finditer(text):
|
||||
start, end = match.span()
|
||||
text = text[:start] + text[end:]
|
||||
paramstring, command = match.groups()
|
||||
if command == BEL:
|
||||
if paramstring.count(";") == 1:
|
||||
params = paramstring.split(";")
|
||||
# 0 - change title and icon (we will only change title)
|
||||
# 1 - change icon (we don't support this)
|
||||
# 2 - change title
|
||||
if params[0] in '02':
|
||||
winterm.set_title(params[1])
|
||||
return text
|
||||
|
||||
|
||||
def flush(self):
|
||||
self.wrapped.flush()
|
||||
@@ -1,121 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import atexit
|
||||
import contextlib
|
||||
import sys
|
||||
|
||||
from .ansitowin32 import AnsiToWin32
|
||||
|
||||
|
||||
def _wipe_internal_state_for_tests():
|
||||
global orig_stdout, orig_stderr
|
||||
orig_stdout = None
|
||||
orig_stderr = None
|
||||
|
||||
global wrapped_stdout, wrapped_stderr
|
||||
wrapped_stdout = None
|
||||
wrapped_stderr = None
|
||||
|
||||
global atexit_done
|
||||
atexit_done = False
|
||||
|
||||
global fixed_windows_console
|
||||
fixed_windows_console = False
|
||||
|
||||
try:
|
||||
# no-op if it wasn't registered
|
||||
atexit.unregister(reset_all)
|
||||
except AttributeError:
|
||||
# python 2: no atexit.unregister. Oh well, we did our best.
|
||||
pass
|
||||
|
||||
|
||||
def reset_all():
|
||||
if AnsiToWin32 is not None: # Issue #74: objects might become None at exit
|
||||
AnsiToWin32(orig_stdout).reset_all()
|
||||
|
||||
|
||||
def init(autoreset=False, convert=None, strip=None, wrap=True):
|
||||
|
||||
if not wrap and any([autoreset, convert, strip]):
|
||||
raise ValueError('wrap=False conflicts with any other arg=True')
|
||||
|
||||
global wrapped_stdout, wrapped_stderr
|
||||
global orig_stdout, orig_stderr
|
||||
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
|
||||
if sys.stdout is None:
|
||||
wrapped_stdout = None
|
||||
else:
|
||||
sys.stdout = wrapped_stdout = \
|
||||
wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
|
||||
if sys.stderr is None:
|
||||
wrapped_stderr = None
|
||||
else:
|
||||
sys.stderr = wrapped_stderr = \
|
||||
wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
|
||||
|
||||
global atexit_done
|
||||
if not atexit_done:
|
||||
atexit.register(reset_all)
|
||||
atexit_done = True
|
||||
|
||||
|
||||
def deinit():
|
||||
if orig_stdout is not None:
|
||||
sys.stdout = orig_stdout
|
||||
if orig_stderr is not None:
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
|
||||
def just_fix_windows_console():
|
||||
global fixed_windows_console
|
||||
|
||||
if sys.platform != "win32":
|
||||
return
|
||||
if fixed_windows_console:
|
||||
return
|
||||
if wrapped_stdout is not None or wrapped_stderr is not None:
|
||||
# Someone already ran init() and it did stuff, so we won't second-guess them
|
||||
return
|
||||
|
||||
# On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the
|
||||
# native ANSI support in the console as a side-effect. We only need to actually
|
||||
# replace sys.stdout/stderr if we're in the old-style conversion mode.
|
||||
new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False)
|
||||
if new_stdout.convert:
|
||||
sys.stdout = new_stdout
|
||||
new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False)
|
||||
if new_stderr.convert:
|
||||
sys.stderr = new_stderr
|
||||
|
||||
fixed_windows_console = True
|
||||
|
||||
@contextlib.contextmanager
|
||||
def colorama_text(*args, **kwargs):
|
||||
init(*args, **kwargs)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
deinit()
|
||||
|
||||
|
||||
def reinit():
|
||||
if wrapped_stdout is not None:
|
||||
sys.stdout = wrapped_stdout
|
||||
if wrapped_stderr is not None:
|
||||
sys.stderr = wrapped_stderr
|
||||
|
||||
|
||||
def wrap_stream(stream, convert, strip, autoreset, wrap):
|
||||
if wrap:
|
||||
wrapper = AnsiToWin32(stream,
|
||||
convert=convert, strip=strip, autoreset=autoreset)
|
||||
if wrapper.should_wrap():
|
||||
stream = wrapper.stream
|
||||
return stream
|
||||
|
||||
|
||||
# Use this for initial setup as well, to reduce code duplication
|
||||
_wipe_internal_state_for_tests()
|
||||
@@ -1 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,76 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main
|
||||
|
||||
from ..ansi import Back, Fore, Style
|
||||
from ..ansitowin32 import AnsiToWin32
|
||||
|
||||
stdout_orig = sys.stdout
|
||||
stderr_orig = sys.stderr
|
||||
|
||||
|
||||
class AnsiTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# sanity check: stdout should be a file or StringIO object.
|
||||
# It will only be AnsiToWin32 if init() has previously wrapped it
|
||||
self.assertNotEqual(type(sys.stdout), AnsiToWin32)
|
||||
self.assertNotEqual(type(sys.stderr), AnsiToWin32)
|
||||
|
||||
def tearDown(self):
|
||||
sys.stdout = stdout_orig
|
||||
sys.stderr = stderr_orig
|
||||
|
||||
|
||||
def testForeAttributes(self):
|
||||
self.assertEqual(Fore.BLACK, '\033[30m')
|
||||
self.assertEqual(Fore.RED, '\033[31m')
|
||||
self.assertEqual(Fore.GREEN, '\033[32m')
|
||||
self.assertEqual(Fore.YELLOW, '\033[33m')
|
||||
self.assertEqual(Fore.BLUE, '\033[34m')
|
||||
self.assertEqual(Fore.MAGENTA, '\033[35m')
|
||||
self.assertEqual(Fore.CYAN, '\033[36m')
|
||||
self.assertEqual(Fore.WHITE, '\033[37m')
|
||||
self.assertEqual(Fore.RESET, '\033[39m')
|
||||
|
||||
# Check the light, extended versions.
|
||||
self.assertEqual(Fore.LIGHTBLACK_EX, '\033[90m')
|
||||
self.assertEqual(Fore.LIGHTRED_EX, '\033[91m')
|
||||
self.assertEqual(Fore.LIGHTGREEN_EX, '\033[92m')
|
||||
self.assertEqual(Fore.LIGHTYELLOW_EX, '\033[93m')
|
||||
self.assertEqual(Fore.LIGHTBLUE_EX, '\033[94m')
|
||||
self.assertEqual(Fore.LIGHTMAGENTA_EX, '\033[95m')
|
||||
self.assertEqual(Fore.LIGHTCYAN_EX, '\033[96m')
|
||||
self.assertEqual(Fore.LIGHTWHITE_EX, '\033[97m')
|
||||
|
||||
|
||||
def testBackAttributes(self):
|
||||
self.assertEqual(Back.BLACK, '\033[40m')
|
||||
self.assertEqual(Back.RED, '\033[41m')
|
||||
self.assertEqual(Back.GREEN, '\033[42m')
|
||||
self.assertEqual(Back.YELLOW, '\033[43m')
|
||||
self.assertEqual(Back.BLUE, '\033[44m')
|
||||
self.assertEqual(Back.MAGENTA, '\033[45m')
|
||||
self.assertEqual(Back.CYAN, '\033[46m')
|
||||
self.assertEqual(Back.WHITE, '\033[47m')
|
||||
self.assertEqual(Back.RESET, '\033[49m')
|
||||
|
||||
# Check the light, extended versions.
|
||||
self.assertEqual(Back.LIGHTBLACK_EX, '\033[100m')
|
||||
self.assertEqual(Back.LIGHTRED_EX, '\033[101m')
|
||||
self.assertEqual(Back.LIGHTGREEN_EX, '\033[102m')
|
||||
self.assertEqual(Back.LIGHTYELLOW_EX, '\033[103m')
|
||||
self.assertEqual(Back.LIGHTBLUE_EX, '\033[104m')
|
||||
self.assertEqual(Back.LIGHTMAGENTA_EX, '\033[105m')
|
||||
self.assertEqual(Back.LIGHTCYAN_EX, '\033[106m')
|
||||
self.assertEqual(Back.LIGHTWHITE_EX, '\033[107m')
|
||||
|
||||
|
||||
def testStyleAttributes(self):
|
||||
self.assertEqual(Style.DIM, '\033[2m')
|
||||
self.assertEqual(Style.NORMAL, '\033[22m')
|
||||
self.assertEqual(Style.BRIGHT, '\033[1m')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,294 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
from io import StringIO, TextIOWrapper
|
||||
from unittest import TestCase, main
|
||||
try:
|
||||
from contextlib import ExitStack
|
||||
except ImportError:
|
||||
# python 2
|
||||
from contextlib2 import ExitStack
|
||||
|
||||
try:
|
||||
from unittest.mock import MagicMock, Mock, patch
|
||||
except ImportError:
|
||||
from mock import MagicMock, Mock, patch
|
||||
|
||||
from ..ansitowin32 import AnsiToWin32, StreamWrapper
|
||||
from ..win32 import ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
from .utils import osname
|
||||
|
||||
|
||||
class StreamWrapperTest(TestCase):
|
||||
|
||||
def testIsAProxy(self):
|
||||
mockStream = Mock()
|
||||
wrapper = StreamWrapper(mockStream, None)
|
||||
self.assertTrue( wrapper.random_attr is mockStream.random_attr )
|
||||
|
||||
def testDelegatesWrite(self):
|
||||
mockStream = Mock()
|
||||
mockConverter = Mock()
|
||||
wrapper = StreamWrapper(mockStream, mockConverter)
|
||||
wrapper.write('hello')
|
||||
self.assertTrue(mockConverter.write.call_args, (('hello',), {}))
|
||||
|
||||
def testDelegatesContext(self):
|
||||
mockConverter = Mock()
|
||||
s = StringIO()
|
||||
with StreamWrapper(s, mockConverter) as fp:
|
||||
fp.write(u'hello')
|
||||
self.assertTrue(s.closed)
|
||||
|
||||
def testProxyNoContextManager(self):
|
||||
mockStream = MagicMock()
|
||||
mockStream.__enter__.side_effect = AttributeError()
|
||||
mockConverter = Mock()
|
||||
with self.assertRaises(AttributeError) as excinfo:
|
||||
with StreamWrapper(mockStream, mockConverter) as wrapper:
|
||||
wrapper.write('hello')
|
||||
|
||||
def test_closed_shouldnt_raise_on_closed_stream(self):
|
||||
stream = StringIO()
|
||||
stream.close()
|
||||
wrapper = StreamWrapper(stream, None)
|
||||
self.assertEqual(wrapper.closed, True)
|
||||
|
||||
def test_closed_shouldnt_raise_on_detached_stream(self):
|
||||
stream = TextIOWrapper(StringIO())
|
||||
stream.detach()
|
||||
wrapper = StreamWrapper(stream, None)
|
||||
self.assertEqual(wrapper.closed, True)
|
||||
|
||||
class AnsiToWin32Test(TestCase):
|
||||
|
||||
def testInit(self):
|
||||
mockStdout = Mock()
|
||||
auto = Mock()
|
||||
stream = AnsiToWin32(mockStdout, autoreset=auto)
|
||||
self.assertEqual(stream.wrapped, mockStdout)
|
||||
self.assertEqual(stream.autoreset, auto)
|
||||
|
||||
@patch('colorama.ansitowin32.winterm', None)
|
||||
@patch('colorama.ansitowin32.winapi_test', lambda *_: True)
|
||||
def testStripIsTrueOnWindows(self):
|
||||
with osname('nt'):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
self.assertTrue(stream.strip)
|
||||
|
||||
def testStripIsFalseOffWindows(self):
|
||||
with osname('posix'):
|
||||
mockStdout = Mock(closed=False)
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
self.assertFalse(stream.strip)
|
||||
|
||||
def testWriteStripsAnsi(self):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
stream.wrapped = Mock()
|
||||
stream.write_and_convert = Mock()
|
||||
stream.strip = True
|
||||
|
||||
stream.write('abc')
|
||||
|
||||
self.assertFalse(stream.wrapped.write.called)
|
||||
self.assertEqual(stream.write_and_convert.call_args, (('abc',), {}))
|
||||
|
||||
def testWriteDoesNotStripAnsi(self):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout)
|
||||
stream.wrapped = Mock()
|
||||
stream.write_and_convert = Mock()
|
||||
stream.strip = False
|
||||
stream.convert = False
|
||||
|
||||
stream.write('abc')
|
||||
|
||||
self.assertFalse(stream.write_and_convert.called)
|
||||
self.assertEqual(stream.wrapped.write.call_args, (('abc',), {}))
|
||||
|
||||
def assert_autoresets(self, convert, autoreset=True):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.convert = convert
|
||||
stream.reset_all = Mock()
|
||||
stream.autoreset = autoreset
|
||||
stream.winterm = Mock()
|
||||
|
||||
stream.write('abc')
|
||||
|
||||
self.assertEqual(stream.reset_all.called, autoreset)
|
||||
|
||||
def testWriteAutoresets(self):
|
||||
self.assert_autoresets(convert=True)
|
||||
self.assert_autoresets(convert=False)
|
||||
self.assert_autoresets(convert=True, autoreset=False)
|
||||
self.assert_autoresets(convert=False, autoreset=False)
|
||||
|
||||
def testWriteAndConvertWritesPlainText(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.write_and_convert( 'abc' )
|
||||
self.assertEqual( stream.wrapped.write.call_args, (('abc',), {}) )
|
||||
|
||||
def testWriteAndConvertStripsAllValidAnsi(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.call_win32 = Mock()
|
||||
data = [
|
||||
'abc\033[mdef',
|
||||
'abc\033[0mdef',
|
||||
'abc\033[2mdef',
|
||||
'abc\033[02mdef',
|
||||
'abc\033[002mdef',
|
||||
'abc\033[40mdef',
|
||||
'abc\033[040mdef',
|
||||
'abc\033[0;1mdef',
|
||||
'abc\033[40;50mdef',
|
||||
'abc\033[50;30;40mdef',
|
||||
'abc\033[Adef',
|
||||
'abc\033[0Gdef',
|
||||
'abc\033[1;20;128Hdef',
|
||||
]
|
||||
for datum in data:
|
||||
stream.wrapped.write.reset_mock()
|
||||
stream.write_and_convert( datum )
|
||||
self.assertEqual(
|
||||
[args[0] for args in stream.wrapped.write.call_args_list],
|
||||
[ ('abc',), ('def',) ]
|
||||
)
|
||||
|
||||
def testWriteAndConvertSkipsEmptySnippets(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.call_win32 = Mock()
|
||||
stream.write_and_convert( '\033[40m\033[41m' )
|
||||
self.assertFalse( stream.wrapped.write.called )
|
||||
|
||||
def testWriteAndConvertCallsWin32WithParamsAndCommand(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
stream.convert = True
|
||||
stream.call_win32 = Mock()
|
||||
stream.extract_params = Mock(return_value='params')
|
||||
data = {
|
||||
'abc\033[adef': ('a', 'params'),
|
||||
'abc\033[;;bdef': ('b', 'params'),
|
||||
'abc\033[0cdef': ('c', 'params'),
|
||||
'abc\033[;;0;;Gdef': ('G', 'params'),
|
||||
'abc\033[1;20;128Hdef': ('H', 'params'),
|
||||
}
|
||||
for datum, expected in data.items():
|
||||
stream.call_win32.reset_mock()
|
||||
stream.write_and_convert( datum )
|
||||
self.assertEqual( stream.call_win32.call_args[0], expected )
|
||||
|
||||
def test_reset_all_shouldnt_raise_on_closed_orig_stdout(self):
|
||||
stream = StringIO()
|
||||
converter = AnsiToWin32(stream)
|
||||
stream.close()
|
||||
|
||||
converter.reset_all()
|
||||
|
||||
def test_wrap_shouldnt_raise_on_closed_orig_stdout(self):
|
||||
stream = StringIO()
|
||||
stream.close()
|
||||
with \
|
||||
patch("colorama.ansitowin32.os.name", "nt"), \
|
||||
patch("colorama.ansitowin32.winapi_test", lambda: True):
|
||||
converter = AnsiToWin32(stream)
|
||||
self.assertTrue(converter.strip)
|
||||
self.assertFalse(converter.convert)
|
||||
|
||||
def test_wrap_shouldnt_raise_on_missing_closed_attr(self):
|
||||
with \
|
||||
patch("colorama.ansitowin32.os.name", "nt"), \
|
||||
patch("colorama.ansitowin32.winapi_test", lambda: True):
|
||||
converter = AnsiToWin32(object())
|
||||
self.assertTrue(converter.strip)
|
||||
self.assertFalse(converter.convert)
|
||||
|
||||
def testExtractParams(self):
|
||||
stream = AnsiToWin32(Mock())
|
||||
data = {
|
||||
'': (0,),
|
||||
';;': (0,),
|
||||
'2': (2,),
|
||||
';;002;;': (2,),
|
||||
'0;1': (0, 1),
|
||||
';;003;;456;;': (3, 456),
|
||||
'11;22;33;44;55': (11, 22, 33, 44, 55),
|
||||
}
|
||||
for datum, expected in data.items():
|
||||
self.assertEqual(stream.extract_params('m', datum), expected)
|
||||
|
||||
def testCallWin32UsesLookup(self):
|
||||
listener = Mock()
|
||||
stream = AnsiToWin32(listener)
|
||||
stream.win32_calls = {
|
||||
1: (lambda *_, **__: listener(11),),
|
||||
2: (lambda *_, **__: listener(22),),
|
||||
3: (lambda *_, **__: listener(33),),
|
||||
}
|
||||
stream.call_win32('m', (3, 1, 99, 2))
|
||||
self.assertEqual(
|
||||
[a[0][0] for a in listener.call_args_list],
|
||||
[33, 11, 22] )
|
||||
|
||||
def test_osc_codes(self):
|
||||
mockStdout = Mock()
|
||||
stream = AnsiToWin32(mockStdout, convert=True)
|
||||
with patch('colorama.ansitowin32.winterm') as winterm:
|
||||
data = [
|
||||
'\033]0\x07', # missing arguments
|
||||
'\033]0;foo\x08', # wrong OSC command
|
||||
'\033]0;colorama_test_title\x07', # should work
|
||||
'\033]1;colorama_test_title\x07', # wrong set command
|
||||
'\033]2;colorama_test_title\x07', # should work
|
||||
'\033]' + ';' * 64 + '\x08', # see issue #247
|
||||
]
|
||||
for code in data:
|
||||
stream.write(code)
|
||||
self.assertEqual(winterm.set_title.call_count, 2)
|
||||
|
||||
def test_native_windows_ansi(self):
|
||||
with ExitStack() as stack:
|
||||
def p(a, b):
|
||||
stack.enter_context(patch(a, b, create=True))
|
||||
# Pretend to be on Windows
|
||||
p("colorama.ansitowin32.os.name", "nt")
|
||||
p("colorama.ansitowin32.winapi_test", lambda: True)
|
||||
p("colorama.win32.winapi_test", lambda: True)
|
||||
p("colorama.winterm.win32.windll", "non-None")
|
||||
p("colorama.winterm.get_osfhandle", lambda _: 1234)
|
||||
|
||||
# Pretend that our mock stream has native ANSI support
|
||||
p(
|
||||
"colorama.winterm.win32.GetConsoleMode",
|
||||
lambda _: ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
||||
)
|
||||
SetConsoleMode = Mock()
|
||||
p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode)
|
||||
|
||||
stdout = Mock()
|
||||
stdout.closed = False
|
||||
stdout.isatty.return_value = True
|
||||
stdout.fileno.return_value = 1
|
||||
|
||||
# Our fake console says it has native vt support, so AnsiToWin32 should
|
||||
# enable that support and do nothing else.
|
||||
stream = AnsiToWin32(stdout)
|
||||
SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
self.assertFalse(stream.strip)
|
||||
self.assertFalse(stream.convert)
|
||||
self.assertFalse(stream.should_wrap())
|
||||
|
||||
# Now let's pretend we're on an old Windows console, that doesn't have
|
||||
# native ANSI support.
|
||||
p("colorama.winterm.win32.GetConsoleMode", lambda _: 0)
|
||||
SetConsoleMode = Mock()
|
||||
p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode)
|
||||
|
||||
stream = AnsiToWin32(stdout)
|
||||
SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
self.assertTrue(stream.strip)
|
||||
self.assertTrue(stream.convert)
|
||||
self.assertTrue(stream.should_wrap())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,189 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main, skipUnless
|
||||
|
||||
try:
|
||||
from unittest.mock import patch, Mock
|
||||
except ImportError:
|
||||
from mock import patch, Mock
|
||||
|
||||
from ..ansitowin32 import StreamWrapper
|
||||
from ..initialise import init, just_fix_windows_console, _wipe_internal_state_for_tests
|
||||
from .utils import osname, replace_by
|
||||
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
|
||||
|
||||
class InitTest(TestCase):
|
||||
|
||||
@skipUnless(sys.stdout.isatty(), "sys.stdout is not a tty")
|
||||
def setUp(self):
|
||||
# sanity check
|
||||
self.assertNotWrapped()
|
||||
|
||||
def tearDown(self):
|
||||
_wipe_internal_state_for_tests()
|
||||
sys.stdout = orig_stdout
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
def assertWrapped(self):
|
||||
self.assertIsNot(sys.stdout, orig_stdout, 'stdout should be wrapped')
|
||||
self.assertIsNot(sys.stderr, orig_stderr, 'stderr should be wrapped')
|
||||
self.assertTrue(isinstance(sys.stdout, StreamWrapper),
|
||||
'bad stdout wrapper')
|
||||
self.assertTrue(isinstance(sys.stderr, StreamWrapper),
|
||||
'bad stderr wrapper')
|
||||
|
||||
def assertNotWrapped(self):
|
||||
self.assertIs(sys.stdout, orig_stdout, 'stdout should not be wrapped')
|
||||
self.assertIs(sys.stderr, orig_stderr, 'stderr should not be wrapped')
|
||||
|
||||
@patch('colorama.initialise.reset_all')
|
||||
@patch('colorama.ansitowin32.winapi_test', lambda *_: True)
|
||||
@patch('colorama.ansitowin32.enable_vt_processing', lambda *_: False)
|
||||
def testInitWrapsOnWindows(self, _):
|
||||
with osname("nt"):
|
||||
init()
|
||||
self.assertWrapped()
|
||||
|
||||
@patch('colorama.initialise.reset_all')
|
||||
@patch('colorama.ansitowin32.winapi_test', lambda *_: False)
|
||||
def testInitDoesntWrapOnEmulatedWindows(self, _):
|
||||
with osname("nt"):
|
||||
init()
|
||||
self.assertNotWrapped()
|
||||
|
||||
def testInitDoesntWrapOnNonWindows(self):
|
||||
with osname("posix"):
|
||||
init()
|
||||
self.assertNotWrapped()
|
||||
|
||||
def testInitDoesntWrapIfNone(self):
|
||||
with replace_by(None):
|
||||
init()
|
||||
# We can't use assertNotWrapped here because replace_by(None)
|
||||
# changes stdout/stderr already.
|
||||
self.assertIsNone(sys.stdout)
|
||||
self.assertIsNone(sys.stderr)
|
||||
|
||||
def testInitAutoresetOnWrapsOnAllPlatforms(self):
|
||||
with osname("posix"):
|
||||
init(autoreset=True)
|
||||
self.assertWrapped()
|
||||
|
||||
def testInitWrapOffDoesntWrapOnWindows(self):
|
||||
with osname("nt"):
|
||||
init(wrap=False)
|
||||
self.assertNotWrapped()
|
||||
|
||||
def testInitWrapOffIncompatibleWithAutoresetOn(self):
|
||||
self.assertRaises(ValueError, lambda: init(autoreset=True, wrap=False))
|
||||
|
||||
@patch('colorama.win32.SetConsoleTextAttribute')
|
||||
@patch('colorama.initialise.AnsiToWin32')
|
||||
def testAutoResetPassedOn(self, mockATW32, _):
|
||||
with osname("nt"):
|
||||
init(autoreset=True)
|
||||
self.assertEqual(len(mockATW32.call_args_list), 2)
|
||||
self.assertEqual(mockATW32.call_args_list[1][1]['autoreset'], True)
|
||||
self.assertEqual(mockATW32.call_args_list[0][1]['autoreset'], True)
|
||||
|
||||
@patch('colorama.initialise.AnsiToWin32')
|
||||
def testAutoResetChangeable(self, mockATW32):
|
||||
with osname("nt"):
|
||||
init()
|
||||
|
||||
init(autoreset=True)
|
||||
self.assertEqual(len(mockATW32.call_args_list), 4)
|
||||
self.assertEqual(mockATW32.call_args_list[2][1]['autoreset'], True)
|
||||
self.assertEqual(mockATW32.call_args_list[3][1]['autoreset'], True)
|
||||
|
||||
init()
|
||||
self.assertEqual(len(mockATW32.call_args_list), 6)
|
||||
self.assertEqual(
|
||||
mockATW32.call_args_list[4][1]['autoreset'], False)
|
||||
self.assertEqual(
|
||||
mockATW32.call_args_list[5][1]['autoreset'], False)
|
||||
|
||||
|
||||
@patch('colorama.initialise.atexit.register')
|
||||
def testAtexitRegisteredOnlyOnce(self, mockRegister):
|
||||
init()
|
||||
self.assertTrue(mockRegister.called)
|
||||
mockRegister.reset_mock()
|
||||
init()
|
||||
self.assertFalse(mockRegister.called)
|
||||
|
||||
|
||||
class JustFixWindowsConsoleTest(TestCase):
|
||||
def _reset(self):
|
||||
_wipe_internal_state_for_tests()
|
||||
sys.stdout = orig_stdout
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
def tearDown(self):
|
||||
self._reset()
|
||||
|
||||
@patch("colorama.ansitowin32.winapi_test", lambda: True)
|
||||
def testJustFixWindowsConsole(self):
|
||||
if sys.platform != "win32":
|
||||
# just_fix_windows_console should be a no-op
|
||||
just_fix_windows_console()
|
||||
self.assertIs(sys.stdout, orig_stdout)
|
||||
self.assertIs(sys.stderr, orig_stderr)
|
||||
else:
|
||||
def fake_std():
|
||||
# Emulate stdout=not a tty, stderr=tty
|
||||
# to check that we handle both cases correctly
|
||||
stdout = Mock()
|
||||
stdout.closed = False
|
||||
stdout.isatty.return_value = False
|
||||
stdout.fileno.return_value = 1
|
||||
sys.stdout = stdout
|
||||
|
||||
stderr = Mock()
|
||||
stderr.closed = False
|
||||
stderr.isatty.return_value = True
|
||||
stderr.fileno.return_value = 2
|
||||
sys.stderr = stderr
|
||||
|
||||
for native_ansi in [False, True]:
|
||||
with patch(
|
||||
'colorama.ansitowin32.enable_vt_processing',
|
||||
lambda *_: native_ansi
|
||||
):
|
||||
self._reset()
|
||||
fake_std()
|
||||
|
||||
# Regular single-call test
|
||||
prev_stdout = sys.stdout
|
||||
prev_stderr = sys.stderr
|
||||
just_fix_windows_console()
|
||||
self.assertIs(sys.stdout, prev_stdout)
|
||||
if native_ansi:
|
||||
self.assertIs(sys.stderr, prev_stderr)
|
||||
else:
|
||||
self.assertIsNot(sys.stderr, prev_stderr)
|
||||
|
||||
# second call without resetting is always a no-op
|
||||
prev_stdout = sys.stdout
|
||||
prev_stderr = sys.stderr
|
||||
just_fix_windows_console()
|
||||
self.assertIs(sys.stdout, prev_stdout)
|
||||
self.assertIs(sys.stderr, prev_stderr)
|
||||
|
||||
self._reset()
|
||||
fake_std()
|
||||
|
||||
# If init() runs first, just_fix_windows_console should be a no-op
|
||||
init()
|
||||
prev_stdout = sys.stdout
|
||||
prev_stderr = sys.stderr
|
||||
just_fix_windows_console()
|
||||
self.assertIs(prev_stdout, sys.stdout)
|
||||
self.assertIs(prev_stderr, sys.stderr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,57 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main
|
||||
|
||||
from ..ansitowin32 import StreamWrapper, AnsiToWin32
|
||||
from .utils import pycharm, replace_by, replace_original_by, StreamTTY, StreamNonTTY
|
||||
|
||||
|
||||
def is_a_tty(stream):
|
||||
return StreamWrapper(stream, None).isatty()
|
||||
|
||||
class IsattyTest(TestCase):
|
||||
|
||||
def test_TTY(self):
|
||||
tty = StreamTTY()
|
||||
self.assertTrue(is_a_tty(tty))
|
||||
with pycharm():
|
||||
self.assertTrue(is_a_tty(tty))
|
||||
|
||||
def test_nonTTY(self):
|
||||
non_tty = StreamNonTTY()
|
||||
self.assertFalse(is_a_tty(non_tty))
|
||||
with pycharm():
|
||||
self.assertFalse(is_a_tty(non_tty))
|
||||
|
||||
def test_withPycharm(self):
|
||||
with pycharm():
|
||||
self.assertTrue(is_a_tty(sys.stderr))
|
||||
self.assertTrue(is_a_tty(sys.stdout))
|
||||
|
||||
def test_withPycharmTTYOverride(self):
|
||||
tty = StreamTTY()
|
||||
with pycharm(), replace_by(tty):
|
||||
self.assertTrue(is_a_tty(tty))
|
||||
|
||||
def test_withPycharmNonTTYOverride(self):
|
||||
non_tty = StreamNonTTY()
|
||||
with pycharm(), replace_by(non_tty):
|
||||
self.assertFalse(is_a_tty(non_tty))
|
||||
|
||||
def test_withPycharmNoneOverride(self):
|
||||
with pycharm():
|
||||
with replace_by(None), replace_original_by(None):
|
||||
self.assertFalse(is_a_tty(None))
|
||||
self.assertFalse(is_a_tty(StreamNonTTY()))
|
||||
self.assertTrue(is_a_tty(StreamTTY()))
|
||||
|
||||
def test_withPycharmStreamWrapped(self):
|
||||
with pycharm():
|
||||
self.assertTrue(AnsiToWin32(StreamTTY()).stream.isatty())
|
||||
self.assertFalse(AnsiToWin32(StreamNonTTY()).stream.isatty())
|
||||
self.assertTrue(AnsiToWin32(sys.stdout).stream.isatty())
|
||||
self.assertTrue(AnsiToWin32(sys.stderr).stream.isatty())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,49 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
from contextlib import contextmanager
|
||||
from io import StringIO
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
class StreamTTY(StringIO):
|
||||
def isatty(self):
|
||||
return True
|
||||
|
||||
class StreamNonTTY(StringIO):
|
||||
def isatty(self):
|
||||
return False
|
||||
|
||||
@contextmanager
|
||||
def osname(name):
|
||||
orig = os.name
|
||||
os.name = name
|
||||
yield
|
||||
os.name = orig
|
||||
|
||||
@contextmanager
|
||||
def replace_by(stream):
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
sys.stdout = stream
|
||||
sys.stderr = stream
|
||||
yield
|
||||
sys.stdout = orig_stdout
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
@contextmanager
|
||||
def replace_original_by(stream):
|
||||
orig_stdout = sys.__stdout__
|
||||
orig_stderr = sys.__stderr__
|
||||
sys.__stdout__ = stream
|
||||
sys.__stderr__ = stream
|
||||
yield
|
||||
sys.__stdout__ = orig_stdout
|
||||
sys.__stderr__ = orig_stderr
|
||||
|
||||
@contextmanager
|
||||
def pycharm():
|
||||
os.environ["PYCHARM_HOSTED"] = "1"
|
||||
non_tty = StreamNonTTY()
|
||||
with replace_by(non_tty), replace_original_by(non_tty):
|
||||
yield
|
||||
del os.environ["PYCHARM_HOSTED"]
|
||||
@@ -1,131 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
import sys
|
||||
from unittest import TestCase, main, skipUnless
|
||||
|
||||
try:
|
||||
from unittest.mock import Mock, patch
|
||||
except ImportError:
|
||||
from mock import Mock, patch
|
||||
|
||||
from ..winterm import WinColor, WinStyle, WinTerm
|
||||
|
||||
|
||||
class WinTermTest(TestCase):
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testInit(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 7 + 6 * 16 + 8
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
self.assertEqual(term._fore, 7)
|
||||
self.assertEqual(term._back, 6)
|
||||
self.assertEqual(term._style, 8)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testGetAttrs(self):
|
||||
term = WinTerm()
|
||||
|
||||
term._fore = 0
|
||||
term._back = 0
|
||||
term._style = 0
|
||||
self.assertEqual(term.get_attrs(), 0)
|
||||
|
||||
term._fore = WinColor.YELLOW
|
||||
self.assertEqual(term.get_attrs(), WinColor.YELLOW)
|
||||
|
||||
term._back = WinColor.MAGENTA
|
||||
self.assertEqual(
|
||||
term.get_attrs(),
|
||||
WinColor.YELLOW + WinColor.MAGENTA * 16)
|
||||
|
||||
term._style = WinStyle.BRIGHT
|
||||
self.assertEqual(
|
||||
term.get_attrs(),
|
||||
WinColor.YELLOW + WinColor.MAGENTA * 16 + WinStyle.BRIGHT)
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testResetAll(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 1 + 2 * 16 + 8
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
|
||||
term.set_console = Mock()
|
||||
term._fore = -1
|
||||
term._back = -1
|
||||
term._style = -1
|
||||
|
||||
term.reset_all()
|
||||
|
||||
self.assertEqual(term._fore, 1)
|
||||
self.assertEqual(term._back, 2)
|
||||
self.assertEqual(term._style, 8)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testFore(self):
|
||||
term = WinTerm()
|
||||
term.set_console = Mock()
|
||||
term._fore = 0
|
||||
|
||||
term.fore(5)
|
||||
|
||||
self.assertEqual(term._fore, 5)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testBack(self):
|
||||
term = WinTerm()
|
||||
term.set_console = Mock()
|
||||
term._back = 0
|
||||
|
||||
term.back(5)
|
||||
|
||||
self.assertEqual(term._back, 5)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def testStyle(self):
|
||||
term = WinTerm()
|
||||
term.set_console = Mock()
|
||||
term._style = 0
|
||||
|
||||
term.style(22)
|
||||
|
||||
self.assertEqual(term._style, 22)
|
||||
self.assertEqual(term.set_console.called, True)
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testSetConsole(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 0
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
term.windll = Mock()
|
||||
|
||||
term.set_console()
|
||||
|
||||
self.assertEqual(
|
||||
mockWin32.SetConsoleTextAttribute.call_args,
|
||||
((mockWin32.STDOUT, term.get_attrs()), {})
|
||||
)
|
||||
|
||||
@patch('colorama.winterm.win32')
|
||||
def testSetConsoleOnStderr(self, mockWin32):
|
||||
mockAttr = Mock()
|
||||
mockAttr.wAttributes = 0
|
||||
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
||||
term = WinTerm()
|
||||
term.windll = Mock()
|
||||
|
||||
term.set_console(on_stderr=True)
|
||||
|
||||
self.assertEqual(
|
||||
mockWin32.SetConsoleTextAttribute.call_args,
|
||||
((mockWin32.STDERR, term.get_attrs()), {})
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,180 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
|
||||
# from winbase.h
|
||||
STDOUT = -11
|
||||
STDERR = -12
|
||||
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
|
||||
|
||||
try:
|
||||
import ctypes
|
||||
from ctypes import LibraryLoader
|
||||
windll = LibraryLoader(ctypes.WinDLL)
|
||||
from ctypes import wintypes
|
||||
except (AttributeError, ImportError):
|
||||
windll = None
|
||||
SetConsoleTextAttribute = lambda *_: None
|
||||
winapi_test = lambda *_: None
|
||||
else:
|
||||
from ctypes import byref, Structure, c_char, POINTER
|
||||
|
||||
COORD = wintypes._COORD
|
||||
|
||||
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
|
||||
"""struct in wincon.h."""
|
||||
_fields_ = [
|
||||
("dwSize", COORD),
|
||||
("dwCursorPosition", COORD),
|
||||
("wAttributes", wintypes.WORD),
|
||||
("srWindow", wintypes.SMALL_RECT),
|
||||
("dwMaximumWindowSize", COORD),
|
||||
]
|
||||
def __str__(self):
|
||||
return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
|
||||
self.dwSize.Y, self.dwSize.X
|
||||
, self.dwCursorPosition.Y, self.dwCursorPosition.X
|
||||
, self.wAttributes
|
||||
, self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
|
||||
, self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
|
||||
)
|
||||
|
||||
_GetStdHandle = windll.kernel32.GetStdHandle
|
||||
_GetStdHandle.argtypes = [
|
||||
wintypes.DWORD,
|
||||
]
|
||||
_GetStdHandle.restype = wintypes.HANDLE
|
||||
|
||||
_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
|
||||
_GetConsoleScreenBufferInfo.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
POINTER(CONSOLE_SCREEN_BUFFER_INFO),
|
||||
]
|
||||
_GetConsoleScreenBufferInfo.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
|
||||
_SetConsoleTextAttribute.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.WORD,
|
||||
]
|
||||
_SetConsoleTextAttribute.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
|
||||
_SetConsoleCursorPosition.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
COORD,
|
||||
]
|
||||
_SetConsoleCursorPosition.restype = wintypes.BOOL
|
||||
|
||||
_FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA
|
||||
_FillConsoleOutputCharacterA.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
c_char,
|
||||
wintypes.DWORD,
|
||||
COORD,
|
||||
POINTER(wintypes.DWORD),
|
||||
]
|
||||
_FillConsoleOutputCharacterA.restype = wintypes.BOOL
|
||||
|
||||
_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
|
||||
_FillConsoleOutputAttribute.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.WORD,
|
||||
wintypes.DWORD,
|
||||
COORD,
|
||||
POINTER(wintypes.DWORD),
|
||||
]
|
||||
_FillConsoleOutputAttribute.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleTitleW = windll.kernel32.SetConsoleTitleW
|
||||
_SetConsoleTitleW.argtypes = [
|
||||
wintypes.LPCWSTR
|
||||
]
|
||||
_SetConsoleTitleW.restype = wintypes.BOOL
|
||||
|
||||
_GetConsoleMode = windll.kernel32.GetConsoleMode
|
||||
_GetConsoleMode.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
POINTER(wintypes.DWORD)
|
||||
]
|
||||
_GetConsoleMode.restype = wintypes.BOOL
|
||||
|
||||
_SetConsoleMode = windll.kernel32.SetConsoleMode
|
||||
_SetConsoleMode.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.DWORD
|
||||
]
|
||||
_SetConsoleMode.restype = wintypes.BOOL
|
||||
|
||||
def _winapi_test(handle):
|
||||
csbi = CONSOLE_SCREEN_BUFFER_INFO()
|
||||
success = _GetConsoleScreenBufferInfo(
|
||||
handle, byref(csbi))
|
||||
return bool(success)
|
||||
|
||||
def winapi_test():
|
||||
return any(_winapi_test(h) for h in
|
||||
(_GetStdHandle(STDOUT), _GetStdHandle(STDERR)))
|
||||
|
||||
def GetConsoleScreenBufferInfo(stream_id=STDOUT):
|
||||
handle = _GetStdHandle(stream_id)
|
||||
csbi = CONSOLE_SCREEN_BUFFER_INFO()
|
||||
success = _GetConsoleScreenBufferInfo(
|
||||
handle, byref(csbi))
|
||||
return csbi
|
||||
|
||||
def SetConsoleTextAttribute(stream_id, attrs):
|
||||
handle = _GetStdHandle(stream_id)
|
||||
return _SetConsoleTextAttribute(handle, attrs)
|
||||
|
||||
def SetConsoleCursorPosition(stream_id, position, adjust=True):
|
||||
position = COORD(*position)
|
||||
# If the position is out of range, do nothing.
|
||||
if position.Y <= 0 or position.X <= 0:
|
||||
return
|
||||
# Adjust for Windows' SetConsoleCursorPosition:
|
||||
# 1. being 0-based, while ANSI is 1-based.
|
||||
# 2. expecting (x,y), while ANSI uses (y,x).
|
||||
adjusted_position = COORD(position.Y - 1, position.X - 1)
|
||||
if adjust:
|
||||
# Adjust for viewport's scroll position
|
||||
sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
|
||||
adjusted_position.Y += sr.Top
|
||||
adjusted_position.X += sr.Left
|
||||
# Resume normal processing
|
||||
handle = _GetStdHandle(stream_id)
|
||||
return _SetConsoleCursorPosition(handle, adjusted_position)
|
||||
|
||||
def FillConsoleOutputCharacter(stream_id, char, length, start):
|
||||
handle = _GetStdHandle(stream_id)
|
||||
char = c_char(char.encode())
|
||||
length = wintypes.DWORD(length)
|
||||
num_written = wintypes.DWORD(0)
|
||||
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
||||
success = _FillConsoleOutputCharacterA(
|
||||
handle, char, length, start, byref(num_written))
|
||||
return num_written.value
|
||||
|
||||
def FillConsoleOutputAttribute(stream_id, attr, length, start):
|
||||
''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
|
||||
handle = _GetStdHandle(stream_id)
|
||||
attribute = wintypes.WORD(attr)
|
||||
length = wintypes.DWORD(length)
|
||||
num_written = wintypes.DWORD(0)
|
||||
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
||||
return _FillConsoleOutputAttribute(
|
||||
handle, attribute, length, start, byref(num_written))
|
||||
|
||||
def SetConsoleTitle(title):
|
||||
return _SetConsoleTitleW(title)
|
||||
|
||||
def GetConsoleMode(handle):
|
||||
mode = wintypes.DWORD()
|
||||
success = _GetConsoleMode(handle, byref(mode))
|
||||
if not success:
|
||||
raise ctypes.WinError()
|
||||
return mode.value
|
||||
|
||||
def SetConsoleMode(handle, mode):
|
||||
success = _SetConsoleMode(handle, mode)
|
||||
if not success:
|
||||
raise ctypes.WinError()
|
||||
@@ -1,195 +0,0 @@
|
||||
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
||||
try:
|
||||
from msvcrt import get_osfhandle
|
||||
except ImportError:
|
||||
def get_osfhandle(_):
|
||||
raise OSError("This isn't windows!")
|
||||
|
||||
|
||||
from . import win32
|
||||
|
||||
# from wincon.h
|
||||
class WinColor(object):
|
||||
BLACK = 0
|
||||
BLUE = 1
|
||||
GREEN = 2
|
||||
CYAN = 3
|
||||
RED = 4
|
||||
MAGENTA = 5
|
||||
YELLOW = 6
|
||||
GREY = 7
|
||||
|
||||
# from wincon.h
|
||||
class WinStyle(object):
|
||||
NORMAL = 0x00 # dim text, dim background
|
||||
BRIGHT = 0x08 # bright text, dim background
|
||||
BRIGHT_BACKGROUND = 0x80 # dim text, bright background
|
||||
|
||||
class WinTerm(object):
|
||||
|
||||
def __init__(self):
|
||||
self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
|
||||
self.set_attrs(self._default)
|
||||
self._default_fore = self._fore
|
||||
self._default_back = self._back
|
||||
self._default_style = self._style
|
||||
# In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style.
|
||||
# So that LIGHT_EX colors and BRIGHT style do not clobber each other,
|
||||
# we track them separately, since LIGHT_EX is overwritten by Fore/Back
|
||||
# and BRIGHT is overwritten by Style codes.
|
||||
self._light = 0
|
||||
|
||||
def get_attrs(self):
|
||||
return self._fore + self._back * 16 + (self._style | self._light)
|
||||
|
||||
def set_attrs(self, value):
|
||||
self._fore = value & 7
|
||||
self._back = (value >> 4) & 7
|
||||
self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND)
|
||||
|
||||
def reset_all(self, on_stderr=None):
|
||||
self.set_attrs(self._default)
|
||||
self.set_console(attrs=self._default)
|
||||
self._light = 0
|
||||
|
||||
def fore(self, fore=None, light=False, on_stderr=False):
|
||||
if fore is None:
|
||||
fore = self._default_fore
|
||||
self._fore = fore
|
||||
# Emulate LIGHT_EX with BRIGHT Style
|
||||
if light:
|
||||
self._light |= WinStyle.BRIGHT
|
||||
else:
|
||||
self._light &= ~WinStyle.BRIGHT
|
||||
self.set_console(on_stderr=on_stderr)
|
||||
|
||||
def back(self, back=None, light=False, on_stderr=False):
|
||||
if back is None:
|
||||
back = self._default_back
|
||||
self._back = back
|
||||
# Emulate LIGHT_EX with BRIGHT_BACKGROUND Style
|
||||
if light:
|
||||
self._light |= WinStyle.BRIGHT_BACKGROUND
|
||||
else:
|
||||
self._light &= ~WinStyle.BRIGHT_BACKGROUND
|
||||
self.set_console(on_stderr=on_stderr)
|
||||
|
||||
def style(self, style=None, on_stderr=False):
|
||||
if style is None:
|
||||
style = self._default_style
|
||||
self._style = style
|
||||
self.set_console(on_stderr=on_stderr)
|
||||
|
||||
def set_console(self, attrs=None, on_stderr=False):
|
||||
if attrs is None:
|
||||
attrs = self.get_attrs()
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
win32.SetConsoleTextAttribute(handle, attrs)
|
||||
|
||||
def get_position(self, handle):
|
||||
position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition
|
||||
# Because Windows coordinates are 0-based,
|
||||
# and win32.SetConsoleCursorPosition expects 1-based.
|
||||
position.X += 1
|
||||
position.Y += 1
|
||||
return position
|
||||
|
||||
def set_cursor_position(self, position=None, on_stderr=False):
|
||||
if position is None:
|
||||
# I'm not currently tracking the position, so there is no default.
|
||||
# position = self.get_position()
|
||||
return
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
win32.SetConsoleCursorPosition(handle, position)
|
||||
|
||||
def cursor_adjust(self, x, y, on_stderr=False):
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
position = self.get_position(handle)
|
||||
adjusted_position = (position.Y + y, position.X + x)
|
||||
win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False)
|
||||
|
||||
def erase_screen(self, mode=0, on_stderr=False):
|
||||
# 0 should clear from the cursor to the end of the screen.
|
||||
# 1 should clear from the cursor to the beginning of the screen.
|
||||
# 2 should clear the entire screen, and move cursor to (1,1)
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
csbi = win32.GetConsoleScreenBufferInfo(handle)
|
||||
# get the number of character cells in the current buffer
|
||||
cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y
|
||||
# get number of character cells before current cursor position
|
||||
cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X
|
||||
if mode == 0:
|
||||
from_coord = csbi.dwCursorPosition
|
||||
cells_to_erase = cells_in_screen - cells_before_cursor
|
||||
elif mode == 1:
|
||||
from_coord = win32.COORD(0, 0)
|
||||
cells_to_erase = cells_before_cursor
|
||||
elif mode == 2:
|
||||
from_coord = win32.COORD(0, 0)
|
||||
cells_to_erase = cells_in_screen
|
||||
else:
|
||||
# invalid mode
|
||||
return
|
||||
# fill the entire screen with blanks
|
||||
win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
|
||||
# now set the buffer's attributes accordingly
|
||||
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
|
||||
if mode == 2:
|
||||
# put the cursor where needed
|
||||
win32.SetConsoleCursorPosition(handle, (1, 1))
|
||||
|
||||
def erase_line(self, mode=0, on_stderr=False):
|
||||
# 0 should clear from the cursor to the end of the line.
|
||||
# 1 should clear from the cursor to the beginning of the line.
|
||||
# 2 should clear the entire line.
|
||||
handle = win32.STDOUT
|
||||
if on_stderr:
|
||||
handle = win32.STDERR
|
||||
csbi = win32.GetConsoleScreenBufferInfo(handle)
|
||||
if mode == 0:
|
||||
from_coord = csbi.dwCursorPosition
|
||||
cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X
|
||||
elif mode == 1:
|
||||
from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
|
||||
cells_to_erase = csbi.dwCursorPosition.X
|
||||
elif mode == 2:
|
||||
from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
|
||||
cells_to_erase = csbi.dwSize.X
|
||||
else:
|
||||
# invalid mode
|
||||
return
|
||||
# fill the entire screen with blanks
|
||||
win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
|
||||
# now set the buffer's attributes accordingly
|
||||
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
|
||||
|
||||
def set_title(self, title):
|
||||
win32.SetConsoleTitle(title)
|
||||
|
||||
|
||||
def enable_vt_processing(fd):
|
||||
if win32.windll is None or not win32.winapi_test():
|
||||
return False
|
||||
|
||||
try:
|
||||
handle = get_osfhandle(fd)
|
||||
mode = win32.GetConsoleMode(handle)
|
||||
win32.SetConsoleMode(
|
||||
handle,
|
||||
mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
||||
)
|
||||
|
||||
mode = win32.GetConsoleMode(handle)
|
||||
if mode & win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING:
|
||||
return True
|
||||
# Can get TypeError in testsuite where 'fd' is a Mock()
|
||||
except (OSError, TypeError):
|
||||
return False
|
||||
@@ -1 +0,0 @@
|
||||
import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim();
|
||||
@@ -1,50 +0,0 @@
|
||||
wxWindows Library Licence, Version 3.1
|
||||
======================================
|
||||
|
||||
Copyright (c) 1998-2005 Julian Smart, Robert Roebling et al
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this licence document, but changing it is not allowed.
|
||||
|
||||
WXWINDOWS LIBRARY LICENCE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public Licence as published by
|
||||
the Free Software Foundation; either version 2 of the Licence, or (at your
|
||||
option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
||||
Licence for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public Licence
|
||||
along with this software, usually in a file named COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
EXCEPTION NOTICE
|
||||
|
||||
1. As a special exception, the copyright holders of this library give
|
||||
permission for additional uses of the text contained in this release of the
|
||||
library as licenced under the wxWindows Library Licence, applying either
|
||||
version 3.1 of the Licence, or (at your option) any later version of the
|
||||
Licence as published by the copyright holders of version 3.1 of the Licence
|
||||
document.
|
||||
|
||||
2. The exception is that you may use, copy, link, modify and distribute
|
||||
under your own terms, binary object code versions of works based on the
|
||||
Library.
|
||||
|
||||
3. If you copy code from files distributed under the terms of the GNU
|
||||
General Public Licence or the GNU Library General Public Licence into a
|
||||
copy of this library, as this licence permits, the exception does not apply
|
||||
to the code that you add in this way. To avoid misleading anyone as to the
|
||||
status of such modified files, you must delete this exception notice from
|
||||
such code and/or adjust the licensing conditions notice accordingly.
|
||||
|
||||
4. If you write modifications of your own for this library, it is your
|
||||
choice whether to permit this exception to apply to your modifications. If
|
||||
you do not wish that, you must delete the exception notice from such code
|
||||
and/or adjust the licensing conditions notice accordingly.
|
||||
@@ -1 +0,0 @@
|
||||
pip
|
||||
@@ -1,50 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: frida
|
||||
Version: 16.1.3
|
||||
Summary: Dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers
|
||||
Home-page: https://frida.re
|
||||
Author: Frida Developers
|
||||
Author-email: oleavr@frida.re
|
||||
License: wxWindows Library Licence, Version 3.1
|
||||
Keywords: frida debugger dynamic instrumentation inject javascript windows macos linux ios iphone ipad android qnx
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Environment :: MacOS X
|
||||
Classifier: Environment :: Win32 (MS Windows)
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Science/Research
|
||||
Classifier: License :: OSI Approved
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Operating System :: POSIX :: Linux
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: JavaScript
|
||||
Classifier: Topic :: Software Development :: Debuggers
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Python: >=3.7
|
||||
Description-Content-Type: text/markdown
|
||||
License-File: COPYING
|
||||
Requires-Dist: typing-extensions ; python_version < "3.11"
|
||||
|
||||
# frida-python
|
||||
|
||||
Python bindings for [Frida](https://frida.re).
|
||||
|
||||
# Some tips during development
|
||||
|
||||
To build and test your own wheel, do something along the following lines:
|
||||
|
||||
```
|
||||
set FRIDA_VERSION=16.0.1-dev.7 # from C:\src\frida\build\tmp-windows\frida-version.h
|
||||
set FRIDA_EXTENSION=C:\src\frida\build\frida-windows\x64-Release\lib\python3.10\site-packages\_frida.pyd
|
||||
cd C:\src\frida\frida-python\
|
||||
pip wheel .
|
||||
pip uninstall frida
|
||||
pip install frida-16.0.1.dev7-cp34-abi3-win_amd64.whl
|
||||
```
|
||||
@@ -1,15 +0,0 @@
|
||||
_frida.pyd,sha256=M5U10KNFg2wonZVvER6TBvI6Vz3Id9TkoLjfFeZLruU,70110208
|
||||
_frida/__init__.pyi,sha256=EpFYaHcVhC_i-s93-VMcsLiz49EXKIpnL7NMcD_LU8s,16686
|
||||
_frida/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
frida-16.1.3.dist-info/COPYING,sha256=gDuLWqQVEDAiGzw_caZF2mJBk4Qh5JkBREp55cynX6g,2466
|
||||
frida-16.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
frida-16.1.3.dist-info/METADATA,sha256=n8pZTLvsnYHHqQFHLzQVEDp3Ykz7Tt4_qDZ3o9GTYJU,2064
|
||||
frida-16.1.3.dist-info/RECORD,,
|
||||
frida-16.1.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
frida-16.1.3.dist-info/WHEEL,sha256=AF8zPkSkcAhmODpLt1et9zmyR4I9Cg-zXEqffJFVfzk,100
|
||||
frida-16.1.3.dist-info/top_level.txt,sha256=hIYINaco86aRnPRwHl5W92UgO9zQ4IeFLomjDZRKcHo,13
|
||||
frida/__init__.py,sha256=CF1g6gjGeLSTtq2N3sql4ydGqBIzrv1OcwlYVRYhgdw,4932
|
||||
frida/__pycache__/__init__.cpython-311.pyc,,
|
||||
frida/__pycache__/core.cpython-311.pyc,,
|
||||
frida/core.py,sha256=LkHIkibX3gn3K3Biq3oAZEsCAeN0V7-Xo3r47a-rNqM,50413
|
||||
frida/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
@@ -1,5 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.40.0)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp37-abi3-win_amd64
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
_frida
|
||||
frida
|
||||
@@ -1,172 +0,0 @@
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||
|
||||
try:
|
||||
import _frida
|
||||
except Exception as ex:
|
||||
print("")
|
||||
print("***")
|
||||
if str(ex).startswith("No module named "):
|
||||
print("Frida native extension not found")
|
||||
print("Please check your PYTHONPATH.")
|
||||
else:
|
||||
print(f"Failed to load the Frida native extension: {ex}")
|
||||
print("Please ensure that the extension was compiled correctly")
|
||||
print("***")
|
||||
print("")
|
||||
raise ex
|
||||
from . import core
|
||||
|
||||
__version__: str = _frida.__version__
|
||||
|
||||
get_device_manager = core.get_device_manager
|
||||
Relay = _frida.Relay
|
||||
PortalService = core.PortalService
|
||||
EndpointParameters = core.EndpointParameters
|
||||
Compiler = core.Compiler
|
||||
FileMonitor = _frida.FileMonitor
|
||||
Cancellable = core.Cancellable
|
||||
|
||||
ServerNotRunningError = _frida.ServerNotRunningError
|
||||
ExecutableNotFoundError = _frida.ExecutableNotFoundError
|
||||
ExecutableNotSupportedError = _frida.ExecutableNotSupportedError
|
||||
ProcessNotFoundError = _frida.ProcessNotFoundError
|
||||
ProcessNotRespondingError = _frida.ProcessNotRespondingError
|
||||
InvalidArgumentError = _frida.InvalidArgumentError
|
||||
InvalidOperationError = _frida.InvalidOperationError
|
||||
PermissionDeniedError = _frida.PermissionDeniedError
|
||||
AddressInUseError = _frida.AddressInUseError
|
||||
TimedOutError = _frida.TimedOutError
|
||||
NotSupportedError = _frida.NotSupportedError
|
||||
ProtocolError = _frida.ProtocolError
|
||||
TransportError = _frida.TransportError
|
||||
OperationCancelledError = _frida.OperationCancelledError
|
||||
|
||||
|
||||
def query_system_parameters() -> Dict[str, Any]:
|
||||
"""
|
||||
Returns a dictionary of information about the host system
|
||||
"""
|
||||
|
||||
return get_local_device().query_system_parameters()
|
||||
|
||||
|
||||
def spawn(
|
||||
program: Union[str, List[Union[str, bytes]], Tuple[Union[str, bytes]]],
|
||||
argv: Union[None, List[Union[str, bytes]], Tuple[Union[str, bytes]]] = None,
|
||||
envp: Optional[Dict[str, str]] = None,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
cwd: Optional[str] = None,
|
||||
stdio: Optional[str] = None,
|
||||
**kwargs: Any,
|
||||
) -> int:
|
||||
"""
|
||||
Spawn a process into an attachable state
|
||||
"""
|
||||
|
||||
return get_local_device().spawn(program=program, argv=argv, envp=envp, env=env, cwd=cwd, stdio=stdio, **kwargs)
|
||||
|
||||
|
||||
def resume(target: core.ProcessTarget) -> None:
|
||||
"""
|
||||
Resume a process from the attachable state
|
||||
:param target: the PID or name of the process
|
||||
"""
|
||||
|
||||
get_local_device().resume(target)
|
||||
|
||||
|
||||
def kill(target: core.ProcessTarget) -> None:
|
||||
"""
|
||||
Kill a process
|
||||
:param target: the PID or name of the process
|
||||
"""
|
||||
|
||||
get_local_device().kill(target)
|
||||
|
||||
|
||||
def attach(
|
||||
target: core.ProcessTarget, realm: Optional[str] = None, persist_timeout: Optional[int] = None
|
||||
) -> core.Session:
|
||||
"""
|
||||
Attach to a process
|
||||
:param target: the PID or name of the process
|
||||
"""
|
||||
|
||||
return get_local_device().attach(target, realm=realm, persist_timeout=persist_timeout)
|
||||
|
||||
|
||||
def inject_library_file(target: core.ProcessTarget, path: str, entrypoint: str, data: str) -> int:
|
||||
"""
|
||||
Inject a library file to a process.
|
||||
:param target: the PID or name of the process
|
||||
"""
|
||||
|
||||
return get_local_device().inject_library_file(target, path, entrypoint, data)
|
||||
|
||||
|
||||
def inject_library_blob(target: core.ProcessTarget, blob: bytes, entrypoint: str, data: str) -> int:
|
||||
"""
|
||||
Inject a library blob to a process
|
||||
:param target: the PID or name of the process
|
||||
"""
|
||||
|
||||
return get_local_device().inject_library_blob(target, blob, entrypoint, data)
|
||||
|
||||
|
||||
def get_local_device() -> core.Device:
|
||||
"""
|
||||
Get the local device
|
||||
"""
|
||||
|
||||
return get_device_manager().get_local_device()
|
||||
|
||||
|
||||
def get_remote_device() -> core.Device:
|
||||
"""
|
||||
Get the first remote device in the devices list
|
||||
"""
|
||||
|
||||
return get_device_manager().get_remote_device()
|
||||
|
||||
|
||||
def get_usb_device(timeout: int = 0) -> core.Device:
|
||||
"""
|
||||
Get the first device connected over USB in the devices list
|
||||
"""
|
||||
|
||||
return get_device_manager().get_usb_device(timeout)
|
||||
|
||||
|
||||
def get_device(id: Optional[str], timeout: int = 0) -> core.Device:
|
||||
"""
|
||||
Get a device by its id
|
||||
"""
|
||||
|
||||
return get_device_manager().get_device(id, timeout)
|
||||
|
||||
|
||||
def get_device_matching(predicate: Callable[[core.Device], bool], timeout: int = 0) -> core.Device:
|
||||
"""
|
||||
Get device matching predicate.
|
||||
:param predicate: a function to filter the devices
|
||||
:param timeout: operation timeout in seconds
|
||||
"""
|
||||
|
||||
return get_device_manager().get_device_matching(predicate, timeout)
|
||||
|
||||
|
||||
def enumerate_devices() -> List[core.Device]:
|
||||
"""
|
||||
Enumerate all the devices from the device manager
|
||||
"""
|
||||
|
||||
return get_device_manager().enumerate_devices()
|
||||
|
||||
|
||||
@core.cancellable
|
||||
def shutdown() -> None:
|
||||
"""
|
||||
Shutdown the main device manager
|
||||
"""
|
||||
|
||||
get_device_manager()._impl.close()
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,50 +0,0 @@
|
||||
wxWindows Library Licence, Version 3.1
|
||||
======================================
|
||||
|
||||
Copyright (c) 1998-2005 Julian Smart, Robert Roebling et al
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this licence document, but changing it is not allowed.
|
||||
|
||||
WXWINDOWS LIBRARY LICENCE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public Licence as published by
|
||||
the Free Software Foundation; either version 2 of the Licence, or (at your
|
||||
option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
||||
Licence for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public Licence
|
||||
along with this software, usually in a file named COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
EXCEPTION NOTICE
|
||||
|
||||
1. As a special exception, the copyright holders of this library give
|
||||
permission for additional uses of the text contained in this release of the
|
||||
library as licenced under the wxWindows Library Licence, applying either
|
||||
version 3.1 of the Licence, or (at your option) any later version of the
|
||||
Licence as published by the copyright holders of version 3.1 of the Licence
|
||||
document.
|
||||
|
||||
2. The exception is that you may use, copy, link, modify and distribute
|
||||
under your own terms, binary object code versions of works based on the
|
||||
Library.
|
||||
|
||||
3. If you copy code from files distributed under the terms of the GNU
|
||||
General Public Licence or the GNU Library General Public Licence into a
|
||||
copy of this library, as this licence permits, the exception does not apply
|
||||
to the code that you add in this way. To avoid misleading anyone as to the
|
||||
status of such modified files, you must delete this exception notice from
|
||||
such code and/or adjust the licensing conditions notice accordingly.
|
||||
|
||||
4. If you write modifications of your own for this library, it is your
|
||||
choice whether to permit this exception to apply to your modifications. If
|
||||
you do not wish that, you must delete the exception notice from such code
|
||||
and/or adjust the licensing conditions notice accordingly.
|
||||
@@ -1 +0,0 @@
|
||||
pip
|
||||
@@ -1,36 +0,0 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: frida-tools
|
||||
Version: 12.2.1
|
||||
Summary: Frida CLI tools
|
||||
Home-page: https://frida.re
|
||||
Author: Frida Developers
|
||||
Author-email: oleavr@frida.re
|
||||
License: wxWindows Library Licence, Version 3.1
|
||||
Keywords: frida debugger dynamic instrumentation inject javascript windows macos linux ios iphone ipad android qnx
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Environment :: MacOS X
|
||||
Classifier: Environment :: Win32 (MS Windows)
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Science/Research
|
||||
Classifier: License :: OSI Approved
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Operating System :: POSIX :: Linux
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: JavaScript
|
||||
Classifier: Topic :: Software Development :: Debuggers
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Description-Content-Type: text/markdown
|
||||
License-File: COPYING
|
||||
Requires-Dist: colorama <1.0.0,>=0.2.7
|
||||
Requires-Dist: frida <17.0.0,>=16.0.9
|
||||
Requires-Dist: prompt-toolkit <4.0.0,>=2.0.0
|
||||
Requires-Dist: pygments <3.0.0,>=2.0.2
|
||||
|
||||
CLI tools for [Frida](https://frida.re).
|
||||
@@ -1,72 +0,0 @@
|
||||
../../Scripts/frida-apk.exe,sha256=iM7jD9tpHYaqJJ2iELDrd5zyan7_kbMF4fOApYYhgZs,108407
|
||||
../../Scripts/frida-compile.exe,sha256=JnuqShZGWyCNPsgHbO39oOgZi0reNPK0aJT3mZ2Z0hA,108412
|
||||
../../Scripts/frida-create.exe,sha256=fvf9LalMxfY51TgGoodgymUejYXNCSVRs_pGJR8xNm0,108411
|
||||
../../Scripts/frida-discover.exe,sha256=1njJR55FJJ7mQx7VP5lzE9NK13MuX7Nro_P-eTdHJQM,108414
|
||||
../../Scripts/frida-itrace.exe,sha256=0uP947JY8u4UGEE-0qkJXdHjnkjnyLvoDQBKtcONutQ,108411
|
||||
../../Scripts/frida-join.exe,sha256=Olynvgzb6_OelCW88N5-Vz2hkY1iyWJToyeKKX9IfN0,108408
|
||||
../../Scripts/frida-kill.exe,sha256=b3z6GzWN7iV6pg3dOdOpKlIYLH4LB58znq-EUY-Cmdo,108408
|
||||
../../Scripts/frida-ls-devices.exe,sha256=FjehR54_t3C6O7VxoMdDV6_aylMMmyd2sA1aVK4Jqns,108407
|
||||
../../Scripts/frida-ls.exe,sha256=VGFmbfFyxB-iYUYHlnhOI0y8SXpVRC3bJWah6qkF4Ys,108406
|
||||
../../Scripts/frida-ps.exe,sha256=KYOPtGO3XK5l1BVDqVac7qg4tuQAh9phtRut2QLDwfU,108406
|
||||
../../Scripts/frida-pull.exe,sha256=z4VJ640wayv7IcChJdKgAc6Kq5d7O4RV9cPXHJGC2Ak,108408
|
||||
../../Scripts/frida-push.exe,sha256=jUbj3DyQiV6BSeBHRK_0uwCalX1nedbPrecVaOQek8Q,108408
|
||||
../../Scripts/frida-rm.exe,sha256=91qmOISMKHGA96TV3UQ8VgOre62leuXcap20qHEjtGo,108406
|
||||
../../Scripts/frida-trace.exe,sha256=le9l_vQQBuQkTZbKGPuqUGHsY-jDxo2a_PgAs1SpjZw,108410
|
||||
../../Scripts/frida.exe,sha256=KYXJSnf4TRAJxMCECMHXsWWPwD0FD9fBlfhdsALwMCQ,108408
|
||||
frida_tools-12.2.1.dist-info/COPYING,sha256=XqFUS1Gii8gjsDFZGQ1BCPn7T075EjifUTfG0pXhdbI,2416
|
||||
frida_tools-12.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
frida_tools-12.2.1.dist-info/METADATA,sha256=7DzmGip4CLBegc8PUu30Id1bvYxCzNbdZLggRWsmuTM,1543
|
||||
frida_tools-12.2.1.dist-info/RECORD,,
|
||||
frida_tools-12.2.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
frida_tools-12.2.1.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
|
||||
frida_tools-12.2.1.dist-info/entry_points.txt,sha256=xiPzs8irCbbs2X9_IThYoZDMfWt9qRjVCVo0N4EjINg,559
|
||||
frida_tools-12.2.1.dist-info/top_level.txt,sha256=sTDYKDnOfQMNcHuhCLoTnVRRjxc-EEQodXY5Fow-8cA,12
|
||||
frida_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
frida_tools/__pycache__/__init__.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/_repl_magic.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/apk.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/application.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/cli_formatting.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/compiler.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/creator.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/discoverer.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/itracer.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/join.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/kill.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/ls.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/lsd.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/model.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/ps.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/pull.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/push.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/reactor.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/repl.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/rm.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/stream_controller.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/tracer.cpython-311.pyc,,
|
||||
frida_tools/__pycache__/units.cpython-311.pyc,,
|
||||
frida_tools/_repl_magic.py,sha256=MlsVMrJKVcx1D4pD2hk8bMERZMS7MLls-52_l5E7ohI,6028
|
||||
frida_tools/apk.py,sha256=DlLkVdMIV544Sj4R0HYN9l1ggDSj2kdppU2AUHpzL7c,12908
|
||||
frida_tools/application.py,sha256=nsb1BhnV1bsrhgewel9_nb1T_RrCb3aPKEeX8nWWHNI,34566
|
||||
frida_tools/cli_formatting.py,sha256=7EZkgVO4iH6UtjfFCp_UHGCzkZkVWYgpEhmAJkjfgOs,1975
|
||||
frida_tools/compiler.py,sha256=FxBtDTuY5SRXtie8GZS28oTCt0gjhEURdlhJ3R5gkBk,4432
|
||||
frida_tools/creator.py,sha256=r9aZo2B3vqFsHBUGEm1cj8FLELmcN6F9Lc3OTpIla7w,6550
|
||||
frida_tools/discoverer.py,sha256=PMz47FWd02ARH0-V_svPVR7b7UlC5DLdRL7Lf0uQVh4,7584
|
||||
frida_tools/fs_agent.js,sha256=nwBQN5fT67pzUOpRNxd_LsXZgnnRkXPkjPx-QkNyjqE,363318
|
||||
frida_tools/itracer.py,sha256=Id0yfI8d89Dr4aJ-5CzTSOAIs_accBcK_dAaK7wrKio,15761
|
||||
frida_tools/itracer_agent.js,sha256=zeroNLZVdBkhbP-RXShuLAgkxnPS5WWFLpNMmnbMamU,56028
|
||||
frida_tools/join.py,sha256=hFr48c0-pqTVEG4wbsL0Q7r7z0yyu3UfkCDUTmgrhJM,2908
|
||||
frida_tools/kill.py,sha256=SI42kXTAX5UBPiZnzX_WXRnj4nwyy9lSZ4ip_ZmtmCc,1167
|
||||
frida_tools/ls.py,sha256=jtJtnrUptyY2XjcPn9uZDKltqzDjs34_Iau6WFDJfhA,4424
|
||||
frida_tools/lsd.py,sha256=RwR4OMbHaw0ssTzuwlySr16LZSTwnvqsybsJ3JW86Gs,3837
|
||||
frida_tools/model.py,sha256=uoFJfVzwr32Zx7E4jz6M6lNY0JJjRDVyjNZ4q-KFJcE,2648
|
||||
frida_tools/ps.py,sha256=zMTIJYW6Dl7MFUQe1L4fXuRarnon4bwpSGgFb3KKj38,11399
|
||||
frida_tools/pull.py,sha256=2yk1YNbdt6rrXhZWR-Z-yL88XlnU2mxxv5ZoAtqEWpU,7307
|
||||
frida_tools/push.py,sha256=DR2-keXGErRZjYoi0oq8XZFZx4GTVxSPVQroh0OQE6A,7181
|
||||
frida_tools/reactor.py,sha256=00SbPxd0KF2I3PS3VJ08L3Dg48cSOoaOvlGcNVd8X4A,3184
|
||||
frida_tools/repl.py,sha256=wFNOrlxeL9z3vaYKuRqIjdgbxNKOg9x4saGJgTgad2I,49579
|
||||
frida_tools/rm.py,sha256=UmWQcWJgm1eTkb7lMDmYZRCfzSPLCgRALZCVllB_Rfk,2321
|
||||
frida_tools/stream_controller.py,sha256=GsNbTZKrTrcdsfDHSQ4sHfyVXela8o2tktCjE1Z_Arc,5592
|
||||
frida_tools/tracer.py,sha256=OhtVTB1-hVEdj3cusyDLu0rpVT9Sxu2IhMFE0iuuAf8,30407
|
||||
frida_tools/tracer_agent.js,sha256=sDemS0VrUboU1NDKEzoijLnJVaj06K2nxhtb57BlvOk,25530
|
||||
frida_tools/units.py,sha256=zTg-GM2btQi2CBl8Y74vhw2ucWFfGvGshlcSHle_DN4,72
|
||||
@@ -1,5 +0,0 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.41.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
[console_scripts]
|
||||
frida = frida_tools.repl:main
|
||||
frida-apk = frida_tools.apk:main
|
||||
frida-compile = frida_tools.compiler:main
|
||||
frida-create = frida_tools.creator:main
|
||||
frida-discover = frida_tools.discoverer:main
|
||||
frida-itrace = frida_tools.itracer:main
|
||||
frida-join = frida_tools.join:main
|
||||
frida-kill = frida_tools.kill:main
|
||||
frida-ls = frida_tools.ls:main
|
||||
frida-ls-devices = frida_tools.lsd:main
|
||||
frida-ps = frida_tools.ps:main
|
||||
frida-pull = frida_tools.pull:main
|
||||
frida-push = frida_tools.push:main
|
||||
frida-rm = frida_tools.rm:main
|
||||
frida-trace = frida_tools.tracer:main
|
||||
@@ -1 +0,0 @@
|
||||
frida_tools
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user