Enhancements

Fix potential crash related to the new file reader.
Fix loading local subscriptions requires token when API mode is disabled.
Add support for parsing Clash Proxy Provider.
Update READMEs.
This commit is contained in:
Tindy X
2020-02-22 02:49:41 +08:00
parent 0527f1ddd4
commit e3726192dd
5 changed files with 104 additions and 42 deletions

View File

@@ -43,7 +43,7 @@
注意:
1. Shadowrocket 用户可以使用 `ss``ssr`以及 `v2ray`参数
1. Shadowrocket 用户可以使用 `ss``ssr` 以及 `v2ray` 参数
2. 类 TG 代理的 HTTP/Socks 链接 由于没有命名设定,所以可以在后方插入`&remark=`进行命名,例如
@@ -256,7 +256,7 @@ http://127.0.0.1:25500/getprofile?name=%NAME%&token=%TOKEN%
| 调用参数 | 必要性 | 示例 | 解释 |
| -------- | :----: | :--------------- | :------------------------ |
| name | 必要 | profiles/formyairport.ini | 指配置档案的存储位置(可使用基于**主程序**的相对位置) |
| name | 必要 | profiles/formyairport.ini | 指配置档案的存储位置(可使用基于**pref 配置文件**的相对位置) |
| token | 必要 | passwd | 为了安全考虑**必须设置token**(详见 [配置文件](#配置文件) 中 `[common] 部分``api_access_token` 的描述) |
应当注意的是,此处文件内的参数**无需进行 URLEncode**,且此处的 `token``api_mode` 的状态无关。
@@ -269,6 +269,7 @@ http://127.0.0.1:25500/getprofile?name=%NAME%&token=%TOKEN%
以上述 [进阶链接](#进阶链接) 的例子而言,`formyairport.ini` 内的内容应当是:
```txt
[Profile]
url=https://dler.cloud/subscribe/ABCDE?clash=vmess
target=surge
surge_ver=4

105
README.md
View File

@@ -16,32 +16,45 @@ Utility to convert between various proxy subscription formats.
- [Quick Usage](#quick-usage)
- [Access Interface](#access-interface)
- [Description](#description)
- [Quick Conversion](#quick-conversion)
- [Advanced Usage](#advanced-usage)
- [Read Before Continue](#read-before-continue)
- [Advanced Details](#advanced-details)
- [Profiles](#profiles)
- [Configuration File](#configuration-file)
- [External Configuration File](#external-configuration-file)
- [Auto Upload](#auto-upload)
## Supported Types
| Type | As Source | As Target | Target Name |
| ------------ | :---------: | :-----------: | ----------- |
| Clash | | | clash |
| ClashR | | | clashr |
| Quantumult | | | quan |
| Quantumult X | | | quanx |
| SS (SIP002) | | | ss |
| SS Android | | | sssub |
| SSD | | | ssd |
| SSR | | | ssr |
| Surfboard | | | surfboard |
| Surge 2 | | | surge&ver=2 |
| Surge 3 | | | surge&ver=3 |
| Surge 4 | | | surge&ver=4 |
| V2Ray | | | v2ray |
| Type | As Source | As Target | Target Name |
| ------------ | :--------: | :----------: | ----------- |
| Clash | | | clash |
| ClashR | | | clashr |
| Quantumult | | | quan |
| Quantumult X | | | quanx |
| Loon | | | loon |
| SS (SIP002) | | | ss |
| SS Android | | | sssub |
| SSD | | | ssd |
| SSR | | | ssr |
| Surfboard | | | surfboard |
| Surge 2 | | | surge&ver=2 |
| Surge 3 | | | surge&ver=3 |
| Surge 4 | | | surge&ver=4 |
| V2Ray | ✓ | ✓ | v2ray |
| Telegram-liked HTTP/Socks 5 links | ✓ | × | Only as source |
Notice:
1. Shadowrocket users should use `ss`, `ssr` or `v2ray` as target.
2. You can add `&remark=` to Telegram-liked HTTP/Socks 5 links to set a remark for this node. For example:
- tg://http?server=1.2.3.4&port=233&user=user&pass=pass&remark=Example
- https://t.me/http?server=1.2.3.4&port=233&user=user&pass=pass&remark=Example
**Notice**Shadowrocket users should use `ss`, `ssr` or `v2ray` as target.
---
@@ -51,7 +64,7 @@ Utility to convert between various proxy subscription formats.
### Access Interface
```TXT
```txt
http://127.0.0.1:25500/sub?target=%TARGET%&url=%URL%&config=%CONFIG%
```
@@ -67,7 +80,7 @@ If you need to merge two or more subscription, you should connect them with '|'
Example:
```TXT
```txt
You have 2 subscriptions and you want to merge them and generate a Clash subscription:
1. https://dler.cloud/subscribe/ABCDE?clash=vmess
2. https://rich.cloud/subscribe/ABCDE?clash=vmess
@@ -84,6 +97,16 @@ http://127.0.0.1:25500/sub?target=clash&url=https%3A%2F%2Fdler.cloud%2Fsubscribe
Finally subscribe this link in Clash and you are done!
```
### Quick Conversion
When the Surge configuration file has already meet your requirements, but you also need a same Clash configuration with the same groups and rules, you can use the following method:
```txt
http://127.0.0.1:25500/surge2clash?link=url_to_Surge_subscription
```
Here `url_to_Surge_subscription` **does not need to be URLEncoded** and no other configuration is needed.
---
## Advanced Usage
@@ -128,10 +151,11 @@ http://127.0.0.1:25500/sub?target=%TARGET%&url=%URL%&emoji=%EMOJI%····
| sort | No | true / false | Sort nodes in alphabetical order. Default is `false`. |
| include | No | See `include_remarks` | Exclude nodes which remarks match the following patterns. Supports regular expression. Process with [URLEncode](https://www.urlencoder.org/) first. **WILL OVERRIDE THE SAME SETTING IN `pref.ini`** |
| exclude | No | See `exclude_remarks` | Only include nodes which remarks match the following patterns. Supports regular expression. Process with [URLEncode](https://www.urlencoder.org/) first. **WILL OVERRIDE THE SAME SETTING IN `pref.ini`** |
| filename | No | MySS | Set the file name while downloading. Can be used as a profile name in Clash for Windows. |
Example:
```TXT
```txt
You have the following subscription: `https://dler.cloud/subscribe/ABCDE?clash=vmess`, and you want to convert it to Surge 4 subscription, set UDP and TFO to enabled,
add Emoji to node remarks and filter out unused nodes named "剩余流量1024G" and "官网地址dler.cloud".
@@ -148,6 +172,49 @@ http://127.0.0.1:25500/sub?surge&ver=4&tfo=true&udp=true&emoji=true&exclude=%28%
Finally subscribe this link in Surge and you are done!
```
### Profiles
> After preparing all the arguments for the subscription link, it may be too long and hard to remember. Now you can consider setting up a profile.
For now **only local profiles are allowed.**
#### Interface for Profiles
```txt
http://127.0.0.1:25500/getprofile?name=%NAME%&token=%TOKEN%
```
#### Description
| Argument | Needed | Example | Explanation |
| -------- | :----: | :--------------- | :------------------------ |
| name | Yes | profiles/formyairport.ini | The path to the profile. (relative to the `pref` configuration) |
| token | Yes | passwd | The access token for authorization. (Please check `api_access_token` in the `[common] section` in `pref` configuration. |
Notice that arguments in the profile **does not require URLEncode**.
Create a new text file **only in the same directory or a sub-directory** of the `pref` configuration (a sub-directory named `profiles` is recommended) and name it, for example `formyairport.ini`, then fill the arguments to the file according to the [example profile](https://github.com/tindy2013/subconverter/blob/master/base/profiles/example_profile.ini), then you are good to go.
<details>
<summary>Example:</summary>
Using the same example in [Advanced Usage](#advanced-usage), the content of `formyairport.ini` should be:
```txt
[Profile]
url=https://dler.cloud/subscribe/ABCDE?clash=vmess
target=surge
surge_ver=4
tfo=true
udp=true
emoji=true
exclude=(流量|官网)
```
After saving it to the `profile` directory, you can access `http://127.0.0.1:25500/getprofile?name=profiles/formyairport.ini&token=passwd` to read this profile.
</details>
### Configuration File
> Check comments inside [pref.ini](https://github.com/tindy2013/subconverter/blob/master/base/pref.ini) for more information.

View File

@@ -903,7 +903,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
extra_settings ext;
std::string subInfo, dummy;
int interval = interval_str.size() ? to_int(interval_str, config_update_interval) : config_update_interval;
bool ruleset_updated = false, authorized = getUrlArg(argument, "token") == access_token, strict = strict_str.size() ? strict_str == "true" : config_update_strict;
bool ruleset_updated = false, authorized = !api_mode || getUrlArg(argument, "token") == access_token, strict = strict_str.size() ? strict_str == "true" : config_update_strict;
if(std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), include) != regex_blacklist.cend() || std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), exclude) != regex_blacklist.cend())
return "Invalid request!";

