-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathlibprivoxy.cpp
302 lines (249 loc) · 7.53 KB
/
libprivoxy.cpp
1
2
3
4
5
6
7
8
9
10
11
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
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#include "LibPrivoxy/stdafx.h"
#include "libprivoxy.h"
#include "LibPrivoxy/Utils.h"
#include "miscutil.h"
#include <assert.h>
/** @brief Many people want to integrate Privoxy into their own projects,
* I made some changes to the Privoxy codes to compiled into a DLL or static library,
* so that you can better integrate it into their own projects. https://www.sockscap64.com
*
* @Author: Taro, https://www.sockscap64.com
*/
#define DEFAULT_PRIVOXY_LISTEN_ADDR "127.0.0.1"
#define DEFAULT_PRIVOXY_LISTEN_PORT 25378
#define DEFAULT_SEARCH_AMOUNT 200
// 具体配置请参考
// http://www.privoxy.org/user-manual/config.html
// forward / parent-proxy.example.org:8080
// forward-socks4a / socks-gw.example.com:1080 .
#define FORWARD_PROXY "%s:%d%s%s"
#define SSCAP_PRIVOXY_CONFIG_TEMPLATE "listen-address %s:%d\n" \
"show-on-task-bar 0\n" \
"activity-animation 0\n" \
"%s / %s %s\n" \
"hide-console\n" \
"accept-intercepted-requests 1\n" \
"logdir %s\n" \
"logfile privoxy-log.log\n"\
"pac-file %s\n"
static bool g_privoxy_service_stareted = false;
static int g_port_of_privoxy_listen = 0;
extern "C" char g_szDirecotryOfLibPrivoxy[1024] = {0};
extern "C" HMODULE g_hLibPrivoxyModule = NULL;
extern "C" int g_terminate;
extern "C" void close_privoxy_listening_socket();
static bool init_libprivoxy_path()
{
if( !g_hLibPrivoxyModule ) return false;
if( !GetModuleFileName(g_hLibPrivoxyModule,g_szDirecotryOfLibPrivoxy, 1024 ) ) return false;
TCHAR *p = _tcsrchr( g_szDirecotryOfLibPrivoxy , '\\' );
if( p )
{
*p=0x00;
return true;
}
return false;
}
static const char *get_forward_type( int proxy_type )
{
if( proxy_type == HTTP )
return "forward-http";
else if( proxy_type == SOCKS4 )
return "forward-socks4";
else if( proxy_type == SOCKS5 )
return "forward-socks5";
return "forward-socks5";
}
static BOOL wirte_parameters_to_config_file(
int proxy_type, /* HTTP,SOCKS4,SOCKS5 */
const char *forward_socks_5_ip,
int forward_socks5_port,
const char *base64_userpass,
const char *listen_addr,
int listen_port ,
const char *pac_file
)
{
TCHAR strConfigFile[1024] = {0};
const char *strForward = get_forward_type( proxy_type );
_stprintf_s( strConfigFile,1024, _T("%s\\privoxy.conf"), g_szDirecotryOfLibPrivoxy );
//char szBuffer[8000] = {0};
char szForwardProxy[1000]= {0};
char *EncryptProxy = NULL;
char *ConfigFileBody = NULL;
snprintf( szForwardProxy, 1000, FORWARD_PROXY,
forward_socks_5_ip, forward_socks5_port,base64_userpass?"@":"",base64_userpass?base64_userpass:""
);
#ifdef FEATURE_ENCRYPTCFG
EncryptProxy = encrypt_msg( szForwardProxy,strlen( szForwardProxy ), TRUE );
#else
EncryptProxy = strdup( szForwardProxy );
#endif
if( !EncryptProxy ) return FALSE;
ConfigFileBody = strdup_printf( SSCAP_PRIVOXY_CONFIG_TEMPLATE,
listen_addr, listen_port,
strForward, EncryptProxy, ".",
g_szDirecotryOfLibPrivoxy,
pac_file
);
free( EncryptProxy );
if( !ConfigFileBody )
{
return FALSE;
}
TCHAR *open_file_mode = _T("wb");
FILE *f=NULL;
f = _tfsopen( strConfigFile, open_file_mode, _SH_DENYNO );
if( f )
{
fwrite( ConfigFileBody,1,strlen(ConfigFileBody),f );
fflush( f );
fclose( f );
free( ConfigFileBody );
return TRUE;
}
free( ConfigFileBody );
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
//
/** @brief 启动privoxy, 可以反复调用, 如果服务本身已经启动, 再次调用只会更新privoxy服务的配置信息,
* 例如更改forwarding socks5 ip,forwarding port, privoxy service port等信息
*
* @param listen_port: PRIVOXY监听端口, 0自动搜索本机可用端口
* @param forward_socks_5_ip: 转发到的SOCKS 5 IP
* @param forward_socks5_port: 转发到的SOCKS 5 PORT
* @param pac_file: pac 文件完整路径
* 用户扩展PAC文件是一个文本文件, 里边指定需要经过代理的域名,每行一条, 换行符分隔
* 如:
* domain1.com
* domain2.com
* domain3.com
*
* @return 0 启动成功, 否则启动失败
* 1 初始化libprivoxy路径失败
* 1 找不到可用的端口用于privoxy服务
* 2 写入配置参数时出错
*/
extern "C" LIBPRIVOXY_API int __stdcall start_privoxy(
int proxy_type, /* HTTP,SOCKS4,SOCKS5 */
const char *forward_socks_5_ip,
int forward_socks5_port,
const char *username,
const char *password,
const char *listen_addr,
int listen_port /*= 0 */,
const char *pac_file /*= "unset"*/
)
{
char szUserPass[1000]={0};
const char *base64_userpass = NULL;
g_terminate = 0;
// 将username, password进行base64处理
if( username != NULL )
{
snprintf(szUserPass,1000,"%s:%s",username?username:"",password?password:"" );
base64_userpass = base64_encode( (const unsigned char *)szUserPass ,strlen( szUserPass ) );
}
// privoxy service already started?
if( g_privoxy_service_stareted )
{
// 未指定新端口, 则直接使用之前已经使用中的端口
if( listen_port == 0 )
listen_port = g_port_of_privoxy_listen ;
else
g_port_of_privoxy_listen = listen_port;
// just update the config of privoxy
if( !wirte_parameters_to_config_file(
proxy_type,
forward_socks_5_ip,
forward_socks5_port,
base64_userpass,
listen_addr,
listen_port,
pac_file
) )
{
freez( base64_userpass );
return 3;
}
freez( base64_userpass );
return 0;
}
if( !init_libprivoxy_path() ) return 1;
g_port_of_privoxy_listen = listen_port;
// Search avaible port?
if( g_port_of_privoxy_listen == 0 )
{
g_port_of_privoxy_listen = SearchAnUnsedPort(DEFAULT_PRIVOXY_LISTEN_PORT, DEFAULT_SEARCH_AMOUNT );
if( g_port_of_privoxy_listen == 0 ) return 2;
}
if( !wirte_parameters_to_config_file(
proxy_type,
forward_socks_5_ip,
forward_socks5_port,
base64_userpass,
listen_addr,
g_port_of_privoxy_listen,
pac_file
) )
{
freez( base64_userpass );
return 3;
}
// start privoxy
WinMain( NULL,NULL,NULL, 0);
g_privoxy_service_stareted = true;
freez( base64_userpass );
return 0;
}
/** @brief 停止privoxy
*/
extern "C" LIBPRIVOXY_API void __stdcall stop_privoxy()
{
close_privoxy_listening_socket();
g_terminate = 1;
g_privoxy_service_stareted = false;
}
/** 获得privoxy工作在哪个端口. 一般用于listen_port=0的情况下, 想知道privoxy工作在哪个端口之下
*/
extern "C" LIBPRIVOXY_API int __stdcall get_privoxy_port()
{
return g_port_of_privoxy_listen;
}
extern "C" LIBPRIVOXY_API int __stdcall is_privoxy_started()
{
return g_privoxy_service_stareted;
}
/** @brief 计算cmd的hash ,用于新加入新的cmd config时.
*/
extern "C" LIBPRIVOXY_API unsigned int __stdcall calc_cmd_hash( const char *cmd )
{
unsigned int hash = hash_string( cmd );
printf("cmd: %s hash: %u\n",cmd, hash );
return hash;
}
/** @biref 取得PAC地址
*/
extern "C" LIBPRIVOXY_API BOOL __stdcall GetPrivoxyPacUrl( char *buf, int buflen )
{
assert( buf != NULL );
assert( buflen > 0 );
if( buf == NULL || buflen <= 0 || !g_privoxy_service_stareted ) return FALSE;
char szPacTick[100] = {0};
snprintf( szPacTick,100,("?t=%u"),GetTickCount() );
snprintf( buf,buflen,("http://%s:%d/echo-pac%s"),
DEFAULT_PRIVOXY_LISTEN_ADDR,
g_port_of_privoxy_listen,szPacTick );
return TRUE;
}
/** @brief 取得PRIVOXY地址
*/
extern "C" LIBPRIVOXY_API BOOL __stdcall GetPrivoxyProxyAddr( char *buf, int buflen )
{
assert( buf != NULL );
assert( buflen > 0 );
if( buf == NULL || buflen <= 0 || !g_privoxy_service_stareted ) return FALSE;
snprintf( buf, buflen, _T("%s:%d"),DEFAULT_PRIVOXY_LISTEN_ADDR, g_port_of_privoxy_listen );
return TRUE;
}