Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

Annotation of /trunk/TTProxy/ProxyWSockHook.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3227 - (hide annotations) (download) (as text)
Tue Mar 24 15:10:33 2009 UTC (15 years, 2 months ago) by maya
File MIME type: text/x-chdr
File size: 88561 byte(s)
CVS から SVN へ移行: 改行コードを LF から CR+LF へ変換
1 maya 3227 #ifndef _YEBISOCKS_PROXYWSOCKHOOK_H_
2     #define _YEBISOCKS_PROXYWSOCKHOOK_H_
3    
4     #include <YCL/StringBuffer.h>
5     #include <YCL/Dialog.h>
6     #include <YCL/ComboBoxCtrl.h>
7     #include <YCL/EditBoxCtrl.h>
8     #include <YCL/IniFile.h>
9     #include <YCL/Resource.h>
10     #include <YCL/FileVersion.h>
11     using namespace yebisuya;
12    
13     #include "resource.h"
14     #include "Hooker.h"
15     #include "Logger.h"
16     #include "SSLSocket.h"
17    
18     #include "ttlib.h"
19     #include "i18n.h"
20    
21     extern char UILanguageFile[MAX_PATH];
22    
23     void UTIL_get_lang_msg(PCHAR key, PCHAR buf, int buf_len, PCHAR def)
24     {
25     GetI18nStr("TTProxy", key, buf, buf_len, def, UILanguageFile);
26     }
27    
28     int UTIL_get_lang_font(PCHAR key, HWND dlg, PLOGFONT logfont, HFONT *font)
29     {
30     if (GetI18nLogfont("TTProxy", key, logfont,
31     GetDeviceCaps(GetDC(dlg),LOGPIXELSY),
32     UILanguageFile) == FALSE) {
33     return FALSE;
34     }
35    
36     if ((*font = CreateFontIndirect(logfont)) == NULL) {
37     return FALSE;
38     }
39    
40     return TRUE;
41     }
42    
43     class ProxyWSockHook {
44     public:
45     class MessageShower {
46     public:
47     virtual void showMessage(const char* message)const = NULL;
48     };
49     private:
50     struct DUMMYHOSTENT {
51     struct hostent entry;
52     in_addr addr;
53     char* addrlist[2];
54     char* alias;
55     char hostname[1];
56     };
57    
58     class AsyncSelectInfoTable {
59     private:
60     struct AsyncSelectInfo {
61     HWND window;
62     UINT message;
63     long event;
64     AsyncSelectInfo():window(NULL), message(0), event(0) {
65     }
66     AsyncSelectInfo(const AsyncSelectInfo& src):window(src.window), message(src.message), event(src.event) {
67     }
68     AsyncSelectInfo(HWND window, UINT message, long event):window(window), message(message), event(event) {
69     }
70     bool operator==(const AsyncSelectInfo& src) {
71     return window == src.window && message == src.message && event == src.event;
72     }
73     void operator=(const AsyncSelectInfo& src) {
74     window = src.window;
75     message = src.message;
76     event = src.event;
77     }
78     void operator=(int v) {
79     if (v == 0) {
80     window = NULL;
81     message = 0;
82     event = 0;
83     }
84     }
85     operator int()const {
86     return window == NULL && message == 0 && event == 0 ? 0 : (int) window;
87     }
88     };
89     Hashtable<SOCKET, AsyncSelectInfo> table;
90     mutable CRITICAL_SECTION section;
91     public:
92     AsyncSelectInfoTable() {
93     ::InitializeCriticalSection(&section);
94     }
95     ~AsyncSelectInfoTable() {
96     ::DeleteCriticalSection(&section);
97     }
98     void put(SOCKET s, HWND window, UINT message, long event) {
99     ::EnterCriticalSection(&section);
100     if (message != 0 || event != 0) {
101     table.put(s, AsyncSelectInfo(window, message, event));
102     }else{
103     table.remove(s);
104     }
105     ::LeaveCriticalSection(&section);
106     }
107     void get(SOCKET s, HWND& window, UINT& message, long& event)const {
108     ::EnterCriticalSection(&section);
109     AsyncSelectInfo info = table.get(s);
110     ::LeaveCriticalSection(&section);
111     window = info.window;
112     message = info.message;
113     event = info.event;
114     }
115     };
116     class ProxyInfo {
117     public:
118     enum Type {
119     TYPE_NONE,
120     TYPE_HTTP,
121     TYPE_TELNET,
122     TYPE_SOCKS4,
123     TYPE_SOCKS5,
124     TYPE_SSL,
125     TYPE_HTTP_SSL,
126     TYPE_TELNET_SSL,
127     TYPE_SOCKS4_SSL,
128     TYPE_SOCKS5_SSL,
129     TYPE_NONE_FORCE,
130     };
131     private:
132     struct PROXY_TYPE_TABLE {
133     Type type;
134     const char* name;
135     };
136     static const PROXY_TYPE_TABLE* proxy_type_table() {
137     static PROXY_TYPE_TABLE table[] = {
138     {TYPE_HTTP, "http"},
139     {TYPE_SOCKS5, "socks"},
140     {TYPE_SOCKS4, "socks4"},
141     {TYPE_TELNET, "telnet"},
142     {TYPE_SOCKS5, "socks5"},
143     {TYPE_NONE_FORCE, "none"},
144     {TYPE_HTTP_SSL, "http+ssl"},
145     {TYPE_SOCKS5_SSL, "socks+ssl"},
146     {TYPE_SOCKS4_SSL, "socks4+ssl"},
147     {TYPE_TELNET_SSL, "telnet+ssl"},
148     {TYPE_SOCKS5_SSL, "socks5+ssl"},
149     {TYPE_SSL, "ssl"},
150     {TYPE_SSL, "none+ssl"},
151     {TYPE_NONE, NULL},
152     };
153     return table;
154     }
155     public:
156     static Type parseType(const char* string) {
157     return parseType(string, string + strlen(string));
158     }
159     static Type parseType(const char* string, const char* end) {
160     int length = end - string;
161     char* buffer = (char*) alloca(length + 1);
162     char* dst = buffer;
163     while (length-- > 0 && *string != '\0') {
164     int ch = *string++;
165     if ('A' <= ch && ch <= 'Z') {
166     ch += 'a' - 'A';
167     }
168     *dst++ = ch;
169     }
170     *dst = '\0';
171     const PROXY_TYPE_TABLE* table = proxy_type_table();
172     while (table->name != NULL) {
173     if (strcmp(buffer, table->name) == 0)
174     return table->type;
175     table++;
176     }
177     return TYPE_NONE;
178     }
179     static const char* getTypeName(Type type) {
180     if (type != TYPE_NONE && type != TYPE_NONE_FORCE) {
181     const PROXY_TYPE_TABLE* table = proxy_type_table();
182     while (table->name != NULL) {
183     if (type == table->type)
184     return table->name;
185     table++;
186     }
187     }
188     return NULL;
189     }
190    
191     static int parsePort(const char* string) {
192     return parsePort(string, string + strlen(string));
193     }
194     static int parsePort(const char* string, const char* end) {
195     if (string > end || *string < '1' || '9' < *string)
196     return -1;
197     int digit = 0;
198     while (string < end) {
199     if (*string < '0' || '9' < *string)
200     return -1;
201     digit = digit * 10 + (*string - '0');
202     if (digit > 65535)
203     return -1;
204     string++;
205     }
206     if (digit == 0)
207     return -1;
208     return digit;
209     }
210    
211     static String parse(const char* url, ProxyInfo& proxy) {
212     char* p = strstr((char*) url, "://");
213     if (p == NULL) {
214     proxy.type = TYPE_NONE;
215     return NULL;
216     }
217     proxy.type = parseType(url, p);
218     if (proxy.type == TYPE_NONE)
219     return NULL;
220     p += 3;
221     const char* start = p;
222     while (*p != '\0' && *p != '/') {
223     if (*p == ':') {
224     if (proxy.host != NULL || start >= p) {
225     proxy.type = TYPE_NONE;
226     return NULL;
227     }
228     proxy.host = urldecode(start, p);
229     start = p + 1;
230     }else if (*p == '@') {
231     if (proxy.user != NULL) {
232     proxy.type = TYPE_NONE;
233     return NULL;
234     }
235     if (proxy.host == NULL) {
236     proxy.user = urldecode(start, p);
237     }else{
238     proxy.user = proxy.host;
239     proxy.pass = urldecode(start, p);
240     proxy.host = NULL;
241     }
242     start = p + 1;
243     }
244     p++;
245     }
246     if (proxy.type != TYPE_NONE_FORCE && proxy.type != TYPE_SSL) {
247     if (proxy.host == NULL) {
248     if (start >= p) {
249     proxy.type = TYPE_NONE;
250     return NULL;
251     }
252     proxy.host = urldecode(start, p);
253     }else{
254     proxy.port = parsePort(start, p);
255     if (proxy.port < 0) {
256     proxy.type = TYPE_NONE;
257     return NULL;
258     }
259     }
260     }
261     if (*p == '/') {
262     p++;
263     return p;
264     }
265     return url;
266     }
267     String generateURL()const {
268     if (type == TYPE_NONE || host == NULL)
269     return NULL;
270     StringBuffer buffer;
271     buffer.append(getTypeName(type));
272     buffer.append("://");
273     if (type != TYPE_SSL) {
274     if (user != NULL) {
275     urlencode(user, buffer);
276     if (pass != NULL) {
277     buffer.append(':');
278     urlencode(pass, buffer);
279     }
280     buffer.append('@');
281     }
282     urlencode(host, buffer);
283     if (port != 0) {
284     buffer.append(':');
285     int digit = 10000;
286     while (digit > 0 && (unsigned) port < (unsigned) digit) {
287     digit /= 10;
288     }
289     while (digit > 0) {
290     int d = (unsigned) port / digit % 10;
291     digit /= 10;
292     buffer.append('0' + d);
293     }
294     }
295     }
296     return buffer.toString();
297     }
298     private:
299     static int hexdigit(int ch) {
300     if ('0' <= ch && ch <= '9') {
301     return ch - '0';
302     }else if ('A' <= ch && ch <= 'F') {
303     return ch - 'A' + 10;
304     }else if ('a' <= ch && ch <= 'f') {
305     return ch - 'a' + 10;
306     }else{
307     return -1;
308     }
309     }
310    
311     static String urldecode(const char* start, const char* end) {
312     char* buffer = (char*) alloca((end - start) * 3 + 1);
313     char* dst = buffer;
314     int c1, c2;
315     while (start < end) {
316     if (*start == '%' && start + 2 < end && (c1 = hexdigit(start[1])) != -1 && (c2 = hexdigit(start[2])) != -1) {
317     *dst++ = (char) (c1 << 4 | c2);
318     start += 3;
319     }else{
320     if (IsDBCSLeadByte(*start)) {
321     *dst++ = *start++;
322     }
323     *dst++ = *start++;
324     }
325     }
326     *dst = '\0';
327     return buffer;
328     }
329     static String urlencode(const char* string, StringBuffer& buffer) {
330     static const char table[] = "0123456789ABCDEF";
331     const char* start = string;
332     while (*string != '\0') {
333     if ('0' <= *string && *string <= '9'
334     || 'A' <= *string && *string <= 'Z'
335     || 'a' <= *string && *string <= 'z'
336     || *string == '-' || *string == '.' || *string == '_') {
337     }else if (::IsDBCSLeadByte(*string)) {
338     string++;
339     }else{
340     if (start < string) {
341     buffer.append(start, string - start);
342     }
343     buffer.append('%');
344     buffer.append(table[(unsigned) *string >> 4]);
345     buffer.append(table[(unsigned) *string & 0x0f]);
346     start = string + 1;
347     }
348     string++;
349     }
350     if (start < string) {
351     buffer.append(start);
352     }
353     return buffer;
354     }
355     public:
356     ProxyInfo():type(TYPE_NONE), port(0) {
357     }
358     ~ProxyInfo() {
359     }
360     unsigned short getPort() {
361     if (port == 0) {
362     switch (type) {
363     case TYPE_SOCKS4:
364     case TYPE_SOCKS5:
365     case TYPE_SOCKS4_SSL:
366     case TYPE_SOCKS5_SSL:
367     return 1080;
368     case TYPE_TELNET:
369     case TYPE_TELNET_SSL:
370     return 23;
371     case TYPE_HTTP:
372     case TYPE_HTTP_SSL:
373     return 80;
374     }
375     }
376     return port;
377     }
378     Type type;
379     String host;
380     unsigned short port;
381     String user;
382     String pass;
383     };
384    
385     struct ConnectionInfo {
386     ProxyInfo proxy;
387     String realhost;
388     unsigned short realport;
389     in_addr addr;
390     char* buffer;
391     DWORD time;
392     ConnectionInfo(ProxyInfo& proxy, String realhost):proxy(proxy), realhost(realhost), buffer(NULL) {
393     }
394     ~ConnectionInfo() {
395     delete[] buffer;
396     }
397     void fillBuffer(char* buffer, int bufferLength) {
398     DUMMYHOSTENT* dst = (DUMMYHOSTENT*) buffer;
399     dst->addr = addr;
400     dst->addrlist[0] = (char*) &dst->addr;
401     dst->addrlist[1] = NULL;
402     dst->entry.h_addr_list = dst->addrlist;
403     dst->alias = NULL;
404     dst->entry.h_aliases = &dst->alias;
405     dst->entry.h_addrtype = AF_INET;
406     dst->entry.h_length = sizeof (in_addr);
407     dst->entry.h_name = dst->hostname;
408     strcpy_s(dst->hostname, bufferLength - sizeof (DUMMYHOSTENT), realhost);
409     }
410     };
411     class ConnectionInfoHolder {
412     private:
413     ConnectionInfo* info;
414     public:
415     ConnectionInfoHolder():info(NULL) {
416     }
417     ~ConnectionInfoHolder() {
418     delete info;
419     }
420     operator ConnectionInfo*()const {
421     return info;
422     }
423     void operator=(ConnectionInfo* newInfo) {
424     if (info != newInfo) {
425     delete info;
426     info = newInfo;
427     }
428     }
429     // �����o�I�����Z�q
430     ConnectionInfo* operator->()const {
431     return info;
432     }
433     };
434    
435     class ConnectionInfoList {
436     private:
437     CRITICAL_SECTION section;
438     ConnectionInfoHolder list[254];
439     Hashtable<String,ConnectionInfo*> table;
440     public:
441     ConnectionInfoList() {
442     ::InitializeCriticalSection(&section);
443     }
444     ~ConnectionInfoList() {
445     ::DeleteCriticalSection(&section);
446     }
447     HANDLE getTask(ConnectionInfo* info) {
448     if (info == NULL)
449     return NULL;
450     return (HANDLE) -info->addr.S_un.S_un_b.s_b4;
451     }
452     ConnectionInfo* get(HANDLE task) {
453     if ((DWORD) task >= 0)
454     return NULL;
455     return get((int) -((long) task) - 1);
456     }
457     ConnectionInfo* get(in_addr addr) {
458     if (addr.S_un.S_un_b.s_b1 != 0 || addr.S_un.S_un_b.s_b2 != 0 || addr.S_un.S_un_b.s_b3 != 0)
459     return NULL;
460     return get(addr.S_un.S_un_b.s_b4 - 1);
461     }
462     ConnectionInfo* get(int index) {
463     ::EnterCriticalSection(&section);
464     ConnectionInfo* info = 0 <= index && index < countof(list) ? (ConnectionInfo*) list[index] : NULL;
465     ::LeaveCriticalSection(&section);
466     return info;
467     }
468     ConnectionInfo* find(const char* url) {
469     ::EnterCriticalSection(&section);
470     ConnectionInfo* info = table.get(url);
471     ::LeaveCriticalSection(&section);
472     if (info != NULL) {
473     info->time = ::GetTickCount();
474     return info;
475     }
476     ProxyInfo proxy;
477     String realhost = ProxyInfo::parse(url, proxy);
478     if (realhost == NULL || realhost.length() == 0) {
479     proxy = instance().defaultProxy;
480     if (proxy.type != ProxyInfo::TYPE_NONE) {
481     realhost = url;
482     }
483     }
484     if (proxy.type == ProxyInfo::TYPE_NONE)
485     return NULL;
486     info = new ConnectionInfo(proxy, realhost);
487    
488     int i;
489     ::EnterCriticalSection(&section);
490     for (i = 0; i < countof(list); i++) {
491     if (list[i] == NULL) {
492     list[i] = info;
493     break;
494     }
495     }
496     if (i >= countof(list)) {
497     DWORD now = ::GetTickCount();
498     DWORD max = 0;
499     int index = -1;
500     for (i = 0; i < countof(list); i++) {
501     if (list[i] != NULL) {
502     if (now - list[i]->time > max) {
503     max = now - list[i]->time;
504     index = i;
505     }
506     }
507     }
508     list[index] = info;
509     }
510     table.put(url, info);
511     ::LeaveCriticalSection(&section);
512     info->addr.s_addr = htonl(i + 1);
513    
514     info->time = ::GetTickCount();
515     return info;
516     }
517     };
518     friend class ConnectionInfoList;
519    
520     class OptionsSettingDialog : public Dialog {
521     private:
522     ComboBoxCtrl resolveCombo;
523     Window host;
524     Window user;
525     Window pass;
526     Window conn;
527     Window erro;
528     Window log;
529     HFONT DlgFont;
530     protected:
531     virtual bool dispatch(int message, int wParam, long lParam) {
532     if (message == WM_COMMAND && wParam == MAKEWPARAM(IDC_REFER, BN_CLICKED)) {
533     char buffer[1024];
534     char uimsg[MAX_UIMSG];
535     OPENFILENAME ofn = {
536     sizeof ofn,
537     *this,
538     };
539     ofn.lpstrFile = buffer;
540     ofn.nMaxFile = countof(buffer);
541     ofn.Flags = OFN_LONGNAMES | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST | OFN_NOREADONLYRETURN | OFN_HIDEREADONLY;
542     UTIL_get_lang_msg("MSG_LOGFILE_SELECT", uimsg, sizeof(uimsg),
543     "Select Logfile");
544     ofn.lpstrTitle = uimsg;
545     if (logfile != NULL) {
546     strcpy_s(buffer, sizeof buffer, logfile);
547     }else{
548     buffer[0] = '\0';
549     }
550     if (::GetSaveFileName(&ofn)) {
551     if (buffer[0] != '\0') {
552     logfile = buffer;
553     }else{
554     logfile = NULL;
555     }
556     log.SetWindowText(buffer);
557     }
558     return true;
559     }
560     return Dialog::dispatch(message, wParam, lParam);
561     }
562     virtual bool onInitDialog() {
563     char uimsg[MAX_UIMSG], uitmp[MAX_UIMSG];
564     LOGFONT logfont;
565     HFONT font;
566    
567     Dialog::onInitDialog();
568    
569     font = (HFONT)SendMessage(WM_GETFONT, 0, 0);
570     GetObject(font, sizeof(LOGFONT), &logfont);
571     if (UTIL_get_lang_font("DLG_TAHOMA_FONT", HWND(), &logfont, &DlgFont)) {
572     SendDlgItemMessage(IDC_GRP_COMMON, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
573     SendDlgItemMessage(IDC_TIMEOUT_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
574     SendDlgItemMessage(IDC_TIMEOUT, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
575     SendDlgItemMessage(IDC_TIMEOUT_SECONDS, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
576     SendDlgItemMessage(IDC_LOGFILE_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
577     SendDlgItemMessage(IDC_LOGFILE, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
578     SendDlgItemMessage(IDC_REFER, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
579     SendDlgItemMessage(IDC_GRP_SOCKS, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
580     SendDlgItemMessage(IDC_RESOLVE_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
581     SendDlgItemMessage(CBS_DROPDOWNLIST, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
582     SendDlgItemMessage(IDC_GRP_TELNET, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
583     SendDlgItemMessage(IDC_HOSTNAME_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
584     SendDlgItemMessage(IDC_HOSTNAME, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
585     SendDlgItemMessage(IDC_USERNAME_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
586     SendDlgItemMessage(IDC_USERNAME, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
587     SendDlgItemMessage(IDC_PASSWORD_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
588     SendDlgItemMessage(IDC_PASSWORD, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
589     SendDlgItemMessage(IDC_CONNECTED_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
590     SendDlgItemMessage(IDC_CONNECTED, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
591     SendDlgItemMessage(IDC_ERROR_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
592     SendDlgItemMessage(IDC_ERROR, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
593     SendDlgItemMessage(IDOK, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
594     SendDlgItemMessage(IDCANCEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
595     }
596     else {
597     DlgFont = NULL;
598     }
599    
600     GetWindowText(uitmp, sizeof(uitmp));
601     UTIL_get_lang_msg("DLG_OTHER_TITLE", uimsg, sizeof(uimsg), uitmp);
602     SetWindowText(uimsg);
603     GetDlgItemText(IDC_GRP_COMMON, uitmp, sizeof(uitmp));
604     UTIL_get_lang_msg("DLG_OTHER_COMMON", uimsg, sizeof(uimsg), uitmp);
605     SetDlgItemText(IDC_GRP_COMMON, uimsg);
606     GetDlgItemText(IDC_TIMEOUT_LABEL, uitmp, sizeof(uitmp));
607     UTIL_get_lang_msg("DLG_OTHER_TIMEOUT", uimsg, sizeof(uimsg), uitmp);
608     SetDlgItemText(IDC_TIMEOUT_LABEL, uimsg);
609     GetDlgItemText(IDC_TIMEOUT_SECONDS, uitmp, sizeof(uitmp));
610     UTIL_get_lang_msg("DLG_OTHER_SECOND", uimsg, sizeof(uimsg), uitmp);
611     SetDlgItemText(IDC_TIMEOUT_SECONDS, uimsg);
612     GetDlgItemText(IDC_LOGFILE_LABEL, uitmp, sizeof(uitmp));
613     UTIL_get_lang_msg("DLG_OTHER_LOG", uimsg, sizeof(uimsg), uitmp);
614     SetDlgItemText(IDC_LOGFILE_LABEL, uimsg);
615     GetDlgItemText(IDC_REFER, uitmp, sizeof(uitmp));
616     UTIL_get_lang_msg("DLG_OTHER_REFER", uimsg, sizeof(uimsg), uitmp);
617     SetDlgItemText(IDC_REFER, uimsg);
618     GetDlgItemText(IDC_GRP_SOCKS, uitmp, sizeof(uitmp));
619     UTIL_get_lang_msg("DLG_OTHER_SOCKS", uimsg, sizeof(uimsg), uitmp);
620     SetDlgItemText(IDC_GRP_SOCKS, uimsg);
621     GetDlgItemText(IDC_RESOLVE_LABEL, uitmp, sizeof(uitmp));
622     UTIL_get_lang_msg("DLG_OTHER_RESOLV", uimsg, sizeof(uimsg), uitmp);
623     SetDlgItemText(IDC_RESOLVE_LABEL, uimsg);
624     GetDlgItemText(IDC_GRP_TELNET, uitmp, sizeof(uitmp));
625     UTIL_get_lang_msg("DLG_OTHER_TELNET", uimsg, sizeof(uimsg), uitmp);
626     SetDlgItemText(IDC_GRP_TELNET, uimsg);
627     GetDlgItemText(IDC_HOSTNAME_LABEL, uitmp, sizeof(uitmp));
628     UTIL_get_lang_msg("DLG_OTHER_HOST", uimsg, sizeof(uimsg), uitmp);
629     SetDlgItemText(IDC_HOSTNAME_LABEL, uimsg);
630     GetDlgItemText(IDC_USERNAME_LABEL, uitmp, sizeof(uitmp));
631     UTIL_get_lang_msg("DLG_OTHER_USER", uimsg, sizeof(uimsg), uitmp);
632     SetDlgItemText(IDC_USERNAME_LABEL, uimsg);
633     GetDlgItemText(IDC_PASSWORD_LABEL, uitmp, sizeof(uitmp));
634     UTIL_get_lang_msg("DLG_OTHER_PASS", uimsg, sizeof(uimsg), uitmp);
635     SetDlgItemText(IDC_PASSWORD_LABEL, uimsg);
636     GetDlgItemText(IDC_CONNECTED_LABEL, uitmp, sizeof(uitmp));
637     UTIL_get_lang_msg("DLG_OTHER_CONNECT", uimsg, sizeof(uimsg), uitmp);
638     SetDlgItemText(IDC_CONNECTED_LABEL, uimsg);
639     GetDlgItemText(IDC_ERROR_LABEL, uitmp, sizeof(uitmp));
640     UTIL_get_lang_msg("DLG_OTHER_ERROR", uimsg, sizeof(uimsg), uitmp);
641     SetDlgItemText(IDC_ERROR_LABEL, uimsg);
642     GetDlgItemText(IDOK, uitmp, sizeof(uitmp));
643     UTIL_get_lang_msg("BTN_OK", uimsg, sizeof(uimsg), uitmp);
644     SetDlgItemText(IDOK, uimsg);
645     GetDlgItemText(IDCANCEL, uitmp, sizeof(uitmp));
646     UTIL_get_lang_msg("BTN_CANCEL", uimsg, sizeof(uimsg), uitmp);
647     SetDlgItemText(IDCANCEL, uimsg);
648    
649     host = GetDlgItem(IDC_HOSTNAME);
650     user = GetDlgItem(IDC_USERNAME);
651     pass = GetDlgItem(IDC_PASSWORD);
652     conn = GetDlgItem(IDC_CONNECTED);
653     erro = GetDlgItem(IDC_ERROR);
654     log = GetDlgItem(IDC_LOGFILE);
655    
656     SetDlgItemInt(IDC_TIMEOUT, timeout, false);
657    
658     resolveCombo <<= GetDlgItem(IDC_RESOLVE);
659     UTIL_get_lang_msg("DLG_OTHER_RESOLV_AUTO", uimsg, sizeof(uimsg), "auto resolve");
660     resolveCombo.addString(uimsg);
661     UTIL_get_lang_msg("DLG_OTHER_RESOLV_REMOTE", uimsg, sizeof(uimsg), "resolve remote");
662     resolveCombo.addString(uimsg);
663     UTIL_get_lang_msg("DLG_OTHER_RESOLV_LOCAL", uimsg, sizeof(uimsg), "resolve local");
664     resolveCombo.addString(uimsg);
665     resolveCombo.setCurSel(resolve);
666    
667     host.SetWindowText(HostnamePrompt);
668     user.SetWindowText(UsernamePrompt);
669     pass.SetWindowText(PasswordPrompt);
670     conn.SetWindowText(ConnectedMessage);
671     erro.SetWindowText(ErrorMessage);
672    
673     if (logfile != NULL)
674     log.SetWindowText(logfile);
675    
676     return true;
677     }
678     virtual void onOK() {
679     if (host.GetWindowTextLength() == 0
680     || user.GetWindowTextLength() == 0
681     || pass.GetWindowTextLength() == 0
682     || conn.GetWindowTextLength() == 0
683     || erro.GetWindowTextLength() == 0) {
684     char uimsg[MAX_UIMSG];
685     UTIL_get_lang_msg("MSG_EMPTY_PARAMETER", uimsg, sizeof(uimsg),
686     "Some parameters are empty!");
687     MessageBox(uimsg, FileVersion::getOwnVersion().getProductName(), MB_OK | MB_ICONERROR);
688     return;
689     }
690    
691     timeout = GetDlgItemInt(IDC_TIMEOUT, 0, false);
692    
693     resolve = resolveCombo.getCurSel();
694    
695     HostnamePrompt = host.GetWindowText();
696     UsernamePrompt = user.GetWindowText();
697     PasswordPrompt = pass.GetWindowText();
698     ConnectedMessage = conn.GetWindowText();
699     ErrorMessage = erro.GetWindowText();
700    
701     logfile = log.GetWindowTextLength() > 0 ? log.GetWindowText() : NULL;
702    
703     if (DlgFont != NULL) {
704     DeleteObject(DlgFont);
705     }
706     Dialog::onOK();
707     }
708     virtual void onCancel() {
709     if (DlgFont != NULL) {
710     DeleteObject(DlgFont);
711     }
712     Dialog::onCancel();
713     }
714     public:
715     String logfile;
716     int timeout;
717     int resolve;
718    
719     String HostnamePrompt;
720     String UsernamePrompt;
721     String PasswordPrompt;
722     String ConnectedMessage;
723     String ErrorMessage;
724    
725     int open(HWND owner) {
726     return Dialog::open(instance().resource_module, IDD_OPTION_SETTING, owner);
727     }
728     };
729     friend class OptionsSettingDialog;
730    
731     class SettingDialog : public Dialog {
732     private:
733     EditBoxCtrl url;
734     ComboBoxCtrl type;
735     EditBoxCtrl host;
736     EditBoxCtrl port;
737     EditBoxCtrl user;
738     EditBoxCtrl pass;
739     bool lock;
740     HFONT DlgFont;
741     protected:
742     virtual bool dispatch(int message, int wParam, long lParam) {
743     if (message == WM_COMMAND) {
744     switch (wParam) {
745     case MAKEWPARAM(IDC_OPTIONS, BN_CLICKED):
746     onOptions();
747     return true;
748     case MAKEWPARAM(IDC_TYPE, CBN_SELCHANGE):
749     case MAKEWPARAM(IDC_HOSTNAME, EN_CHANGE):
750     case MAKEWPARAM(IDC_PORT, EN_CHANGE):
751     case MAKEWPARAM(IDC_USERNAME, EN_CHANGE):
752     case MAKEWPARAM(IDC_PASSWORD, EN_CHANGE):
753     if (!lock)
754     onChanged(LOWORD(wParam));
755     return true;
756     }
757     }
758     return Dialog::dispatch(message, wParam, lParam);
759     }
760     virtual bool onInitDialog() {
761     char uimsg[MAX_UIMSG], uitmp[MAX_UIMSG];
762     LOGFONT logfont;
763     HFONT font;
764    
765     Dialog::onInitDialog();
766    
767     font = (HFONT)SendMessage(WM_GETFONT, 0, 0);
768     GetObject(font, sizeof(LOGFONT), &logfont);
769     if (UTIL_get_lang_font("DLG_TAHOMA_FONT", HWND(), &logfont, &DlgFont)) {
770     SendDlgItemMessage(IDC_URL_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
771     SendDlgItemMessage(IDC_URL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
772     SendDlgItemMessage(IDC_TYPE_LEBEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
773     SendDlgItemMessage(IDC_TYPE, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
774     SendDlgItemMessage(IDC_HOSTNAME_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
775     SendDlgItemMessage(IDC_HOSTNAME, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
776     SendDlgItemMessage(IDC_PORT_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
777     SendDlgItemMessage(IDC_PORT, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
778     SendDlgItemMessage(IDC_USERNAME_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
779     SendDlgItemMessage(IDC_USERNAME, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
780     SendDlgItemMessage(IDC_PASSWORD_LABEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
781     SendDlgItemMessage(IDC_PASSWORD, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
782     SendDlgItemMessage(IDC_OPTIONS, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
783     SendDlgItemMessage(IDOK, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
784     SendDlgItemMessage(IDCANCEL, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
785     }
786     else {
787     DlgFont = NULL;
788     }
789    
790     GetWindowText(uitmp, sizeof(uitmp));
791     UTIL_get_lang_msg("DLG_SETUP_TITLE", uimsg, sizeof(uimsg), uitmp);
792     SetWindowText(uimsg);
793     GetDlgItemText(IDC_URL_LABEL, uitmp, sizeof(uitmp));
794     UTIL_get_lang_msg("DLG_SETUP_URL", uimsg, sizeof(uimsg), uitmp);
795     SetDlgItemText(IDC_URL_LABEL, uimsg);
796     GetDlgItemText(IDC_TYPE_LEBEL, uitmp, sizeof(uitmp));
797     UTIL_get_lang_msg("DLG_SETUP_TYPE", uimsg, sizeof(uimsg), uitmp);
798     SetDlgItemText(IDC_TYPE_LEBEL, uimsg);
799     GetDlgItemText(IDC_HOSTNAME_LABEL, uitmp, sizeof(uitmp));
800     UTIL_get_lang_msg("DLG_SETUP_HOST", uimsg, sizeof(uimsg), uitmp);
801     SetDlgItemText(IDC_HOSTNAME_LABEL, uimsg);
802     GetDlgItemText(IDC_PORT_LABEL, uitmp, sizeof(uitmp));
803     UTIL_get_lang_msg("DLG_SETUP_PORT", uimsg, sizeof(uimsg), uitmp);
804     SetDlgItemText(IDC_PORT_LABEL, uimsg);
805     GetDlgItemText(IDC_USERNAME_LABEL, uitmp, sizeof(uitmp));
806     UTIL_get_lang_msg("DLG_SETUP_USER", uimsg, sizeof(uimsg), uitmp);
807     SetDlgItemText(IDC_USERNAME_LABEL, uimsg);
808     GetDlgItemText(IDC_PASSWORD_LABEL, uitmp, sizeof(uitmp));
809     UTIL_get_lang_msg("DLG_SETUP_PASS", uimsg, sizeof(uimsg), uitmp);
810     SetDlgItemText(IDC_PASSWORD_LABEL, uimsg);
811     GetDlgItemText(IDC_OPTIONS, uitmp, sizeof(uitmp));
812     UTIL_get_lang_msg("DLG_SETUP_OTHER", uimsg, sizeof(uimsg), uitmp);
813     SetDlgItemText(IDC_OPTIONS, uimsg);
814     GetDlgItemText(IDOK, uitmp, sizeof(uitmp));
815     UTIL_get_lang_msg("BTN_OK", uimsg, sizeof(uimsg), uitmp);
816     SetDlgItemText(IDOK, uimsg);
817     GetDlgItemText(IDCANCEL, uitmp, sizeof(uitmp));
818     UTIL_get_lang_msg("BTN_CANCEL", uimsg, sizeof(uimsg), uitmp);
819     SetDlgItemText(IDCANCEL, uimsg);
820    
821     url <<= GetDlgItem(IDC_URL);
822     type <<= GetDlgItem(IDC_TYPE);
823     host <<= GetDlgItem(IDC_HOSTNAME);
824     port <<= GetDlgItem(IDC_PORT);
825     user <<= GetDlgItem(IDC_USERNAME);
826     pass <<= GetDlgItem(IDC_PASSWORD);
827    
828     lock = true;
829     UTIL_get_lang_msg("MSG_TYPE_NONE", uimsg, sizeof(uimsg), "Without Proxy");
830     type.addString(uimsg);
831     type.addString("HTTP");
832     type.addString("TELNET");
833     type.addString("SOCKS4");
834     type.addString("SOCKS5");
835     type.addString("SSL");
836     type.addString("HTTP+SSL");
837     type.addString("TELNET+SSL");
838     type.addString("SOCKS4+SSL");
839     type.addString("SOCKS5+SSL");
840     type.setCurSel(proxy.type);
841    
842     if (proxy.type != ProxyInfo::TYPE_NONE && proxy.type != ProxyInfo::TYPE_SSL) {
843     if (proxy.host != NULL) {
844     host.SetWindowText(proxy.host);
845     if (proxy.port != 0) {
846     char buffer[16];
847     _itoa_s(proxy.port, buffer, sizeof buffer, 10);
848     port.SetWindowText(buffer);
849     }
850     if (proxy.user != NULL) {
851     user.SetWindowText(proxy.user);
852     if (proxy.pass != NULL) {
853     pass.SetWindowText(proxy.pass);
854     }
855     }
856     }
857     }
858     lock = false;
859     onChanged(0);
860     return true;
861     }
862     virtual void onOK() {
863     char uimsg[MAX_UIMSG];
864     if (proxy.type != ProxyInfo::TYPE_NONE && proxy.type != ProxyInfo::TYPE_SSL) {
865     if (proxy.host == NULL) {
866     UTIL_get_lang_msg("MSG_EMPTY_HOSTNAME", uimsg, sizeof(uimsg),
867     "Hostname is empty!");
868     MessageBox(uimsg, FileVersion::getOwnVersion().getProductName(), MB_OK | MB_ICONERROR);
869     return;
870     }
871     if (port.GetWindowTextLength() != 0 && proxy.port <= 0) {
872     UTIL_get_lang_msg("MSG_ILLEGAL_PORT", uimsg, sizeof(uimsg),
873     "Illegal port number!");
874     MessageBox(uimsg, FileVersion::getOwnVersion().getProductName(), MB_OK | MB_ICONERROR);
875     return;
876     }
877     }
878     if (DlgFont != NULL) {
879     DeleteObject(DlgFont);
880     }
881     Dialog::onOK();
882     }
883     virtual void onCancel() {
884     if (DlgFont != NULL) {
885     DeleteObject(DlgFont);
886     }
887     Dialog::onCancel();
888     }
889     void onOptions() {
890     OptionsSettingDialog dlg;
891     dlg.timeout = instance().timeout;
892     switch (instance().resolve) {
893     case RESOLVE_REMOTE:
894     dlg.resolve = 1;
895     break;
896     case RESOLVE_LOCAL:
897     dlg.resolve = 2;
898     break;
899     default:
900     dlg.resolve = 0;
901     break;
902     }
903     dlg.HostnamePrompt = instance().prompt_table[0];
904     dlg.UsernamePrompt = instance().prompt_table[1];
905     dlg.PasswordPrompt = instance().prompt_table[2];
906     dlg.ConnectedMessage = instance().prompt_table[3];
907     dlg.ErrorMessage = instance().prompt_table[4];
908     dlg.logfile = instance().logfile;
909     if (dlg.open(*this) == IDOK) {
910     instance().timeout = dlg.timeout;
911     switch (dlg.resolve) {
912     case 1:
913     instance().resolve = RESOLVE_REMOTE;
914     break;
915     case 2:
916     instance().resolve = RESOLVE_LOCAL;
917     break;
918     default:
919     instance().resolve = RESOLVE_AUTO;
920     break;
921     }
922     instance().prompt_table[0] = dlg.HostnamePrompt;
923     instance().prompt_table[1] = dlg.UsernamePrompt;
924     instance().prompt_table[2] = dlg.PasswordPrompt;
925     instance().prompt_table[3] = dlg.ConnectedMessage;
926     instance().prompt_table[4] = dlg.ErrorMessage;
927    
928     if (instance().logfile != dlg.logfile) {
929     instance().logfile = dlg.logfile;
930     Logger::open(dlg.logfile);
931     }
932     }
933     }
934     void onChanged(int id) {
935     if (id == 0 || id == IDC_TYPE || id == IDC_HOSTNAME || id == IDC_USERNAME) {
936     int enabled = 0;
937     int typeN = type.getCurSel();
938     if (typeN != ProxyInfo::TYPE_NONE && typeN != ProxyInfo::TYPE_SSL) {
939     enabled |= 1;
940     if (::GetWindowTextLength(GetDlgItem(IDC_HOSTNAME)) > 0) {
941     enabled |= 2;
942     if (::GetWindowTextLength(GetDlgItem(IDC_USERNAME)) > 0) {
943     enabled |= 4;
944     }
945     }
946     }
947     ::EnableWindow(GetDlgItem(IDC_HOSTNAME), (enabled & 1) != 0);
948     ::EnableWindow(GetDlgItem(IDC_PORT), (enabled & 2) != 0);
949     ::EnableWindow(GetDlgItem(IDC_USERNAME), (enabled & 2) != 0);
950     ::EnableWindow(GetDlgItem(IDC_PASSWORD), (enabled & 4) != 0);
951     }
952    
953     if (id != 0) {
954     proxy.type = (ProxyInfo::Type) type.getCurSel();
955     if (proxy.type != ProxyInfo::TYPE_NONE && proxy.type != ProxyInfo::TYPE_SSL) {
956     proxy.host = host.GetWindowText();
957     if (host.GetWindowTextLength() == 0) {
958     proxy.host = NULL;
959     }else{
960     proxy.host = host.GetWindowText();
961     }
962     proxy.port = GetDlgItemInt(IDC_PORT, NULL, FALSE);
963     proxy.user = user.GetWindowTextLength() > 0 ? user.GetWindowText() : NULL;
964     proxy.pass = pass.GetWindowTextLength() > 0 ? pass.GetWindowText() : NULL;
965     }else{
966     proxy.host = NULL;
967     proxy.port = 0;
968     proxy.user = NULL;
969     proxy.pass = NULL;
970     }
971     }
972     String urlS = proxy.generateURL();
973     if (urlS == NULL) {
974     urlS = "none:///";
975     }
976     url.SetWindowText(urlS);
977     }
978     public:
979     ProxyInfo proxy;
980     SettingDialog():lock(false) {
981     }
982    
983     int open(HWND owner) {
984     return Dialog::open(instance().resource_module, IDD_SETTING, owner);
985     }
986     };
987     friend class SettingDialog;
988    
989     class AboutDialog : public Dialog {
990     private:
991     HFONT DlgFont;
992     virtual bool onInitDialog() {
993     String buf;
994     char *buf2;
995     const char *ver;
996     int n, a, b, c, d, len;
997     char uimsg[MAX_UIMSG], uimsg2[MAX_UIMSG], uimsg3[MAX_UIMSG];
998     LOGFONT logfont;
999     HFONT font;
1000    
1001     font = (HFONT)SendMessage(WM_GETFONT, 0, 0);
1002     GetObject(font, sizeof(LOGFONT), &logfont);
1003     if (UTIL_get_lang_font("DLG_TAHOMA_FONT", HWND(), &logfont, &DlgFont)) {
1004     SendDlgItemMessage(IDC_VERSION, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
1005     SendDlgItemMessage(IDOK, WM_SETFONT, (WPARAM)DlgFont, MAKELPARAM(TRUE,0));
1006     }
1007     else {
1008     DlgFont = NULL;
1009     }
1010    
1011     GetWindowText(uimsg2, sizeof(uimsg2));
1012     UTIL_get_lang_msg("DLG_ABOUT_TITLE", uimsg, sizeof(uimsg), uimsg2);
1013     SetWindowText(uimsg);
1014    
1015     UTIL_get_lang_msg("DLG_ABOUT_EXTENTION", uimsg, sizeof(uimsg),
1016     "Tera Term proxy extension");
1017     UTIL_get_lang_msg("DLG_ABOUT_YEBISUYA", uimsg2, sizeof(uimsg2),
1018     "YebisuyaHompo");
1019     UTIL_get_lang_msg("DLG_ABOUT_HOMEPAGE", uimsg3, sizeof(uimsg3),
1020     "TTProxy home page");
1021     buf = GetDlgItemText(IDC_VERSION);
1022     len = buf.length() + 50;
1023     buf2 = (char *)_alloca(len);
1024     if (buf2 == NULL) {
1025     return true;
1026     }
1027     ver = FileVersion::getOwnVersion().getFileVersion();
1028     n = sscanf_s(ver, "%d, %d, %d, %d", &a, &b, &c, &d);
1029     if (n == 4) {
1030     sprintf_s(buf2, len, buf, uimsg, a, b, c, d, uimsg2, uimsg3);
1031     }
1032     SetDlgItemText(IDC_VERSION, (n == 4) ? buf2 : buf);
1033    
1034     GetDlgItemText(IDOK, uimsg, sizeof(uimsg));
1035     UTIL_get_lang_msg("BTN_OK", uimsg, sizeof(uimsg),"OK");
1036     SetDlgItemText(IDOK, uimsg);
1037    
1038     return true;
1039     }
1040     virtual void onOK() {
1041     if (DlgFont != NULL) {
1042     DeleteObject(DlgFont);
1043     }
1044     Dialog::onOK();
1045     }
1046     public :
1047     int open(HWND owner) {
1048     return Dialog::open(instance().resource_module, IDD_ABOUTDIALOG, owner);
1049     }
1050     };
1051     friend class AboutDialog;
1052    
1053     int _sendToSocket(SOCKET s, const unsigned char* buffer, int size) {
1054     int count = 0;
1055     while (count < size) {
1056     struct timeval tv = {timeout, 0};
1057     fd_set fd;
1058     FD_ZERO(&fd);
1059     FD_SET(s, &fd);
1060     if (select((int) (s + 1), NULL, &fd, NULL, timeout > 0 ? &tv : NULL) == SOCKET_ERROR)
1061     return SOCKET_ERROR;
1062     if (!FD_ISSET(s, &fd)) {
1063     return SOCKET_ERROR;
1064     }
1065     int written = ORIG_send(s, (const char*) buffer + count, size - count, 0);
1066     if (written == SOCKET_ERROR)
1067     return SOCKET_ERROR;
1068     count += written;
1069     }
1070     return count;
1071     }
1072    
1073     int sendToSocket(SOCKET s, const unsigned char* buffer, int size) {
1074     int i = 0;
1075     Logger::log("send", buffer, size);
1076     return _sendToSocket(s, buffer, size);
1077     }
1078    
1079     int sendToSocketFormat(SOCKET s, const char* format, ...) {
1080     char buf[1025];
1081     int len;
1082     va_list arglist;
1083     va_start(arglist, format);
1084     len = wvsprintf(buf, format, arglist);
1085     va_end(arglist);
1086     Logger::log("send", buf);
1087     return _sendToSocket(s, (const unsigned char*) buf, len);
1088     }
1089    
1090     int recieveFromSocketTimeout(SOCKET s, unsigned char* buffer, int size, int timeout) {
1091     int ready = 0;
1092     while (!ready) {
1093     struct timeval tv = {timeout, 0};
1094     fd_set fd;
1095     FD_ZERO(&fd);
1096     FD_SET(s, &fd);
1097     switch (select((int) (s + 1), &fd, NULL, NULL, timeout > 0 ? &tv : NULL)) {
1098     case SOCKET_ERROR:
1099     return SOCKET_ERROR;
1100     case 0:
1101     return 0;
1102     default:
1103     ready = FD_ISSET(s, &fd);
1104     break;
1105     }
1106     }
1107     return ORIG_recv(s, (char*) buffer, size, 0);
1108     }
1109    
1110     int recieveFromSocket(SOCKET s, unsigned char* buffer, int size) {
1111     int result = recieveFromSocketTimeout(s, buffer, size, timeout);
1112     if (result != SOCKET_ERROR) {
1113     Logger::log("recv", buffer, result);
1114     }
1115     return result;
1116     }
1117    
1118     int line_input(SOCKET s, char *buf, int size) {
1119     char* dst = buf;
1120     if (size == 0)
1121     return 0; /* no error */
1122     size--;
1123     while (size > 0) {
1124     switch (recieveFromSocketTimeout(s, (unsigned char*) dst, 1, timeout)) {
1125     case SOCKET_ERROR:
1126     return SOCKET_ERROR;
1127     case 0:
1128     size = 0;
1129     break;
1130     default:
1131     if (*dst == '\n') {
1132     size = 0;
1133     } else {
1134     size--;
1135     }
1136     dst++;
1137     break;
1138     }
1139     }
1140     *dst = '\0';
1141     Logger::log("recv", buf);
1142     return 0;
1143     }
1144    
1145     int wait_for_prompt(SOCKET s, String prompts[], int count, int timeout /* sec */) {
1146     char buf[1024];
1147     while (1) {
1148     char *dst = buf;
1149     char *end = buf + sizeof buf - 1;
1150     while (dst < end) {
1151     switch (recieveFromSocketTimeout(s, (unsigned char*) dst, 1, timeout)) { /* recv one-by-one */
1152     case SOCKET_ERROR:
1153     if (WSAGetLastError() != WSAEWOULDBLOCK) {
1154     return SOCKET_ERROR;
1155     }
1156     // no break
1157     case 0:
1158     end = dst; /* end of stream */
1159     break;
1160     default:
1161     /* continue reading until last 1 char is EOL? */
1162     if (*dst++ == '\n') {
1163     /* finished */
1164     end = dst;
1165     }
1166     }
1167     }
1168     if (dst > buf) {
1169     int i;
1170     *dst = '\0';
1171     Logger::log("recv", buf);
1172     for (i = 0; i < count; i++) {
1173     char* found = strstr(buf, prompts[i]);
1174     if (found != NULL) {
1175     return i;
1176     }
1177     }
1178     }
1179     }
1180     }
1181    
1182     int begin_relay_http(ProxyInfo& proxy, String realhost, unsigned short realport, SOCKET s) {
1183     static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1184     char buf[1024];
1185     int status_code;
1186     if (sendToSocketFormat(s, "CONNECT %s:%d HTTP/1.0\r\n", realhost, realport) == SOCKET_ERROR)
1187     return SOCKET_ERROR;
1188     if (proxy.user != NULL) {
1189     int userlen = strlen(proxy.user);
1190     int passlen = strlen(proxy.pass);
1191     int authlen = userlen + 1 + passlen;
1192     int encodedlen = (authlen + 2) / 3 * 4;
1193     char* auth = (char*) alloca(authlen + 1);
1194     char* encoded = (char*) alloca(encodedlen + 1);
1195     unsigned char *src = (unsigned char *) auth;
1196     char *dst = encoded;
1197     int bits = 0;
1198     int data = 0;
1199     strcpy_s(auth, userlen + 1, proxy.user);
1200     auth[userlen] = ':';
1201     strcpy_s(auth + userlen + 1, passlen, proxy.pass);
1202    
1203     /* make base64 string */
1204     while (*src != '\0') {
1205     data = (data << 8) | *src++;
1206     bits += 8;
1207     while (bits >= 6){
1208     bits -= 6;
1209     *dst++ = base64_table[0x3F & (data >> bits)];
1210     encodedlen--;
1211     }
1212     }
1213     while (encodedlen-- > 0) {
1214     *dst++ = '=';
1215     }
1216     *dst = '\0';
1217    
1218     if (sendToSocketFormat(s, "Proxy-Authorization: Basic %s\r\n", encoded) == SOCKET_ERROR)
1219     return SOCKET_ERROR;
1220     }
1221     if (sendToSocketFormat(s, "\r\n") == SOCKET_ERROR)
1222     return SOCKET_ERROR;
1223     if (line_input(s, buf, sizeof buf) == SOCKET_ERROR)
1224     return SOCKET_ERROR;
1225     status_code = atoi(strchr(buf, ' '));
1226     do {
1227     if (line_input(s, buf, sizeof buf) == SOCKET_ERROR) {
1228     return SOCKET_ERROR;
1229     }
1230     } while (strcmp(buf,"\r\n") != 0);
1231     if (status_code != 200) {
1232     char uimsg[MAX_UIMSG];
1233     switch (status_code) {
1234     case 401:
1235     case 407:
1236     UTIL_get_lang_msg("MSG_PROXY_UNAUTHORIZED", uimsg, sizeof(uimsg),
1237     "Proxy authorization failed!");
1238     break;
1239     case 400:
1240     case 405:
1241     case 406:
1242     case 403:
1243     UTIL_get_lang_msg("MSG_PROXY_BAD_REQUEST", uimsg, sizeof(uimsg),
1244     "Proxy prevent this connection!");
1245     break;
1246     }
1247     return setError(s, uimsg);
1248     }
1249     return 0;
1250     }
1251    
1252     enum {
1253     SOCKS5_VERSION = 5,
1254     SOCKS5_REJECT = 0xFF, /* No acceptable */
1255     SOCKS5_CMD_CONNECT = 1,
1256     SOCKS5_ATYP_IPv4 = 1,
1257     SOCKS5_ATYP_DOMAINNAME = 3,
1258     SOCKS5_ATYP_IPv6 = 4,
1259     SOCKS5_AUTH_SUBNEGOVER = 1,
1260    
1261     /* informations for SOCKS */
1262     SOCKS5_REP_SUCCEEDED = 0x00, /* succeeded */
1263     SOCKS5_REP_FAIL = 0x01, /* general SOCKS serer failure */
1264     SOCKS5_REP_NALLOWED = 0x02, /* connection not allowed by ruleset */
1265     SOCKS5_REP_NUNREACH = 0x03, /* Network unreachable */
1266     SOCKS5_REP_HUNREACH = 0x04, /* Host unreachable */
1267     SOCKS5_REP_REFUSED = 0x05, /* connection refused */
1268     SOCKS5_REP_EXPIRED = 0x06, /* TTL expired */
1269     SOCKS5_REP_CNOTSUP = 0x07, /* Command not supported */
1270     SOCKS5_REP_ANOTSUP = 0x08, /* Address not supported */
1271     SOCKS5_REP_INVADDR = 0x09, /* Inalid address */
1272    
1273     /* SOCKS5 authentication methods */
1274     SOCKS5_AUTH_NOAUTH = 0x00, /* without authentication */
1275     SOCKS5_AUTH_GSSAPI = 0x01, /* GSSAPI */
1276     SOCKS5_AUTH_USERPASS = 0x02, /* User/Password */
1277     SOCKS5_AUTH_CHAP = 0x03, /* Challenge-Handshake Auth Proto. */
1278     SOCKS5_AUTH_EAP = 0x05, /* Extensible Authentication Proto. */
1279     SOCKS5_AUTH_MAF = 0x08, /* Multi-Authentication Framework */
1280     };
1281     int begin_relay_socks5(ProxyInfo& proxy, String realhost, unsigned short realport, SOCKET s) {
1282     int len;
1283     unsigned char auth_method;
1284     int auth_result;
1285     unsigned char buf[256];
1286     unsigned char* ptr = buf;
1287     char uimsg[MAX_UIMSG];
1288     *ptr++ = SOCKS5_VERSION;
1289     if (proxy.user != NULL && proxy.pass != NULL) {
1290     *ptr++ = 2; // support 2 auth methods : SOCKS5_AUTH_NOAUTH, SOCKS5_AUTH_USERPASS
1291     *ptr++ = SOCKS5_AUTH_NOAUTH;
1292     *ptr++ = SOCKS5_AUTH_USERPASS;
1293     }else{
1294     *ptr++ = 1; // support only 1 auth method : SOCKS5_AUTH_NOAUTH
1295     *ptr++ = SOCKS5_AUTH_NOAUTH;
1296     }
1297     if (sendToSocket(s, buf, ptr - buf) == SOCKET_ERROR)
1298     return SOCKET_ERROR;
1299     if (recieveFromSocket(s, buf, 2) == SOCKET_ERROR)
1300     return SOCKET_ERROR;
1301    
1302     if (buf[0] != SOCKS5_VERSION || buf[1] == SOCKS5_REJECT) {
1303     char uimsg[MAX_UIMSG];
1304     UTIL_get_lang_msg("MSG_PROXY_BAD_REQUEST", uimsg, sizeof(uimsg),
1305     "Proxy prevent this connection!");
1306     return setError(s, uimsg);
1307     }
1308     auth_method = buf[1];
1309    
1310     auth_result = -1;
1311     switch (auth_method) {
1312     case SOCKS5_AUTH_NOAUTH:
1313     /* nothing to do */
1314     auth_result = 0;
1315     break;
1316     case SOCKS5_AUTH_USERPASS:
1317     /* make authentication packet */
1318     ptr = buf;
1319     *ptr++ = SOCKS5_AUTH_SUBNEGOVER;
1320     len = proxy.user.length();
1321     *ptr++ = len;
1322     strcpy_s((char*) ptr, sizeof buf - (ptr - buf), proxy.user);
1323     ptr += len;
1324     len = proxy.pass.length();
1325     *ptr++ = len;
1326     strcpy_s((char*) ptr, sizeof buf - (ptr - buf), proxy.pass);
1327     ptr += len;
1328    
1329     /* send it and get answer */
1330     if (sendToSocket(s, buf, ptr - buf) == SOCKET_ERROR)
1331     return SOCKET_ERROR;
1332     if (recieveFromSocket(s, buf, 2) == SOCKET_ERROR)
1333     return SOCKET_ERROR;
1334    
1335     /* check status */
1336     auth_result = buf[1] != 0;
1337     break;
1338     default:
1339     UTIL_get_lang_msg("MSG_PROXY_BAD_REQUEST", uimsg, sizeof(uimsg),
1340     "Proxy prevent this connection!");
1341     return setError(s, uimsg);
1342     }
1343     if (auth_result == SOCKET_ERROR) {
1344     return SOCKET_ERROR;
1345     }else if (auth_result != 0) {
1346     UTIL_get_lang_msg("MSG_PROXY_UNAUTHORIZED", uimsg, sizeof(uimsg),
1347     "Proxy authorization failed!");
1348     return setError(s, uimsg);
1349     }
1350     /* request to connect */
1351     ptr = buf;
1352     *ptr++ = SOCKS5_VERSION;
1353     *ptr++ = SOCKS5_CMD_CONNECT;
1354     *ptr++ = 0; /* reserved */
1355     in_addr addr;
1356     addr.s_addr = INADDR_NONE;
1357     char ch = realhost.charAt(0);
1358     if ('0' <= ch && ch <= '9') {
1359     addr.s_addr = inet_addr(realhost);
1360     }
1361     if (addr.s_addr != INADDR_NONE) {
1362     *ptr++ = SOCKS5_ATYP_IPv4;
1363     memcpy(ptr, &addr, sizeof addr);
1364     ptr += sizeof addr;
1365     }else{
1366     struct hostent* entry = resolve != RESOLVE_REMOTE ? gethostbyname(realhost) : NULL;
1367     if (entry != NULL) {
1368     #ifndef AF_INET6
1369     #define AF_INET6 23
1370     #endif
1371     if ((entry->h_addrtype == AF_INET || entry->h_addrtype == AF_INET6)
1372     && entry->h_length == (entry->h_addrtype == AF_INET ? 4 : 16)) {
1373     *ptr++ = entry->h_addrtype == AF_INET ? SOCKS5_ATYP_IPv4 : SOCKS5_ATYP_IPv6;
1374     memcpy(ptr, entry->h_addr_list[0], entry->h_length);
1375     ptr += entry->h_length;
1376     }else{
1377     WSASetLastError(WSAECONNREFUSED);
1378     return SOCKET_ERROR;
1379     }
1380     }else if (resolve == RESOLVE_LOCAL) {
1381     WSASetLastError(WSAECONNREFUSED);
1382     return SOCKET_ERROR;
1383     }else{
1384     *ptr++ = SOCKS5_ATYP_DOMAINNAME;
1385     len = strlen(realhost);
1386     *ptr++ = len;
1387     memcpy(ptr, realhost, len);
1388     ptr += len;
1389     }
1390     }
1391     *ptr++ = realport >> 8; /* DST.PORT */
1392     *ptr++ = realport & 0xFF;
1393     if (sendToSocket(s, buf, ptr - buf) == SOCKET_ERROR)
1394     return SOCKET_ERROR;
1395     if (recieveFromSocket(s, buf, 4) == SOCKET_ERROR)
1396     return SOCKET_ERROR;
1397     if (buf[0] != SOCKS5_VERSION || buf[1] != SOCKS5_REP_SUCCEEDED) { /* check reply code */
1398     UTIL_get_lang_msg("MSG_PROXY_BAD_REQUEST", uimsg, sizeof(uimsg),
1399     "Proxy prevent this connection!");
1400     return setError(s, uimsg);
1401     }
1402     // buf[2] is reserved
1403     switch (buf[3]) { /* case by ATYP */
1404     case SOCKS5_ATYP_IPv4:
1405     /* recv IPv4 addr and port */
1406     if (recieveFromSocket(s, buf, 4 + 2) == SOCKET_ERROR)
1407     return SOCKET_ERROR;
1408     break;
1409     case SOCKS5_ATYP_DOMAINNAME:
1410     /* recv name and port */
1411     if (recieveFromSocket(s, buf, 1) == SOCKET_ERROR)
1412     return SOCKET_ERROR;
1413     if (recieveFromSocket(s, buf, buf[0] + 2) == SOCKET_ERROR)
1414     return SOCKET_ERROR;
1415     break;
1416     case SOCKS5_ATYP_IPv6:
1417     /* recv IPv6 addr and port */
1418     if (recieveFromSocket(s, buf, 16 + 2) == SOCKET_ERROR)
1419     return SOCKET_ERROR;
1420     break;
1421     }
1422     /* Conguraturation, connected via SOCKS5 server! */
1423     return 0;
1424     }
1425    
1426     enum {
1427     SOCKS4_VERSION = 4,
1428     SOCKS4_CMD_CONNECT = 1,
1429    
1430     SOCKS4_REP_SUCCEEDED = 90, /* rquest granted (succeeded) */
1431     SOCKS4_REP_REJECTED = 91, /* request rejected or failed */
1432     SOCKS4_REP_IDENT_FAIL = 92, /* cannot connect identd */
1433     SOCKS4_REP_USERID = 93, /* user id not matched */
1434     };
1435    
1436     int begin_relay_socks4(ProxyInfo& proxy, String realhost, unsigned short realport, SOCKET s) {
1437     unsigned char buf[256], *ptr;
1438    
1439     /* make connect request packet
1440     protocol v4:
1441     VN:1, CD:1, PORT:2, ADDR:4, USER:n, NULL:1
1442     protocol v4a:
1443     VN:1, CD:1, PORT:2, DUMMY:4, USER:n, NULL:1, HOSTNAME:n, NULL:1
1444     */
1445     ptr = buf;
1446     *ptr++ = SOCKS4_VERSION;
1447     *ptr++ = SOCKS4_CMD_CONNECT;
1448     *ptr++ = realport >> 8;
1449     *ptr++ = realport & 0xFF;
1450     in_addr addr;
1451     addr.s_addr = INADDR_NONE;
1452     char ch = realhost.charAt(0);
1453     if ('0' <= ch && ch <= '9') {
1454     addr.s_addr = inet_addr(realhost);
1455     }
1456     if (addr.s_addr != INADDR_NONE) {
1457     memcpy(ptr, &addr, sizeof addr);
1458     ptr += sizeof addr;
1459     }else{
1460     struct hostent* entry = resolve != RESOLVE_REMOTE ? gethostbyname(realhost) : NULL;
1461     if (entry != NULL && entry->h_addrtype == AF_INET && entry->h_length == sizeof (in_addr)) {
1462     addr.s_addr = INADDR_LOOPBACK;
1463     memcpy(ptr, entry->h_addr_list[0], entry->h_length);
1464     ptr += entry->h_length;
1465     }else if (resolve == RESOLVE_LOCAL) {
1466     WSASetLastError(WSAECONNREFUSED);
1467     return SOCKET_ERROR;
1468     }else{
1469     /* destination IP fake, protocol 4a */
1470     *ptr++ = 0;
1471     *ptr++ = 0;
1472     *ptr++ = 0;
1473     *ptr++ = 1;
1474     }
1475     }
1476     /* username */
1477     if (proxy.user != NULL) {
1478     strcpy_s((char*) ptr, sizeof buf - (ptr - buf), proxy.user);
1479     ptr += proxy.user.length() + 1;
1480     }else{
1481     *ptr++ = '\0';
1482     }
1483     if (addr.s_addr == INADDR_NONE) {
1484     /* destination host name (for protocol 4a) */
1485     strcpy_s((char*) ptr, sizeof buf - (ptr - buf), realhost);
1486     ptr += strlen(realhost) + 1;
1487     }
1488     /* send command and get response
1489     response is: VN:1, CD:1, PORT:2, ADDR:4 */
1490     if (sendToSocket(s, buf, ptr - buf) == SOCKET_ERROR) {
1491     return SOCKET_ERROR;
1492     }
1493     if (recieveFromSocket(s, buf, 8) == SOCKET_ERROR) {
1494     return SOCKET_ERROR;
1495     }
1496     char uimsg[MAX_UIMSG];
1497     uimsg[0] = NULL;
1498     if (buf[0] != 0) {
1499     UTIL_get_lang_msg("MSG_PROXY_BAD_REQUEST", uimsg, sizeof(uimsg),
1500     "Proxy prevent this connection!");
1501     }else if (buf[1] == SOCKS4_REP_IDENT_FAIL || buf[1] == SOCKS4_REP_USERID) {
1502     UTIL_get_lang_msg("MSG_PROXY_UNAUTHORIZED", uimsg, sizeof(uimsg),
1503     "Proxy authorization failed!");
1504     }else if (buf[1] != SOCKS4_REP_SUCCEEDED) {
1505     UTIL_get_lang_msg("MSG_PROXY_BAD_REQUEST", uimsg, sizeof(uimsg),
1506     "Proxy prevent this connection!");
1507     }
1508     if (uimsg[0] != NULL) {
1509     return setError(s, uimsg);
1510     }
1511    
1512     /* Conguraturation, connected via SOCKS4 server! */
1513     return 0;
1514     }
1515    
1516     int begin_relay_telnet(ProxyInfo& proxy, String realhost, unsigned short realport, SOCKET s) {
1517     int err = 0;
1518     char uimsg[MAX_UIMSG];
1519    
1520     while (!err) {
1521     switch (wait_for_prompt(s, prompt_table, countof(prompt_table), 10)) {
1522     case 0: /* Hostname prompt */
1523     if (sendToSocketFormat(s, "%s:%d\n", realhost, realport) == SOCKET_ERROR)
1524     return SOCKET_ERROR;
1525     break;
1526     case 1: /* Username prompt */
1527     if (sendToSocketFormat(s, "%s\n", proxy.user) == SOCKET_ERROR)
1528     return SOCKET_ERROR;
1529     break;
1530     case 2: /* Password prompt */
1531     if (sendToSocketFormat(s, "%s\n", proxy.pass) == SOCKET_ERROR)
1532     return SOCKET_ERROR;
1533     break;
1534     case 3: /* Established message */
1535     return 0;
1536     case 4: /* Refused message */
1537     default: /* Connection error, etc. */
1538     err = 1;
1539     break;
1540     }
1541     }
1542     UTIL_get_lang_msg("MSG_PROXY_BAD_REQUEST", uimsg, sizeof(uimsg),
1543     "Proxy prevent this connection!");
1544     return setError(s, uimsg);
1545     }
1546    
1547     int setError(SOCKET s, char *p) {
1548     if (*p != NULL)
1549     showMessage(p);
1550     HWND window;
1551     UINT message;
1552     long event;
1553     asyncselectinfo.get(s, window, message, event);
1554     if ((event & FD_CONNECT) != 0) {
1555     MSG msg;
1556     while (::PeekMessage(&msg, window, message, message, PM_REMOVE))
1557     ;
1558     }
1559     WSASetLastError(WSAECONNREFUSED);
1560     return SOCKET_ERROR;
1561     }
1562     void showMessage(char *p) {
1563     if (shower != NULL) {
1564     shower->showMessage(p);
1565     }
1566     }
1567    
1568     #define DECLARE_HOOKAPI(RETTYPE, APINAME, ARGLIST, ARGS) \
1569     public: \
1570     static FARPROC hook_##APINAME(FARPROC original) { \
1571     (FARPROC&) instance().ORIG_##APINAME = original; \
1572     return (FARPROC) HOOKEDAPI_##APINAME; \
1573     } \
1574     static FARPROC unhook_##APINAME(FARPROC hookedProc) { \
1575     return hookedProc == (FARPROC) HOOKEDAPI_##APINAME \
1576     ? (FARPROC) instance().ORIG_##APINAME \
1577     : hookedProc; \
1578     } \
1579     private: \
1580     static RETTYPE PASCAL HOOKEDAPI_##APINAME ARGLIST { \
1581     return instance().hooked_##APINAME ARGS; \
1582     } \
1583     RETTYPE (PASCAL* ORIG_##APINAME) ARGLIST; \
1584     RETTYPE hooked_##APINAME ARGLIST
1585    
1586     #define INSTALL_HOOKAPI(APINAME) \
1587     Hooker::hook(module, (FARPROC) instance().ORIG_##APINAME, (FARPROC) HOOKEDAPI_##APINAME);
1588    
1589     #define UNINSTALL_HOOKAPI(APINAME) \
1590     Hooker::hook(module, (FARPROC) HOOKEDAPI_##APINAME, (FARPROC) instance().ORIG_##APINAME);
1591    
1592     #define LOADAPI(APINAME) \
1593     (FARPROC&) ORIG_##APINAME = ::GetProcAddress(wsock32, #APINAME);
1594    
1595     #define SETUP_HOOKAPI(APINAME) \
1596     Hooker::setup((FARPROC) instance().ORIG_##APINAME, (FARPROC) HOOKEDAPI_##APINAME);
1597    
1598     DECLARE_HOOKAPI(int, connect, (SOCKET s, const struct sockaddr* name, int namelen), (s, name, namelen)) {
1599     ConnectionInfo* info = NULL;
1600     ConnectionInfoHolder holder;
1601     if (name->sa_family == AF_INET) {
1602     struct sockaddr_in* in = (struct sockaddr_in*) name;
1603     info = connectioninfolist.get(in->sin_addr);
1604     if (info == NULL && defaultProxy.type != ProxyInfo::TYPE_NONE) {
1605     info = new ConnectionInfo(defaultProxy, inet_ntoa(in->sin_addr));
1606     holder = info;
1607     }
1608     }
1609     if (info != NULL) {
1610     if (info->proxy.type == ProxyInfo::TYPE_NONE_FORCE) {
1611     info = NULL;
1612     }else{
1613     const char* hostname;
1614     if (info->proxy.type == ProxyInfo::TYPE_SSL) {
1615     hostname = info->realhost;
1616     }else{
1617     info->realport = ntohs(((struct sockaddr_in*) name)->sin_port);
1618     ((struct sockaddr_in*) name)->sin_port = htons(info->proxy.getPort());
1619     hostname = info->proxy.host;
1620     }
1621     struct hostent* entry = ORIG_gethostbyname(hostname);
1622     if (entry == NULL) {
1623     WSASetLastError(WSAECONNREFUSED);
1624     return SOCKET_ERROR;
1625     }
1626     memcpy(&((struct sockaddr_in*) name)->sin_addr, entry->h_addr_list[0], entry->h_length);
1627     }
1628     }
1629     int result = ORIG_connect(s, name, namelen);
1630     if (info == NULL || info->proxy.port == 0) {
1631     return result;
1632     }
1633     if (result == 0) {
1634     // do nothing
1635     }else if (WSAGetLastError() == WSAEWOULDBLOCK) {
1636     struct timeval tv = {timeout, 0};
1637     fd_set ifd;
1638     fd_set ofd;
1639     fd_set efd;
1640     FD_ZERO(&ifd);
1641     FD_ZERO(&ofd);
1642     FD_ZERO(&efd);
1643     FD_SET(s, &ifd);
1644     FD_SET(s, &ofd);
1645     FD_SET(s, &efd);
1646     if (select((int) (s + 1), &ifd, &ofd, &efd, timeout > 0 ? &tv : NULL) == SOCKET_ERROR)
1647     return SOCKET_ERROR;
1648     if (FD_ISSET(s, &efd)) {
1649     WSASetLastError(WSAECONNREFUSED);
1650     return SOCKET_ERROR;
1651     }
1652     }else{
1653     return SOCKET_ERROR;
1654     }
1655     switch (info->proxy.type) {
1656     default:
1657     result = 0;
1658     break;
1659     case ProxyInfo::TYPE_HTTP:
1660     case ProxyInfo::TYPE_HTTP_SSL:
1661     result = begin_relay_http(info->proxy, info->realhost, info->realport, s);
1662     break;
1663     case ProxyInfo::TYPE_TELNET:
1664     case ProxyInfo::TYPE_TELNET_SSL:
1665     result = begin_relay_telnet(info->proxy, info->realhost, info->realport, s);
1666     break;
1667     case ProxyInfo::TYPE_SOCKS4:
1668     case ProxyInfo::TYPE_SOCKS4_SSL:
1669     result = begin_relay_socks4(info->proxy, info->realhost, info->realport, s);
1670     break;
1671     case ProxyInfo::TYPE_SOCKS5:
1672     case ProxyInfo::TYPE_SOCKS5_SSL:
1673     result = begin_relay_socks5(info->proxy, info->realhost, info->realport, s);
1674     break;
1675     }
1676     if (result == 0) {
1677     if (info->proxy.type == ProxyInfo::TYPE_SSL
1678     || info->proxy.type == ProxyInfo::TYPE_HTTP_SSL
1679     || info->proxy.type == ProxyInfo::TYPE_TELNET_SSL
1680     || info->proxy.type == ProxyInfo::TYPE_SOCKS4_SSL
1681     || info->proxy.type == ProxyInfo::TYPE_SOCKS5_SSL) {
1682     if (!SSLSocket::isEnabled()) {
1683     WSASetLastError(WSAECONNREFUSED);
1684     return SOCKET_ERROR;
1685     }
1686     SSLSocket* ssl = new SSLSocket();
1687     if (!ssl->connect(s, info->realhost)) {
1688     shutdown(s, SD_BOTH);
1689     int error_code = ssl->get_verify_result();
1690     char uimsg[MAX_UIMSG];
1691     delete ssl;
1692     switch (error_code) {
1693     case IDS_UNABLE_TO_GET_ISSUER_CERT:
1694     UTIL_get_lang_msg("MSG_UNABLE_TO_GET_ISSUER_CERT", uimsg, sizeof(uimsg),
1695     "Unable to get Issuer Certificate");
1696     case IDS_UNABLE_TO_GET_CRL:
1697     UTIL_get_lang_msg("MSG_UNABLE_TO_GET_CRL", uimsg, sizeof(uimsg),
1698     "Unable to get Ceritifcate CRL");
1699     case IDS_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
1700     UTIL_get_lang_msg("MSG_UNABLE_TO_DECRYPT_CERT_SIGNATURE", uimsg, sizeof(uimsg),
1701     "Unable to decrypt Certificate's Signature");
1702     case IDS_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
1703     UTIL_get_lang_msg("MSG_UNABLE_TO_DECRYPT_CRL_SIGNATURE", uimsg, sizeof(uimsg),
1704     "Unable to decrypt CRL's Signature");
1705     case IDS_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
1706     UTIL_get_lang_msg("MSG_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", uimsg, sizeof(uimsg),
1707     "Unable to decode Issuer Public Key");
1708     case IDS_CERT_SIGNATURE_FAILURE:
1709     UTIL_get_lang_msg("MSG_CERT_SIGNATURE_FAILURE", uimsg, sizeof(uimsg),
1710     "Certificate Signature failure");
1711     case IDS_CRL_SIGNATURE_FAILURE:
1712     UTIL_get_lang_msg("MSG_CRL_SIGNATURE_FAILURE", uimsg, sizeof(uimsg),
1713     "CRL Signature failure");
1714     case IDS_CERT_NOT_YET_VALID:
1715     UTIL_get_lang_msg("MSG_CERT_NOT_YET_VALID", uimsg, sizeof(uimsg),
1716     "Certificate is not yet valid");
1717     case IDS_CERT_HAS_EXPIRED:
1718     UTIL_get_lang_msg("MSG_CERT_HAS_EXPIRED", uimsg, sizeof(uimsg),
1719     "Certificate has expired");
1720     case IDS_CRL_NOT_YET_VALID:
1721     UTIL_get_lang_msg("MSG_CRL_NOT_YET_VALID", uimsg, sizeof(uimsg),
1722     "CRL is not yet valid");
1723     case IDS_CRL_HAS_EXPIRED:
1724     UTIL_get_lang_msg("MSG_CRL_HAS_EXPIRED", uimsg, sizeof(uimsg),
1725     "CRL has expired");
1726     case IDS_ERROR_IN_CERT_NOT_BEFORE_FIELD:
1727     UTIL_get_lang_msg("MSG_ERROR_IN_CERT_NOT_BEFORE_FIELD", uimsg, sizeof(uimsg),
1728     "Format error in Certificate's notBefore field");
1729     case IDS_ERROR_IN_CERT_NOT_AFTER_FIELD:
1730     UTIL_get_lang_msg("MSG_ERROR_IN_CERT_NOT_AFTER_FIELD", uimsg, sizeof(uimsg),
1731     "Format error in Certificate's notAfter field");
1732     case IDS_ERROR_IN_CRL_LAST_UPDATE_FIELD:
1733     UTIL_get_lang_msg("MSG_ERROR_IN_CRL_LAST_UPDATE_FIELD", uimsg, sizeof(uimsg),
1734     "Format error in CRL's lastUpdate field");
1735     case IDS_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
1736     UTIL_get_lang_msg("MSG_ERROR_IN_CRL_NEXT_UPDATE_FIELD", uimsg, sizeof(uimsg),
1737     "Format error in CRL's nextUpdate field");
1738     case IDS_OUT_OF_MEM:
1739     UTIL_get_lang_msg("MSG_OUT_OF_MEM", uimsg, sizeof(uimsg),
1740     "Out of memory");
1741     case IDS_DEPTH_ZERO_SELF_SIGNED_CERT:
1742     UTIL_get_lang_msg("MSG_DEPTH_ZERO_SELF_SIGNED_CERT", uimsg, sizeof(uimsg),
1743     "Self-signed Certificate");
1744     case IDS_SELF_SIGNED_CERT_IN_CHAIN:
1745     UTIL_get_lang_msg("MSG_SELF_SIGNED_CERT_IN_CHAIN", uimsg, sizeof(uimsg),
1746     "Self-signed Certificate found in Certificate chain");
1747     case IDS_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1748     UTIL_get_lang_msg("MSG_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", uimsg, sizeof(uimsg),
1749     "Unable to get Local Issuer Certificate");
1750     case IDS_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1751     UTIL_get_lang_msg("MSG_UNABLE_TO_VERIFY_LEAF_SIGNATURE", uimsg, sizeof(uimsg),
1752     "Unable to verify the first Certificate");
1753     case IDS_CERT_CHAIN_TOO_LONG:
1754     UTIL_get_lang_msg("MSG_CERT_CHAIN_TOO_LONG", uimsg, sizeof(uimsg),
1755     "Certificate chain too long");
1756     case IDS_CERT_REVOKED:
1757     UTIL_get_lang_msg("MSG_CERT_REVOKED", uimsg, sizeof(uimsg),
1758     "Certificate revoked");
1759     case IDS_INVALID_CA:
1760     UTIL_get_lang_msg("MSG_INVALID_CA", uimsg, sizeof(uimsg),
1761     "Invalid CA Certificate");
1762     case IDS_PATH_LENGTH_EXCEEDED:
1763     UTIL_get_lang_msg("MSG_PATH_LENGTH_EXCEEDED", uimsg, sizeof(uimsg),
1764     "Path length constraint exceeded");
1765     case IDS_INVALID_PURPOSE:
1766     UTIL_get_lang_msg("MSG_INVALID_PURPOSE", uimsg, sizeof(uimsg),
1767     "Unsupported Certificate purpose");
1768     case IDS_CERT_UNTRUSTED:
1769     UTIL_get_lang_msg("MSG_CERT_UNTRUSTED", uimsg, sizeof(uimsg),
1770     "Certificate not trusted");
1771     case IDS_CERT_REJECTED:
1772     UTIL_get_lang_msg("MSG_CERT_REJECTED", uimsg, sizeof(uimsg),
1773     "Certificate rejected");
1774     case IDS_SUBJECT_ISSUER_MISMATCH:
1775     UTIL_get_lang_msg("MSG_SUBJECT_ISSUER_MISMATCH", uimsg, sizeof(uimsg),
1776     "Subject Issuer mismatch");
1777     case IDS_AKID_SKID_MISMATCH:
1778     UTIL_get_lang_msg("MSG_AKID_SKID_MISMATCH", uimsg, sizeof(uimsg),
1779     "Authority and Subject Key Identifier mismatch");
1780     case IDS_AKID_ISSUER_SERIAL_MISMATCH:
1781     UTIL_get_lang_msg("MSG_AKID_ISSUER_SERIAL_MISMATCH", uimsg, sizeof(uimsg),
1782     "Authority and Issuer Serial Number mismatch");
1783     case IDS_KEYUSAGE_NO_CERTSIGN:
1784     UTIL_get_lang_msg("MSG_KEYUSAGE_NO_CERTSIGN", uimsg, sizeof(uimsg),
1785     "Key usage does not include Ceritifcate signing");
1786     case IDS_APPLICATION_VERIFICATION:
1787     UTIL_get_lang_msg("MSG_APPLICATION_VERIFICATION", uimsg, sizeof(uimsg),
1788     "Application verification failure");
1789     case IDS_UNMATCH_COMMON_NAME:
1790     UTIL_get_lang_msg("MSG_UNMATCH_COMMON_NAME", uimsg, sizeof(uimsg),
1791     "Umatch Common Name");
1792     case IDS_UNABLE_TO_GET_COMMON_NAME:
1793     UTIL_get_lang_msg("MSG_UNABLE_TO_GET_COMMON_NAME", uimsg, sizeof(uimsg),
1794     "Unable to get Common Name");
1795     default:
1796     uimsg[0] = NULL;
1797     }
1798     return setError(s, uimsg);
1799     }
1800     sslmap.put(s,ssl);
1801     }
1802     }
1803     return result;
1804     }
1805    
1806     DECLARE_HOOKAPI(struct hostent*, gethostbyname, (const char* hostname), (hostname)) {
1807     ConnectionInfo* info = connectioninfolist.find(hostname);
1808     if (info != NULL) {
1809     if (info->proxy.type == ProxyInfo::TYPE_NONE_FORCE) {
1810     hostname = info->realhost;
1811     }else{
1812     if (info->proxy.type == ProxyInfo::TYPE_SSL
1813     || info->proxy.type == ProxyInfo::TYPE_HTTP_SSL
1814     || info->proxy.type == ProxyInfo::TYPE_TELNET_SSL
1815     || info->proxy.type == ProxyInfo::TYPE_SOCKS4_SSL
1816     || info->proxy.type == ProxyInfo::TYPE_SOCKS5_SSL) {
1817     if (!SSLSocket::isEnabled()) {
1818     ::WSASetLastError(WSAHOST_NOT_FOUND);
1819     return NULL;
1820     }
1821     }
1822     if (info->buffer == NULL) {
1823     int bufferLength = sizeof (DUMMYHOSTENT) + strlen(info->realhost);
1824     info->buffer = new char[bufferLength];
1825     info->fillBuffer(info->buffer, bufferLength);
1826     }
1827     return (struct hostent*) info->buffer;
1828     }
1829     }
1830     return ORIG_gethostbyname(hostname);
1831     }
1832    
1833     DECLARE_HOOKAPI(HANDLE, WSAAsyncGetHostByName, (HWND window, UINT message, const char* hostname, char* buffer, int bufferLength), (window, message, hostname, buffer, bufferLength)) {
1834     ConnectionInfo* info = connectioninfolist.find(hostname);
1835     if (info == NULL || info->proxy.type == ProxyInfo::TYPE_NONE_FORCE) {
1836     return ORIG_WSAAsyncGetHostByName(window, message, hostname, buffer, bufferLength);
1837     }
1838     if (info->proxy.type == ProxyInfo::TYPE_SSL
1839     || info->proxy.type == ProxyInfo::TYPE_HTTP_SSL
1840     || info->proxy.type == ProxyInfo::TYPE_TELNET_SSL
1841     || info->proxy.type == ProxyInfo::TYPE_SOCKS4_SSL
1842     || info->proxy.type == ProxyInfo::TYPE_SOCKS5_SSL) {
1843     if (!SSLSocket::isEnabled()) {
1844     ::WSASetLastError(WSAHOST_NOT_FOUND);
1845     return NULL;
1846     }
1847     }
1848     HANDLE handle = connectioninfolist.getTask(info);
1849     int len = sizeof (DUMMYHOSTENT) + strlen(hostname);
1850     if (bufferLength < len) {
1851     ::PostMessage(window, message, (WPARAM) handle, MAKELPARAM(len, WSAENOBUFS));
1852     ::WSASetLastError(WSAENOBUFS);
1853     return handle;
1854     }
1855     info->fillBuffer(buffer, bufferLength);
1856     ::PostMessage(window, message, (WPARAM) handle, MAKELPARAM(len, 0));
1857     return handle;
1858     }
1859    
1860     DECLARE_HOOKAPI(int, WSAAsyncSelect, (SOCKET s, HWND window, UINT message, long event), (s, window, message, event)) {
1861     asyncselectinfo.put(s, window, message, event);
1862     return ORIG_WSAAsyncSelect(s, window, message, event);
1863     }
1864    
1865     DECLARE_HOOKAPI(int, WSACancelAsyncRequest, (HANDLE task), (task)) {
1866     ConnectionInfo* info = connectioninfolist.get(task);
1867     if (info != NULL) {
1868     return 0;
1869     }
1870     return ORIG_WSACancelAsyncRequest(task);
1871     }
1872    
1873     DECLARE_HOOKAPI(int, send, (SOCKET s, const char* buf, int len, int flags), (s, buf, len, flags)) {
1874     SSLSocket* ssl = sslmap.get(s);
1875     if (ssl != NULL)
1876     return ssl->write(buf, len);
1877     return ORIG_send(s, buf, len, flags);
1878     }
1879     DECLARE_HOOKAPI(int, sendto, (SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen), (s, buf, len, flags, to, tolen)) {
1880     return ORIG_sendto(s, buf, len, flags, to, tolen);
1881     }
1882     DECLARE_HOOKAPI(int, recv, (SOCKET s, char* buf, int len, int flags), (s, buf, len, flags)) {
1883     SSLSocket* ssl = sslmap.get(s);
1884     if (ssl != NULL)
1885     return ssl->read(buf, len);
1886     return ORIG_recv(s, buf, len, flags);
1887     }
1888     DECLARE_HOOKAPI(int, recvfrom, (SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen), (s, buf, len, flags, from, fromlen)) {
1889     return ORIG_recvfrom(s, buf, len, flags, from, fromlen);
1890     }
1891     DECLARE_HOOKAPI(int, closesocket, (SOCKET s), (s)) {
1892     SSLSocket* ssl = sslmap.get(s);
1893     if (ssl != NULL) {
1894     ssl->close();
1895     sslmap.remove(s);
1896     delete ssl;
1897     }
1898     return ORIG_closesocket(s);
1899     }
1900    
1901     String logfile;
1902     int timeout;
1903     enum SocksResolve {
1904     RESOLVE_AUTO,
1905     RESOLVE_REMOTE,
1906     RESOLVE_LOCAL,
1907     } resolve;
1908     String prompt_table[5];
1909     ProxyInfo defaultProxy;
1910     ConnectionInfoList connectioninfolist;
1911     Hashtable<SOCKET, SSLSocket*> sslmap;
1912     MessageShower* shower;
1913     HWND owner;
1914     HMODULE resource_module;
1915     AsyncSelectInfoTable asyncselectinfo;
1916    
1917     ProxyWSockHook():shower(NULL), owner(NULL), resource_module(GetInstanceHandle()), timeout(0) {
1918     HMODULE wsock32 = ::GetModuleHandle("wsock32.dll");
1919     LOADAPI(connect)
1920     LOADAPI(gethostbyname)
1921     LOADAPI(WSAAsyncGetHostByName)
1922     LOADAPI(WSAAsyncSelect)
1923     LOADAPI(WSACancelAsyncRequest)
1924     LOADAPI(send)
1925     LOADAPI(sendto)
1926     LOADAPI(recv)
1927     LOADAPI(recvfrom)
1928     LOADAPI(closesocket)
1929     }
1930     static ProxyWSockHook& instance() {
1931     static ProxyWSockHook instance;
1932     return instance;
1933     }
1934     void _load(IniFile& ini) {
1935     String temp;
1936     temp = ini.getString("ProxyType");
1937     if (temp != NULL) {
1938     defaultProxy.type = ProxyInfo::parseType(temp);
1939     if (defaultProxy.type != ProxyInfo::TYPE_NONE) {
1940     defaultProxy.host = ini.getString("ProxyHost");
1941     if (defaultProxy.host == NULL || defaultProxy.type == ProxyInfo::TYPE_NONE_FORCE) {
1942     defaultProxy.type = ProxyInfo::TYPE_NONE;
1943     }else{
1944     defaultProxy.port = (unsigned short) ini.getInteger("ProxyPort");
1945     defaultProxy.user = ini.getString("ProxyUser");
1946     if (defaultProxy.user != NULL)
1947     defaultProxy.pass = ini.getString("ProxyPass");
1948     }
1949     }
1950     }
1951    
1952     timeout = ini.getInteger("ConnectionTimeout", 10);
1953    
1954     temp = ini.getString("SocksResolve");
1955     if (temp.equalsIgnoreCase("remote")) {
1956     resolve = RESOLVE_REMOTE;
1957     }else if (temp.equalsIgnoreCase("local")) {
1958     resolve = RESOLVE_LOCAL;
1959     }else{
1960     resolve = RESOLVE_AUTO;
1961     }
1962    
1963     prompt_table[0] = ini.getString("TelnetHostnamePrompt", ">> Host name: ");
1964     prompt_table[1] = ini.getString("TelnetUsernamePrompt", "Username:");
1965     prompt_table[2] = ini.getString("TelnetPasswordPrompt", "Password:");
1966     prompt_table[3] = ini.getString("TelnetConnectedMessage", "-- Connected to ");
1967     prompt_table[4] = ini.getString("TelnetErrorMessage", "!!!!!!!!");
1968    
1969     logfile = ini.getString("DebugLog");
1970     Logger::open(logfile);
1971     }
1972     void _save(IniFile& ini) {
1973     const char* type = NULL;
1974     const char* host = NULL;
1975     const char* port = NULL;
1976     const char* user = NULL;
1977     const char* pass = NULL;
1978     if (defaultProxy.type != ProxyInfo::TYPE_NONE && defaultProxy.type != ProxyInfo::TYPE_NONE_FORCE && defaultProxy.host != NULL) {
1979     type = ProxyInfo::getTypeName(defaultProxy.type);
1980     host = defaultProxy.host;
1981     if (defaultProxy.port != 0) {
1982     char* buffer = (char*) alloca(5);
1983     _itoa_s(defaultProxy.port, buffer, 5, 10);
1984     port = buffer;
1985     }
1986     if (defaultProxy.user != NULL) {
1987     user = defaultProxy.user;
1988     if (defaultProxy.pass != NULL) {
1989     pass = defaultProxy.pass;
1990     }
1991     }
1992     }
1993     ini.setString("ProxyType", type);
1994     ini.setString("ProxyHost", host);
1995     ini.setString("ProxyPort", port);
1996     ini.setString("ProxyUser", user);
1997     ini.setString("ProxyPass", pass);
1998    
1999     ini.setInteger("ConnectionTimeout", timeout);
2000    
2001     switch (resolve) {
2002     case RESOLVE_REMOTE:
2003     type = "remote";
2004     break;
2005     case RESOLVE_LOCAL:
2006     type = "local";
2007     break;
2008     default:
2009     type = "auto";
2010     break;
2011     }
2012     ini.setString("SocksResolve", type);
2013    
2014     ini.setString("TelnetHostnamePrompt", prompt_table[0]);
2015     ini.setString("TelnetUsernamePrompt", prompt_table[1]);
2016     ini.setString("TelnetPasswordPrompt", prompt_table[2]);
2017     ini.setString("TelnetConnectedMessage", prompt_table[3]);
2018     ini.setString("TelnetErrorMessage", prompt_table[4]);
2019    
2020     ini.setString("DebugLog", logfile);
2021     }
2022     public:
2023     static void setOwner(HWND owner) {
2024     instance().owner = owner;
2025     }
2026     static void setMessageShower(MessageShower* shower) {
2027     instance().shower = shower;
2028     }
2029     static void load(IniFile& ini) {
2030     instance()._load(ini);
2031     }
2032     static void save(IniFile& ini) {
2033     instance()._save(ini);
2034     }
2035     static bool setupDialog(HWND owner) {
2036     SettingDialog dlg;
2037     dlg.proxy = instance().defaultProxy;
2038     if (dlg.open(owner) == IDOK) {
2039     instance().defaultProxy = dlg.proxy;
2040     return true;
2041     }
2042     return false;
2043     }
2044     static bool aboutDialog(HWND owner) {
2045     AboutDialog dlg;
2046     if (dlg.open(owner) == IDOK) {
2047     return true;
2048     }
2049     return false;
2050     }
2051    
2052    
2053     static void setupHooks() {
2054     SETUP_HOOKAPI(connect)
2055     SETUP_HOOKAPI(gethostbyname)
2056     SETUP_HOOKAPI(WSAAsyncGetHostByName)
2057     SETUP_HOOKAPI(WSAAsyncSelect)
2058     SETUP_HOOKAPI(WSACancelAsyncRequest)
2059     SETUP_HOOKAPI(send)
2060     SETUP_HOOKAPI(sendto)
2061     SETUP_HOOKAPI(recv)
2062     SETUP_HOOKAPI(recvfrom)
2063     SETUP_HOOKAPI(closesocket)
2064     }
2065     static void installHook(HMODULE module) {
2066     INSTALL_HOOKAPI(connect)
2067     INSTALL_HOOKAPI(gethostbyname)
2068     INSTALL_HOOKAPI(WSAAsyncGetHostByName)
2069     INSTALL_HOOKAPI(WSAAsyncSelect)
2070     INSTALL_HOOKAPI(WSACancelAsyncRequest)
2071     INSTALL_HOOKAPI(send)
2072     INSTALL_HOOKAPI(sendto)
2073     INSTALL_HOOKAPI(recv)
2074     INSTALL_HOOKAPI(recvfrom)
2075     INSTALL_HOOKAPI(closesocket)
2076     }
2077    
2078     static void uninstallHook(HMODULE module) {
2079     UNINSTALL_HOOKAPI(connect)
2080     UNINSTALL_HOOKAPI(gethostbyname)
2081     UNINSTALL_HOOKAPI(WSAAsyncGetHostByName)
2082     UNINSTALL_HOOKAPI(WSAAsyncSelect)
2083     UNINSTALL_HOOKAPI(WSACancelAsyncRequest)
2084     UNINSTALL_HOOKAPI(send)
2085     UNINSTALL_HOOKAPI(sendto)
2086     UNINSTALL_HOOKAPI(recv)
2087     UNINSTALL_HOOKAPI(recvfrom)
2088     UNINSTALL_HOOKAPI(closesocket)
2089     }
2090     static String generateURL() {
2091     return instance().defaultProxy.generateURL();
2092     }
2093     static String parseURL(const char* url, BOOL prefix) {
2094     ProxyInfo proxy;
2095     String realhost = ProxyInfo::parse(url, proxy);
2096     if (realhost != NULL) {
2097     if (realhost.indexOf("://") != -1 && !prefix) {
2098     proxy.type = proxy.TYPE_NONE;
2099     }
2100     instance().defaultProxy = proxy;
2101     if (realhost.length() == 0)
2102     realhost = NULL;
2103     }
2104     return realhost;
2105     }
2106     static void setResourceModule(HMODULE module) {
2107     instance().resource_module = module;
2108     }
2109     };
2110    
2111     #endif//_YEBISOCKS_PROXYWSOCKHOOK_H_

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26