View File

@@ -5,6 +5,7 @@
#include <sstream>
#include <iosfwd>
#include <iostream>
#include <cstdio>
//#include <filesystem>
#include <unistd.h>
@@ -688,10 +689,8 @@ std::string getMD5(const std::string &data)
// TODO: Add preprocessor option to disable (open web service safety)
std::string fileGet(const std::string &path, bool binary, bool scope_limit)
{
std::ifstream infile;
//std::stringstream strstrm;
std::string content;
std::ios::openmode mode = binary ? std::ios::binary : std::ios::in;
const char *mode = binary ? "rb" : "r";
if(scope_limit)
{
@@ -704,20 +703,14 @@ std::string fileGet(const std::string &path, bool binary, bool scope_limit)
#endif // _WIN32
}
infile.open(path, mode);
if(infile)
std::FILE *fp = std::fopen(path.c_str(), mode);
if(fp)
{
//move to a faster method
infile.seekg(0, std::ios::end);
content.resize(infile.tellg());
infile.seekg(0, std::ios::beg);
infile.read(&content[0], content.size());
infile.close();
/*
strstrm << infile.rdbuf();
infile.close();
return strstrm.str();
*/
std::fseek(fp, 0, SEEK_END);
content.resize(std::ftell(fp));
std::rewind(fp);
std::fread(&content[0], 1, content.size(), fp);
std::fclose(fp);
}
return content;
}

View File

@@ -736,9 +736,10 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, pluginopts_mux; //ss
std::string protocol, protoparam, obfs, obfsparam; //ssr
std::string user; //socks
for(unsigned int i = 0; i < yamlnode["Proxy"].size(); i++)
const std::string section = yamlnode["proxies"].IsDefined() ? "proxies" : "Proxy";
for(unsigned int i = 0; i < yamlnode[section].size(); i++)
{
singleproxy = yamlnode["Proxy"][i];
singleproxy = yamlnode[section][i];
singleproxy["type"] >> proxytype;
singleproxy["name"] >> ps;
singleproxy["server"] >> server;
@@ -1521,10 +1522,10 @@ void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom
//try to parse as clash configuration
try
{
if(!processed && strFind(sub, "Proxy"))
if(!processed && (strFind(sub, "Proxy:") || strFind(sub, "proxies:")))
{
Node yamlnode = Load(sub);
if(yamlnode.size() && yamlnode["Proxy"])
if(yamlnode.size() && (yamlnode["Proxy"].IsDefined() || yamlnode["proxies"].IsDefined()))
{
explodeClash(yamlnode, custom_port, local_port, nodes, sslibev, ssrlibev);
processed = true;