├── .gitignore ├── META-INF └── MANIFEST.MF ├── src └── main │ ├── java │ ├── META-INF │ │ └── MANIFEST.MF │ ├── org │ │ └── cq │ │ │ ├── ClassPathAgent.java │ │ │ ├── jartool │ │ │ ├── JarException.java │ │ │ ├── resource │ │ │ │ └── jar_zh_CN.java │ │ │ ├── CommandLine.java │ │ │ ├── FingerPrint.java │ │ │ └── Validator.java │ │ │ └── Main.java │ └── charles │ │ ├── VersionModifier.java │ │ ├── VersionFactory.java │ │ ├── version461 │ │ ├── modifiers │ │ │ ├── BundleStringEncodingModifier.java │ │ │ ├── ClassFileModifier.java │ │ │ ├── JavaSourceReplace.java │ │ │ └── MenuEncodingModifier.java │ │ └── Modifier461.java │ │ └── version462 │ │ ├── Modifier462.java │ │ └── modifiers │ │ └── MenuModifier.java │ └── source │ ├── 4.6.1 │ ├── gui │ │ ├── CharlesFrame.class │ │ ├── menus │ │ │ ├── tfse.class │ │ │ ├── EditMenu.class │ │ │ ├── ViewMenu.class │ │ │ └── ProxyMenu.class │ │ └── session │ │ │ └── AbstractSessionFrame.class │ ├── helper │ │ ├── BreakpointsEditor.html │ │ ├── frag │ │ │ ├── SelectedLocations.html │ │ │ └── LocationMatching.html │ │ ├── ProxySettings-Options.html │ │ ├── ClientSSLCertificates.html │ │ ├── ImportedSSLCertificates.html │ │ ├── ServerSSLCertificates.html │ │ ├── AutoSave.html │ │ ├── Whitelist.html │ │ ├── Blacklist.html │ │ ├── ProxySettings-SSL.html │ │ ├── MapEditor.html │ │ ├── BlockCookies.html │ │ ├── DNSSpoofing.html │ │ ├── ReverseProxies.html │ │ ├── ClientProcess.html │ │ ├── SSL.html │ │ ├── ProxySettings-OS.html │ │ ├── PortForwarding.html │ │ ├── UISettings.html │ │ ├── PortForwardingEditor.html │ │ ├── ViewerContentType.html │ │ ├── ViewerContentTypeEditor.html │ │ ├── Breakpoints.html │ │ ├── NoCaching.html │ │ ├── Rewrite.html │ │ ├── ExternalProxies.html │ │ ├── MapLocalEditor.html │ │ ├── ProxySettings-Mozilla.html │ │ ├── Mirror.html │ │ ├── Map.html │ │ ├── MapLocal.html │ │ ├── ReverseProxiesEditor.html │ │ ├── Protobuf.html │ │ ├── Throttling.html │ │ ├── LocationsTableHelper.html │ │ ├── RewriteEditor.html │ │ └── ProxySettings-Proxies.html │ └── strings.properties │ └── 4.6.2 │ └── com │ └── xk72 │ └── charles │ ├── helper │ ├── BreakpointsEditor.html │ ├── frag │ │ ├── SelectedLocations.html │ │ └── LocationMatching.html │ ├── ProxySettings-Options.html │ ├── ClientSSLCertificates.html │ ├── ImportedSSLCertificates.html │ ├── ServerSSLCertificates.html │ ├── AutoSave.html │ ├── Whitelist.html │ ├── Blacklist.html │ ├── ProxySettings-SSL.html │ ├── MapEditor.html │ ├── BlockCookies.html │ ├── DNSSpoofing.html │ ├── ReverseProxies.html │ ├── ClientProcess.html │ ├── SSL.html │ ├── ProxySettings-OS.html │ ├── PortForwarding.html │ ├── UISettings.html │ ├── PortForwardingEditor.html │ ├── ViewerContentType.html │ ├── ViewerContentTypeEditor.html │ ├── Breakpoints.html │ ├── NoCaching.html │ ├── Rewrite.html │ ├── ExternalProxies.html │ ├── MapLocalEditor.html │ ├── ProxySettings-Mozilla.html │ ├── Mirror.html │ ├── Map.html │ ├── MapLocal.html │ ├── ReverseProxiesEditor.html │ ├── Protobuf.html │ ├── Throttling.html │ ├── LocationsTableHelper.html │ ├── RewriteEditor.html │ └── ProxySettings-Proxies.html │ └── strings.properties ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | *.jar 4 | 4.6.1/* 5 | out 6 | target -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: org.cq.Main 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: org.cq.Main 3 | Agent-Class: org.cq.ClassPathAgent 4 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/gui/CharlesFrame.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuiqingandroid/CharlesZH/HEAD/src/main/source/4.6.1/gui/CharlesFrame.class -------------------------------------------------------------------------------- /src/main/source/4.6.1/gui/menus/tfse.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuiqingandroid/CharlesZH/HEAD/src/main/source/4.6.1/gui/menus/tfse.class -------------------------------------------------------------------------------- /src/main/source/4.6.1/gui/menus/EditMenu.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuiqingandroid/CharlesZH/HEAD/src/main/source/4.6.1/gui/menus/EditMenu.class -------------------------------------------------------------------------------- /src/main/source/4.6.1/gui/menus/ViewMenu.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuiqingandroid/CharlesZH/HEAD/src/main/source/4.6.1/gui/menus/ViewMenu.class -------------------------------------------------------------------------------- /src/main/source/4.6.1/gui/menus/ProxyMenu.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuiqingandroid/CharlesZH/HEAD/src/main/source/4.6.1/gui/menus/ProxyMenu.class -------------------------------------------------------------------------------- /src/main/source/4.6.1/gui/session/AbstractSessionFrame.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuiqingandroid/CharlesZH/HEAD/src/main/source/4.6.1/gui/session/AbstractSessionFrame.class -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/BreakpointsEditor.html: -------------------------------------------------------------------------------- 1 |

Breakpoint

2 |

A breakpoint consists of a location match and whether to match the request, response or both.

3 | 4 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/BreakpointsEditor.html: -------------------------------------------------------------------------------- 1 |

Breakpoint

2 |

A breakpoint consists of a location match and whether to match the request, response or both.

3 | 4 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/frag/SelectedLocations.html: -------------------------------------------------------------------------------- 1 |

Selected Locations

2 |

The tool can be enabled for every request or only for selected locations. When used for selected locations you 3 | limit the tool's effects to specified hosts and or paths using simple but powerful pattern matches.

4 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/frag/LocationMatching.html: -------------------------------------------------------------------------------- 1 |

Location Matching

2 |

Each location match may contain protocol, host, port and path patterns to match specific URLs. Locations may include wildcards. More help 3 | for creating location matches may be found when you add a new location to this tool.

4 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/frag/SelectedLocations.html: -------------------------------------------------------------------------------- 1 |

Selected Locations

2 |

The tool can be enabled for every request or only for selected locations. When used for selected locations you 3 | limit the tool's effects to specified hosts and or paths using simple but powerful pattern matches.

4 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/frag/LocationMatching.html: -------------------------------------------------------------------------------- 1 |

Location Matching

2 |

Each location match may contain protocol, host, port and path patterns to match specific URLs. Locations may include wildcards. More help 3 | for creating location matches may be found when you add a new location to this tool.

4 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ProxySettings-Options.html: -------------------------------------------------------------------------------- 1 |

Options

2 | 3 |

Bypass proxies

4 |

A list of hosts and domain names for which your browser should be configured to bypass Charles. The list 5 | is space or comma-separated and is injected into your browser when Charles configures its proxy settings. See the 6 | OS and browser specific tabs for more information.

7 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ProxySettings-Options.html: -------------------------------------------------------------------------------- 1 |

Options

2 | 3 |

Bypass proxies

4 |

A list of hosts and domain names for which your browser should be configured to bypass Charles. The list 5 | is space or comma-separated and is injected into your browser when Charles configures its proxy settings. See the 6 | OS and browser specific tabs for more information.

7 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ClientSSLCertificates.html: -------------------------------------------------------------------------------- 1 |

Client SSL Certificates

2 |

Add PKCS#12 certificates for selected hosts to enable client SSL certificate authentication through Charles.

3 |

When an SSL connection is established to a matching host you will be prompted for your password, and then the given 4 | certificate will be made available to the remote host for authentication purposes.

-------------------------------------------------------------------------------- /src/main/java/org/cq/ClassPathAgent.java: -------------------------------------------------------------------------------- 1 | package org.cq; 2 | 3 | import java.io.IOException; 4 | import java.lang.instrument.Instrumentation; 5 | import java.util.jar.JarFile; 6 | 7 | public class ClassPathAgent { 8 | public static void agentmain(String args, Instrumentation instrumentation) throws IOException { 9 | instrumentation.appendToSystemClassLoaderSearch(new JarFile(args)); 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ClientSSLCertificates.html: -------------------------------------------------------------------------------- 1 |

Client SSL Certificates

2 |

Add PKCS#12 certificates for selected hosts to enable client SSL certificate authentication through Charles.

3 |

When an SSL connection is established to a matching host you will be prompted for your password, and then the given 4 | certificate will be made available to the remote host for authentication purposes.

-------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ImportedSSLCertificates.html: -------------------------------------------------------------------------------- 1 |

Server SSL Certificates

2 |

Add PKCS#12 certificates for use when establishing SSL connections to clients.

3 |

When an SSL connection is established to a host that uses a matching server certificate Charles can use that certificate to establish the 4 | connection to the client. If no matching certificate is found Charles must generate its own certificate which the client may not trust.

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ImportedSSLCertificates.html: -------------------------------------------------------------------------------- 1 |

Server SSL Certificates

2 |

Add PKCS#12 certificates for use when establishing SSL connections to clients.

3 |

When an SSL connection is established to a host that uses a matching server certificate Charles can use that certificate to establish the 4 | connection to the client. If no matching certificate is found Charles must generate its own certificate which the client may not trust.

-------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ServerSSLCertificates.html: -------------------------------------------------------------------------------- 1 |

Custom Root Certificates

2 |

You can use your own Root certificate to sign the SSL certificates issued by Charles for SSL Proxying.

3 | 4 |

Choose a certificate file in PKCS#12 format. You will be prompted for a password. Once accepted, Charles will start issuing 5 | SSL certificates signed with your root certificate when you use SSL Proxying.

6 |

Charles will prompt for the password to your Root certificate each time you start Charles.

7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 本工程通过修改字节码实现charles汉化,目前最新的Charles仅部分支持语言包,所以大部分汉化工作都是通过直接修改字节码实现。 2 | 3 | 4 | 5 | 汉化步骤 6 | 7 | ## 1. 依赖环境 8 | `JRE11`及以上 9 | 10 | ## 2. 运行 11 | 使用命令`java -jar charlesZh.jar`或双击`charlesZh.jar` 12 | 13 | ## 3. 替换charles.jar 14 | 替换charles安装目录下lib里面的charles为刚刚的`origin_charles.jar` 15 | 16 | ## 4. 已知问题 17 | 1. 会影响charles web服务 18 | 19 | **注意:** 20 | 1. 在替换charles.jar之前,做好备份,以免打不开 21 | 2. 本项目只做charles汉化,不包含破解,还请支持正版,[购买连接](https://www.charlesproxy.com/buy/) 22 | 23 | # TODO 24 | - [ ] 支持多语言 25 | - [ ] 支持语言切换 26 | - [ ] 支持插件开发 -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ServerSSLCertificates.html: -------------------------------------------------------------------------------- 1 |

Custom Root Certificates

2 |

You can use your own Root certificate to sign the SSL certificates issued by Charles for SSL Proxying.

3 | 4 |

Choose a certificate file in PKCS#12 format. You will be prompted for a password. Once accepted, Charles will start issuing 5 | SSL certificates signed with your root certificate when you use SSL Proxying.

6 |

Charles will prompt for the password to your Root certificate each time you start Charles.

7 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/AutoSave.html: -------------------------------------------------------------------------------- 1 |

自动保存工具

2 |

自动自动保存工具自动保存和清除记录会话在设置的时间间隔

3 | 4 |

如果您让Charles长时间监视网络活动,这是很有用的 5 | 并希望将记录分解成易于管理的单元,或避免内存不足的情况 6 | 这可能是由于大量数据造成的。

7 | 8 |

输入保存间隔(以分钟为单位)和保存会话文件的目录。 9 | 您可以选择每次运行Charles时是否启动自动保存工具,否则 10 | 当Charles启动时,自动保存工具将永远被禁用。 11 |

12 |

您可以选择启动 13 | 保存间隔计时器上的保存间隔分钟过去一小时的倍数。您的第一个保存间隔将 14 | 使其更短,以对齐间隔到倍数。例如,如果您的保存间隔是15分钟 15 | 您在10:10启动工具,第一个保存间隔将是10:15,以对齐15分钟的倍数, 16 | 之后每15分钟就会有一次。

17 | 18 |

会话文件的名称中带有时间戳,格式为yyyyMMddHHmm,即年、月、日、小时、分钟 19 | 这样当按字母顺序排序时,它们就会以正确的顺序出现。

20 | 21 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Whitelist.html: -------------------------------------------------------------------------------- 1 |

White List Tool

2 |

The White List tool lets you block all requests except those to selected locations. When a request is received by 3 | Charles that does not match a white listed location Charles blocks the request. You can choose whether Charles will 4 | simply close the connection from the browser or return an error page (with a 403 response) to the browser.

5 |

There is also a Black List tool for blocking only selected locations. 6 | If a request matches both the Black List and White List then it is blocked.

7 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/AutoSave.html: -------------------------------------------------------------------------------- 1 |

自动保存工具

2 |

自动自动保存工具自动保存和清除记录会话在设置的时间间隔

3 | 4 |

如果您让Charles长时间监视网络活动,这是很有用的 5 | 并希望将记录分解成易于管理的单元,或避免内存不足的情况 6 | 这可能是由于大量数据造成的。

7 | 8 |

输入保存间隔(以分钟为单位)和保存会话文件的目录。 9 | 您可以选择每次运行Charles时是否启动自动保存工具,否则 10 | 当Charles启动时,自动保存工具将永远被禁用。 11 |

12 |

您可以选择启动 13 | 保存间隔计时器上的保存间隔分钟过去一小时的倍数。您的第一个保存间隔将 14 | 使其更短,以对齐间隔到倍数。例如,如果您的保存间隔是15分钟 15 | 您在10:10启动工具,第一个保存间隔将是10:15,以对齐15分钟的倍数, 16 | 之后每15分钟就会有一次。

17 | 18 |

会话文件的名称中带有时间戳,格式为yyyyMMddHHmm,即年、月、日、小时、分钟 19 | 这样当按字母顺序排序时,它们就会以正确的顺序出现。

20 | 21 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Blacklist.html: -------------------------------------------------------------------------------- 1 |

Black List Tool

2 |

The Black List tool lets you block requests to selected locations. When a request is received by Charles that matches 3 | a black listed location Charles blocks the request. You can choose whether Charles will 4 | simply close the connection from the browser or return an error page (with a 403 response) to the browser.

5 |

There is also a White List tool that allows you to block all requests except those to selected locations. 6 | If a request matches both the Black List and White List then it is blocked.

7 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Whitelist.html: -------------------------------------------------------------------------------- 1 |

White List Tool

2 |

The White List tool lets you block all requests except those to selected locations. When a request is received by 3 | Charles that does not match a white listed location Charles blocks the request. You can choose whether Charles will 4 | simply close the connection from the browser or return an error page (with a 403 response) to the browser.

5 |

There is also a Black List tool for blocking only selected locations. 6 | If a request matches both the Black List and White List then it is blocked.

7 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Blacklist.html: -------------------------------------------------------------------------------- 1 |

Black List Tool

2 |

The Black List tool lets you block requests to selected locations. When a request is received by Charles that matches 3 | a black listed location Charles blocks the request. You can choose whether Charles will 4 | simply close the connection from the browser or return an error page (with a 403 response) to the browser.

5 |

There is also a White List tool that allows you to block all requests except those to selected locations. 6 | If a request matches both the Black List and White List then it is blocked.

7 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ProxySettings-SSL.html: -------------------------------------------------------------------------------- 1 |

SSL

2 |

SSL代理

3 |

SSL代理 拦截所有SSL请求并可以SSL请求的纯文本内容,而不仅仅是查看加密的文本

4 |

开启 SSL代理 , 您的浏览器或应用程序将收到由Charles签名的证书,而不是来自远程web服务器的原始证书。 5 | 这将在浏览器或应用程序中触发警告, 有些应用程序可能会拒绝连接

6 |

7 | 您可以将您的浏览器或应用程序配置为接受Charles的证书 8 | http://www.charlesproxy.com/ssl或在Charles的帮助菜单中的SSL代理菜单。 9 |

10 | 11 |

匹配规则

12 |

13 | 应该逐个列出需要Charles抓包SSL请求。为保护您的个人信息安全,您应该只包含您想要的抓包SSL站点。 14 |

15 |

16 | 可以将通配符添加到位置列表中,以匹配多个或所有位置。要匹配所有位置,请输入*。 17 |

18 |

19 | 对于要被代理的站点,它必须同时匹配包含位置和不匹配任何排除位置。 20 | 当您在包含位置中使用了通配符时,排除位置最有用。 21 |

22 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ProxySettings-SSL.html: -------------------------------------------------------------------------------- 1 |

SSL

2 |

SSL代理

3 |

SSL代理 拦截所有SSL请求并可以SSL请求的纯文本内容,而不仅仅是查看加密的文本

4 |

开启 SSL代理 , 您的浏览器或应用程序将收到由Charles签名的证书,而不是来自远程web服务器的原始证书。 5 | 这将在浏览器或应用程序中触发警告, 有些应用程序可能会拒绝连接

6 |

7 | 您可以将您的浏览器或应用程序配置为接受Charles的证书 8 | http://www.charlesproxy.com/ssl或在Charles的帮助菜单中的SSL代理菜单。 9 |

10 | 11 |

匹配规则

12 |

13 | 应该逐个列出需要Charles抓包SSL请求。为保护您的个人信息安全,您应该只包含您想要的抓包SSL站点。 14 |

15 |

16 | 可以将通配符添加到位置列表中,以匹配多个或所有位置。要匹配所有位置,请输入*。 17 |

18 |

19 | 对于要被代理的站点,它必须同时匹配包含位置和不匹配任何排除位置。 20 | 当您在包含位置中使用了通配符时,排除位置最有用。 21 |

22 | -------------------------------------------------------------------------------- /src/main/java/charles/VersionModifier.java: -------------------------------------------------------------------------------- 1 | package charles; 2 | 3 | 4 | public abstract class VersionModifier { 5 | 6 | private static String mSavePath = null; 7 | private static String mOriginJar = null; 8 | public VersionModifier(String originJar, String savePath){ 9 | mSavePath = savePath; 10 | mOriginJar = originJar; 11 | } 12 | public abstract boolean modifyByteCode(); 13 | public abstract String getSourcePath(); 14 | 15 | public final String getTempPath(){ 16 | return mSavePath; 17 | } 18 | 19 | protected final String getOriginJarPath(){ 20 | return mOriginJar; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/MapEditor.html: -------------------------------------------------------------------------------- 1 |

Remote Mapping

2 |

A remote mapping consists of a Map From location and a Map To location.

3 | 4 |

Map From

5 |

The Map From location is a regular location pattern. See the section on Location matching below.

6 | 7 |

Map To

8 |

The Map To location specifies what to change about the original request. Any field left blank will be 9 | left unchanged.

10 |

If a path is specified it should end with a /. The original request path will be made relative 11 | to the Map From location pattern and then mapped to be relative to the Map To path.

12 | 13 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/MapEditor.html: -------------------------------------------------------------------------------- 1 |

Remote Mapping

2 |

A remote mapping consists of a Map From location and a Map To location.

3 | 4 |

Map From

5 |

The Map From location is a regular location pattern. See the section on Location matching below.

6 | 7 |

Map To

8 |

The Map To location specifies what to change about the original request. Any field left blank will be 9 | left unchanged.

10 |

If a path is specified it should end with a /. The original request path will be made relative 11 | to the Map From location pattern and then mapped to be relative to the Map To path.

12 | 13 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/java/org/cq/jartool/JarException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 | * 5 | * 6 | * 7 | * 8 | * 9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | */ 25 | 26 | package org.cq.jartool; 27 | 28 | import java.io.IOException; 29 | 30 | public 31 | class JarException extends IOException { 32 | 33 | static final long serialVersionUID = -4351820108009811497L; 34 | 35 | public JarException() { 36 | super(); 37 | } 38 | 39 | public JarException(String s) { 40 | super(s); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/BlockCookies.html: -------------------------------------------------------------------------------- 1 |

Block Cookies Tool

2 |

The Block Cookies tool blocks the sending and receiving of cookies. It can be used to test websites as if you have 3 | cookies disabled in your browser. Note that web spiders (such as Google) often don't support Cookies so the tool can 4 | also be used to simulate a spider's view of a website.

5 | 6 | @@tools.gen.locations.selectedLocations@@ 7 | 8 |

How it works

9 |

The Cookie header is removed from requests, preventing cookie values being sent from the client application (eg. web browser) 10 | to the remote server. The Set-Cookie header is removed from responses, preventing requests to set cookies being received 11 | by the client application from the remote server.

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/BlockCookies.html: -------------------------------------------------------------------------------- 1 |

Block Cookies Tool

2 |

The Block Cookies tool blocks the sending and receiving of cookies. It can be used to test websites as if you have 3 | cookies disabled in your browser. Note that web spiders (such as Google) often don't support Cookies so the tool can 4 | also be used to simulate a spider's view of a website.

5 | 6 | @@tools.gen.locations.selectedLocations@@ 7 | 8 |

How it works

9 |

The Cookie header is removed from requests, preventing cookie values being sent from the client application (eg. web browser) 10 | to the remote server. The Set-Cookie header is removed from responses, preventing requests to set cookies being received 11 | by the client application from the remote server.

-------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/DNSSpoofing.html: -------------------------------------------------------------------------------- 1 |

DNS Spoofing Tool

2 |

The DNS Spoofing tool enables you to spoof DNS lookups by specifying your own hostname to remote address mappings. When a request 3 | passes through Charles your DNS mappings will take precedence.

4 |

DNS Spoofing is useful for testing virtual hosted websites prior to a DNS change, as your browser will behave 5 | as if the DNS change has been made. DNS changes often take up as long as 24 hours to take effect and without 6 | DNS Spoofing it can be very difficult to test what the website will 7 | look like once the DNS change goes live.

8 | 9 |

You can map hostnames to an IP address or to another hostname, which will be looked up in DNS by Charles to find its IP address.

10 | 11 |

Hostnames may contain wildcards.

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/DNSSpoofing.html: -------------------------------------------------------------------------------- 1 |

DNS Spoofing Tool

2 |

The DNS Spoofing tool enables you to spoof DNS lookups by specifying your own hostname to remote address mappings. When a request 3 | passes through Charles your DNS mappings will take precedence.

4 |

DNS Spoofing is useful for testing virtual hosted websites prior to a DNS change, as your browser will behave 5 | as if the DNS change has been made. DNS changes often take up as long as 24 hours to take effect and without 6 | DNS Spoofing it can be very difficult to test what the website will 7 | look like once the DNS change goes live.

8 | 9 |

You can map hostnames to an IP address or to another hostname, which will be looked up in DNS by Charles to find its IP address.

10 | 11 |

Hostnames may contain wildcards.

-------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ReverseProxies.html: -------------------------------------------------------------------------------- 1 |

Reverse Proxies

2 |

3 | A reverse proxy creates a web server on a local port that transparently proxies requests to a 4 | remote web server. All the requests and responses on the reverse proxy may be recorded in Charles. 5 |

6 |

7 | A reverse proxy is useful if you have a client application that doesn't support the use of 8 | an HTTP proxy, or you want to avoid configuring it to use a proxy. 9 | Create a reverse proxy to the original destination web server and then connect 10 | the client application to the local port; the reverse proxy is transparent to the client 11 | application and enables you to view the traffic in Charles where you previously may not have 12 | been able to. 13 |

14 |

15 | Read more about reverse proxies at http://en.wikipedia.org/wiki/Reverse_proxy 16 |

17 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.cq 8 | CharlesZH 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 11 13 | 11 14 | 15 | 16 | 17 | org.javassist 18 | javassist 19 | 3.27.0-GA 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ReverseProxies.html: -------------------------------------------------------------------------------- 1 |

Reverse Proxies

2 |

3 | A reverse proxy creates a web server on a local port that transparently proxies requests to a 4 | remote web server. All the requests and responses on the reverse proxy may be recorded in Charles. 5 |

6 |

7 | A reverse proxy is useful if you have a client application that doesn't support the use of 8 | an HTTP proxy, or you want to avoid configuring it to use a proxy. 9 | Create a reverse proxy to the original destination web server and then connect 10 | the client application to the local port; the reverse proxy is transparent to the client 11 | application and enables you to view the traffic in Charles where you previously may not have 12 | been able to. 13 |

14 |

15 | Read more about reverse proxies at http://en.wikipedia.org/wiki/Reverse_proxy 16 |

17 | -------------------------------------------------------------------------------- /src/main/java/charles/VersionFactory.java: -------------------------------------------------------------------------------- 1 | package charles; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import charles.version461.Modifier461; 7 | import charles.version462.Modifier462; 8 | 9 | public class VersionFactory { 10 | 11 | public static final String V_461 = "4.6.1"; 12 | public static final String V_462 = "4.6.2"; 13 | 14 | public static final List SUPPORT_VERSIONS = new ArrayList<>(){}; 15 | 16 | static { 17 | SUPPORT_VERSIONS.add(V_462); 18 | } 19 | 20 | public static VersionModifier createVersionModifier(String version, String originJar, String savePath){ 21 | if (V_461.equals(version)) { 22 | return new Modifier461(originJar, savePath); 23 | } else if (V_462.equals(version)) { 24 | return new Modifier462(originJar, savePath); 25 | } 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ClientProcess.html: -------------------------------------------------------------------------------- 1 |

Client Process Tool

2 |

The Client Process tool shows the name of the local client process that is responsible for 3 | making each request. The client process will usually be your web browser, such as firefox.exe, but 4 | there are many potentially unknown HTTP clients that the Client Process tool can help you discover. 5 |

6 | 7 |

The client process name is displayed in the Notes area on each request.

8 | 9 |

10 | The Client Process tool is useful if you 11 | can see requests in Charles that you're not sure of the origin process. It 12 | only works for requests originating on the computer on which Charles is running. 13 |

14 | 15 |

16 | This tool will introduce a short delay before each connection is accepted by Charles. 17 | The delay is usually not noticeable or significant. 18 |

19 | 20 | @@tools.gen.locations.selectedLocations@@ 21 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ClientProcess.html: -------------------------------------------------------------------------------- 1 |

Client Process Tool

2 |

The Client Process tool shows the name of the local client process that is responsible for 3 | making each request. The client process will usually be your web browser, such as firefox.exe, but 4 | there are many potentially unknown HTTP clients that the Client Process tool can help you discover. 5 |

6 | 7 |

The client process name is displayed in the Notes area on each request.

8 | 9 |

10 | The Client Process tool is useful if you 11 | can see requests in Charles that you're not sure of the origin process. It 12 | only works for requests originating on the computer on which Charles is running. 13 |

14 | 15 |

16 | This tool will introduce a short delay before each connection is accepted by Charles. 17 | The delay is usually not noticeable or significant. 18 |

19 | 20 | @@tools.gen.locations.selectedLocations@@ 21 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/SSL.html: -------------------------------------------------------------------------------- 1 |

Charles Root Certificates

2 |

Charles uses its own Root SSL certificate for SSL requests through Charles to hosts enabled for SSL Proxying. The Root 3 | certificate is generated automatically for each Charles installation.

4 | 5 |

Because Charles has signed the Root certificate itself, it won't be trusted by your browsers or applications. In order to use the 6 | SSL Proxying feature in Charles you therefore need to add the Root certificate for your copy of Charles to the 7 | trust-store on your OS, and perhaps in your browser.

8 | 9 |

Use the options in the SSL submenu in the Help menu in Charles to help install the Root certificate. You can install the certificate 10 | on the current OS, or on remote devices or browsers.

11 | 12 |

To install the certificate in Mozilla Firefox, first configure Firefox to use Charles as its proxy then browse to chls.pro/ssl.

13 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/SSL.html: -------------------------------------------------------------------------------- 1 |

Charles Root Certificates

2 |

Charles uses its own Root SSL certificate for SSL requests through Charles to hosts enabled for SSL Proxying. The Root 3 | certificate is generated automatically for each Charles installation.

4 | 5 |

Because Charles has signed the Root certificate itself, it won't be trusted by your browsers or applications. In order to use the 6 | SSL Proxying feature in Charles you therefore need to add the Root certificate for your copy of Charles to the 7 | trust-store on your OS, and perhaps in your browser.

8 | 9 |

Use the options in the SSL submenu in the Help menu in Charles to help install the Root certificate. You can install the certificate 10 | on the current OS, or on remote devices or browsers.

11 | 12 |

To install the certificate in Mozilla Firefox, first configure Firefox to use Charles as its proxy then browse to chls.pro/ssl.

13 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ProxySettings-OS.html: -------------------------------------------------------------------------------- 1 |

OS Proxy Settings

2 |

Charles can automatically configure your operating system's proxy settings. This will effect most 3 | web browsers and applications on your computer, so they will you use Charles and thus their activity 4 | will be visible in Charles.

5 | 6 |

You can enable the proxy configuration and then choose whether to configure the system to use Charles 7 | as an HTTP proxy or SOCKS proxy, if the SOCKS Proxy is itself enables on the Proxies tab. See the Proxies 8 | tab for information on the differences between HTTP and SOCKS.

9 | 10 |

The operating system proxy configuration can be enabled at start up, which is the default behaviour, so 11 | that when you start Charles it is ready to be used. Alternatively you can disable this and enable the operating 12 | system proxy settings manually or configure your browser and other applications manually to use Charles with 13 | their own proxy settings configuration interface.

14 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ProxySettings-OS.html: -------------------------------------------------------------------------------- 1 |

OS Proxy Settings

2 |

Charles can automatically configure your operating system's proxy settings. This will effect most 3 | web browsers and applications on your computer, so they will you use Charles and thus their activity 4 | will be visible in Charles.

5 | 6 |

You can enable the proxy configuration and then choose whether to configure the system to use Charles 7 | as an HTTP proxy or SOCKS proxy, if the SOCKS Proxy is itself enables on the Proxies tab. See the Proxies 8 | tab for information on the differences between HTTP and SOCKS.

9 | 10 |

The operating system proxy configuration can be enabled at start up, which is the default behaviour, so 11 | that when you start Charles it is ready to be used. Alternatively you can disable this and enable the operating 12 | system proxy settings manually or configure your browser and other applications manually to use Charles with 13 | their own proxy settings configuration interface.

14 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/PortForwarding.html: -------------------------------------------------------------------------------- 1 |

Port Forwarding

2 |

Port forwarding enables you to transparently forward a local TCP or UDP port to a 3 | remote host and port. All the requests and responses on the port may be recorded in Charles.

4 | 5 |

The port forwarding traffic is recorded in Charles as a socket://host:port/ URL

6 | 7 |

8 | Port forwarding is useful if you have a non-HTTP application that you want to monitor with Charles. 9 | Create a port forward to the original destination server and then connect the client application 10 | to the local port; the port forwarding is transparent to the client application and enables you to 11 | view the traffic in Charles where you previously may not have been able to. 12 |

13 | 14 |

Examples

15 |

You can forward TCP port 2525 on your local host to port 25 on a remote host. Then when you connect to localhost:2525 16 | Charles will transparently forward the traffic to the remote host as if you had connected directly. You will see 17 | the traffic recorded in Charles as socket://localhost:2525/. 18 |

19 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/PortForwarding.html: -------------------------------------------------------------------------------- 1 |

Port Forwarding

2 |

Port forwarding enables you to transparently forward a local TCP or UDP port to a 3 | remote host and port. All the requests and responses on the port may be recorded in Charles.

4 | 5 |

The port forwarding traffic is recorded in Charles as a socket://host:port/ URL

6 | 7 |

8 | Port forwarding is useful if you have a non-HTTP application that you want to monitor with Charles. 9 | Create a port forward to the original destination server and then connect the client application 10 | to the local port; the port forwarding is transparent to the client application and enables you to 11 | view the traffic in Charles where you previously may not have been able to. 12 |

13 | 14 |

Examples

15 |

You can forward TCP port 2525 on your local host to port 25 on a remote host. Then when you connect to localhost:2525 16 | Charles will transparently forward the traffic to the remote host as if you had connected directly. You will see 17 | the traffic recorded in Charles as socket://localhost:2525/. 18 |

19 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/UISettings.html: -------------------------------------------------------------------------------- 1 |

User Interface Settings

2 |

Look and Feel

3 |

The native platform look and feel is usually the best as it makes Charles appear like other 4 | applications on your system. However you can choose another look and feel to suit your preferences or requirements.

5 | 6 |

Display Font

7 |

The display font is used in some viewers such as the Text viewer. If you have specific requirements for viewing 8 | information you can change the font here, such as to a font that includes foreign-language character sets.

9 | 10 |

Display Font Size

11 |

The size to use for the display font.

12 | 13 |

Minimise to System Tray

14 |

Windows only option. When Charles is minimised its window will be hidden from the task bar and can be restored 15 | by clicking the Charles icon in your system tray.

16 | 17 |

Enable Global Hotkeys

18 |

Windows only option. Bring Charles to the front from any application by pressing either WINDOWS-C or 19 | ALT-CONTROL-SHIFT C.

20 | 21 |

Show Memory Usage

22 |

Show Charles's memory usage in the status bar.

23 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/UISettings.html: -------------------------------------------------------------------------------- 1 |

User Interface Settings

2 |

Look and Feel

3 |

The native platform look and feel is usually the best as it makes Charles appear like other 4 | applications on your system. However you can choose another look and feel to suit your preferences or requirements.

5 | 6 |

Display Font

7 |

The display font is used in some viewers such as the Text viewer. If you have specific requirements for viewing 8 | information you can change the font here, such as to a font that includes foreign-language character sets.

9 | 10 |

Display Font Size

11 |

The size to use for the display font.

12 | 13 |

Minimise to System Tray

14 |

Windows only option. When Charles is minimised its window will be hidden from the task bar and can be restored 15 | by clicking the Charles icon in your system tray.

16 | 17 |

Enable Global Hotkeys

18 |

Windows only option. Bring Charles to the front from any application by pressing either WINDOWS-C or 19 | ALT-CONTROL-SHIFT C.

20 | 21 |

Show Memory Usage

22 |

Show Charles's memory usage in the status bar.

23 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/PortForwardingEditor.html: -------------------------------------------------------------------------------- 1 |

Port Forwarding

2 | 3 |

Protocol

4 |

Choose either TCP or UDP protocol for the forwarding. TCP is the most common Internet protocol; UDP is most commonly used for DNS or real-time applications 5 | such as streaming.

6 | 7 |

Start Port / End Port

8 |

9 | The Start Port is the local port that you want to forward. If you want to forward a range of ports you can enter in an End Port, 10 | otherwise you may leave the End Port field blank. 11 |

12 | 13 |

Remote Host and Port

14 |

15 | The remote host and port to forward to. If you have entered a range of ports using the End Port field the same range of ports 16 | will be forwarded to using the remote port as the base port. 17 |

18 | 19 |

Listen On A Specific Address

20 |

21 | If you want to specify the local address to listen on for the reverse proxy you can enable this option and enter in the IP address here. 22 | This is useful if you want to run multiple network services on the same port but on different IP addresses on the same machine. 23 | When this option is disabled the reverse proxy binds to all available local addresses. 24 |

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/PortForwardingEditor.html: -------------------------------------------------------------------------------- 1 |

Port Forwarding

2 | 3 |

Protocol

4 |

Choose either TCP or UDP protocol for the forwarding. TCP is the most common Internet protocol; UDP is most commonly used for DNS or real-time applications 5 | such as streaming.

6 | 7 |

Start Port / End Port

8 |

9 | The Start Port is the local port that you want to forward. If you want to forward a range of ports you can enter in an End Port, 10 | otherwise you may leave the End Port field blank. 11 |

12 | 13 |

Remote Host and Port

14 |

15 | The remote host and port to forward to. If you have entered a range of ports using the End Port field the same range of ports 16 | will be forwarded to using the remote port as the base port. 17 |

18 | 19 |

Listen On A Specific Address

20 |

21 | If you want to specify the local address to listen on for the reverse proxy you can enable this option and enter in the IP address here. 22 | This is useful if you want to run multiple network services on the same port but on different IP addresses on the same machine. 23 | When this option is disabled the reverse proxy binds to all available local addresses. 24 |

-------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ViewerContentType.html: -------------------------------------------------------------------------------- 1 |

Viewer Content Type Mapping

2 |

3 | The Viewer Content Type Mappings allow you to explicitly map selected locations to particular viewer content types. 4 | This will automatically enable the appropriate content type specific viewers when viewing requests from those 5 | locations. 6 |

7 | 8 |

9 | Normally Charles attempts to automatically detect the appropriate viewer content type based upon the content of the 10 | request or response, usually based on the Content-Type header. However some websites do not set the correct 11 | Content-Type value for their content so not all of the appropriate content viewers are available. Configuring 12 | appropriate viewer content type mappings for these locations will allow you to view these requests with the 13 | best possible viewers. 14 |

15 | 16 |

How it works

17 |

18 | When a request that matches one of the configured mappings is viewed within Charles any viewers that are appropriate 19 | for the configured viewer content type are enabled in addition to the automatically detected viewers. No changes are 20 | made to the actual request or response. 21 |

22 | 23 | @@tools.gen.locations.locationMatching@@ 24 | 25 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ViewerContentTypeEditor.html: -------------------------------------------------------------------------------- 1 |

Viewer Content Type Mapping

2 |

A viewer content type mapping consists of a location match and the desired request and response viewer content type.

3 |

You may specify a desired request type or response type or both. You may also specify neither a request or response 4 | type in which case the mapping will have no effect. It is more usual to specify a response type as you are more likely 5 | to be interested in the viewing of response content than the request content (which is often empty)

6 | 7 |

Viewer Content Types

8 | 9 |

The viewer content types that may be selected relate to the types of specialised viewers that Charles has available 10 | (e.g. XML, Javascript and Protocol Buffers) and not to generic MIME types. For most of the viewer content types there is 11 | no further information to specify, the exception to this is the Protocol Buffers content type. When you select the 12 | Protocol Buffers content type you may specify the location (URL) of the protocol buffers descriptor file, the name of the 13 | message type and whether the content is a single message or a delimited list of messages.

14 | 15 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ViewerContentType.html: -------------------------------------------------------------------------------- 1 |

Viewer Content Type Mapping

2 |

3 | The Viewer Content Type Mappings allow you to explicitly map selected locations to particular viewer content types. 4 | This will automatically enable the appropriate content type specific viewers when viewing requests from those 5 | locations. 6 |

7 | 8 |

9 | Normally Charles attempts to automatically detect the appropriate viewer content type based upon the content of the 10 | request or response, usually based on the Content-Type header. However some websites do not set the correct 11 | Content-Type value for their content so not all of the appropriate content viewers are available. Configuring 12 | appropriate viewer content type mappings for these locations will allow you to view these requests with the 13 | best possible viewers. 14 |

15 | 16 |

How it works

17 |

18 | When a request that matches one of the configured mappings is viewed within Charles any viewers that are appropriate 19 | for the configured viewer content type are enabled in addition to the automatically detected viewers. No changes are 20 | made to the actual request or response. 21 |

22 | 23 | @@tools.gen.locations.locationMatching@@ 24 | 25 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ViewerContentTypeEditor.html: -------------------------------------------------------------------------------- 1 |

Viewer Content Type Mapping

2 |

A viewer content type mapping consists of a location match and the desired request and response viewer content type.

3 |

You may specify a desired request type or response type or both. You may also specify neither a request or response 4 | type in which case the mapping will have no effect. It is more usual to specify a response type as you are more likely 5 | to be interested in the viewing of response content than the request content (which is often empty)

6 | 7 |

Viewer Content Types

8 | 9 |

The viewer content types that may be selected relate to the types of specialised viewers that Charles has available 10 | (e.g. XML, Javascript and Protocol Buffers) and not to generic MIME types. For most of the viewer content types there is 11 | no further information to specify, the exception to this is the Protocol Buffers content type. When you select the 12 | Protocol Buffers content type you may specify the location (URL) of the protocol buffers descriptor file, the name of the 13 | message type and whether the content is a single message or a delimited list of messages.

14 | 15 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Breakpoints.html: -------------------------------------------------------------------------------- 1 |

Breakpoints Tool

2 |

The Breakpoints tool lets you intercept requests and responses before they are passed through Charles. You can 3 | examine and edit the request or response and then decide whether to allow it to proceed or to block it.

4 | 5 |

Each breakpoint matches a URL using location matching patterns, see below. Each breakpoint is also assigned 6 | to either the request, or response, or both so you break exactly where you want.

7 | 8 |

How it works

9 |

When a request or response trips a breakpoint the Breakpoints window automatically opens in Charles and comes to the front. The 10 | Breakpoints window contains a list of the requests and responses currently intercepted and waiting for your action. Select 11 | the request or response to view and edit the contents. Then decide to Execute, Abort or Cancel the breakpoint.

12 | 13 |

The Execute button applies any changes that you have made and lets the request or response proceed. The Abort button 14 | blocks the request or response and sends an error message to the client. The Cancel button discards any changes that you 15 | have made and lets the request or response proceed as if it wasn't intercepted.

16 | 17 | @@tools.gen.locations.locationMatching@@ -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Breakpoints.html: -------------------------------------------------------------------------------- 1 |

Breakpoints Tool

2 |

The Breakpoints tool lets you intercept requests and responses before they are passed through Charles. You can 3 | examine and edit the request or response and then decide whether to allow it to proceed or to block it.

4 | 5 |

Each breakpoint matches a URL using location matching patterns, see below. Each breakpoint is also assigned 6 | to either the request, or response, or both so you break exactly where you want.

7 | 8 |

How it works

9 |

When a request or response trips a breakpoint the Breakpoints window automatically opens in Charles and comes to the front. The 10 | Breakpoints window contains a list of the requests and responses currently intercepted and waiting for your action. Select 11 | the request or response to view and edit the contents. Then decide to Execute, Abort or Cancel the breakpoint.

12 | 13 |

The Execute button applies any changes that you have made and lets the request or response proceed. The Abort button 14 | blocks the request or response and sends an error message to the client. The Cancel button discards any changes that you 15 | have made and lets the request or response proceed as if it wasn't intercepted.

16 | 17 | @@tools.gen.locations.locationMatching@@ -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/NoCaching.html: -------------------------------------------------------------------------------- 1 |

No Caching Tool

2 |

3 | The No Caching tool prevents client applications, such as web browsers, from caching any resources. Therefore requests are always 4 | made to the remote website and you always see the latest version.

5 | 6 | @@tools.gen.locations.selectedLocations@@ 7 | 8 |

About caching

9 |

10 | Caching enables a client application, such as a web browser, to use a local copy of a response rather than 11 | requesting it from the website. Caching is a very important part of the web as often the same resources are reused across multiple pages, 12 | and having to reload each resource for each page would greatly slow down the browsing experience. However caching can mean 13 | that you are not seeing the latest version of a resource, which is a problem when you're developing a web application - 14 | you want to always see your latest changes. 15 |

16 | 17 |

How it works

18 |

The No Caching tool prevents caching by manipulating the HTTP headers that control the caching of responses. The If-Modified-Since and If-None-Match 19 | headers are removed from requests, Pragma: no-cache and Cache-control: no-cache are added. The Expires, Last-Modified and ETag headers are removed 20 | from responses and Expires: 0 and Cache-Control: no-cache are added.

21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/NoCaching.html: -------------------------------------------------------------------------------- 1 |

No Caching Tool

2 |

3 | The No Caching tool prevents client applications, such as web browsers, from caching any resources. Therefore requests are always 4 | made to the remote website and you always see the latest version.

5 | 6 | @@tools.gen.locations.selectedLocations@@ 7 | 8 |

About caching

9 |

10 | Caching enables a client application, such as a web browser, to use a local copy of a response rather than 11 | requesting it from the website. Caching is a very important part of the web as often the same resources are reused across multiple pages, 12 | and having to reload each resource for each page would greatly slow down the browsing experience. However caching can mean 13 | that you are not seeing the latest version of a resource, which is a problem when you're developing a web application - 14 | you want to always see your latest changes. 15 |

16 | 17 |

How it works

18 |

The No Caching tool prevents caching by manipulating the HTTP headers that control the caching of responses. The If-Modified-Since and If-None-Match 19 | headers are removed from requests, Pragma: no-cache and Cache-control: no-cache are added. The Expires, Last-Modified and ETag headers are removed 20 | from responses and Expires: 0 and Cache-Control: no-cache are added.

21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Rewrite.html: -------------------------------------------------------------------------------- 1 |

Rewrite Tool

2 |

The Rewrite tool enables you to create rules that modify requests and responses as they pass through Charles. Rules such as 3 | adding or changing a header or search and replace some text in the response body.

4 | 5 |

Rewrite Sets

6 |

Rewrite sets can be individual activated and deactivated. Each set contains a list of locations and rules. The locations 7 | choose the requests and responses on which the rules will operate.

8 | 9 |

Rewrite Rules

10 |

Each rule describes a single rewrite operation. The rule may affect the headers, the body, or parts of the request URL; it may operate 11 | on the request and or the response; it may then define search and replace or just replace style rewriting.

12 |

More documentation for the rewrite rules is available in the Rewrite Rule editing dialog.

13 | 14 | @@tools.gen.locations.locationMatching@@ 15 | 16 |

Debugging

17 |

The Rewrite tool can be difficult to debug when your rewrite operation isn't working as expected. If you have trouble try including a very basic rule 18 | such as one that adds an obvious header, so you can see whether your rules are matching the request at all. Also turn on Debug in Error Log to get some 19 | debugging information printed in the Error Log accessed from the Window menu in Charles.

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Rewrite.html: -------------------------------------------------------------------------------- 1 |

Rewrite Tool

2 |

The Rewrite tool enables you to create rules that modify requests and responses as they pass through Charles. Rules such as 3 | adding or changing a header or search and replace some text in the response body.

4 | 5 |

Rewrite Sets

6 |

Rewrite sets can be individual activated and deactivated. Each set contains a list of locations and rules. The locations 7 | choose the requests and responses on which the rules will operate.

8 | 9 |

Rewrite Rules

10 |

Each rule describes a single rewrite operation. The rule may affect the headers, the body, or parts of the request URL; it may operate 11 | on the request and or the response; it may then define search and replace or just replace style rewriting.

12 |

More documentation for the rewrite rules is available in the Rewrite Rule editing dialog.

13 | 14 | @@tools.gen.locations.locationMatching@@ 15 | 16 |

Debugging

17 |

The Rewrite tool can be difficult to debug when your rewrite operation isn't working as expected. If you have trouble try including a very basic rule 18 | such as one that adds an obvious header, so you can see whether your rules are matching the request at all. Also turn on Debug in Error Log to get some 19 | debugging information printed in the Error Log accessed from the Window menu in Charles.

-------------------------------------------------------------------------------- /src/main/java/charles/version461/modifiers/BundleStringEncodingModifier.java: -------------------------------------------------------------------------------- 1 | package charles.version461.modifiers; 2 | 3 | import java.io.IOException; 4 | 5 | import javassist.CannotCompileException; 6 | import javassist.ClassPool; 7 | import javassist.CtClass; 8 | import javassist.CtMethod; 9 | import javassist.NotFoundException; 10 | 11 | public class BundleStringEncodingModifier { 12 | public static void modify(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 13 | CtClass ctClass = classPool.get("com.xk72.lib.uAtD"); 14 | CtClass ccString = classPool.get("java.lang.String"); 15 | CtMethod ctMethod =ctClass.getDeclaredMethod("XdKP",new CtClass[]{ccString}); 16 | ctMethod.setBody("{int i = $1.indexOf(\"@@\");\n" + 17 | " while (i != -1) {\n" + 18 | " int j = $1.indexOf(\"@@\", i + 2);\n" + 19 | " if (j != -1) {\n" + 20 | " String str = $1.substring(i + 2, j);\n" + 21 | " $1 = $1.substring(0, i) + $1.substring(0, i) + getString(str);\n" + 22 | " i = $1.indexOf(\"@@\", i);\n" + 23 | " } \n" + 24 | " } \n" + 25 | "$1 = new String($1.getBytes(\"ISO-8859-1\"), \"utf-8\");\n"+ 26 | " return $1;}"); 27 | ctClass.writeFile(savePath); 28 | 29 | 30 | 31 | 32 | 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ExternalProxies.html: -------------------------------------------------------------------------------- 1 |

External Proxies

2 |

3 | You may have a proxy server on your network that you have to use in order to access the Internet. In that case you need to configure Charles to use your existing proxy when it attempts to access the Internet. 4 |

5 |

6 | You can configure separate proxy addresses and ports for: 7 |

8 | 13 |

14 | If you have a SOCKS proxy Charles will use it for all non-HTTP(S) traffic such as for Port Forwarding. 15 |

16 | 17 |

Authentication

18 |

19 | You can configure authentication information for each proxy type. Charles supports Basic Authentication and NTLM Authentication. 20 | For NTLM Authentication you can enter an option Domain field. 21 |

22 |

23 | If you don't configure authentication and your external proxy requests authentication Charles will pass on the authentication 24 | request to your browser as if Charles itself was requesting the authentication. 25 |

26 | 27 |

Bypass List

28 |

29 | You can enter a list of locations to bypass the external proxy for. This list is whitespace separated, each location is a host or ip address match with an optional port (eg. hostname:port). 30 | Wildcards are supported. 31 |

32 |

Note that previously Charles automatically did prefix matches on the bypass locations list. This was changed in Charles 3.5 to 33 | support the full location wildcard system. 34 |

35 | -------------------------------------------------------------------------------- /src/main/java/charles/version461/modifiers/ClassFileModifier.java: -------------------------------------------------------------------------------- 1 | package charles.version461.modifiers; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.StandardCopyOption; 7 | 8 | public class ClassFileModifier { 9 | public static void copySource(String sourcePath,String savePath){ 10 | System.out.println(); 11 | copy(sourcePath, sourcePath, savePath); 12 | } 13 | 14 | private static void copy(String originSourcePath, String sourcePath,String savePath){ 15 | File sourceFile = new File(sourcePath); 16 | File[] childFiles = sourceFile.listFiles(); 17 | if (childFiles != null){ 18 | for (File file : childFiles){ 19 | if (file.isFile()){ 20 | try { 21 | File destFile = new File(savePath, file.getAbsolutePath().replace(originSourcePath, "")); 22 | if (!destFile.getParentFile().exists()){ 23 | destFile.getParentFile().mkdirs(); 24 | } 25 | Files.copy(file.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } 29 | } else if (file.isDirectory()){ 30 | copy(originSourcePath, file.getAbsolutePath(), savePath); 31 | } 32 | 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/charles/version461/modifiers/JavaSourceReplace.java: -------------------------------------------------------------------------------- 1 | package charles.version461.modifiers; 2 | 3 | import javassist.*; 4 | 5 | import java.io.IOException; 6 | 7 | public class JavaSourceReplace { 8 | public static void modify(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 9 | addHelpMenu(classPool, savePath); 10 | register(classPool, savePath); 11 | } 12 | 13 | 14 | /** 15 | * help menu增加菜单 16 | */ 17 | private static void addHelpMenu(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 18 | CtClass ctClass = classPool.get("com.xk72.charles.gui.menus.HelpMenu"); 19 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 20 | ctConstructor.insertAfter("{" + 21 | "add(new com.xk72.charles.gui.menus.HelpMenuUrl(\"翻译支持\",\"https://github.com/cuiqingandroid/CharlesZH\"));" + 22 | "}"); 23 | ctClass.writeFile(savePath); 24 | } 25 | 26 | private static void register(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 27 | CtClass ctClass = classPool.get("com.xk72.charles.p"); 28 | CtMethod ctMethod =ctClass.getDeclaredMethod("a",null); 29 | ctMethod.setBody("{return true;}"); 30 | ctMethod = ctClass.getDeclaredMethod("c",null); 31 | ctMethod.setBody("{return \"cuiqing\";}"); 32 | ctClass.writeFile(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ExternalProxies.html: -------------------------------------------------------------------------------- 1 |

External Proxies

2 |

3 | You may have a proxy server on your network that you have to use in order to access the Internet. In that case you need to configure Charles to use your existing proxy when it attempts to access the Internet. 4 |

5 |

6 | You can configure separate proxy addresses and ports for: 7 |

8 | 13 |

14 | If you have a SOCKS proxy Charles will use it for all non-HTTP(S) traffic such as for Port Forwarding. 15 |

16 | 17 |

Authentication

18 |

19 | You can configure authentication information for each proxy type. Charles supports Basic Authentication and NTLM Authentication. 20 | For NTLM Authentication you can enter an option Domain field. 21 |

22 |

23 | If you don't configure authentication and your external proxy requests authentication Charles will pass on the authentication 24 | request to your browser as if Charles itself was requesting the authentication. 25 |

26 | 27 |

Bypass List

28 |

29 | You can enter a list of locations to bypass the external proxy for. This list is whitespace separated, each location is a host or ip address match with an optional port (eg. hostname:port). 30 | Wildcards are supported. 31 |

32 |

Note that previously Charles automatically did prefix matches on the bypass locations list. This was changed in Charles 3.5 to 33 | support the full location wildcard system. 34 |

35 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/MapLocalEditor.html: -------------------------------------------------------------------------------- 1 |

Local Mapping

2 |

A local mapping consists of a location match and the local directory from which to try to serve the matches.

3 |

Files are searched for in the local directory using the relative path. The relative path is the part of the 4 | requested location left over after the path part of the match. This is best explained by the examples below.

5 | 6 |

Local mappings can be case-sensitive, so that regardless of whether your local filesystem is in fact 7 | case-sensitive, the local mapping will always check the case. Case-sensitivity is the default.

8 | 9 |

Examples

10 |

The following examples help to explain how the location match relates to the local directory. The "local" 11 | column is presented as relative to the local directory.

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
HostPathRequestLocal
xk72.comxk72.com/charles/index.phpcharles/index.php
xk72.com/charles/xk72.com/charles/index.phpindex.php
xk72.com/*.phpxk72.com/charles/index.phpcharles/index.php
xk72.com/charles/*.phpxk72.com/charles/index.phpindex.php
44 | 45 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/MapLocalEditor.html: -------------------------------------------------------------------------------- 1 |

Local Mapping

2 |

A local mapping consists of a location match and the local directory from which to try to serve the matches.

3 |

Files are searched for in the local directory using the relative path. The relative path is the part of the 4 | requested location left over after the path part of the match. This is best explained by the examples below.

5 | 6 |

Local mappings can be case-sensitive, so that regardless of whether your local filesystem is in fact 7 | case-sensitive, the local mapping will always check the case. Case-sensitivity is the default.

8 | 9 |

Examples

10 |

The following examples help to explain how the location match relates to the local directory. The "local" 11 | column is presented as relative to the local directory.

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
HostPathRequestLocal
xk72.comxk72.com/charles/index.phpcharles/index.php
xk72.com/charles/xk72.com/charles/index.phpindex.php
xk72.com/*.phpxk72.com/charles/index.phpcharles/index.php
xk72.com/charles/*.phpxk72.com/charles/index.phpindex.php
44 | 45 | @@tools.gen.locations.locationMatchingEditor@@ -------------------------------------------------------------------------------- /src/main/java/charles/version461/Modifier461.java: -------------------------------------------------------------------------------- 1 | package charles.version461; 2 | 3 | import charles.VersionModifier; 4 | import charles.version461.modifiers.BundleStringEncodingModifier; 5 | import charles.version461.modifiers.JavaSourceReplace; 6 | import charles.version461.modifiers.MenuEncodingModifier; 7 | import charles.version461.modifiers.ClassFileModifier; 8 | import javassist.CannotCompileException; 9 | import javassist.ClassPool; 10 | import javassist.NotFoundException; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | 15 | public class Modifier461 extends VersionModifier { 16 | 17 | public Modifier461(String originJar, String savePath) { 18 | super(originJar, savePath); 19 | } 20 | 21 | @Override 22 | public boolean modifyByteCode() { 23 | try { 24 | ClassPool classPool=ClassPool.getDefault(); 25 | classPool.insertClassPath(getOriginJarPath()); 26 | BundleStringEncodingModifier.modify(classPool, getTempPath()); 27 | ClassFileModifier.copySource(getSourcePath(), getTempPath()); 28 | MenuEncodingModifier.modify(classPool, getTempPath()); 29 | JavaSourceReplace.modify(classPool, getTempPath()); 30 | return true; 31 | } catch (NotFoundException | CannotCompileException | IOException e) { 32 | e.printStackTrace(); 33 | } 34 | return false; 35 | } 36 | 37 | @Override 38 | public String getSourcePath() { 39 | return new File(System.getProperty("user.dir"),"src/main/java/charles/version461/source").getAbsolutePath(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ProxySettings-Mozilla.html: -------------------------------------------------------------------------------- 1 |

Mozilla Firefox Proxy Settings

2 |

Charles can automatically configure Mozilla Firefox's proxy settings. When the proxy settings 3 | are configured, Firefox will use Charles and thus its activity 4 | will be visible in Charles. Firefox is configured separately from your OS proxy settings as it uses 5 | its own proxy settings independent of your OS.

6 | 7 |

You can enable the proxy configuration and then choose whether to configure Firefox to use Charles 8 | as an HTTP proxy or SOCKS proxy, if the SOCKS Proxy is itself enables on the Proxies tab. See the Proxies 9 | tab for information on the differences between HTTP and SOCKS.

10 | 11 |

The Firefox proxy configuration can be enabled at start up, which is the default behaviour, so 12 | that when you start Charles it is ready to be used. Alternatively you can disable this and enable the Firefox 13 | proxy settings manually or configure Firefox manually to use Charles with 14 | its own proxy settings configuration interface.

15 | 16 |

Mozilla Firefox Add-on

17 |

In order to configure Mozilla Firefox's proxy settings you must install the Charles Autoconfiguration 18 | add-on for Mozilla Firefox. You will be notified if the add-on is not installed and prompted to download 19 | and install it.

20 | 21 |

Manually choose profile path

22 |

Charles automatically locates your Mozilla Firefox profile for the purposes of configuring the proxy settings. 23 | Sometimes Charles may be unable to find your profile directory, although this is extremely rare so you should 24 | only use this option if you have no success with auto detection.

25 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ProxySettings-Mozilla.html: -------------------------------------------------------------------------------- 1 |

Mozilla Firefox Proxy Settings

2 |

Charles can automatically configure Mozilla Firefox's proxy settings. When the proxy settings 3 | are configured, Firefox will use Charles and thus its activity 4 | will be visible in Charles. Firefox is configured separately from your OS proxy settings as it uses 5 | its own proxy settings independent of your OS.

6 | 7 |

You can enable the proxy configuration and then choose whether to configure Firefox to use Charles 8 | as an HTTP proxy or SOCKS proxy, if the SOCKS Proxy is itself enables on the Proxies tab. See the Proxies 9 | tab for information on the differences between HTTP and SOCKS.

10 | 11 |

The Firefox proxy configuration can be enabled at start up, which is the default behaviour, so 12 | that when you start Charles it is ready to be used. Alternatively you can disable this and enable the Firefox 13 | proxy settings manually or configure Firefox manually to use Charles with 14 | its own proxy settings configuration interface.

15 | 16 |

Mozilla Firefox Add-on

17 |

In order to configure Mozilla Firefox's proxy settings you must install the Charles Autoconfiguration 18 | add-on for Mozilla Firefox. You will be notified if the add-on is not installed and prompted to download 19 | and install it.

20 | 21 |

Manually choose profile path

22 |

Charles automatically locates your Mozilla Firefox profile for the purposes of configuring the proxy settings. 23 | Sometimes Charles may be unable to find your profile directory, although this is extremely rare so you should 24 | only use this option if you have no success with auto detection.

25 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Mirror.html: -------------------------------------------------------------------------------- 1 |

Mirror Tool

2 |

The Mirror tool saves responses to disk as they are received, creating a mirror copy of websites as you browse them.

3 | 4 |

The responses are saved in the same directory structure as the website, with a root directory created for the hostname. 5 | File names are derived from the URL and converted to be suitable for saving. Query strings are included in the filename.

6 | 7 |

If two responses are received for the same URL they overwrite each other, so you will always have the latest response 8 | saved in the mirror.

9 | 10 |

The Mirror tool saves responses as they stream through Charles, therefore it is not effected by the recording limit set in 11 | the Recording Settings.

12 | 13 | @@tools.gen.locations.selectedLocations@@ 14 | 15 |

Alternative

16 |

Rather than using the Mirror tool you can also right-click on a node in the tree in Charles to save all the responses 17 | to disk after you've recorded them; that may prove to be an easier approach than configuring this tool. 18 | The only exception to this is that the Mirror tool is not limited by the recording limit set in the Recording Settings, 19 | whereas saving responses later is limited so very large responses will be lost.

20 | 21 |

Side Effects

22 |

23 | If the Mirror tool is enabled for a request it will cause any compressed or encoded responses to be decoded. 24 | So if the server delivers a compressed response it will be decompressed by Charles before being passed on 25 | to the client, which usually won't have any effect but you may notice if you have built your own client or 26 | if the client is expecting compressed responses. With web browsers there is no effect. 27 |

28 | 29 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Mirror.html: -------------------------------------------------------------------------------- 1 |

Mirror Tool

2 |

The Mirror tool saves responses to disk as they are received, creating a mirror copy of websites as you browse them.

3 | 4 |

The responses are saved in the same directory structure as the website, with a root directory created for the hostname. 5 | File names are derived from the URL and converted to be suitable for saving. Query strings are included in the filename.

6 | 7 |

If two responses are received for the same URL they overwrite each other, so you will always have the latest response 8 | saved in the mirror.

9 | 10 |

The Mirror tool saves responses as they stream through Charles, therefore it is not effected by the recording limit set in 11 | the Recording Settings.

12 | 13 | @@tools.gen.locations.selectedLocations@@ 14 | 15 |

Alternative

16 |

Rather than using the Mirror tool you can also right-click on a node in the tree in Charles to save all the responses 17 | to disk after you've recorded them; that may prove to be an easier approach than configuring this tool. 18 | The only exception to this is that the Mirror tool is not limited by the recording limit set in the Recording Settings, 19 | whereas saving responses later is limited so very large responses will be lost.

20 | 21 |

Side Effects

22 |

23 | If the Mirror tool is enabled for a request it will cause any compressed or encoded responses to be decoded. 24 | So if the server delivers a compressed response it will be decompressed by Charles before being passed on 25 | to the client, which usually won't have any effect but you may notice if you have built your own client or 26 | if the client is expecting compressed responses. With web browsers there is no effect. 27 |

28 | 29 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Map.html: -------------------------------------------------------------------------------- 1 |

Map Remote Tool

2 |

The Map Remote tool changes the request location, per the configured mappings, so that the response 3 | is transparently served from the new location as if that was the original request.

4 |

This mapping enables you to serve all or part of one site from another. For example, you could serve 5 | a subdirectory of one site for another with a mapping from xk72.com/charles/ to localhost/charlesdev/, 6 | or serve all files with a given suffix from another site with a mapping from xk72.com/*.php to localhost/charlesdev/.

7 | 8 |

Usage Suggestions

9 |

Map Remote is useful if you have a development version of a site and would like to be able to browse the live 10 | site with some of the requests being served from development. For example, you may want to serve the css and images 11 | directories from your development server. Use a mapping like live.com/css/ to dev.com/css/ or live.com/*.css to dev.com. 12 | 13 |

Mapping Types

14 | 19 | 20 |

If you don't specify a path in the destination mapping then the path part of the URL will not be changed. If you want 21 | to map to the root directory, put a / in the destination path field.

22 | 23 |

Map Local

24 |

Also see the Map Local tool, which can serve requests from local files so you can use the latest development 25 | files from your computer as if they were part of a remote website.

26 | 27 | @@tools.gen.locations.locationMatching@@ -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Map.html: -------------------------------------------------------------------------------- 1 |

Map Remote Tool

2 |

The Map Remote tool changes the request location, per the configured mappings, so that the response 3 | is transparently served from the new location as if that was the original request.

4 |

This mapping enables you to serve all or part of one site from another. For example, you could serve 5 | a subdirectory of one site for another with a mapping from xk72.com/charles/ to localhost/charlesdev/, 6 | or serve all files with a given suffix from another site with a mapping from xk72.com/*.php to localhost/charlesdev/.

7 | 8 |

Usage Suggestions

9 |

Map Remote is useful if you have a development version of a site and would like to be able to browse the live 10 | site with some of the requests being served from development. For example, you may want to serve the css and images 11 | directories from your development server. Use a mapping like live.com/css/ to dev.com/css/ or live.com/*.css to dev.com. 12 | 13 |

Mapping Types

14 | 19 | 20 |

If you don't specify a path in the destination mapping then the path part of the URL will not be changed. If you want 21 | to map to the root directory, put a / in the destination path field.

22 | 23 |

Map Local

24 |

Also see the Map Local tool, which can serve requests from local files so you can use the latest development 25 | files from your computer as if they were part of a remote website.

26 | 27 | @@tools.gen.locations.locationMatching@@ -------------------------------------------------------------------------------- /src/main/java/org/cq/jartool/resource/jar_zh_CN.java: -------------------------------------------------------------------------------- 1 | package org.cq.jartool.resource; 2 | 3 | import java.util.ListResourceBundle; 4 | 5 | public final class jar_zh_CN extends ListResourceBundle { 6 | public jar_zh_CN() { 7 | } 8 | 9 | protected final Object[][] getContents() { 10 | return new Object[][]{{"error.bad.cflag", "'c' 标记要求指定清单或输入文件!"}, {"error.bad.eflag", "不能同时指定 'e' 标记和具有 'Main-Class' 属性的\n清单!"}, {"error.bad.option", "必须指定 {ctxu} 中的任一选项。"}, {"error.bad.uflag", "'u' 标记要求指定清单, 'e' 标记或输入文件!"}, {"error.cant.open", "无法打开: {0} "}, {"error.create.dir", "{0}: 无法创建目录"}, {"error.create.tempfile", "无法创建临时文件"}, {"error.illegal.option", "非法选项: {0}"}, {"error.incorrect.length", "处理时遇到不正确的长度: {0}"}, {"error.nosuch.fileordir", "{0}: 没有这个文件或目录"}, {"error.write.file", "写入现有的 jar 文件时出错"}, {"out.added.manifest", "已添加清单"}, {"out.adding", "正在添加: {0}"}, {"out.create", " 已创建: {0}"}, {"out.deflated", "(压缩了 {0}%)"}, {"out.extracted", "已提取: {0}"}, {"out.ignore.entry", "正在忽略条目{0}"}, {"out.inflated", " 已解压: {0}"}, {"out.size", "(输入 = {0}) (输出 = {1})"}, {"out.stored", "(存储了 0%)"}, {"out.update.manifest", "已更新清单"}, {"usage", "用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n选项:\n -c 创建新档案\n -t 列出档案目录\n -x 从档案中提取指定的 (或所有) 文件\n -u 更新现有档案\n -v 在标准输出中生成详细输出\n -f 指定档案文件名\n -m 包含指定清单文件中的清单信息\n -n 创建新档案后执行 Pack200 规范化\n -e 为捆绑到可执行 jar 文件的独立应用程序\n 指定应用程序入口点\n -0 仅存储; 不使用任何 ZIP 压缩\n -P 保留文件名中的前导 '/' (绝对路径) 和 \"..\" (父目录) 组件\n -M 不创建条目的清单文件\n -i 为指定的 jar 文件生成索引信息\n -C 更改为指定的目录并包含以下文件\n如果任何文件为目录, 则对其进行递归处理。\n清单文件名, 档案文件名和入口点名称的指定顺序\n与 'm', 'f' 和 'e' 标记的指定顺序相同。\n\n示例 1: 将两个类文件归档到一个名为 classes.jar 的档案中: \n jar cvf classes.jar Foo.class Bar.class \n示例 2: 使用现有的清单文件 'mymanifest' 并\n 将 foo/ 目录中的所有文件归档到 'classes.jar' 中: \n jar cvfm classes.jar mymanifest -C foo/ .\n"}}; 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/MapLocal.html: -------------------------------------------------------------------------------- 1 |

Map Local Tool

2 |

3 | The Map Local tool enables you to use local files as if they were part of a remote website. 4 | You can develop your files locally and test them as if they were live. 5 | The contents of the local file is returned to the client as if it was the normal remote response. 6 |

7 | 8 |

9 | Map Local can greatly speed development and testing in the case where you would otherwise have to upload files to 10 | a website to test the results. With Map Local you can test safely in your development environment. 11 |

12 | 13 |

Dynamic files

14 |

Dynamic files, such as files containing server-side scripting, 15 | aren't executed by Map Local so if there is any script in the file that script will be returned to the browser 16 | as is - probably not the intended result. 17 |

18 |

19 | If you'd like to use dynamic files as if they were part of a remote website, 20 | see the Map Remote tool. 21 |

22 | 23 |

How it works

24 |

25 | When a request matches a Map Local mapping it checks for a local file matching the path. 26 | It does not include the query string, if there is one. If the requested file is found locally 27 | then it is returned as the response, as if it was loaded from the remote site so it is 28 | transparent to the client. If the requested file isn't found locally then the request will be 29 | served by the website as usual. 30 |

31 | 32 |

Examples

33 |

If you are testing css, swf or image changes you can map those file types to your local development 34 | copy of the website so you can browse the live site with all your development assets. Create a mapping 35 | from live.com/*.css to the root of your local development copy, and similar mappings for the other file types. 36 | Alternatively you can map whole directories or individual files as required. 37 |

38 | 39 | @@tools.gen.locations.locationMatching@@ 40 | 41 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/MapLocal.html: -------------------------------------------------------------------------------- 1 |

Map Local Tool

2 |

3 | The Map Local tool enables you to use local files as if they were part of a remote website. 4 | You can develop your files locally and test them as if they were live. 5 | The contents of the local file is returned to the client as if it was the normal remote response. 6 |

7 | 8 |

9 | Map Local can greatly speed development and testing in the case where you would otherwise have to upload files to 10 | a website to test the results. With Map Local you can test safely in your development environment. 11 |

12 | 13 |

Dynamic files

14 |

Dynamic files, such as files containing server-side scripting, 15 | aren't executed by Map Local so if there is any script in the file that script will be returned to the browser 16 | as is - probably not the intended result. 17 |

18 |

19 | If you'd like to use dynamic files as if they were part of a remote website, 20 | see the Map Remote tool. 21 |

22 | 23 |

How it works

24 |

25 | When a request matches a Map Local mapping it checks for a local file matching the path. 26 | It does not include the query string, if there is one. If the requested file is found locally 27 | then it is returned as the response, as if it was loaded from the remote site so it is 28 | transparent to the client. If the requested file isn't found locally then the request will be 29 | served by the website as usual. 30 |

31 | 32 |

Examples

33 |

If you are testing css, swf or image changes you can map those file types to your local development 34 | copy of the website so you can browse the live site with all your development assets. Create a mapping 35 | from live.com/*.css to the root of your local development copy, and similar mappings for the other file types. 36 | Alternatively you can map whole directories or individual files as required. 37 |

38 | 39 | @@tools.gen.locations.locationMatching@@ 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/charles/version461/modifiers/MenuEncodingModifier.java: -------------------------------------------------------------------------------- 1 | package charles.version461.modifiers; 2 | 3 | import javassist.*; 4 | 5 | import java.io.IOException; 6 | 7 | import javax.swing.AbstractAction; 8 | 9 | public class MenuEncodingModifier { 10 | public static void modify(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 11 | modifyViewMenu(classPool, savePath); 12 | modifySessionMenu(classPool, savePath); 13 | } 14 | 15 | /** 16 | * 修改文件菜单的open和import 17 | */ 18 | private static void modifySessionMenu(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 19 | CtClass ctClass = classPool.get("com.xk72.charles.ZOpb"); 20 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 21 | ctConstructor.setBody("{kbzH = (javax.swing.Action)new com.xk72.charles.CharlesGUIFileManager$1(this, \"打开会话\",\"打开之前的会话\");ERKX = (javax.swing.Action)new com.xk72.charles.CharlesGUIFileManager$2(this, \"导入\", \"导入文件到会话\");}"); 22 | ctClass.writeFile(savePath); 23 | } 24 | 25 | /** 26 | * 修改视图菜单 27 | */ 28 | private static void modifyViewMenu(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 29 | CtClass ctClass = classPool.get("com.xk72.charles.gui.transaction.frames.SkbX"); 30 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 31 | ctConstructor.insertAfter("{" + 32 | "kbzH.putValue(javax.swing.Action.NAME, \"备注\");" + 33 | "ERKX.putValue(javax.swing.Action.NAME, \"请求\");" + 34 | "gMxR.putValue(javax.swing.Action.NAME, \"响应\");" + 35 | "PRdh.putValue(javax.swing.Action.NAME, \"总览\");" + 36 | "Idso.putValue(javax.swing.Action.NAME, \"概览\");" + 37 | "Vvaz.putValue(javax.swing.Action.NAME, \"图表\");" + 38 | "}"); 39 | ctClass.writeFile(savePath); 40 | } 41 | 42 | 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ReverseProxiesEditor.html: -------------------------------------------------------------------------------- 1 |

Local Port

2 |

The port on the localhost to create the reverse proxy on. This field may be automatically populated with an available port. If there is 3 | another application using that port you will receive a warning message when the reverse proxy starts.

4 |

eg. Given a local port of 8001 you will connect to the reverse proxy at http://localhost:8001/

5 | 6 |

Remote Host and Port

7 |

The hostname or IP address and port of the remote host that is the destination of the reverse proxy. 8 | The remote port defaults to 80 which is the default port for HTTP.

9 |

eg. Enter a remote host of xk72.com and a remote port of 80, then http://localhost:8001/ will be as if you had connected 10 | to http://xk72.com/

11 | 12 |

Options

13 | 14 |

Rewrite Redirects

15 |

16 | Redirect responses from the remote server will be rewritten to match the 17 | reverse proxy source address. Defaults to on. 18 |

19 |

Redirect responses from the remote server are to fully qualified 20 | URLs even if they are within the same website. If the redirect is to the remote server address it is necessary to rewrite 21 | it to the reverse proxy local address, otherwise the client will use the redirect URL to 22 | the remote host and thus no longer be connecting through the reverse proxy. 23 |

24 | 25 |

Preserve Host Header

26 |

27 | The Host HTTP header is passed unchanged from the incoming request, 28 | instead of the normal rewriting of the Host header to match the reverse proxy remote host. 29 | Defaults to off. 30 |

31 |

32 | Preserving the Host header is only necessary if you have specific requirements; it is not required for ordinary use. 33 |

34 | 35 |

Listen On A Specific Address

36 |

37 | If you want to specify the local address to listen on for the reverse proxy you can enable this option and enter in the IP address here. 38 | This is useful if you want to run multiple network services on the same port but on different IP addresses on the same machine. 39 | When this option is disabled the reverse proxy binds to all available local addresses. 40 |

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ReverseProxiesEditor.html: -------------------------------------------------------------------------------- 1 |

Local Port

2 |

The port on the localhost to create the reverse proxy on. This field may be automatically populated with an available port. If there is 3 | another application using that port you will receive a warning message when the reverse proxy starts.

4 |

eg. Given a local port of 8001 you will connect to the reverse proxy at http://localhost:8001/

5 | 6 |

Remote Host and Port

7 |

The hostname or IP address and port of the remote host that is the destination of the reverse proxy. 8 | The remote port defaults to 80 which is the default port for HTTP.

9 |

eg. Enter a remote host of xk72.com and a remote port of 80, then http://localhost:8001/ will be as if you had connected 10 | to http://xk72.com/

11 | 12 |

Options

13 | 14 |

Rewrite Redirects

15 |

16 | Redirect responses from the remote server will be rewritten to match the 17 | reverse proxy source address. Defaults to on. 18 |

19 |

Redirect responses from the remote server are to fully qualified 20 | URLs even if they are within the same website. If the redirect is to the remote server address it is necessary to rewrite 21 | it to the reverse proxy local address, otherwise the client will use the redirect URL to 22 | the remote host and thus no longer be connecting through the reverse proxy. 23 |

24 | 25 |

Preserve Host Header

26 |

27 | The Host HTTP header is passed unchanged from the incoming request, 28 | instead of the normal rewriting of the Host header to match the reverse proxy remote host. 29 | Defaults to off. 30 |

31 |

32 | Preserving the Host header is only necessary if you have specific requirements; it is not required for ordinary use. 33 |

34 | 35 |

Listen On A Specific Address

36 |

37 | If you want to specify the local address to listen on for the reverse proxy you can enable this option and enter in the IP address here. 38 | This is useful if you want to run multiple network services on the same port but on different IP addresses on the same machine. 39 | When this option is disabled the reverse proxy binds to all available local addresses. 40 |

-------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Protobuf.html: -------------------------------------------------------------------------------- 1 |

Protocol Buffers Descriptor Registry

2 |

3 | Charles identifies that an HTTP request or response contains a Protocol Buffers message when the Content-Type header has a MIME type of 4 | application/x-protobuf or application/x-google-protobuf. 5 |

6 |

7 | In order to parse the content Charles needs to know the protobuf type for the message and be able to load the protobuf descriptor for that type. 8 | The message type can be specified by: 9 |

    10 |
  1. Giving the fully qualified name of the type in a MIME type parameter (named messageType) as part of the Content-Type header
  2. 11 |
  3. Configuring a Viewer Mapping for the remote location the message was transported to or from
  4. 12 |
13 | Similarly there are two ways to supply the descriptor to Charles: 14 |
    15 |
  1. The URL from which the descriptor can be loaded can be given in another MIME type parameter (named desc) as part of the Content-Type header
  2. 16 |
  3. Add the descriptor file to this registry
  4. 17 |
18 | A Content-Type header specifying both the descriptor and messageType would look like: 19 | 20 |

Content-Type: application/x-protobuf; desc="http://server/Model.desc"; messageType="com.sample.Message"

21 | 22 |

23 |

24 | There are two base descriptor files - google.protobuf.desc and unknown.desc - that contain the default message types used by Charles, these descriptors cannot be removed. 25 |

26 |

27 | Order is important, the descriptors are loaded in the order in which they appear in the registry list, so if you have dependencies between your descriptor files you need to add them in the correct order. 28 | Additionally if you have same message type defined in more than one descriptor whichever descriptor is loaded last takes precedence. 29 | This means you can overwrite the default set of message types in google.protobuf.desc by adding a new descriptor with updated versions of those message types to your registry. 30 |

31 |

32 | The Messages list is not editable, it simply allows you to inspect the list of message types contained within the currently loaded descriptor files. 33 |

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Protobuf.html: -------------------------------------------------------------------------------- 1 |

Protocol Buffers Descriptor Registry

2 |

3 | Charles identifies that an HTTP request or response contains a Protocol Buffers message when the Content-Type header has a MIME type of 4 | application/x-protobuf or application/x-google-protobuf. 5 |

6 |

7 | In order to parse the content Charles needs to know the protobuf type for the message and be able to load the protobuf descriptor for that type. 8 | The message type can be specified by: 9 |

    10 |
  1. Giving the fully qualified name of the type in a MIME type parameter (named messageType) as part of the Content-Type header
  2. 11 |
  3. Configuring a Viewer Mapping for the remote location the message was transported to or from
  4. 12 |
13 | Similarly there are two ways to supply the descriptor to Charles: 14 |
    15 |
  1. The URL from which the descriptor can be loaded can be given in another MIME type parameter (named desc) as part of the Content-Type header
  2. 16 |
  3. Add the descriptor file to this registry
  4. 17 |
18 | A Content-Type header specifying both the descriptor and messageType would look like: 19 | 20 |

Content-Type: application/x-protobuf; desc="http://server/Model.desc"; messageType="com.sample.Message"

21 | 22 |

23 |

24 | There are two base descriptor files - google.protobuf.desc and unknown.desc - that contain the default message types used by Charles, these descriptors cannot be removed. 25 |

26 |

27 | Order is important, the descriptors are loaded in the order in which they appear in the registry list, so if you have dependencies between your descriptor files you need to add them in the correct order. 28 | Additionally if you have same message type defined in more than one descriptor whichever descriptor is loaded last takes precedence. 29 | This means you can overwrite the default set of message types in google.protobuf.desc by adding a new descriptor with updated versions of those message types to your registry. 30 |

31 |

32 | The Messages list is not editable, it simply allows you to inspect the list of message types contained within the currently loaded descriptor files. 33 |

-------------------------------------------------------------------------------- /src/main/java/org/cq/jartool/CommandLine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. 3 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 | * 5 | * 6 | * 7 | * 8 | * 9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | */ 25 | 26 | package org.cq.jartool; 27 | 28 | import java.io.IOException; 29 | import java.io.Reader; 30 | import java.io.FileReader; 31 | import java.io.BufferedReader; 32 | import java.io.StreamTokenizer; 33 | import java.util.List; 34 | import java.util.ArrayList; 35 | 36 | /** 37 | * Various utility methods for processing Java tool command line arguments. 38 | * 39 | *

This is NOT part of any API supported by Oracle. If 40 | * you write code that depends on this, you do so at your own risk. 41 | * This code and its internal interfaces are subject to change or 42 | * deletion without notice. 43 | */ 44 | public class CommandLine { 45 | /** 46 | * Process Win32-style command files for the specified command line 47 | * arguments and return the resulting arguments. A command file argument 48 | * is of the form '@file' where 'file' is the name of the file whose 49 | * contents are to be parsed for additional arguments. The contents of 50 | * the command file are parsed using StreamTokenizer and the original 51 | * '@file' argument replaced with the resulting tokens. Recursive command 52 | * files are not supported. The '@' character itself can be quoted with 53 | * the sequence '@@'. 54 | */ 55 | public static String[] parse(String[] args) 56 | throws IOException 57 | { 58 | List newArgs = new ArrayList<>(args.length); 59 | for (int i = 0; i < args.length; i++) { 60 | String arg = args[i]; 61 | if (arg.length() > 1 && arg.charAt(0) == '@') { 62 | arg = arg.substring(1); 63 | if (arg.charAt(0) == '@') { 64 | newArgs.add(arg); 65 | } else { 66 | loadCmdFile(arg, newArgs); 67 | } 68 | } else { 69 | newArgs.add(arg); 70 | } 71 | } 72 | return newArgs.toArray(new String[newArgs.size()]); 73 | } 74 | 75 | private static void loadCmdFile(String name, List args) 76 | throws IOException 77 | { 78 | Reader r = new BufferedReader(new FileReader(name)); 79 | StreamTokenizer st = new StreamTokenizer(r); 80 | st.resetSyntax(); 81 | st.wordChars(' ', 255); 82 | st.whitespaceChars(0, ' '); 83 | st.commentChar('#'); 84 | st.quoteChar('"'); 85 | st.quoteChar('\''); 86 | while (st.nextToken() != StreamTokenizer.TT_EOF) { 87 | args.add(st.sval); 88 | } 89 | r.close(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/Throttling.html: -------------------------------------------------------------------------------- 1 |

Throttle Settings

2 |

3 | Throttling allows you to restrict the available bandwidth client applications, such as web browsers, may use to access remote servers. 4 | You can also introduce additional latency, reliability and stability constraints. 5 | This functionality allows you to simulate various connection situations, such as slow, high latency or unstable internet connections. 6 |

7 | 8 | @@tools.gen.locations.selectedLocations@@ 9 | 10 |

Throttle Presets

11 |

12 | There are a number of pre-defined throttle presets that simulate common internet connection types. 13 | New presets may be created by editing the throttle settings of an existing preset and selecting 'Add Preset'. 14 | Presets that you create may be removed later. The pre-defined presets cannot be removed. 15 |

16 | 17 |

Bandwidth

18 |

19 | Bandwidth defines the maximum amount of data that can be transferred over time, it is specified in kilobits per second. You can specify different bandwidth limits for upload and download links. 20 |

21 | 22 |

Utilisation

23 |

24 | Utilisation is the percentage of the total bandwidth that can be used at any one time. It is simply applied as a scaling factor on the available bandwidth. 25 | For most modern internet connections utilisation is always 100%. 26 |

27 | 28 |

Latency

29 |

30 | Latency measures the delay in milliseconds on the first round-trip communication between the client and remote server. It is only applied once for each request from client to server. 31 |

32 | 33 |

MTU

34 |

35 | MTU is the maximum transmission unit, the largest size for a TCP packet in any transmission. 36 | Specifying the MTU doesn't change the available bandwidth but allows Charles to allocate the bandwidth in MTU sized chunks, resulting in a realistic level of packet fragmentation in each transmission. 37 |

38 | 39 |

Reliability

40 |

41 | Reliability is a measure of how likely a connection is to fail completely. This is useful for simulating unreliable network conditions. 42 | Reliability is specified as the likelihood of successfully transmitting a 10KiB message, so a value of 50% means that half of all 10KiB transmissions will succeed. 43 | Larger messages or smaller messages are more or less likely to fail respectively, so that a 20KiB transmission would have only a 25% success rate and a 5KiB transmission approximately 70% success rate. 44 |

45 | 46 |

Stability

47 |

48 | Stability is a measure of how likely a connection is to be 'unstable' and therefore have reduced quality. 49 | This is useful for simulating networks, such as mobile networks, that periodically have poor connection quality. 50 | If a connection is unstable then the quality of the connection will fall randomly in the unstable quality range. 51 | This quality value is then applied as another scaling factor on the available bandwidth. 52 |

53 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/LocationsTableHelper.html: -------------------------------------------------------------------------------- 1 |

Location matching

2 |

3 | The location match contains protocol, host, port and path fields that may be used to match the URL of the request. 4 | Any of the fields may be left blank, in which case they will match any value. 5 |

6 | 7 |

Wildcards

8 |

Wildcards are supported using either *, ? or character ranges [...]. The * matches zero or more characters. The ? matches one character. 9 | Character ranges match one character in the range, eg. [a-z] or [aeiou].

10 | 11 |

Paths

12 |

13 | To match subpaths you must end your path with a /*. NOTE: In previous versions of Charles this was implicit, but it is now required. 14 |

15 | 16 |

Query

17 |

18 | The query field matches the query string contents. Do not include the ? that starts the query string. 19 | Note that the ? character is a wildcard character. 20 |

21 |

22 | The query field can include wildcards, like the other fields, so you can do queries such as: "*page=1*" to match "page=1" anywhere 23 | in the query string. 24 |

25 | 26 |

Common Uses

27 |

28 | To match every request to a given host enter the hostname and leave the other fields blank. 29 | To match every request to a given path on a host enter the hostname and the path ending with a /, leave the other fields blank. 30 | To match every file with a given suffix on a host enter the hostname and /*.suffix, leave the other fields blank. 31 |

32 | 33 |

Examples

34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
HostPathResult
charlesproxy.comMatches all requests to host charlesproxy.com
*.charlesproxy.comMatches all requests to hosts ending in .charlesproxy.com
charlesproxy.com/charles/Matches all requests to charlesproxy.com/charles/ only
charlesproxy.com/charles/*Matches all requests to charlesproxy.com/charles/ including files and subpaths
charlesproxy.com/charlesMatches all requests to charlesproxy.com/charles only
charlesproxy.com/index.htmlMatches all requests to charlesproxy.com/charles.html only
charlesproxy.com/*.htmlMatches all requests to files ending in .html on host charlesproxy.com
/charles/*.htmlMatches all requests to files ending in .html under the path /charles/ (including subpaths) on any host
81 | 82 |

Protocol and port matches can be added to the above to further narrow the location match.

-------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/Throttling.html: -------------------------------------------------------------------------------- 1 |

Throttle Settings

2 |

3 | Throttling allows you to restrict the available bandwidth client applications, such as web browsers, may use to access remote servers. 4 | You can also introduce additional latency, reliability and stability constraints. 5 | This functionality allows you to simulate various connection situations, such as slow, high latency or unstable internet connections. 6 |

7 | 8 | @@tools.gen.locations.selectedLocations@@ 9 | 10 |

Throttle Presets

11 |

12 | There are a number of pre-defined throttle presets that simulate common internet connection types. 13 | New presets may be created by editing the throttle settings of an existing preset and selecting 'Add Preset'. 14 | Presets that you create may be removed later. The pre-defined presets cannot be removed. 15 |

16 | 17 |

Bandwidth

18 |

19 | Bandwidth defines the maximum amount of data that can be transferred over time, it is specified in kilobits per second. You can specify different bandwidth limits for upload and download links. 20 |

21 | 22 |

Utilisation

23 |

24 | Utilisation is the percentage of the total bandwidth that can be used at any one time. It is simply applied as a scaling factor on the available bandwidth. 25 | For most modern internet connections utilisation is always 100%. 26 |

27 | 28 |

Latency

29 |

30 | Latency measures the delay in milliseconds on the first round-trip communication between the client and remote server. It is only applied once for each request from client to server. 31 |

32 | 33 |

MTU

34 |

35 | MTU is the maximum transmission unit, the largest size for a TCP packet in any transmission. 36 | Specifying the MTU doesn't change the available bandwidth but allows Charles to allocate the bandwidth in MTU sized chunks, resulting in a realistic level of packet fragmentation in each transmission. 37 |

38 | 39 |

Reliability

40 |

41 | Reliability is a measure of how likely a connection is to fail completely. This is useful for simulating unreliable network conditions. 42 | Reliability is specified as the likelihood of successfully transmitting a 10KiB message, so a value of 50% means that half of all 10KiB transmissions will succeed. 43 | Larger messages or smaller messages are more or less likely to fail respectively, so that a 20KiB transmission would have only a 25% success rate and a 5KiB transmission approximately 70% success rate. 44 |

45 | 46 |

Stability

47 |

48 | Stability is a measure of how likely a connection is to be 'unstable' and therefore have reduced quality. 49 | This is useful for simulating networks, such as mobile networks, that periodically have poor connection quality. 50 | If a connection is unstable then the quality of the connection will fall randomly in the unstable quality range. 51 | This quality value is then applied as another scaling factor on the available bandwidth. 52 |

53 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/LocationsTableHelper.html: -------------------------------------------------------------------------------- 1 |

Location matching

2 |

3 | The location match contains protocol, host, port and path fields that may be used to match the URL of the request. 4 | Any of the fields may be left blank, in which case they will match any value. 5 |

6 | 7 |

Wildcards

8 |

Wildcards are supported using either *, ? or character ranges [...]. The * matches zero or more characters. The ? matches one character. 9 | Character ranges match one character in the range, eg. [a-z] or [aeiou].

10 | 11 |

Paths

12 |

13 | To match subpaths you must end your path with a /*. NOTE: In previous versions of Charles this was implicit, but it is now required. 14 |

15 | 16 |

Query

17 |

18 | The query field matches the query string contents. Do not include the ? that starts the query string. 19 | Note that the ? character is a wildcard character. 20 |

21 |

22 | The query field can include wildcards, like the other fields, so you can do queries such as: "*page=1*" to match "page=1" anywhere 23 | in the query string. 24 |

25 | 26 |

Common Uses

27 |

28 | To match every request to a given host enter the hostname and leave the other fields blank. 29 | To match every request to a given path on a host enter the hostname and the path ending with a /, leave the other fields blank. 30 | To match every file with a given suffix on a host enter the hostname and /*.suffix, leave the other fields blank. 31 |

32 | 33 |

Examples

34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
HostPathResult
charlesproxy.comMatches all requests to host charlesproxy.com
*.charlesproxy.comMatches all requests to hosts ending in .charlesproxy.com
charlesproxy.com/charles/Matches all requests to charlesproxy.com/charles/ only
charlesproxy.com/charles/*Matches all requests to charlesproxy.com/charles/ including files and subpaths
charlesproxy.com/charlesMatches all requests to charlesproxy.com/charles only
charlesproxy.com/index.htmlMatches all requests to charlesproxy.com/charles.html only
charlesproxy.com/*.htmlMatches all requests to files ending in .html on host charlesproxy.com
/charles/*.htmlMatches all requests to files ending in .html under the path /charles/ (including subpaths) on any host
81 | 82 |

Protocol and port matches can be added to the above to further narrow the location match.

-------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/RewriteEditor.html: -------------------------------------------------------------------------------- 1 |

Rewrite Rule

2 |

Each rule describes a single rewrite operation.

3 | 4 |

Type

5 |

The type specifies the type of rewriting operation to perform. There are four different categories of rewrite rule types; 6 | header rules, URL rules, query parameter rules, response status rules and body rules. The header and query parameter rules effect the header fields 7 | and query string parameters respectively; adding, modifying or removing headers and parameters. The URL and body rules perform 8 | find and replace on the different parts of the URL and on the body. The response status rule performs find and replace on the response status code and description, eg. 200 OK.

9 | 10 |

Where

11 |

Choose where to apply the rewrite rule; on the request, response or both.

12 | 13 |

Match

14 |

The match fields contain the text to match in the request or response to decide whether to fire this rule. You can leave either the name or value blank, or both, to 15 | match any value. If you leave both the name and value fields blank you will match all requests / responses.

16 |

Regex support may be enabled, providing Perl-style regular expressions for your match. If you include groups in your regular expression they 17 | may be used in the match fields.

18 |

The name field is an exact match field unless regex is enabled, in which case it supports partial matches. The name field is case-insensitive 19 | for both regex and normal matching. 20 | The name field may be disabled if you are creating a rewrite rule type that doesn't require it.

21 |

The value field is a partial match unless you turn on Match whole value in which case it is an exact match. The value field is case-insensitive 22 | for both regex and normal matching for header and query parameter rules, and case-sensitive for URL and body rules.

23 | 24 |

New / Replace

25 |

The new/replace fields contain the text to add or replace in the request or response when this rule is fired. Leave either the name or value blank 26 | to leave them the same as the matched name or value.

27 |

If regex support is enabled for the match you may reference match groups using $1, $2 and so on.

28 |

The behaviour of the name and value fields depends upon the match. If there is a corresponding match then the field acts as a replacement 29 | for the matched text, otherwise if the match is blank then the fields replaces the whole name or value.

30 |

The value field supports Replace First or Replace All modes. The name field always operates in replace-first mode if the name match is a regex, 31 | otherwise it is an exact match and replaces the whole name.

32 |

The name and or value fields may be disabled if you are creating a rewrite rule type that doesn't require them.

33 | 34 |

Recommendations

35 |

Rewrite rules can be difficult to debug if they are not working as you expect. It is often best to build up a rule slowly with frequent testing.

36 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/RewriteEditor.html: -------------------------------------------------------------------------------- 1 |

Rewrite Rule

2 |

Each rule describes a single rewrite operation.

3 | 4 |

Type

5 |

The type specifies the type of rewriting operation to perform. There are four different categories of rewrite rule types; 6 | header rules, URL rules, query parameter rules, response status rules and body rules. The header and query parameter rules effect the header fields 7 | and query string parameters respectively; adding, modifying or removing headers and parameters. The URL and body rules perform 8 | find and replace on the different parts of the URL and on the body. The response status rule performs find and replace on the response status code and description, eg. 200 OK.

9 | 10 |

Where

11 |

Choose where to apply the rewrite rule; on the request, response or both.

12 | 13 |

Match

14 |

The match fields contain the text to match in the request or response to decide whether to fire this rule. You can leave either the name or value blank, or both, to 15 | match any value. If you leave both the name and value fields blank you will match all requests / responses.

16 |

Regex support may be enabled, providing Perl-style regular expressions for your match. If you include groups in your regular expression they 17 | may be used in the match fields.

18 |

The name field is an exact match field unless regex is enabled, in which case it supports partial matches. The name field is case-insensitive 19 | for both regex and normal matching. 20 | The name field may be disabled if you are creating a rewrite rule type that doesn't require it.

21 |

The value field is a partial match unless you turn on Match whole value in which case it is an exact match. The value field is case-insensitive 22 | for both regex and normal matching for header and query parameter rules, and case-sensitive for URL and body rules.

23 | 24 |

New / Replace

25 |

The new/replace fields contain the text to add or replace in the request or response when this rule is fired. Leave either the name or value blank 26 | to leave them the same as the matched name or value.

27 |

If regex support is enabled for the match you may reference match groups using $1, $2 and so on.

28 |

The behaviour of the name and value fields depends upon the match. If there is a corresponding match then the field acts as a replacement 29 | for the matched text, otherwise if the match is blank then the fields replaces the whole name or value.

30 |

The value field supports Replace First or Replace All modes. The name field always operates in replace-first mode if the name match is a regex, 31 | otherwise it is an exact match and replaces the whole name.

32 |

The name and or value fields may be disabled if you are creating a rewrite rule type that doesn't require them.

33 | 34 |

Recommendations

35 |

Rewrite rules can be difficult to debug if they are not working as you expect. It is often best to build up a rule slowly with frequent testing.

36 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/helper/ProxySettings-Proxies.html: -------------------------------------------------------------------------------- 1 |

Proxies

2 |

Charles can operate as an HTTP proxy and as a SOCKS proxy. The HTTP proxy is the default mode and most commonly used, however the SOCKS proxy yields 3 | more true-to-life performance.

4 | 5 |

You can configure the ports on which Charles listens for the HTTP and SOCKS proxy as well as enable or disable the SOCKS proxy. 6 | The HTTP proxy is always enabled.

7 | 8 |

Using Proxies

9 |

The proxy method used will depend upon the configuration of your application or OS. See the OS or browser specific tabs in 10 | the Proxy Settings, or see 11 | the configuration in your application for which port it is connecting to.

12 | 13 |

Dynamic ports

14 |

Enable the dynamic ports option to listen on a dynamic port, chosen each time Charles starts. This avoids conflicts with 15 | other network services that may be running on your computer, including other instances of Charles if it is a shared computer.

16 | 17 |

Transparent HTTP Proxying

18 |

Transparent proxying enables Charles to support clients who do not support HTTP proxy servers, or who are not aware that 19 | they are using an HTTP proxy server such as if a TCP/IP connection is redirected through Charles by a router or firewall.

20 | 21 |

SOCKS Proxy

22 |

The SOCKS proxy can proxy any protocol, not just HTTP and HTTPS, so you may see raw socket streams being 23 | proxied through Charles with the SOCKS proxy configured.

24 |

It is recommended to enable HTTP proxying over SOCKS. That identifies HTTP traffic and 25 | improves the display of it in Charles to match the behaviour when using the HTTP proxy. To achieve this Charles 26 | recognises some ports as carrying HTTP traffic. You may need to add to or change this list to suit your needs. 27 | In this way the SOCKS proxy may require more configuration than the HTTP proxy.

28 | 29 |

SOCKS Proxy Performance

30 |

31 | Browsers limit the number of connections they will have open to a web server, in order to not overload the server. 32 | The HTTP/1.1 specification states that a browser should limit itself to 2 connections per server. For HTTP/1.0 there are 33 | non-standardized limits across different browsers. 34 |

35 |

36 | This limit can cause loading problems with websites as only 2 files (pages / images / css / javascript etc) can be downloaded at once. 37 | To get around this issue, developers sometimes distribute resources across different servers. For instance, http://maps.google.com/ 38 | loads map tiles from mt0.google.com through mt3.google.com. That is 4 different server names, so even though these may actually all 39 | resolve to the same IP address and the same physical server, the browser treats them as different web sites each allowed 2 connections. 40 | This means that it can load 8 map tile images concurrently rather than the usual 2. 41 |

42 |

43 | When browsers use an HTTP proxy (such as Charles in HTTP proxy mode) they impose various different limits and also limit the total 44 | number of connections to the proxy server itself, thus subtley changing the behaviour and performance of websites. 45 | Charles is intended to have as little effect as possible on the regular performance of the web browser but in this case is at the 46 | mercy of the HTTP specification and browsers' behaviour with HTTP proxies. 47 |

48 |

49 | Fortunately when browsers use a SOCKS proxy the proxy is ignored in the calculation of connection limits, so the browser behaviour and performance is as normal. 50 | Therefore if you are performance testing a website or concerned about performance you should consider using Charles in SOCKS proxy mode. 51 |

52 | 53 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/helper/ProxySettings-Proxies.html: -------------------------------------------------------------------------------- 1 |

Proxies

2 |

Charles can operate as an HTTP proxy and as a SOCKS proxy. The HTTP proxy is the default mode and most commonly used, however the SOCKS proxy yields 3 | more true-to-life performance.

4 | 5 |

You can configure the ports on which Charles listens for the HTTP and SOCKS proxy as well as enable or disable the SOCKS proxy. 6 | The HTTP proxy is always enabled.

7 | 8 |

Using Proxies

9 |

The proxy method used will depend upon the configuration of your application or OS. See the OS or browser specific tabs in 10 | the Proxy Settings, or see 11 | the configuration in your application for which port it is connecting to.

12 | 13 |

Dynamic ports

14 |

Enable the dynamic ports option to listen on a dynamic port, chosen each time Charles starts. This avoids conflicts with 15 | other network services that may be running on your computer, including other instances of Charles if it is a shared computer.

16 | 17 |

Transparent HTTP Proxying

18 |

Transparent proxying enables Charles to support clients who do not support HTTP proxy servers, or who are not aware that 19 | they are using an HTTP proxy server such as if a TCP/IP connection is redirected through Charles by a router or firewall.

20 | 21 |

SOCKS Proxy

22 |

The SOCKS proxy can proxy any protocol, not just HTTP and HTTPS, so you may see raw socket streams being 23 | proxied through Charles with the SOCKS proxy configured.

24 |

It is recommended to enable HTTP proxying over SOCKS. That identifies HTTP traffic and 25 | improves the display of it in Charles to match the behaviour when using the HTTP proxy. To achieve this Charles 26 | recognises some ports as carrying HTTP traffic. You may need to add to or change this list to suit your needs. 27 | In this way the SOCKS proxy may require more configuration than the HTTP proxy.

28 | 29 |

SOCKS Proxy Performance

30 |

31 | Browsers limit the number of connections they will have open to a web server, in order to not overload the server. 32 | The HTTP/1.1 specification states that a browser should limit itself to 2 connections per server. For HTTP/1.0 there are 33 | non-standardized limits across different browsers. 34 |

35 |

36 | This limit can cause loading problems with websites as only 2 files (pages / images / css / javascript etc) can be downloaded at once. 37 | To get around this issue, developers sometimes distribute resources across different servers. For instance, http://maps.google.com/ 38 | loads map tiles from mt0.google.com through mt3.google.com. That is 4 different server names, so even though these may actually all 39 | resolve to the same IP address and the same physical server, the browser treats them as different web sites each allowed 2 connections. 40 | This means that it can load 8 map tile images concurrently rather than the usual 2. 41 |

42 |

43 | When browsers use an HTTP proxy (such as Charles in HTTP proxy mode) they impose various different limits and also limit the total 44 | number of connections to the proxy server itself, thus subtley changing the behaviour and performance of websites. 45 | Charles is intended to have as little effect as possible on the regular performance of the web browser but in this case is at the 46 | mercy of the HTTP specification and browsers' behaviour with HTTP proxies. 47 |

48 |

49 | Fortunately when browsers use a SOCKS proxy the proxy is ignored in the calculation of connection limits, so the browser behaviour and performance is as normal. 50 | Therefore if you are performance testing a website or concerned about performance you should consider using Charles in SOCKS proxy mode. 51 |

52 | 53 | -------------------------------------------------------------------------------- /src/main/java/charles/version462/Modifier462.java: -------------------------------------------------------------------------------- 1 | package charles.version462; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.net.URL; 8 | import java.util.Enumeration; 9 | import java.util.jar.JarEntry; 10 | import java.util.jar.JarFile; 11 | 12 | import charles.VersionModifier; 13 | import charles.version462.modifiers.MenuModifier; 14 | import javassist.CannotCompileException; 15 | import javassist.ClassPool; 16 | import javassist.CtClass; 17 | import javassist.CtMethod; 18 | import javassist.NotFoundException; 19 | 20 | public class Modifier462 extends VersionModifier { 21 | 22 | public Modifier462(String originJar, String savePath) { 23 | super(originJar, savePath); 24 | } 25 | 26 | @Override 27 | public boolean modifyByteCode() { 28 | try { 29 | ClassPool classPool=ClassPool.getDefault(); 30 | classPool.insertClassPath(getOriginJarPath()); 31 | classPool.insertClassPath(getTempPath()); 32 | modifyBundleStringEncoding(classPool, getTempPath()); 33 | replaceSource(); 34 | MenuModifier.modify(classPool, getTempPath()); 35 | return true; 36 | } catch (NotFoundException | CannotCompileException | IOException e) { 37 | e.printStackTrace(); 38 | } 39 | return false; 40 | } 41 | 42 | @Override 43 | public String getSourcePath() { 44 | return "4.6.2"; 45 | } 46 | 47 | /** 48 | * 替换资源文件,包括class文件 49 | */ 50 | private void replaceSource(){ 51 | String sourcePath = getSourcePath(); 52 | 53 | URL classResourceURL = getClass().getResource("/"+sourcePath); 54 | String jarPath = classResourceURL.getPath().substring(classResourceURL.getPath().indexOf("/"), classResourceURL.getPath() 55 | .indexOf("!")); 56 | 57 | JarFile jarFile; 58 | try { 59 | jarFile = new JarFile(jarPath); 60 | Enumeration jarEntries = jarFile.entries(); 61 | 62 | while (jarEntries.hasMoreElements()) { 63 | JarEntry jarEntry = jarEntries.nextElement(); 64 | String resourceName = jarEntry.getName(); 65 | if (resourceName.startsWith(sourcePath) && !jarEntry.isDirectory()) { 66 | File saveFile = new File(getTempPath(), resourceName.replace(sourcePath, "")); 67 | if(!saveFile.getParentFile().exists()){ 68 | saveFile.getParentFile().mkdirs(); 69 | } 70 | if(!saveFile.exists()){ 71 | saveFile.createNewFile(); 72 | } 73 | InputStream inputStream = jarFile.getInputStream(jarEntry); 74 | FileOutputStream fileOutputStream = new FileOutputStream(saveFile); 75 | fileOutputStream.write(inputStream.readAllBytes()); 76 | inputStream.close(); 77 | fileOutputStream.close(); 78 | } 79 | 80 | } 81 | } catch (IOException e) { 82 | e.printStackTrace(); 83 | 84 | } 85 | 86 | } 87 | 88 | /** 89 | * 修改string bundle的字符编码 90 | */ 91 | public void modifyBundleStringEncoding(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 92 | CtClass ctClass = classPool.get("com.xk72.lib.d"); 93 | CtClass ccString = classPool.get("java.lang.String"); 94 | CtMethod ctMethod =ctClass.getDeclaredMethod("a",new CtClass[]{ccString}); 95 | ctMethod.setBody("{int i = $1.indexOf(\"@@\");\n" + 96 | " while (i != -1) {\n" + 97 | " int j = $1.indexOf(\"@@\", i + 2);\n" + 98 | " if (j != -1) {\n" + 99 | " String str = $1.substring(i + 2, j);\n" + 100 | " $1 = $1.substring(0, i) + $1.substring(0, i) + getString(str);\n" + 101 | " i = $1.indexOf(\"@@\", i);\n" + 102 | " } \n" + 103 | " } \n" + 104 | "$1 = new String($1.getBytes(\"ISO-8859-1\"), \"utf-8\");\n"+ 105 | " return $1;}"); 106 | ctClass.writeFile(savePath); 107 | ctClass.detach(); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/main/source/4.6.1/strings.properties: -------------------------------------------------------------------------------- 1 | tools.ViewerContentType.name=Viewer Mappings 2 | tools.ViewerContentType.blurb=Map selected locations to particular viewer content types 3 | tools.ViewerContentType.help=@/com/xk72/charles/help/ViewerContentType.html 4 | tools.ViewerContentType.editor.blurb=To map from a path and its subdirectories you must end the path with a *. To map an entire host leave the path blank. 5 | tools.ViewerContentType.editor.help=@/com/xk72/charles/help/ViewerContentTypeEditor.html 6 | 7 | tools.NoCaching.name=禁用缓存 8 | tools.NoCaching.blurb=通过修改请求和响应头来防止缓存。 9 | tools.NoCaching.help=@/com/xk72/charles/help/NoCaching.html 10 | 11 | tools.Blacklist.name=拦截列表 12 | tools.Blacklist.blurb=拦截选择的请求。 13 | tools.Blacklist.help=@/com/xk72/charles/help/Blacklist.html 14 | 15 | tools.Whitelist.name=允许列表 16 | tools.Whitelist.blurb=仅允许选中的请求。 17 | tools.Whitelist.help=@/com/xk72/charles/help/Whitelist.html 18 | 19 | tools.AutoSave.name=自动保存 20 | tools.AutoSave.blurb=自动保存和清理会话记录。 21 | tools.AutoSave.help=@/com/xk72/charles/help/AutoSave.html 22 | 23 | tools.Breakpoints.name=断点 24 | tools.Breakpoints.blurb=拦截并修改请求参数和返回结果。 25 | tools.Breakpoints.help=@/com/xk72/charles/help/Breakpoints.html 26 | tools.Breakpoints.editor.blurb= 27 | tools.Breakpoints.editor.help=@/com/xk72/charles/help/BreakpointsEditor.html 28 | 29 | tools.BlockCookies.name=拦截Cookies 30 | tools.BlockCookies.blurb=拦截cookies发送和接收。 31 | tools.BlockCookies.help=@/com/xk72/charles/help/BlockCookies.html 32 | 33 | #tools.RefererEnhancement.name=Referer Enhancement 34 | #tools.RefererEnhancement.blurb=Add referer headers to some requests which do not otherwise get them. 35 | #tools.RefererEnhancement.help=Enhances referer detection by adding referer headers to requests which do not \ 36 | #otherwise get them. Currently only adds referer headers to SWF files. 37 | 38 | tools.Mirror.name=镜像 39 | tools.Mirror.blurb=保存请求会话的镜像到本地磁盘。 40 | tools.Mirror.help=@/com/xk72/charles/help/Mirror.html 41 | 42 | tools.Map.blurb=映射修改到另一个远程位置。 43 | tools.Map.name=远程映射 44 | tools.Map.help=@/com/xk72/charles/help/Map.html 45 | tools.Map.editor.blurb=要映射路径及其子目录,必须以*结尾。要映射整个主机,请将路径留空。 46 | tools.Map.editor.help=@/com/xk72/charles/help/MapEditor.html 47 | 48 | tools.MapLocal.name=本地映射 49 | tools.MapLocal.blurb=使用本地文件映射请求。 50 | tools.MapLocal.help=@/com/xk72/charles/help/MapLocal.html 51 | tools.MapLocal.editor.blurb=要映射路径及其子目录,必须以*结尾。要映射整个主机,请将路径留空。 52 | tools.MapLocal.editor.help=@/com/xk72/charles/help/MapLocalEditor.html 53 | 54 | tools.DNSSpoofing.name=DNS欺骗 55 | tools.DNSSpoofing.blurb=欺骗DNS查询修改域名的ip. 56 | tools.DNSSpoofing.help=@/com/xk72/charles/help/DNSSpoofing.html 57 | tools.DNSSpoofing.editor.help= 58 | 59 | tools.ClientProcess.name=客户端进程 60 | tools.ClientProcess.blurb=显示连接的客户端进程信息 61 | tools.ClientProcess.help=@/com/xk72/charles/help/ClientProcess.html 62 | 63 | tools.Rewrite.name=请求改写 64 | tools.Rewrite.blurb=修改请求或返回结果的内容 65 | tools.Rewrite.help=@/com/xk72/charles/help/Rewrite.html 66 | tools.Rewrite.editor.help=@/com/xk72/charles/help/RewriteEditor.html 67 | 68 | tools.ReverseProxies.name=代理转发 69 | tools.ReverseProxies.blurb=转发http和https代理到其他代理服务 70 | tools.ReverseProxies.help=@/com/xk72/charles/help/ReverseProxies.html 71 | tools.ReverseProxies.editor.help=@/com/xk72/charles/help/ReverseProxiesEditor.html 72 | 73 | tools.PortForwarding.name=端口转发 74 | tools.PortForwarding.blurb=转发本地TCP和UDP端口到远程服务器。 75 | tools.PortForwarding.help=@/com/xk72/charles/help/PortForwarding.html 76 | tools.PortForwarding.editor.help=@/com/xk72/charles/help/PortForwardingEditor.html 77 | 78 | tools.Throttling.name=限速 79 | tools.Throttling.help=@/com/xk72/charles/help/Throttling.html 80 | tools.Throttling.blurb= 81 | tools.Throttling.editor.help= 82 | tools.Throttling.editor.blurb= 83 | 84 | tools.gen.locations.name=Locations 85 | tools.gen.locations.selectedLocations=@/com/xk72/charles/help/frag/SelectedLocations.html 86 | tools.gen.locations.locationMatching=@/com/xk72/charles/help/frag/LocationMatching.html 87 | tools.gen.locations.locationMatchingEditor=@/com/xk72/charles/help/LocationsTableHelper.html 88 | 89 | #lib.LocationsTableHelper.blurb=Locations may include host names and or paths. Wildcards are supported using *, ? and [...]. \ 90 | #eg.\u00A0xk72.com, *.xk72.com, xk72.com/charles/, xk72.com/*.php, /*.php 91 | lib.LocationsTableHelper.blurb= 92 | lib.LocationsTableHelper.editor.blurb=Empty fields match all values. Wildcards * and ? may be used. See the Help for more information. 93 | lib.LocationsTableHelper.editor.help=@/com/xk72/charles/help/LocationsTableHelper.html 94 | 95 | settings.proxy.proxies.name=代理 96 | settings.proxy.proxies.help=@/com/xk72/charles/help/ProxySettings-Proxies.html 97 | settings.proxy.options.name=选项 98 | settings.proxy.options.help=@/com/xk72/charles/help/ProxySettings-Options.html 99 | settings.proxy.ssl.name=SSL代理 100 | settings.proxy.ssl.help=@/com/xk72/charles/help/ProxySettings-SSL.html 101 | settings.proxy.ssl.blurb=Charles支持显示SSL的请求和返回结果。Charles仅显示下方匹配的请求. Charles使用自签名的SSL证书, 点击帮助按钮查看更多。 102 | settings.proxy.windows.name=Windows 103 | settings.proxy.windows.help=@/com/xk72/charles/help/ProxySettings-OS.html 104 | settings.proxy.macosx.name=macOS 105 | settings.proxy.macosx.help=@/com/xk72/charles/help/ProxySettings-OS.html 106 | settings.proxy.mozilla.name=Mozilla Firefox 107 | settings.proxy.mozilla.help=@/com/xk72/charles/help/ProxySettings-Mozilla.html 108 | 109 | settings.externalproxy.name=外部代理 110 | settings.externalproxy.help=@/com/xk72/charles/help/ExternalProxies.html 111 | 112 | settings.focussed.name=Focused Hosts 113 | settings.focussed.help= 114 | settings.focussed.blurb=Focused locations are given more emphasis in the Structure view. Requests that match one of the locations below will be focused. 115 | 116 | settings.highlight.name=高亮规则 117 | settings.highlight.blurb=高亮匹配规则的请求。 118 | settings.highlight.help= 119 | settings.highlight.editor.blurb= 120 | settings.highlight.editor.help= 121 | 122 | settings.protobuf.help=@/com/xk72/charles/help/Protobuf.html 123 | settings.protobuf.blurb=The descriptor registry contains the descriptors used when parsing protobuf messages. Order is important, descriptors listed first will be loaded first. When descriptors contain overlapping sets of message types those loaded later will take precedence. 124 | 125 | settings.recording.limits.name=选项 126 | settings.recording.limits.help= 127 | settings.recording.exclude.name=排除 128 | settings.recording.exclude.help= 129 | settings.recording.exclude.blurb=排除匹配以下规则的请求。 130 | settings.recording.include.name=Include 131 | settings.recording.include.help= 132 | settings.recording.include.blurb=Only requests that match one of the locations below will be recorded. If this list is empty, all requests will be recorded unless otherwise excluded. 133 | 134 | settings.ui.name=软件界面 135 | settings.ui.help=@/com/xk72/charles/help/UISettings.html 136 | 137 | settings.clientSSLCertificates.name=客户端证书 138 | settings.clientSSLCertificates.blurb=为匹配规则的hosts配置客户端证书,证书格式:PKCS#12 139 | settings.clientSSLCertificates.help=@/com/xk72/charles/help/ClientSSLCertificates.html 140 | settings.clientSSLCertificates.editor.blurb= 141 | settings.clientSSLCertificates.editor.help= 142 | 143 | settings.importedSSLCertificates.name=服务端证书 144 | settings.importedSSLCertificates.blurb=配置PKCS#12证书,以便在建立到客户端的SSL连接时使用。 145 | settings.importedSSLCertificates.help=@/com/xk72/charles/help/ImportedSSLCertificates.html 146 | settings.importedSSLCertificates.editor.blurb= 147 | settings.importedSSLCertificates.editor.help= 148 | 149 | settings.serverSSLCertificates.name=系统根证书 150 | settings.serverSSLCertificates.blurb=管理Charles用于与客户端建立SSL连接的根证书。 151 | settings.serverSSLCertificates.help=@/com/xk72/charles/help/ServerSSLCertificates.html 152 | settings.serverSSLCertificates.editor.blurb= 153 | settings.serverSSLCertificates.editor.help= 154 | 155 | help.css=@/com/xk72/charles/help/help.css 156 | 157 | ssl.help=@/com/xk72/charles/help/SSL.html 158 | -------------------------------------------------------------------------------- /src/main/source/4.6.2/com/xk72/charles/strings.properties: -------------------------------------------------------------------------------- 1 | tools.ViewerContentType.name=Viewer Mappings 2 | tools.ViewerContentType.blurb=Map selected locations to particular viewer content types 3 | tools.ViewerContentType.help=@/com/xk72/charles/help/ViewerContentType.html 4 | tools.ViewerContentType.editor.blurb=To map from a path and its subdirectories you must end the path with a *. To map an entire host leave the path blank. 5 | tools.ViewerContentType.editor.help=@/com/xk72/charles/help/ViewerContentTypeEditor.html 6 | 7 | tools.NoCaching.name=禁用缓存 8 | tools.NoCaching.blurb=通过修改请求和响应头来防止缓存。 9 | tools.NoCaching.help=@/com/xk72/charles/help/NoCaching.html 10 | 11 | tools.Blacklist.name=拦截列表 12 | tools.Blacklist.blurb=拦截选择的请求。 13 | tools.Blacklist.help=@/com/xk72/charles/help/Blacklist.html 14 | 15 | tools.Whitelist.name=允许列表 16 | tools.Whitelist.blurb=仅允许选中的请求。 17 | tools.Whitelist.help=@/com/xk72/charles/help/Whitelist.html 18 | 19 | tools.AutoSave.name=自动保存 20 | tools.AutoSave.blurb=自动保存和清理会话记录。 21 | tools.AutoSave.help=@/com/xk72/charles/help/AutoSave.html 22 | 23 | tools.Breakpoints.name=断点 24 | tools.Breakpoints.blurb=拦截并修改请求参数和返回结果。 25 | tools.Breakpoints.help=@/com/xk72/charles/help/Breakpoints.html 26 | tools.Breakpoints.editor.blurb= 27 | tools.Breakpoints.editor.help=@/com/xk72/charles/help/BreakpointsEditor.html 28 | 29 | tools.BlockCookies.name=拦截Cookies 30 | tools.BlockCookies.blurb=拦截cookies发送和接收。 31 | tools.BlockCookies.help=@/com/xk72/charles/help/BlockCookies.html 32 | 33 | #tools.RefererEnhancement.name=Referer Enhancement 34 | #tools.RefererEnhancement.blurb=Add referer headers to some requests which do not otherwise get them. 35 | #tools.RefererEnhancement.help=Enhances referer detection by adding referer headers to requests which do not \ 36 | #otherwise get them. Currently only adds referer headers to SWF files. 37 | 38 | tools.Mirror.name=镜像 39 | tools.Mirror.blurb=保存请求会话的镜像到本地磁盘。 40 | tools.Mirror.help=@/com/xk72/charles/help/Mirror.html 41 | 42 | tools.Map.blurb=映射修改到另一个远程位置。 43 | tools.Map.name=远程映射 44 | tools.Map.help=@/com/xk72/charles/help/Map.html 45 | tools.Map.editor.blurb=要映射路径及其子目录,必须以*结尾。要映射整个主机,请将路径留空。 46 | tools.Map.editor.help=@/com/xk72/charles/help/MapEditor.html 47 | 48 | tools.MapLocal.name=本地映射 49 | tools.MapLocal.blurb=使用本地文件映射请求。 50 | tools.MapLocal.help=@/com/xk72/charles/help/MapLocal.html 51 | tools.MapLocal.editor.blurb=要映射路径及其子目录,必须以*结尾。要映射整个主机,请将路径留空。 52 | tools.MapLocal.editor.help=@/com/xk72/charles/help/MapLocalEditor.html 53 | 54 | tools.DNSSpoofing.name=DNS欺骗 55 | tools.DNSSpoofing.blurb=欺骗DNS查询修改域名的ip. 56 | tools.DNSSpoofing.help=@/com/xk72/charles/help/DNSSpoofing.html 57 | tools.DNSSpoofing.editor.help= 58 | 59 | tools.ClientProcess.name=客户端进程 60 | tools.ClientProcess.blurb=显示连接的客户端进程信息 61 | tools.ClientProcess.help=@/com/xk72/charles/help/ClientProcess.html 62 | 63 | tools.Rewrite.name=请求改写 64 | tools.Rewrite.blurb=修改请求或返回结果的内容 65 | tools.Rewrite.help=@/com/xk72/charles/help/Rewrite.html 66 | tools.Rewrite.editor.help=@/com/xk72/charles/help/RewriteEditor.html 67 | 68 | tools.ReverseProxies.name=代理转发 69 | tools.ReverseProxies.blurb=转发http和https代理到其他代理服务 70 | tools.ReverseProxies.help=@/com/xk72/charles/help/ReverseProxies.html 71 | tools.ReverseProxies.editor.help=@/com/xk72/charles/help/ReverseProxiesEditor.html 72 | 73 | tools.PortForwarding.name=端口转发 74 | tools.PortForwarding.blurb=转发本地TCP和UDP端口到远程服务器。 75 | tools.PortForwarding.help=@/com/xk72/charles/help/PortForwarding.html 76 | tools.PortForwarding.editor.help=@/com/xk72/charles/help/PortForwardingEditor.html 77 | 78 | tools.Throttling.name=限速 79 | tools.Throttling.help=@/com/xk72/charles/help/Throttling.html 80 | tools.Throttling.blurb= 81 | tools.Throttling.editor.help= 82 | tools.Throttling.editor.blurb= 83 | 84 | tools.gen.locations.name=Locations 85 | tools.gen.locations.selectedLocations=@/com/xk72/charles/help/frag/SelectedLocations.html 86 | tools.gen.locations.locationMatching=@/com/xk72/charles/help/frag/LocationMatching.html 87 | tools.gen.locations.locationMatchingEditor=@/com/xk72/charles/help/LocationsTableHelper.html 88 | 89 | #lib.LocationsTableHelper.blurb=Locations may include host names and or paths. Wildcards are supported using *, ? and [...]. \ 90 | #eg.\u00A0xk72.com, *.xk72.com, xk72.com/charles/, xk72.com/*.php, /*.php 91 | lib.LocationsTableHelper.blurb= 92 | lib.LocationsTableHelper.editor.blurb=Empty fields match all values. Wildcards * and ? may be used. See the Help for more information. 93 | lib.LocationsTableHelper.editor.help=@/com/xk72/charles/help/LocationsTableHelper.html 94 | 95 | settings.proxy.proxies.name=代理 96 | settings.proxy.proxies.help=@/com/xk72/charles/help/ProxySettings-Proxies.html 97 | settings.proxy.options.name=选项 98 | settings.proxy.options.help=@/com/xk72/charles/help/ProxySettings-Options.html 99 | settings.proxy.ssl.name=SSL代理 100 | settings.proxy.ssl.help=@/com/xk72/charles/help/ProxySettings-SSL.html 101 | settings.proxy.ssl.blurb=Charles支持显示SSL的请求和返回结果。Charles仅显示下方匹配的请求. Charles使用自签名的SSL证书, 点击帮助按钮查看更多。 102 | settings.proxy.windows.name=Windows 103 | settings.proxy.windows.help=@/com/xk72/charles/help/ProxySettings-OS.html 104 | settings.proxy.macosx.name=macOS 105 | settings.proxy.macosx.help=@/com/xk72/charles/help/ProxySettings-OS.html 106 | settings.proxy.mozilla.name=Mozilla Firefox 107 | settings.proxy.mozilla.help=@/com/xk72/charles/help/ProxySettings-Mozilla.html 108 | 109 | settings.externalproxy.name=外部代理 110 | settings.externalproxy.help=@/com/xk72/charles/help/ExternalProxies.html 111 | 112 | settings.focussed.name=Focused Hosts 113 | settings.focussed.help= 114 | settings.focussed.blurb=Focused locations are given more emphasis in the Structure view. Requests that match one of the locations below will be focused. 115 | 116 | settings.highlight.name=高亮规则 117 | settings.highlight.blurb=高亮匹配规则的请求。 118 | settings.highlight.help= 119 | settings.highlight.editor.blurb= 120 | settings.highlight.editor.help= 121 | 122 | settings.protobuf.help=@/com/xk72/charles/help/Protobuf.html 123 | settings.protobuf.blurb=The descriptor registry contains the descriptors used when parsing protobuf messages. Order is important, descriptors listed first will be loaded first. When descriptors contain overlapping sets of message types those loaded later will take precedence. 124 | 125 | settings.recording.limits.name=选项 126 | settings.recording.limits.help= 127 | settings.recording.exclude.name=排除 128 | settings.recording.exclude.help= 129 | settings.recording.exclude.blurb=排除匹配以下规则的请求。 130 | settings.recording.include.name=Include 131 | settings.recording.include.help= 132 | settings.recording.include.blurb=Only requests that match one of the locations below will be recorded. If this list is empty, all requests will be recorded unless otherwise excluded. 133 | 134 | settings.ui.name=软件界面 135 | settings.ui.help=@/com/xk72/charles/help/UISettings.html 136 | 137 | settings.clientSSLCertificates.name=客户端证书 138 | settings.clientSSLCertificates.blurb=为匹配规则的hosts配置客户端证书,证书格式:PKCS#12 139 | settings.clientSSLCertificates.help=@/com/xk72/charles/help/ClientSSLCertificates.html 140 | settings.clientSSLCertificates.editor.blurb= 141 | settings.clientSSLCertificates.editor.help= 142 | 143 | settings.importedSSLCertificates.name=服务端证书 144 | settings.importedSSLCertificates.blurb=配置PKCS#12证书,以便在建立到客户端的SSL连接时使用。 145 | settings.importedSSLCertificates.help=@/com/xk72/charles/help/ImportedSSLCertificates.html 146 | settings.importedSSLCertificates.editor.blurb= 147 | settings.importedSSLCertificates.editor.help= 148 | 149 | settings.serverSSLCertificates.name=系统根证书 150 | settings.serverSSLCertificates.blurb=管理Charles用于与客户端建立SSL连接的根证书。 151 | settings.serverSSLCertificates.help=@/com/xk72/charles/help/ServerSSLCertificates.html 152 | settings.serverSSLCertificates.editor.blurb= 153 | settings.serverSSLCertificates.editor.help= 154 | 155 | help.css=@/com/xk72/charles/help/help.css 156 | 157 | ssl.help=@/com/xk72/charles/help/SSL.html 158 | -------------------------------------------------------------------------------- /src/main/java/org/cq/Main.java: -------------------------------------------------------------------------------- 1 | package org.cq; 2 | 3 | import org.cq.jartool.JarTool; 4 | 5 | import java.awt.Component; 6 | import java.awt.Dimension; 7 | import java.awt.FlowLayout; 8 | import java.awt.GridBagConstraints; 9 | import java.awt.GridBagLayout; 10 | import java.awt.Insets; 11 | import java.awt.Toolkit; 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.nio.file.Files; 15 | import java.nio.file.Path; 16 | import java.util.Comparator; 17 | 18 | import javax.swing.JButton; 19 | import javax.swing.JComboBox; 20 | import javax.swing.JFileChooser; 21 | import javax.swing.JFrame; 22 | import javax.swing.JLabel; 23 | import javax.swing.JOptionPane; 24 | import javax.swing.JPanel; 25 | import javax.swing.JTextArea; 26 | import javax.swing.JTextField; 27 | import javax.swing.UIManager; 28 | import javax.swing.UnsupportedLookAndFeelException; 29 | 30 | import charles.VersionFactory; 31 | import charles.VersionModifier; 32 | 33 | public class Main { 34 | 35 | public static void main(String[] args) { 36 | new GUI(); 37 | } 38 | 39 | private static String translate(File originPath, String version, boolean deleteTemp, boolean newOutput) { 40 | String filename = originPath.getName(); 41 | String tempPath = new File(originPath.getParent(), filename + "_temp").getAbsolutePath(); 42 | String outputFilename = filename.substring(0, filename.lastIndexOf(".")) + "_zh.jar"; 43 | File outputFile; 44 | if (newOutput) { 45 | outputFile = new File(originPath.getParent(), outputFilename); 46 | } else { 47 | outputFile = originPath; 48 | } 49 | VersionModifier modifier = VersionFactory.createVersionModifier(version, originPath.getAbsolutePath(), tempPath); 50 | if (modifier != null) { 51 | boolean bytecodeModify = modifier.modifyByteCode(); 52 | if (!bytecodeModify) { 53 | return "翻译失败,请选择对应版本的charles.jar"; 54 | } 55 | if (!newOutput && outputFile.exists()) { 56 | outputFile.delete(); 57 | } 58 | if (JarTool.artifactFiles(originPath.getAbsolutePath(), modifier.getTempPath(), outputFile.getAbsolutePath())) { 59 | System.out.println("done"); 60 | if (deleteTemp && new File(tempPath).exists()) { 61 | try { 62 | Files.walk(Path.of(tempPath)) 63 | .sorted(Comparator.reverseOrder()) 64 | .map(Path::toFile) 65 | .forEach(File::delete); 66 | } catch (IOException e) { 67 | e.printStackTrace(); 68 | } 69 | System.out.println("delete file done"); 70 | } 71 | return null; 72 | } else { 73 | return "压缩文件失败,请关闭charles后重试"; 74 | } 75 | } else { 76 | return "暂不支持当前版本"; 77 | } 78 | } 79 | 80 | 81 | 82 | static class GUI extends JPanel { 83 | 84 | protected static final Insets spaceInsets = new Insets(10, 10, 4, 10); 85 | private final JFrame jFrame; 86 | 87 | JComboBox jComboBox; 88 | JTextField textField; 89 | 90 | 91 | private void moveFrameToCenter() { 92 | Toolkit kit = Toolkit.getDefaultToolkit(); 93 | Dimension screenSize = kit.getScreenSize(); 94 | int width = screenSize.width; 95 | int height = screenSize.height; 96 | int x = (width - jFrame.getWidth()) / 2; 97 | int y = (height - jFrame.getHeight()) / 2; 98 | jFrame.setLocation(x, y); 99 | } 100 | 101 | protected void createTips(){ 102 | JTextArea desc = new JTextArea("找到charles安装目录里的charles.jar:" +System.getProperty("line.separator")+ 103 | "Windows在C:/Program Files/Charles/lib/charles.jar" + System.getProperty("line.separator")+ 104 | "mac在/Applications/Charles.app/Contents/Java/charles.jar" +System.getProperty("line.separator")+ 105 | "将原文件拷贝到可以读写目录,在下方选择刚刚拷贝的文件,点击生成后,使用生成的文件替换charles安装目录的charles.jar。" +System.getProperty("line.separator")+ 106 | "替换之前注意备份原始charles.jar,避免出现不可预知的问题。"); 107 | desc.setLineWrap(true); 108 | desc.setMargin(new Insets(5, 5, 5, 5)); 109 | desc.setOpaque(false); 110 | addComponent( desc, 0); 111 | 112 | } 113 | 114 | protected void createVersionSelect() { 115 | JPanel jPanel = new JPanel(); 116 | FlowLayout flowLayout = new FlowLayout(); 117 | flowLayout.setAlignment(FlowLayout.LEFT); 118 | jPanel.setLayout(flowLayout); 119 | 120 | JLabel okButton = new JLabel("选择charles版本:"); 121 | jPanel.add(okButton); 122 | 123 | jComboBox = new JComboBox<>(); 124 | jComboBox.addItem("选择Charles版本"); 125 | for (String supportVersion: VersionFactory.SUPPORT_VERSIONS) { 126 | jComboBox.addItem(supportVersion); 127 | } 128 | 129 | jPanel.add(jComboBox); 130 | addComponent( jPanel, 1 131 | ); 132 | 133 | } 134 | 135 | protected void createPath() { 136 | JPanel jPanel = new JPanel(); 137 | FlowLayout flowLayout = new FlowLayout(); 138 | flowLayout.setAlignment(FlowLayout.LEFT); 139 | jPanel.setLayout(flowLayout); 140 | 141 | JLabel jLabel = new JLabel("选择charles.jar路径:"); 142 | jPanel.add(jLabel); 143 | 144 | textField = new JTextField(); 145 | Dimension d = textField.getPreferredSize(); 146 | d.width = 300; 147 | textField.setPreferredSize(d); 148 | jPanel.add(textField); 149 | 150 | 151 | JButton button = new JButton("选择"); 152 | button.addActionListener(e -> { 153 | JFileChooser jfc = new JFileChooser(); 154 | jfc.setFileSelectionMode(JFileChooser.FILES_ONLY); 155 | jfc.showDialog(new JLabel(), "选择charles.jar文件"); 156 | File file = jfc.getSelectedFile(); 157 | if (file != null) { 158 | textField.setText(file.getAbsolutePath()); 159 | System.out.println("文件路径:" + textField.getText()); 160 | } else { 161 | System.out.println("操作取消"); 162 | } 163 | }); 164 | jPanel.add(button); 165 | 166 | addComponent( jPanel, 2 167 | ); 168 | } 169 | 170 | protected void createOkButton() { 171 | JPanel jPanel = new JPanel(); 172 | jPanel.setLayout(new FlowLayout()); 173 | 174 | JButton okButton = new JButton("OK"); 175 | jPanel.add(okButton); 176 | okButton.addActionListener(e -> { 177 | if (jComboBox.getSelectedIndex() <= 0) { 178 | JOptionPane.showMessageDialog(this, "请选择版本", "报错", JOptionPane.ERROR_MESSAGE); 179 | return; 180 | } 181 | String version = (String) jComboBox.getSelectedItem(); 182 | String path = textField.getText(); 183 | if (path == null || path.length() <= 0) { 184 | JOptionPane.showMessageDialog(this, "请先选择原始charles.jar", "报错", JOptionPane.ERROR_MESSAGE); 185 | } else { 186 | File file = new File(path); 187 | if (file.exists()) { 188 | String errMsg = translate(file, version, true, true); 189 | if (errMsg == null) { 190 | JOptionPane.showMessageDialog(this, "翻译成功,替换charles.jar后重启charles", "成功", JOptionPane.INFORMATION_MESSAGE); 191 | } else { 192 | JOptionPane.showMessageDialog(this, errMsg, "报错", JOptionPane.ERROR_MESSAGE); 193 | } 194 | 195 | } else { 196 | JOptionPane.showMessageDialog(this, "选择的文件不存在", "报错", JOptionPane.ERROR_MESSAGE); 197 | } 198 | } 199 | }); 200 | 201 | addComponent( jPanel, 4 202 | ); 203 | 204 | } 205 | 206 | protected void addComponent(Component component, 207 | int gridy) { 208 | GridBagConstraints gbc = new GridBagConstraints(0, gridy, 209 | 1, 1, 1.0, 0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, GUI.spaceInsets, 0, 0); 210 | add(component, gbc); 211 | } 212 | 213 | GUI() { 214 | try { 215 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 216 | } catch (ClassNotFoundException e) { 217 | e.printStackTrace(); 218 | } catch (InstantiationException e) { 219 | e.printStackTrace(); 220 | } catch (IllegalAccessException e) { 221 | e.printStackTrace(); 222 | } catch (UnsupportedLookAndFeelException e) { 223 | e.printStackTrace(); 224 | } 225 | 226 | int w = 600; 227 | int h = 400; 228 | 229 | jFrame = new JFrame("Charles汉化工具"); 230 | jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 231 | jFrame.setSize(w, h); 232 | jFrame.setContentPane(this); 233 | jFrame.setResizable(false); 234 | 235 | moveFrameToCenter(); 236 | 237 | GridBagLayout lay = new GridBagLayout(); 238 | setLayout(lay); 239 | 240 | setLayout(new GridBagLayout()); 241 | 242 | createTips(); 243 | createVersionSelect(); 244 | createPath(); 245 | createOkButton(); 246 | 247 | jFrame.setVisible(true); 248 | } 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /src/main/java/org/cq/jartool/FingerPrint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 | * 5 | * 6 | * 7 | * 8 | * 9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | */ 25 | 26 | package org.cq.jartool; 27 | 28 | 29 | import jdk.internal.org.objectweb.asm.*; 30 | 31 | import java.io.IOException; 32 | import java.security.MessageDigest; 33 | import java.security.NoSuchAlgorithmException; 34 | import java.util.HashSet; 35 | import java.util.Set; 36 | 37 | /** 38 | * A FingerPrint is an abstract representation of a JarFile entry that contains 39 | * information to determine if the entry represents a class or a 40 | * resource, and whether two entries are identical. If the FingerPrint represents 41 | * a class, it also contains information to (1) describe the public API; 42 | * (2) compare the public API of this class with another class; (3) determine 43 | * whether or not it's a nested class and, if so, the name of the associated 44 | * outer class; and (4) for an canonically ordered set of classes determine 45 | * if the class versions are compatible. A set of classes is canonically 46 | * ordered if the classes in the set have the same name, and the base class 47 | * precedes the versioned classes and if each versioned class with version 48 | * {@code n} precedes classes with versions {@code > n} for all versions 49 | * {@code n}. 50 | */ 51 | final class FingerPrint { 52 | private static final MessageDigest MD; 53 | 54 | private final String basename; 55 | private final String entryName; 56 | private final int mrversion; 57 | 58 | private final byte[] sha1; 59 | private final ClassAttributes attrs; 60 | private final boolean isClassEntry; 61 | 62 | static { 63 | try { 64 | MD = MessageDigest.getInstance("SHA-1"); 65 | } catch (NoSuchAlgorithmException x) { 66 | // log big problem? 67 | throw new RuntimeException(x); 68 | } 69 | } 70 | 71 | public FingerPrint(String basename, String entryName, int mrversion, byte[] bytes) 72 | throws IOException { 73 | this.basename = basename; 74 | this.entryName = entryName; 75 | this.mrversion = mrversion; 76 | if (isCafeBabe(bytes)) { 77 | isClassEntry = true; 78 | sha1 = sha1(bytes, 8); // skip magic number and major/minor version 79 | attrs = getClassAttributes(bytes); 80 | } else { 81 | isClassEntry = false; 82 | sha1 = null; 83 | attrs = null; 84 | } 85 | } 86 | 87 | public boolean isClass() { 88 | return isClassEntry; 89 | } 90 | 91 | public boolean isNestedClass() { 92 | return attrs.nestedClass; 93 | } 94 | 95 | public boolean isPublicClass() { 96 | return attrs.publicClass; 97 | } 98 | 99 | public boolean isIdentical(FingerPrint that) { 100 | if (that == null) return false; 101 | if (this == that) return true; 102 | return isEqual(this.sha1, that.sha1); 103 | } 104 | 105 | public boolean isCompatibleVersion(FingerPrint that) { 106 | return attrs.version >= that.attrs.version; 107 | } 108 | 109 | public boolean isSameAPI(FingerPrint that) { 110 | if (that == null) return false; 111 | return attrs.equals(that.attrs); 112 | } 113 | 114 | public String basename() { 115 | return basename; 116 | } 117 | 118 | public String entryName() { 119 | return entryName; 120 | } 121 | 122 | public String className() { 123 | return attrs.name; 124 | } 125 | 126 | public int mrversion() { 127 | return mrversion; 128 | } 129 | 130 | public String outerClassName() { 131 | return attrs.outerClassName; 132 | } 133 | 134 | private byte[] sha1(byte[] entry) { 135 | MD.update(entry); 136 | return MD.digest(); 137 | } 138 | 139 | private byte[] sha1(byte[] entry, int offset) { 140 | MD.update(entry, offset, entry.length - offset); 141 | return MD.digest(); 142 | } 143 | 144 | private boolean isEqual(byte[] sha1_1, byte[] sha1_2) { 145 | return MessageDigest.isEqual(sha1_1, sha1_2); 146 | } 147 | 148 | private static final byte[] cafeBabe = {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe}; 149 | 150 | private boolean isCafeBabe(byte[] bytes) { 151 | if (bytes.length < 4) return false; 152 | for (int i = 0; i < 4; i++) { 153 | if (bytes[i] != cafeBabe[i]) { 154 | return false; 155 | } 156 | } 157 | return true; 158 | } 159 | 160 | private ClassAttributes getClassAttributes(byte[] bytes) { 161 | ClassReader rdr = new ClassReader(bytes); 162 | ClassAttributes attrs = new ClassAttributes(); 163 | rdr.accept(attrs, 0); 164 | return attrs; 165 | } 166 | 167 | private static final class Field { 168 | private final int access; 169 | private final String name; 170 | private final String desc; 171 | 172 | Field(int access, String name, String desc) { 173 | this.access = access; 174 | this.name = name; 175 | this.desc = desc; 176 | } 177 | 178 | @Override 179 | public boolean equals(Object that) { 180 | if (that == null) return false; 181 | if (this == that) return true; 182 | if (!(that instanceof Field)) return false; 183 | Field field = (Field)that; 184 | return (access == field.access) && name.equals(field.name) 185 | && desc.equals(field.desc); 186 | } 187 | 188 | @Override 189 | public int hashCode() { 190 | int result = 17; 191 | result = 37 * result + access; 192 | result = 37 * result + name.hashCode(); 193 | result = 37 * result + desc.hashCode(); 194 | return result; 195 | } 196 | } 197 | 198 | private static final class Method { 199 | private final int access; 200 | private final String name; 201 | private final String desc; 202 | private final Set exceptions; 203 | 204 | Method(int access, String name, String desc, Set exceptions) { 205 | this.access = access; 206 | this.name = name; 207 | this.desc = desc; 208 | this.exceptions = exceptions; 209 | } 210 | 211 | @Override 212 | public boolean equals(Object that) { 213 | if (that == null) return false; 214 | if (this == that) return true; 215 | if (!(that instanceof Method)) return false; 216 | Method method = (Method)that; 217 | return (access == method.access) && name.equals(method.name) 218 | && desc.equals(method.desc) 219 | && exceptions.equals(method.exceptions); 220 | } 221 | 222 | @Override 223 | public int hashCode() { 224 | int result = 17; 225 | result = 37 * result + access; 226 | result = 37 * result + name.hashCode(); 227 | result = 37 * result + desc.hashCode(); 228 | result = 37 * result + exceptions.hashCode(); 229 | return result; 230 | } 231 | } 232 | 233 | private static final class ClassAttributes extends ClassVisitor { 234 | private String name; 235 | private String outerClassName; 236 | private String superName; 237 | private int version; 238 | private int access; 239 | private boolean publicClass; 240 | private boolean nestedClass; 241 | private final Set fields = new HashSet<>(); 242 | private final Set methods = new HashSet<>(); 243 | 244 | public ClassAttributes() { 245 | super(Opcodes.ASM6); 246 | } 247 | 248 | private boolean isPublic(int access) { 249 | return ((access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC) 250 | || ((access & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED); 251 | } 252 | 253 | @Override 254 | public void visit(int version, int access, String name, String signature, 255 | String superName, String[] interfaces) { 256 | this.version = version; 257 | this.access = access; 258 | this.name = name; 259 | this.nestedClass = name.contains("$"); 260 | this.superName = superName; 261 | this.publicClass = isPublic(access); 262 | } 263 | 264 | @Override 265 | public void visitOuterClass(String owner, String name, String desc) { 266 | if (!this.nestedClass) return; 267 | this.outerClassName = owner; 268 | } 269 | 270 | @Override 271 | public void visitInnerClass(String name, String outerName, String innerName, 272 | int access) { 273 | if (!this.nestedClass) return; 274 | if (outerName == null) return; 275 | if (!this.name.equals(name)) return; 276 | if (this.outerClassName == null) this.outerClassName = outerName; 277 | } 278 | 279 | @Override 280 | public FieldVisitor visitField(int access, String name, String desc, 281 | String signature, Object value) { 282 | if (isPublic(access)) { 283 | fields.add(new Field(access, name, desc)); 284 | } 285 | return null; 286 | } 287 | 288 | @Override 289 | public MethodVisitor visitMethod(int access, String name, String desc, 290 | String signature, String[] exceptions) { 291 | if (isPublic(access)) { 292 | Set exceptionSet = new HashSet<>(); 293 | if (exceptions != null) { 294 | for (String e : exceptions) { 295 | exceptionSet.add(e); 296 | } 297 | } 298 | // treat type descriptor as a proxy for signature because signature 299 | // is usually null, need to strip off the return type though 300 | int n; 301 | if (desc != null && (n = desc.lastIndexOf(')')) != -1) { 302 | desc = desc.substring(0, n + 1); 303 | methods.add(new Method(access, name, desc, exceptionSet)); 304 | } 305 | } 306 | return null; 307 | } 308 | 309 | @Override 310 | public void visitEnd() { 311 | this.nestedClass = this.outerClassName != null; 312 | } 313 | 314 | @Override 315 | public boolean equals(Object that) { 316 | if (that == null) return false; 317 | if (this == that) return true; 318 | if (!(that instanceof ClassAttributes)) return false; 319 | ClassAttributes clsAttrs = (ClassAttributes)that; 320 | boolean superNameOkay = superName != null 321 | ? superName.equals(clsAttrs.superName) : true; 322 | return access == clsAttrs.access 323 | && superNameOkay 324 | && fields.equals(clsAttrs.fields) 325 | && methods.equals(clsAttrs.methods); 326 | } 327 | 328 | @Override 329 | public int hashCode() { 330 | int result = 17; 331 | result = 37 * result + access; 332 | result = 37 * result + superName != null ? superName.hashCode() : 0; 333 | result = 37 * result + fields.hashCode(); 334 | result = 37 * result + methods.hashCode(); 335 | return result; 336 | } 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /src/main/java/org/cq/jartool/Validator.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package org.cq.jartool; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.lang.module.ModuleDescriptor; 8 | import java.util.Collections; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Set; 14 | import java.util.TreeMap; 15 | import java.util.function.Function; 16 | import java.util.stream.Collectors; 17 | import java.util.zip.ZipEntry; 18 | import java.util.zip.ZipFile; 19 | 20 | import static org.cq.jartool.JarTool.*; 21 | 22 | final class Validator { 23 | 24 | private final Map classes = new HashMap<>(); 25 | private final JarTool main; 26 | private final ZipFile zf; 27 | private boolean isValid = true; 28 | private Set concealedPkgs = Collections.emptySet(); 29 | private ModuleDescriptor md; 30 | private String mdName; 31 | 32 | private Validator(JarTool jarTool, ZipFile zf) { 33 | this.main = jarTool; 34 | this.zf = zf; 35 | } 36 | 37 | static boolean validate(JarTool jarTool, ZipFile zf) throws IOException { 38 | return new Validator(jarTool, zf).validate(); 39 | } 40 | 41 | private boolean validate() { 42 | try { 43 | zf.stream() 44 | .filter(e -> e.getName().endsWith(".class")) 45 | .map(this::getFingerPrint) 46 | .filter(FingerPrint::isClass) // skip any non-class entry 47 | .collect(Collectors.groupingBy( 48 | FingerPrint::mrversion, 49 | TreeMap::new, 50 | Collectors.toMap(FingerPrint::className, 51 | Function.identity(), 52 | this::sameNameFingerPrint))) 53 | .forEach((version, entries) -> { 54 | if (version == 0) 55 | validateBase(entries); 56 | else 57 | validateVersioned(entries); 58 | }); 59 | } catch (InvalidJarException e) { 60 | errorAndInvalid(e.getMessage()); 61 | } 62 | return isValid; 63 | } 64 | 65 | static class InvalidJarException extends RuntimeException { 66 | private static final long serialVersionUID = -3642329147299217726L; 67 | InvalidJarException(String msg) { 68 | super(msg); 69 | } 70 | } 71 | 72 | private FingerPrint sameNameFingerPrint(FingerPrint fp1, FingerPrint fp2) { 73 | checkClassName(fp1); 74 | checkClassName(fp2); 75 | // entries/classes with same name, return fp2 for now ? 76 | return fp2; 77 | } 78 | 79 | private FingerPrint getFingerPrint(ZipEntry ze) { 80 | // figure out the version and basename from the ZipEntry 81 | String ename = ze.getName(); 82 | String bname = ename; 83 | int version = 0; 84 | 85 | if (ename.startsWith(VERSIONS_DIR)) { 86 | int n = ename.indexOf("/", VERSIONS_DIR_LENGTH); 87 | if (n == -1) { 88 | throw new InvalidJarException( 89 | formatMsg("error.validator.version.notnumber", ename)); 90 | } 91 | try { 92 | version = Integer.parseInt(ename, VERSIONS_DIR_LENGTH, n, 10); 93 | } catch (NumberFormatException x) { 94 | throw new InvalidJarException( 95 | formatMsg("error.validator.version.notnumber", ename)); 96 | } 97 | if (n == ename.length()) { 98 | throw new InvalidJarException( 99 | formatMsg("error.validator.entryname.tooshort", ename)); 100 | } 101 | bname = ename.substring(n + 1); 102 | } 103 | 104 | // return the cooresponding fingerprint entry 105 | try (InputStream is = zf.getInputStream(ze)) { 106 | return new FingerPrint(bname, ename, version, is.readAllBytes()); 107 | } catch (IOException x) { 108 | throw new InvalidJarException(x.getMessage()); 109 | } 110 | } 111 | 112 | /* 113 | * Validates (a) if there is any isolated nested class, and (b) if the 114 | * class name in class file (by asm) matches the entry's basename. 115 | */ 116 | public void validateBase(Map fps) { 117 | fps.values().forEach( fp -> { 118 | if (!checkClassName(fp)) { 119 | return; 120 | } 121 | if (fp.isNestedClass()) { 122 | checkNestedClass(fp, fps); 123 | } 124 | classes.put(fp.className(), fp); 125 | }); 126 | } 127 | 128 | public void validateVersioned(Map fps) { 129 | 130 | fps.values().forEach( fp -> { 131 | 132 | // validate the versioned module-info 133 | // process a versioned entry, look for previous entry with same name 134 | FingerPrint matchFp = classes.get(fp.className()); 135 | if (matchFp == null) { 136 | // no match found 137 | if (fp.isNestedClass()) { 138 | checkNestedClass(fp, fps); 139 | return; 140 | } 141 | if (fp.isPublicClass()) { 142 | if (!isConcealed(fp.className())) { 143 | errorAndInvalid(formatMsg("error.validator.new.public.class", 144 | fp.entryName())); 145 | return; 146 | } 147 | // entry is a public class entry in a concealed package 148 | warn(formatMsg("warn.validator.concealed.public.class", 149 | fp.entryName())); 150 | } 151 | classes.put(fp.className(), fp); 152 | return; 153 | } 154 | 155 | // are the two classes/resources identical? 156 | if (fp.isIdentical(matchFp)) { 157 | warn(formatMsg("warn.validator.identical.entry", fp.entryName())); 158 | return; // it's okay, just takes up room 159 | } 160 | 161 | // ok, not identical, check for compatible class version and api 162 | if (fp.isNestedClass()) { 163 | checkNestedClass(fp, fps); 164 | return; // fall through, need check nested public class?? 165 | } 166 | if (!fp.isCompatibleVersion(matchFp)) { 167 | errorAndInvalid(formatMsg("error.validator.incompatible.class.version", 168 | fp.entryName())); 169 | return; 170 | } 171 | if (!fp.isSameAPI(matchFp)) { 172 | errorAndInvalid(formatMsg("error.validator.different.api", 173 | fp.entryName())); 174 | return; 175 | } 176 | if (!checkClassName(fp)) { 177 | return; 178 | } 179 | classes.put(fp.className(), fp); 180 | 181 | return; 182 | }); 183 | } 184 | 185 | /* 186 | * Checks whether or not the given versioned module descriptor's attributes 187 | * are valid when compared against the root/base module descriptor. 188 | * 189 | * A versioned module descriptor must be identical to the root/base module 190 | * descriptor, with two exceptions: 191 | * - A versioned descriptor can have different non-public `requires` 192 | * clauses of platform ( `java.*` and `jdk.*` ) modules, and 193 | * - A versioned descriptor can have different `uses` clauses, even of 194 | * service types defined outside of the platform modules. 195 | */ 196 | private void checkModuleDescriptor(String miName) { 197 | ZipEntry ze = zf.getEntry(miName); 198 | if (ze != null) { 199 | try (InputStream jis = zf.getInputStream(ze)) { 200 | ModuleDescriptor md = ModuleDescriptor.read(jis); 201 | // Initialize the base md if it's not yet. A "base" md can be either the 202 | // root module-info.class or the first versioned module-info.class 203 | ModuleDescriptor base = this.md; 204 | 205 | if (base == null) { 206 | concealedPkgs = new HashSet<>(md.packages()); 207 | md.exports().stream().map(ModuleDescriptor.Exports::source).forEach(concealedPkgs::remove); 208 | md.opens().stream().map(ModuleDescriptor.Opens::source).forEach(concealedPkgs::remove); 209 | // must have the implementation class of the services it 'provides'. 210 | if (md.provides().stream().map(ModuleDescriptor.Provides::providers) 211 | .flatMap(List::stream) 212 | .filter(p -> zf.getEntry(toBinaryName(p)) == null) 213 | .peek(p -> error(formatMsg("error.missing.provider", p))) 214 | .count() != 0) { 215 | isValid = false; 216 | return; 217 | } 218 | this.md = md; 219 | this.mdName = miName; 220 | return; 221 | } 222 | 223 | if (!base.name().equals(md.name())) { 224 | errorAndInvalid(getMsg("error.validator.info.name.notequal")); 225 | } 226 | if (!base.requires().equals(md.requires())) { 227 | Set baseRequires = base.requires(); 228 | for (ModuleDescriptor.Requires r : md.requires()) { 229 | if (baseRequires.contains(r)) 230 | continue; 231 | if (r.modifiers().contains(ModuleDescriptor.Requires.Modifier.TRANSITIVE)) { 232 | errorAndInvalid(getMsg("error.validator.info.requires.transitive")); 233 | } else if (!isPlatformModule(r.name())) { 234 | errorAndInvalid(getMsg("error.validator.info.requires.added")); 235 | } 236 | } 237 | for (ModuleDescriptor.Requires r : baseRequires) { 238 | Set mdRequires = md.requires(); 239 | if (mdRequires.contains(r)) 240 | continue; 241 | if (!isPlatformModule(r.name())) { 242 | errorAndInvalid(getMsg("error.validator.info.requires.dropped")); 243 | } 244 | } 245 | } 246 | if (!base.exports().equals(md.exports())) { 247 | errorAndInvalid(getMsg("error.validator.info.exports.notequal")); 248 | } 249 | if (!base.opens().equals(md.opens())) { 250 | errorAndInvalid(getMsg("error.validator.info.opens.notequal")); 251 | } 252 | if (!base.provides().equals(md.provides())) { 253 | errorAndInvalid(getMsg("error.validator.info.provides.notequal")); 254 | } 255 | if (!base.mainClass().equals(md.mainClass())) { 256 | errorAndInvalid(formatMsg("error.validator.info.manclass.notequal", 257 | ze.getName())); 258 | } 259 | if (!base.version().equals(md.version())) { 260 | errorAndInvalid(formatMsg("error.validator.info.version.notequal", 261 | ze.getName())); 262 | } 263 | } catch (Exception x) { 264 | errorAndInvalid(x.getMessage() + " : " + miName); 265 | } 266 | } 267 | } 268 | 269 | private boolean checkClassName(FingerPrint fp) { 270 | if (fp.className().equals(className(fp.basename()))) { 271 | return true; 272 | } 273 | error(formatMsg2("error.validator.names.mismatch", 274 | fp.entryName(), fp.className().replace("/", "."))); 275 | return isValid = false; 276 | } 277 | 278 | private boolean checkNestedClass(FingerPrint fp, Map outerClasses) { 279 | if (outerClasses.containsKey(fp.outerClassName())) { 280 | return true; 281 | } 282 | // outer class was not available 283 | 284 | error(formatMsg("error.validator.isolated.nested.class", fp.entryName())); 285 | return isValid = false; 286 | } 287 | 288 | private boolean isConcealed(String className) { 289 | if (concealedPkgs.isEmpty()) { 290 | return false; 291 | } 292 | int idx = className.lastIndexOf('/'); 293 | String pkgName = idx != -1 ? className.substring(0, idx).replace('/', '.') : ""; 294 | return concealedPkgs.contains(pkgName); 295 | } 296 | 297 | private static boolean isPlatformModule(String name) { 298 | return name.startsWith("java.") || name.startsWith("jdk."); 299 | } 300 | 301 | private static String className(String entryName) { 302 | return entryName.endsWith(".class") ? entryName.substring(0, entryName.length() - 6) : null; 303 | } 304 | 305 | private void error(String msg) { 306 | main.error(msg); 307 | } 308 | 309 | private void errorAndInvalid(String msg) { 310 | main.error(msg); 311 | isValid = false; 312 | } 313 | 314 | private void warn(String msg) { 315 | main.warn(msg); 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /src/main/java/charles/version462/modifiers/MenuModifier.java: -------------------------------------------------------------------------------- 1 | package charles.version462.modifiers; 2 | 3 | import java.io.IOException; 4 | 5 | 6 | import javax.swing.JMenu; 7 | 8 | import javassist.CannotCompileException; 9 | import javassist.ClassPool; 10 | import javassist.CtClass; 11 | import javassist.CtConstructor; 12 | import javassist.CtMethod; 13 | import javassist.Modifier; 14 | import javassist.NotFoundException; 15 | 16 | public class MenuModifier extends JMenu{ 17 | public static void modify(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 18 | modifyViewMenu(classPool, savePath); 19 | modifySessionMenu(classPool, savePath); 20 | modifyCharlesFrame(classPool, savePath); 21 | modifyActionSwitchboard(classPool, savePath); 22 | modifyCompose(classPool, savePath); 23 | editMenu(classPool, savePath); 24 | copyUrl(classPool, savePath); 25 | addHelpMenu(classPool, savePath); 26 | } 27 | 28 | /** 29 | * 修改文件菜单的open和import 30 | */ 31 | private static void modifySessionMenu(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 32 | CtClass ctClass = classPool.get("com.xk72.charles.i"); 33 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 34 | ctConstructor.insertAfter("{" + 35 | "l.putValue(javax.swing.Action.NAME, \"打开会话\");" + 36 | "l.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"打开之前的会话\");" + 37 | "m.putValue(javax.swing.Action.NAME, \"导入\");" + 38 | "m.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"导入文件到会话\");" + 39 | "}"); 40 | ctClass.writeFile(savePath); 41 | ctClass.detach(); 42 | } 43 | 44 | /** 45 | * 修改视图菜单 46 | */ 47 | private static void modifyViewMenu(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 48 | CtClass ctClass = classPool.get("com.xk72.charles.gui.transaction.frames.n"); 49 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 50 | ctConstructor.insertAfter("{" + 51 | "l.putValue(javax.swing.Action.NAME, \"备注\");" + 52 | "m.putValue(javax.swing.Action.NAME, \"请求\");" + 53 | "n.putValue(javax.swing.Action.NAME, \"响应\");" + 54 | "}"); 55 | ctClass.writeFile(savePath); 56 | ctClass.detach(); 57 | 58 | 59 | 60 | 61 | ctClass = classPool.get("com.xk72.charles.gui.transaction.frames.d"); 62 | ctConstructor = ctClass.getConstructors()[0]; 63 | ctConstructor.insertAfter("{" + 64 | "e.putValue(javax.swing.Action.NAME, \"总览\");" + 65 | "f.putValue(javax.swing.Action.NAME, \"概览\");" + 66 | "g.putValue(javax.swing.Action.NAME, \"图表\");" + 67 | "}"); 68 | ctClass.writeFile(savePath); 69 | ctClass.detach(); 70 | } 71 | 72 | 73 | /** 74 | * 修改视图菜单 75 | */ 76 | private static void modifyCharlesFrame(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 77 | CtClass ctClass = classPool.get("com.xk72.charles.gui.CharlesFrame"); 78 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 79 | ctConstructor.insertAfter("{" + 80 | "newSessionAction.putValue(javax.swing.Action.NAME, \"新建会话\");" + 81 | "newSessionAction.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"创建新的会话并开始记录\");" + 82 | "quitAction.putValue(javax.swing.Action.NAME, \"退出\");" + 83 | "preferencesAction.putValue(javax.swing.Action.NAME, \"选项\");" + 84 | "recordingSettingsAction.putValue(javax.swing.Action.NAME, \"记录设置\");" + 85 | "proxySettingsAction.putValue(javax.swing.Action.NAME, \"代理设置\");" + 86 | "dnsSettingsAction.putValue(javax.swing.Action.NAME, \"DNS设置\");" + 87 | "accessControlSettingsAction.putValue(javax.swing.Action.NAME, \"访问控制设置\");" + 88 | "externalProxySettingsAction.putValue(javax.swing.Action.NAME, \"外部代理设置\");" + 89 | "externalDnsResolverSettingsAction.putValue(javax.swing.Action.NAME, \"外部DNS设置\");" + 90 | "remoteControlSettingsAction.putValue(javax.swing.Action.NAME, \"Web接口设置\");" + 91 | "sslSettingsAction.putValue(javax.swing.Action.NAME, \"SSL代理设置\");" + 92 | "errorLogAction.putValue(javax.swing.Action.NAME, \"错误日志\");" + 93 | "errorLogAction.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"查看错误日志\");" + 94 | "activeConnectionsAction.putValue(javax.swing.Action.NAME, \"活动链接\");" + 95 | "activeConnectionsAction.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"查看活动链接列表\");" + 96 | "}"); 97 | 98 | CtMethod g = ctClass.getDeclaredMethod("g"); 99 | g.setBody(" { javax.swing.JMenuBar jMenuBar = new javax.swing.JMenuBar();\n" + 100 | " com.xk72.charles.gui.lib.UIUtils.a(jMenuBar);\n" + 101 | " com.xk72.charles.gui.menus.FileMenu fileMenu = new com.xk72.charles.gui.menus.FileMenu(\"文件\", this);\n" + 102 | " fileMenu.setMnemonic('f');\n" + 103 | " com.xk72.charles.gui.lib.UIUtils.a((javax.swing.JMenu)fileMenu);\n" + 104 | " jMenuBar.add((javax.swing.JMenu)fileMenu);\n" + 105 | " com.xk72.charles.gui.menus.EditMenu editMenu = new com.xk72.charles.gui.menus.EditMenu(\"编辑\", this);\n" + 106 | " editMenu.setMnemonic('e');\n" + 107 | " com.xk72.charles.gui.lib.UIUtils.a((javax.swing.JMenu)editMenu);\n" + 108 | " jMenuBar.add((javax.swing.JMenu)editMenu);\n" + 109 | " com.xk72.charles.gui.menus.ViewMenu viewMenu = this.actionSwitchboard.A;\n" + 110 | " viewMenu.setMnemonic('v');\n" + 111 | " com.xk72.charles.gui.lib.UIUtils.a((javax.swing.JMenu)viewMenu);\n" + 112 | "viewMenu.setText(\"视图\");\n" + 113 | " jMenuBar.add((javax.swing.JMenu)viewMenu);\n" + 114 | " com.xk72.charles.gui.menus.ProxyMenu proxyMenu = new com.xk72.charles.gui.menus.ProxyMenu(\"代理\", this);\n" + 115 | " proxyMenu.setMnemonic('p');\n" + 116 | " com.xk72.charles.gui.lib.UIUtils.a((javax.swing.JMenu)proxyMenu);\n" + 117 | " jMenuBar.add((javax.swing.JMenu)proxyMenu);\n" + 118 | " com.xk72.charles.gui.menus.ToolsMenu toolsMenu = new com.xk72.charles.gui.menus.ToolsMenu(\"工具\", this);\n" + 119 | " toolsMenu.setMnemonic('t');\n" + 120 | " com.xk72.charles.gui.lib.UIUtils.a((javax.swing.JMenu)toolsMenu);\n" + 121 | " jMenuBar.add((javax.swing.JMenu)toolsMenu);\n" + 122 | " com.xk72.charles.gui.menus.WindowMenu windowMenu = new com.xk72.charles.gui.menus.WindowMenu(\"窗口\", this);\n" + 123 | " windowMenu.setMnemonic('w');\n" + 124 | " com.xk72.charles.gui.lib.UIUtils.a((javax.swing.JMenu)windowMenu);\n" + 125 | " this.desktop.a((java.awt.event.ContainerListener)windowMenu);\n" + 126 | " jMenuBar.add((javax.swing.JMenu)windowMenu);\n" + 127 | " com.xk72.charles.gui.menus.HelpMenu helpMenu = h();\n" + 128 | "helpMenu.setText(\"帮助\");\n" + 129 | " jMenuBar.add((javax.swing.JMenu)helpMenu);\n" + 130 | " if (com.xk72.charles.macos.g.a())\n" + 131 | " ((com.xk72.charles.macos.gui.a)com.xk72.charles.macos.g.b()).a(this); \n" + 132 | " setJMenuBar(jMenuBar);}"); 133 | ctClass.writeFile(savePath); 134 | ctClass.detach(); 135 | } 136 | 137 | /** 138 | * 修改子菜单 139 | */ 140 | private static void modifyActionSwitchboard(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 141 | CtClass ctClass = classPool.get("com.xk72.charles.gui.a"); 142 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 143 | ctConstructor.insertAfter("{" + 144 | "m.putValue(javax.swing.Action.NAME, \"清空会话\");" + 145 | "m.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"清空当前会话\");" + 146 | "n.putValue(javax.swing.Action.NAME, \"保存会话\");" + 147 | "n.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"保存当前会话\");" + 148 | "o.putValue(javax.swing.Action.NAME, \"会话另存为\");" + 149 | "o.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"会话另存为到新文件\");" + 150 | "p.putValue(javax.swing.Action.NAME, \"导出会话\");" + 151 | "p.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"导出当前会话\");" + 152 | "q.putValue(javax.swing.Action.NAME, \"关闭会话\");" + 153 | "q.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"关闭当前会话\");" + 154 | "r.putValue(javax.swing.Action.NAME, \"查找\");" + 155 | "r.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"查找当前会话\");" + 156 | "s.putValue(javax.swing.Action.NAME, \"查找下一个\");" + 157 | "s.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"查找到下一个\");" + 158 | "t.putValue(javax.swing.Action.NAME, \"查找上一个\");" + 159 | "t.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"查找到上一个\");" + 160 | "u.putValue(javax.swing.Action.NAME, \"修改请求\");" + 161 | "u.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"修改选中请求\");" + 162 | "v.putValue(javax.swing.Action.NAME, \"新建请求\");" + 163 | "v.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"新建请求\");" + 164 | "w.putValue(javax.swing.Action.NAME, \"重发请求\");" + 165 | "w.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"重发选中请求\");" + 166 | "x.putValue(javax.swing.Action.NAME, \"批量重发\");" + 167 | "x.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"批量重复发送请求\");" + 168 | "y.putValue(javax.swing.Action.NAME, \"验证\");" + 169 | "y.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"验证选中请求\");" + 170 | "z.putValue(javax.swing.Action.NAME, \"发布到Gist\");" + 171 | "z.putValue(javax.swing.Action.SHORT_DESCRIPTION, \"发送request和response到gist\");" + 172 | "}"); 173 | 174 | ctClass.writeFile(savePath); 175 | ctClass.detach(); 176 | } 177 | 178 | 179 | /** 180 | * 修改请求重发 181 | */ 182 | private static void modifyCompose(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 183 | // CtClass ctClass = classPool.get("com.xk72.charles.tools.ComposeTool"); 184 | // CtConstructor ctConstructor = ctClass.getConstructors()[0]; 185 | // ctConstructor.setBody("{" + 186 | // "super(\"修改请求\");;" + 187 | // "}"); 188 | // 189 | // ctClass.writeFile(savePath); 190 | // ctClass.detach(); 191 | // 192 | // CtClass ctClass1 = classPool.get("com.xk72.charles.gui.session.actions.AbstractComposeAction"); 193 | // CtConstructor ctConstructor1 = ctClass1.getConstructors()[0]; 194 | // ctConstructor1.insertAfter("{" + 195 | // "putValue(javax.swing.Action.NAME, \"修改请求\");" + 196 | // "}"); 197 | // 198 | // ctClass1.writeFile(savePath); 199 | // ctClass1.detach(); 200 | } 201 | 202 | /** 203 | * 右键菜单拷贝 URL 204 | */ 205 | private static void copyUrl(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 206 | CtClass ctClass = classPool.get("com.xk72.charles.gui.transaction.actions.CopyURLAction"); 207 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 208 | ctConstructor.insertAfter("{" + 209 | "putValue(javax.swing.Action.NAME, \"复制URL\");" + 210 | "}"); 211 | 212 | ctClass.writeFile(savePath); 213 | ctClass.detach(); 214 | } 215 | 216 | /** 217 | * 右键菜单拷贝 URL 218 | */ 219 | private static void editMenu(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 220 | CtClass ctClass = classPool.get("com.xk72.charles.gui.menus.EditMenu"); 221 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 222 | ctConstructor.insertAfter("{" + 223 | "getItem(0).getAction().putValue(javax.swing.Action.NAME, \"剪切\");" + 224 | "getItem(1).getAction().putValue(javax.swing.Action.NAME, \"复制\");" + 225 | "getItem(2).getAction().putValue(javax.swing.Action.NAME, \"粘贴\");" + 226 | "getItem(3).getAction().putValue(javax.swing.Action.NAME, \"全选\");" + 227 | "}"); 228 | 229 | ctClass.writeFile(savePath); 230 | ctClass.detach(); 231 | } 232 | 233 | /** 234 | * help menu增加菜单 235 | */ 236 | private static void addHelpMenu(ClassPool classPool, String savePath) throws NotFoundException, CannotCompileException, IOException { 237 | if (classPool.find("com.xk72.charles.gui.menus.HelpMenuUrl") == null) { 238 | CtClass helpUrlClass = classPool.makeClass("com.xk72.charles.gui.menus.HelpMenuUrl", classPool.get("javax.swing.AbstractAction")); 239 | CtConstructor urlConstruct = new CtConstructor(new CtClass[] {classPool.get("java.lang.String")}, helpUrlClass); 240 | urlConstruct.setBody("{" + 241 | "super($1);\n"+ 242 | "}"); 243 | helpUrlClass.addConstructor(urlConstruct); 244 | CtMethod ctMethod=new CtMethod(CtClass.voidType,"actionPerformed",new CtClass[]{classPool.get("java.awt.event.ActionEvent")}, helpUrlClass); 245 | ctMethod.setModifiers(Modifier.PUBLIC); 246 | ctMethod.setBody("{com.xk72.util.k.a(\"https://github.com/cuiqingandroid/CharlesZH\");}"); 247 | helpUrlClass.addMethod(ctMethod); 248 | helpUrlClass.writeFile(savePath); 249 | helpUrlClass.detach(); 250 | } 251 | CtClass ctClass = classPool.get("com.xk72.charles.gui.menus.HelpMenu"); 252 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 253 | ctConstructor.insertAfter("{" + 254 | "add(new com.xk72.charles.gui.menus.HelpMenuUrl(\"翻译支持\"));"+ 255 | "}"); 256 | ctClass.writeFile(savePath); 257 | ctClass.detach(); 258 | } 259 | 260 | } 261 | --------------------------------------------------------------------------------