Tommy 碎碎念
https://blog.teatime.com.tw/
Tommy Wu's blog
tommy
2024-03-19T13:14:40Z
-
讓 vsftpd 3.0.3 在 local 網路連線時, 不使用 pasv_address 的設定
https://blog.teatime.com.tw/1/post/487
<p>近來 (應該也有一陣子了) 發現用 <a href="https://filezilla-project.org/" target="_blank">FileZilla</a> 連到家裡的 ftp 時, 使用 TLS 連線會每隔 20 秒出現一次逾時錯誤訊息就離線. 而且在部網路直接連線時, 會有一樣的問題, 應該跟 firewall 沒關係. <a href="https://forum.filezilla-project.org/viewtopic.php?f=2&t=7688" target="_blank">在 FileZilla 的討論區有提到 Pure-ftpd <= 1.0.38 時會有問題</a>, 不過家裡的伺服器應該是 1.0.46 (印象中, 以前使用 1.0.3x 的版本並沒有這個錯誤). 所以試著換了 <a href="https://security.appspot.com/vsftpd.html" target="_blank">vsftpd</a> 3.0.3 來使用, 還真的就不會出現這個訊息了.</p><p>不過換上 vsftpd 之後, 就碰到之前在 <a href="https://www.pureftpd.org/project/pure-ftpd" target="_blank">pure-ftpd</a> 時相同的問題, 就是使用 passive 模式時, 如果指定使用外部的 ip 之後, 會造成內部的連線也收到外部的 ip 而無法使用. 如果不指定外部 ip 時, 會造成外部的連線收到內部的 ip 而無法連線 (使用 filezilla 時, 這情形會用連線的 ip 取代, 可以繼續使用).</p><p>所以... 就把之前給 pure-ftpd 的 patch 改了一下給 vsftpd 用:</p><pre class="diff"><div class="insertcode">diff --show-c-function -Nur vsftpd-3.0.3.orig/main.c vsftpd-3.0.3/main.c<br /><span class="re3">--- vsftpd-3.0.3.orig/main.c 2012-09-16 12:27:13.000000000 +0800</span><br /><span class="re4">+++ vsftpd-3.0.3/main.c 2017-09-28 21:10:16.620440681 +0800</span><br /><span class="re6">@@ -32,6 +32,70 @@ static void session_init<span class="br0">(</span>struct vsf_sess</span><br /> static void env_init<span class="br0">(</span>void<span class="br0">)</span>;<br /> static void limits_init<span class="br0">(</span>void<span class="br0">)</span>;<br /> <br /><span class="re8">+// add by twu2 20170928 begin</span><br /><span class="re8">+#include <stdio.h></span><br /><span class="re8">+#include "filestr.h"</span><br /><span class="re8">+// check local net in /etc/localnet</span><br /><span class="re8">+static int check_local_net<span class="br0">(</span>const struct vsf_sysutil_sockaddr * const addr<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ unsigned long a1 = 0U;</span><br /><span class="re8">+ unsigned long a2 = 0U;</span><br /><span class="re8">+ unsigned long mask = 0U;</span><br /><span class="re8">+ unsigned int b1, b2, b3, b4;</span><br /><span class="re8">+ unsigned int m1, m2, m3, m4;</span><br /><span class="re8">+ static struct mystr s_curr_line_str;</span><br /><span class="re8">+ unsigned int pos = <span class="nu0">0</span>;</span><br /><span class="re8">+ struct mystr localnet_file = INIT_MYSTR;</span><br /><span class="re8">+ int retval = -<span class="nu0">1</span>;</span><br /><span class="re8">+ const void* p_v4addr;</span><br /><span class="re8">+ int is_ipv6;</span><br /><span class="re8">+ const char *ip;</span><br /><span class="re8">+ int is_local;</span><br /><span class="re8">+</span><br /><span class="re8">+ if <span class="br0">(</span>!addr<span class="br0">)</span> return <span class="nu0">0</span>;</span><br /><span class="re8">+ is_ipv6 = vsf_sysutil_sockaddr_is_ipv6<span class="br0">(</span>addr<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>is_ipv6<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ p_v4addr = vsf_sysutil_sockaddr_ipv6_v4<span class="br0">(</span>addr<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>!p_v4addr<span class="br0">)</span> return <span class="nu0">0</span>;</span><br /><span class="re8">+ ip = vsf_sysutil_inet_ntoa<span class="br0">(</span>p_v4addr<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else</span><br /><span class="re8">+ ip = vsf_sysutil_inet_ntop<span class="br0">(</span>addr<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>!ip<span class="br0">)</span> return <span class="nu0">0</span>;</span><br /><span class="re8">+ b1 = b2 = b3 = b4 = <span class="nu0">0</span>;</span><br /><span class="re8">+ if <span class="br0">(</span><span class="br0">(</span>sscanf<span class="br0">(</span>ip, "%u.%u.%u.%u", &b1, &b2, &b3, &b4<span class="br0">)</span> != <span class="nu0">4</span><span class="br0">)</span> ||</span><br /><span class="re8">+ b1 > 255U || b2 > 255U || b3 > 255U || b4 > 255U ||</span><br /><span class="re8">+ <span class="br0">(</span>b1 | b2 | b3 | b4<span class="br0">)</span> == 0U<span class="br0">)</span></span><br /><span class="re8">+ return <span class="nu0">0</span>;</span><br /><span class="re8">+ a1 = b1 << <span class="nu0">24</span> | b2 << <span class="nu0">16</span> | b3 << <span class="nu0">8</span> | b4;</span><br /><span class="re8">+ retval = str_fileread<span class="br0">(</span>&localnet_file, tunable_local_net_file,</span><br /><span class="re8">+ VSFTP_CONF_FILE_MAX<span class="br0">)</span>;</span><br /><span class="re8">+ // no localnet file</span><br /><span class="re8">+ if <span class="br0">(</span>vsf_sysutil_retval_is_error<span class="br0">(</span>retval<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ return <span class="nu0">0</span>;</span><br /><span class="re8">+ is_local = <span class="nu0">0</span>;</span><br /><span class="re8">+ while <span class="br0">(</span>str_getline<span class="br0">(</span>&localnet_file, &s_curr_line_str, &pos<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ b1 = b2 = b3 = b4 = m1 = m2 = m3 = m4 = <span class="nu0">0</span>;</span><br /><span class="re8">+ if <span class="br0">(</span><span class="br0">(</span>sscanf<span class="br0">(</span>str_getbuf<span class="br0">(</span>&s_curr_line_str<span class="br0">)</span>, "%u.%u.%u.%u/%u.%u.%u.%u", &b1, &b2, &b3, &b4, &m1, &m2, &m3, &m4<span class="br0">)</span> != <span class="nu0">8</span><span class="br0">)</span> ||</span><br /><span class="re8">+ b1 > 255U || b2 > 255U || b3 > 255U || b4 > 255U ||</span><br /><span class="re8">+ <span class="br0">(</span>b1 | b2 | b3 | b4<span class="br0">)</span> == 0U ||</span><br /><span class="re8">+ m1 > 255U || m2 > 255U || m3 > 255U || m4 > 255U ||</span><br /><span class="re8">+ <span class="br0">(</span>m1 | m2 | m3 | m4<span class="br0">)</span> == 0U<span class="br0">)</span></span><br /><span class="re8">+ continue;</span><br /><span class="re8">+ a2 = b1 << <span class="nu0">24</span> | b2 << <span class="nu0">16</span> | b3 << <span class="nu0">8</span> | b4;</span><br /><span class="re8">+ mask = m1 << <span class="nu0">24</span> | m2 << <span class="nu0">16</span> | m3 << <span class="nu0">8</span> | m4;</span><br /><span class="re8">+ // correct format</span><br /><span class="re8">+ if <span class="br0">(</span><span class="br0">(</span>a1 & mask<span class="br0">)</span> == <span class="br0">(</span>a2 & mask<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ // same subnet</span><br /><span class="re8">+ is_local = <span class="nu0">1</span>;</span><br /><span class="re8">+ break;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ str_free<span class="br0">(</span>&localnet_file<span class="br0">)</span>;</span><br /><span class="re8">+ return is_local;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+// add by twu2 20170928 end</span><br /><span class="re8">+</span><br /> int<br /> main<span class="br0">(</span>int argc, const char* argv<span class="br0">[</span><span class="br0">]</span><span class="br0">)</span><br /> <span class="br0">{</span><br /><span class="re6">@@ -67,6 +131,12 @@ main<span class="br0">(</span>int argc, const char* argv<span class="br0">[</span><span class="br0">]</span><span class="br0">)</span></span><br /> <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, INIT_MYSTR, <span class="nu0">0</span>, -<span class="nu0">1</span>, -<span class="nu0">1</span>,<br /> /* Login fails */<br /> <span class="nu0">0</span><br /><span class="re8">+ // add by twu2 20170928 begin</span><br /><span class="re8">+ /* is_local */</span><br /><span class="re8">+ ,0</span><br /><span class="re8">+ /* nomaxrate */</span><br /><span class="re8">+ ,0</span><br /><span class="re8">+ // add by twu2 20170928 end</span><br /> <span class="br0">}</span>;<br /> int config_loaded = <span class="nu0">0</span>;<br /> int i;<br /><span class="re6">@@ -243,6 +313,9 @@ main<span class="br0">(</span>int argc, const char* argv<span class="br0">[</span><span class="br0">]</span><span class="br0">)</span></span><br /> tunable_chown_uploads = <span class="nu0">0</span>;<br /> <span class="br0">}</span><br /> <span class="br0">}</span><br /><span class="re8">+ // add by twu2 20170928 begin</span><br /><span class="re8">+ the_session.is_local = check_local_net<span class="br0">(</span>the_session.p_remote_addr<span class="br0">)</span>;</span><br /><span class="re8">+ // add by twu2 20170928 end</span><br /> if <span class="br0">(</span>tunable_one_process_model<span class="br0">)</span><br /> <span class="br0">{</span><br /> vsf_one_process_start<span class="br0">(</span>&the_session<span class="br0">)</span>;<br />diff --show-c-function -Nur vsftpd-3.0.3.orig/parseconf.c vsftpd-3.0.3/parseconf.c<br /><span class="re3">--- vsftpd-3.0.3.orig/parseconf.c 2017-09-28 14:40:29.000000000 +0800</span><br /><span class="re4">+++ vsftpd-3.0.3/parseconf.c 2017-09-28 21:10:31.892567245 +0800</span><br /><span class="re6">@@ -158,6 +158,10 @@ parseconf_str_array<span class="br0">[</span><span class="br0">]</span> =</span><br /> <span class="br0">{</span> "ftpd_banner", &tunable_ftpd_banner <span class="br0">}</span>,<br /> <span class="br0">{</span> "banned_email_file", &tunable_banned_email_file <span class="br0">}</span>,<br /> <span class="br0">{</span> "chroot_list_file", &tunable_chroot_list_file <span class="br0">}</span>,<br /><span class="re8">+ // add by twu2 20170928 begin</span><br /><span class="re8">+ <span class="br0">{</span> "local_net_file", &tunable_local_net_file <span class="br0">}</span>,</span><br /><span class="re8">+ <span class="br0">{</span> "nomaxrate_list_file", &tunable_nomaxrate_list_file <span class="br0">}</span>,</span><br /><span class="re8">+ // add by twu2 20170928 end</span><br /> <span class="br0">{</span> "pam_service_name", &tunable_pam_service_name <span class="br0">}</span>,<br /> <span class="br0">{</span> "guest_username", &tunable_guest_username <span class="br0">}</span>,<br /> <span class="br0">{</span> "userlist_file", &tunable_userlist_file <span class="br0">}</span>,<br />diff --show-c-function -Nur vsftpd-3.0.3.orig/postlogin.c vsftpd-3.0.3/postlogin.c<br /><span class="re3">--- vsftpd-3.0.3.orig/postlogin.c 2017-09-28 14:40:29.000000000 +0800</span><br /><span class="re4">+++ vsftpd-3.0.3/postlogin.c 2017-09-28 22:27:59.791545391 +0800</span><br /><span class="re6">@@ -94,6 +94,10 @@ process_post_login<span class="br0">(</span>struct vsf_session* p</span><br /> vsf_sysutil_set_umask<span class="br0">(</span>tunable_local_umask<span class="br0">)</span>;<br /> p_sess->bw_rate_max = tunable_local_max_rate;<br /> <span class="br0">}</span><br /><span class="re8">+ // modified by twu2 20170928 begin</span><br /><span class="re8">+ if <span class="br0">(</span>p_sess->nomaxrate<span class="br0">)</span></span><br /><span class="re8">+ p_sess->bw_rate_max = <span class="nu0">0</span>;</span><br /><span class="re8">+ // modified by twu2 20170928 end</span><br /> if <span class="br0">(</span>p_sess->is_http<span class="br0">)</span><br /> <span class="br0">{</span><br /> handle_http<span class="br0">(</span>p_sess<span class="br0">)</span>;<br /><span class="re6">@@ -606,8 +610,10 @@ handle_pasv<span class="br0">(</span>struct vsf_session* p_sess,</span><br /> str_append_text<span class="br0">(</span>&s_pasv_res_str, "|<span class="br0">)</span>"<span class="br0">)</span>;<br /> vsf_cmdio_write_str<span class="br0">(</span>p_sess, FTP_EPSVOK, &s_pasv_res_str<span class="br0">)</span>;<br /> return;<br /><span class="re7">- <span class="br0">}</span></span><br /><span class="re7">- if <span class="br0">(</span>tunable_pasv_address != 0<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">}</span> </span><br /><span class="re8">+ // modified by twu2 20170928 begin</span><br /><span class="re8">+ if <span class="br0">(</span>tunable_pasv_address != 0 && p_sess->is_local == 0<span class="br0">)</span></span><br /><span class="re8">+ // modified by twu2 20170928 end</span><br /> <span class="br0">{</span><br /> vsf_sysutil_sockaddr_alloc_ipv4<span class="br0">(</span>&s_p_sockaddr<span class="br0">)</span>;<br /> /* Report passive address as specified in configuration */<br /><span class="re6">@@ -1829,6 +1835,12 @@ handle_stat<span class="br0">(</span>struct vsf_session* p_sess<span class="br0">)</span></span><br /> vsf_cmdio_write_hyphen<span class="br0">(</span>p_sess, FTP_STATOK, "FTP server status:"<span class="br0">)</span>;<br /> vsf_cmdio_write_raw<span class="br0">(</span>p_sess, " Connected to "<span class="br0">)</span>;<br /> vsf_cmdio_write_raw<span class="br0">(</span>p_sess, str_getbuf<span class="br0">(</span>&p_sess->remote_ip_str<span class="br0">)</span><span class="br0">)</span>;<br /><span class="re8">+ // modified by twu2 20170928 begin</span><br /><span class="re8">+ if <span class="br0">(</span>p_sess->is_local<span class="br0">)</span></span><br /><span class="re8">+ vsf_cmdio_write_raw<span class="br0">(</span>p_sess, ", <span class="br0">(</span>LAN<span class="br0">)</span>"<span class="br0">)</span>;</span><br /><span class="re8">+ else</span><br /><span class="re8">+ vsf_cmdio_write_raw<span class="br0">(</span>p_sess, ", <span class="br0">(</span>WAN<span class="br0">)</span>"<span class="br0">)</span>;</span><br /><span class="re8">+ // modified by twu2 20170928 end</span><br /> vsf_cmdio_write_raw<span class="br0">(</span>p_sess, "\r\n"<span class="br0">)</span>;<br /> vsf_cmdio_write_raw<span class="br0">(</span>p_sess, " Logged in as "<span class="br0">)</span>;<br /> vsf_cmdio_write_raw<span class="br0">(</span>p_sess, str_getbuf<span class="br0">(</span>&p_sess->user_str<span class="br0">)</span><span class="br0">)</span>;<br />diff --show-c-function -Nur vsftpd-3.0.3.orig/session.h vsftpd-3.0.3/session.h<br /><span class="re3">--- vsftpd-3.0.3.orig/session.h 2012-04-05 09:27:19.000000000 +0800</span><br /><span class="re4">+++ vsftpd-3.0.3/session.h 2017-09-28 21:09:03.871838330 +0800</span><br /><span class="re6">@@ -99,6 +99,10 @@ struct vsf_session</span><br /> int ssl_slave_fd;<br /> int ssl_consumer_fd;<br /> unsigned int login_fails;<br /><span class="re8">+ // add by twu2 20170928 begin</span><br /><span class="re8">+ int is_local;</span><br /><span class="re8">+ int nomaxrate;</span><br /><span class="re8">+ // add by twu2 20170928 end</span><br /> <span class="br0">}</span>;<br /> <br /> #endif /* VSF_SESSION_H */<br />diff --show-c-function -Nur vsftpd-3.0.3.orig/tunables.c vsftpd-3.0.3/tunables.c<br /><span class="re3">--- vsftpd-3.0.3.orig/tunables.c 2017-09-28 14:40:29.000000000 +0800</span><br /><span class="re4">+++ vsftpd-3.0.3/tunables.c 2017-09-28 21:10:58.748789905 +0800</span><br /><span class="re6">@@ -<span class="nu0">121</span>,<span class="nu0">6</span> +<span class="nu0">121</span>,<span class="nu0">10</span> @@ const char* tunable_nopriv_user;</span><br /> const char* tunable_ftpd_banner;<br /> const char* tunable_banned_email_file;<br /> const char* tunable_chroot_list_file;<br /><span class="re8">+// add by twu2 20170928 begin</span><br /><span class="re8">+const char* tunable_local_net_file;</span><br /><span class="re8">+const char* tunable_nomaxrate_list_file;</span><br /><span class="re8">+// add by twu2 20170928 end</span><br /> const char* tunable_pam_service_name;<br /> const char* tunable_guest_username;<br /> const char* tunable_userlist_file;<br /><span class="re6">@@ -268,6 +272,10 @@ tunables_load_defaults<span class="br0">(</span><span class="br0">)</span></span><br /> install_str_setting<span class="br0">(</span><span class="nu0">0</span>, &tunable_ftpd_banner<span class="br0">)</span>;<br /> install_str_setting<span class="br0">(</span>"/etc/vsftpd.banned_emails", &tunable_banned_email_file<span class="br0">)</span>;<br /> install_str_setting<span class="br0">(</span>"/etc/vsftpd.chroot_list", &tunable_chroot_list_file<span class="br0">)</span>;<br /><span class="re8">+ // add by twu2 20170928 begin</span><br /><span class="re8">+ install_str_setting<span class="br0">(</span>"/etc/localnet", &tunable_local_net_file<span class="br0">)</span>;</span><br /><span class="re8">+ install_str_setting<span class="br0">(</span>"/etc/vsftpd.nomaxrate_list", &tunable_nomaxrate_list_file<span class="br0">)</span>;</span><br /><span class="re8">+ // add by twu2 20170928 end</span><br /> install_str_setting<span class="br0">(</span>"vsftpd", &tunable_pam_service_name<span class="br0">)</span>;<br /> install_str_setting<span class="br0">(</span>"ftp", &tunable_guest_username<span class="br0">)</span>;<br /> install_str_setting<span class="br0">(</span>"/etc/vsftpd.user_list", &tunable_userlist_file<span class="br0">)</span>;<br />diff --show-c-function -Nur vsftpd-3.0.3.orig/tunables.h vsftpd-3.0.3/tunables.h<br /><span class="re3">--- vsftpd-3.0.3.orig/tunables.h 2017-09-28 14:40:29.000000000 +0800</span><br /><span class="re4">+++ vsftpd-3.0.3/tunables.h 2017-09-28 20:57:15.750028392 +0800</span><br /><span class="re6">@@ -<span class="nu0">124</span>,<span class="nu0">6</span> +<span class="nu0">124</span>,<span class="nu0">10</span> @@ extern const char* tunable_nopriv_user;</span><br /> extern const char* tunable_ftpd_banner;<br /> extern const char* tunable_banned_email_file;<br /> extern const char* tunable_chroot_list_file;<br /><span class="re8">+// add by twu2 20170928 begin</span><br /><span class="re8">+extern const char* tunable_local_net_file;</span><br /><span class="re8">+extern const char* tunable_nomaxrate_list_file;</span><br /><span class="re8">+// add by twu2 20170928 end</span><br /> extern const char* tunable_pam_service_name;<br /> extern const char* tunable_guest_username;<br /> extern const char* tunable_userlist_file;<br />diff --show-c-function -Nur vsftpd-3.0.3.orig/twoprocess.c vsftpd-3.0.3/twoprocess.c<br /><span class="re3">--- vsftpd-3.0.3.orig/twoprocess.c 2012-09-16 15:15:49.000000000 +0800</span><br /><span class="re4">+++ vsftpd-3.0.3/twoprocess.c 2017-09-29 23:18:56.487053338 +0800</span><br /><span class="re6">@@ -358,6 +358,9 @@ process_login_req<span class="br0">(</span>struct vsf_session* p_</span><br /> if <span class="br0">(</span>do_chroot<span class="br0">)</span><br /> <span class="br0">{</span><br /> do_chroot = <span class="nu0">0</span>;<br /><span class="re8">+ // add by twu2 20170928 begin</span><br /><span class="re8">+ tunable_idle_session_timeout = <span class="nu0">0</span>;</span><br /><span class="re8">+ // add by twu2 20170928 end</span><br /> <span class="br0">}</span><br /> else<br /> <span class="br0">{</span><br /><span class="re6">@@ -366,6 +369,23 @@ process_login_req<span class="br0">(</span>struct vsf_session* p_</span><br /> <span class="br0">}</span><br /> str_free<span class="br0">(</span>&chroot_list_file<span class="br0">)</span>;<br /> <span class="br0">}</span><br /><span class="re8">+ // add by twu2 20170928 begin</span><br /><span class="re8">+ p_sess->nomaxrate = <span class="nu0">0</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>tunable_nomaxrate_list_file<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ struct mystr nomaxrate_list_file = INIT_MYSTR;</span><br /><span class="re8">+ int retval;</span><br /><span class="re8">+</span><br /><span class="re8">+ retval = str_fileread<span class="br0">(</span>&nomaxrate_list_file, tunable_nomaxrate_list_file,</span><br /><span class="re8">+ VSFTP_CONF_FILE_MAX<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>!vsf_sysutil_retval_is_error<span class="br0">(</span>retval<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>str_contains_line<span class="br0">(</span>&nomaxrate_list_file, &p_sess->user_str<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ p_sess->nomaxrate = <span class="nu0">1</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ str_free<span class="br0">(</span>&nomaxrate_list_file<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ // add by twu2 20170928 end</span><br /> common_do_login<span class="br0">(</span>p_sess, &p_sess->user_str, do_chroot, <span class="nu0">0</span><span class="br0">)</span>;<br /> <span class="br0">}</span><br /> break;</div></pre><p> </p><p>檔案可以在這兒抓: <a href="https://www.teatime.com.tw/~tommy/mypatch/vsftpd-3.0.3-localnet.patch" target="_blank">https://www.teatime.com.tw/~tommy/mypatch/vsftpd-3.0.3-localnet.patch</a> </p><p>patch 的內容有三個部份:</p><p> </p><ol><li>主要是上面提到的 <a href="https://blog.teatime.com.tw/1/post/76" target="_blank">pasv_address 會依據 /etc/localnet 的內容決定是否使用</a> .</li><li>檢查 /etc/vsftpd.nomaxrate_list, 如果在裡頭就<a href="https://blog.teatime.com.tw/1/post/122" target="_blank">不限制傳輸的速度</a> </li><li>如果預設是 chroot, 而列在 /etc/vsftpd.chroot_list 是不使用 chroot 時, 則這些使用者也不會有 idle_timeout 的限制</li></ol>這些應該是之前也有寫給 pure-ftpd 使用的修改, 換回 vsftpd 之後, 順便就改回來了.<p> </p>
Patch
FTP
2017-10-01T09:26:26Z
tommy
-
讓 FileZilla 儲存所選擇的憑證, 而非只能儲存站台本身的憑證
https://blog.teatime.com.tw/1/post/478
<p>由於<a href="https://blog.teatime.com.tw/1/post/477" target="_blank">之前提到改用 Let's Encrypt 來產生憑證</a>之後, 會造成平均每兩個月就會更換一次憑證, 而 <a href="https://filezilla-project.org/index.php" target="_blank">FileZilla</a> 本身只能儲存並信任站台本身的憑證, 所以... 變成每次更換憑證會就會要求再信任一次.</p><p>所以, 就改了一下 FileZilla, 把憑證儲存的地方, 改成依據目前選擇查閱的憑證來儲存 (這時會改存 CN 而不是 Host, 而 Port 一律為 0), 然後在每次檢查信任憑證的地方, 改成檢查所有的憑證, 只要有一個是信任的就可以.</p><pre class="diff"><div class="insertcode">diff -Nurp filezilla.orig/src/interface/verifycertdialog.cpp filezilla/src/interface/verifycertdialog.cpp<br /><span class="re3">--- filezilla.orig/src/interface/verifycertdialog.cpp 2016-05-25 16:19:18.590183991 +0800</span><br /><span class="re4">+++ filezilla/src/interface/verifycertdialog.cpp 2016-05-26 13:14:03.897443962 +0800</span><br /><span class="re6">@@ -147,6 +147,7 @@ void CVerifyCertDialog::ShowVerification</span><br /> XRCCTRL<span class="br0">(</span>*m_pDlg, "ID_ALWAYS", wxCheckBox<span class="br0">)</span>->Hide<span class="br0">(</span><span class="br0">)</span>;<br /> <span class="br0">}</span><br /> <br /><span class="re8">+ m_curSelect = <span class="nu0">0</span>;</span><br /> m_certificates = notification.GetCertificates<span class="br0">(</span><span class="br0">)</span>;<br /> if <span class="br0">(</span>m_certificates.size<span class="br0">(</span><span class="br0">)</span> == <span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span><br /> XRCCTRL<span class="br0">(</span>*m_pDlg, "ID_CHAIN_DESC", wxStaticText<span class="br0">)</span>->Hide<span class="br0">(</span><span class="br0">)</span>;<br /><span class="re6">@@ -230,6 +231,52 @@ void CVerifyCertDialog::ShowVerification</span><br /> m_pDlg = <span class="nu0">0</span>;<br /> <span class="br0">}</span><br /> <br /><span class="re8">+wxString CVerifyCertDialog::GetCNValue<span class="br0">(</span>const wxString& dn<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ wxStringTokenizer tokens<span class="br0">(</span>dn, _T<span class="br0">(</span>","<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ std::list<wxString> tokenlist;</span><br /><span class="re8">+ while <span class="br0">(</span>tokens.HasMoreTokens<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ tokenlist.push_back<span class="br0">(</span>tokens.GetNextToken<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString prefix = _T<span class="br0">(</span>"CN="<span class="br0">)</span>;</span><br /><span class="re8">+ int len = prefix.Length<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString value;</span><br /><span class="re8">+</span><br /><span class="re8">+ bool append = false;</span><br /><span class="re8">+</span><br /><span class="re8">+ auto iter = tokenlist.begin<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ while <span class="br0">(</span>iter != tokenlist.end<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>!append<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>iter->Left<span class="br0">(</span>len<span class="br0">)</span> != prefix<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ ++iter;</span><br /><span class="re8">+ continue;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>!value.empty<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ value += _T<span class="br0">(</span>"\n"<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else</span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ append = false;</span><br /><span class="re8">+ value += _T<span class="br0">(</span>","<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ value += iter->Mid<span class="br0">(</span>len<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>iter->Last<span class="br0">(</span><span class="br0">)</span> == '\\'<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ value.RemoveLast<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ append = true;</span><br /><span class="re8">+ len = <span class="nu0">0</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ auto remove = iter++;</span><br /><span class="re8">+ tokenlist.erase<span class="br0">(</span>remove<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ return value;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /> void CVerifyCertDialog::ParseDN<span class="br0">(</span>wxWindow* parent, const wxString& dn, wxSizer* pSizer<span class="br0">)</span><br /> <span class="br0">{</span><br /> pSizer->Clear<span class="br0">(</span>true<span class="br0">)</span>;<br /><span class="re6">@@ -329,11 +376,28 @@ bool CVerifyCertDialog::IsTrusted<span class="br0">(</span>CCerti</span><br /> <br /> LoadTrustedCerts<span class="br0">(</span><span class="br0">)</span>;<br /> <br /><span class="re7">- unsigned int len;</span><br /><span class="re7">- CCertificate cert = notification.GetCertificates<span class="br0">(</span><span class="br0">)</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>;</span><br /><span class="re7">- const unsigned char* data = cert.GetRawData<span class="br0">(</span>len<span class="br0">)</span>;</span><br /><span class="re8">+ for <span class="br0">(</span>unsigned int i = <span class="nu0">0</span>; i < notification.GetCertificates<span class="br0">(</span><span class="br0">)</span>.size<span class="br0">(</span><span class="br0">)</span>; ++i<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>i > 0<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ unsigned int len;</span><br /><span class="re8">+ CCertificate cert = notification.GetCertificates<span class="br0">(</span><span class="br0">)</span><span class="br0">[</span>i<span class="br0">]</span>;</span><br /><span class="re8">+ const unsigned char* data = cert.GetRawData<span class="br0">(</span>len<span class="br0">)</span>;</span><br /><span class="re8">+ wxString sCN = GetCNValue<span class="br0">(</span>cert.GetSubject<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /> <br /><span class="re7">- return IsTrusted<span class="br0">(</span>notification.GetHost<span class="br0">(</span><span class="br0">)</span>, notification.GetPort<span class="br0">(</span><span class="br0">)</span>, data, len, false<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>IsTrusted<span class="br0">(</span>sCN, 0, data, len, false<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ return true;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else <span class="br0">{</span></span><br /><span class="re8">+ unsigned int len;</span><br /><span class="re8">+ CCertificate cert = notification.GetCertificates<span class="br0">(</span><span class="br0">)</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>;</span><br /><span class="re8">+ const unsigned char* data = cert.GetRawData<span class="br0">(</span>len<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ if <span class="br0">(</span>IsTrusted<span class="br0">(</span>notification.GetHost<span class="br0">(</span><span class="br0">)</span>, notification.GetPort<span class="br0">(</span><span class="br0">)</span>, data, len, false<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ return true;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ return false;</span><br /> <span class="br0">}</span><br /> <br /> bool CVerifyCertDialog::DoIsTrusted<span class="br0">(</span>const wxString& host, int port, const unsigned char* data, unsigned int len, std::list<CVerifyCertDialog::t_certData> const& trustedCerts<span class="br0">)</span><br /><span class="re6">@@ -465,7 +529,10 @@ void CVerifyCertDialog::LoadTrustedCerts</span><br /> <br /> data.host = GetTextElement<span class="br0">(</span>cert, "Host"<span class="br0">)</span>;<br /> data.port = GetTextElementInt<span class="br0">(</span>cert, "Port"<span class="br0">)</span>;<br /><span class="re7">- if <span class="br0">(</span>data.host.empty<span class="br0">(</span><span class="br0">)</span> || data.port < <span class="nu0">1</span> || data.port > 65535<span class="br0">)</span></span><br /><span class="re8">+ if <span class="br0">(</span>data.port == 0<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ // use for non-first cert</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else if <span class="br0">(</span>data.host.empty<span class="br0">(</span><span class="br0">)</span> || data.port < <span class="nu0">1</span> || data.port > 65535<span class="br0">)</span></span><br /> remove = cert;<br /> <br /> int64_t activationTime = GetTextElementInt<span class="br0">(</span>cert, "ActivationTime", <span class="nu0">0</span><span class="br0">)</span>;<br /><span class="re6">@@ -498,20 +565,35 @@ void CVerifyCertDialog::LoadTrustedCerts</span><br /> <br /> void CVerifyCertDialog::SetPermanentlyTrusted<span class="br0">(</span>CCertificateNotification const& notification<span class="br0">)</span><br /> <span class="br0">{</span><br /><span class="re7">- const CCertificate certificate = notification.GetCertificates<span class="br0">(</span><span class="br0">)</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>;</span><br /><span class="re8">+ wxString sCN = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ const CCertificate certificate = notification.GetCertificates<span class="br0">(</span><span class="br0">)</span><span class="br0">[</span>m_curSelect<span class="br0">]</span>;</span><br /> unsigned int len;<br /> const unsigned char* const data = certificate.GetRawData<span class="br0">(</span>len<span class="br0">)</span>;<br /> <br /> CReentrantInterProcessMutexLocker mutex<span class="br0">(</span>MUTEX_TRUSTEDCERTS<span class="br0">)</span>;<br /> LoadTrustedCerts<span class="br0">(</span><span class="br0">)</span>;<br /> <br /><span class="re7">- if <span class="br0">(</span>IsTrusted<span class="br0">(</span>notification.GetHost<span class="br0">(</span><span class="br0">)</span>, notification.GetPort<span class="br0">(</span><span class="br0">)</span>, data, len, true<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re7">- return;</span><br /><span class="re8">+ if <span class="br0">(</span>m_curSelect > 0<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ sCN = GetCNValue<span class="br0">(</span>certificate.GetSubject<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>IsTrusted<span class="br0">(</span>sCN, 0, data, len, true<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else <span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>IsTrusted<span class="br0">(</span>notification.GetHost<span class="br0">(</span><span class="br0">)</span>, notification.GetPort<span class="br0">(</span><span class="br0">)</span>, data, len, true<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /> <span class="br0">}</span><br /> <br /> t_certData cert;<br /><span class="re7">- cert.host = notification.GetHost<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re7">- cert.port = notification.GetPort<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>m_curSelect > 0<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ cert.host = sCN;</span><br /><span class="re8">+ cert.port = <span class="nu0">0</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else <span class="br0">{</span></span><br /><span class="re8">+ cert.host = notification.GetHost<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ cert.port = notification.GetPort<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /> cert.len = len;<br /> cert.data = new unsigned char<span class="br0">[</span>len<span class="br0">]</span>;<br /> memcpy<span class="br0">(</span>cert.data, data, len<span class="br0">)</span>;<br /><span class="re6">@@ -534,8 +616,14 @@ void CVerifyCertDialog::SetPermanentlyTr</span><br /> AddTextElement<span class="br0">(</span>xCert, "Data", ConvertHexToString<span class="br0">(</span>data, len<span class="br0">)</span><span class="br0">)</span>;<br /> AddTextElement<span class="br0">(</span>xCert, "ActivationTime", static_cast<int64_t><span class="br0">(</span>certificate.GetActivationTime<span class="br0">(</span><span class="br0">)</span>.get_time_t<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span>;<br /> AddTextElement<span class="br0">(</span>xCert, "ExpirationTime", static_cast<int64_t><span class="br0">(</span>certificate.GetExpirationTime<span class="br0">(</span><span class="br0">)</span>.get_time_t<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span>;<br /><span class="re7">- AddTextElement<span class="br0">(</span>xCert, "Host", notification.GetHost<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re7">- AddTextElement<span class="br0">(</span>xCert, "Port", notification.GetPort<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>m_curSelect > 0<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ AddTextElement<span class="br0">(</span>xCert, "Host", sCN<span class="br0">)</span>;</span><br /><span class="re8">+ AddTextElement<span class="br0">(</span>xCert, "Port", <span class="nu0">0</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else <span class="br0">{</span></span><br /><span class="re8">+ AddTextElement<span class="br0">(</span>xCert, "Host", notification.GetHost<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ AddTextElement<span class="br0">(</span>xCert, "Port", notification.GetPort<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /> <br /> m_xmlFile.Save<span class="br0">(</span>true<span class="br0">)</span>;<br /> <span class="br0">}</span><br /><span class="re6">@@ -590,6 +678,7 @@ void CVerifyCertDialog::OnCertificateCho</span><br /> int sel = event.GetSelection<span class="br0">(</span><span class="br0">)</span>;<br /> if <span class="br0">(</span>sel < <span class="nu0">0</span> || sel > <span class="br0">(</span>int<span class="br0">)</span>m_certificates.size<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /> return;<br /><span class="re8">+ m_curSelect = sel;</span><br /> DisplayCert<span class="br0">(</span>m_pDlg, m_certificates<span class="br0">[</span>sel<span class="br0">]</span><span class="br0">)</span>;<br /> <br /> m_pDlg->Layout<span class="br0">(</span><span class="br0">)</span>;<br />diff -Nurp filezilla.orig/src/interface/verifycertdialog.h filezilla/src/interface/verifycertdialog.h<br /><span class="re3">--- filezilla.orig/src/interface/verifycertdialog.h 2016-05-25 15:15:10.164819057 +0800</span><br /><span class="re4">+++ filezilla/src/interface/verifycertdialog.h 2016-05-26 13:14:03.897443962 +0800</span><br /><span class="re6">@@ -28,6 +28,7 @@ private:</span><br /> <br /> bool DisplayCert<span class="br0">(</span>wxDialogEx* pDlg, const CCertificate& cert<span class="br0">)</span>;<br /> <br /><span class="re8">+ wxString GetCNValue<span class="br0">(</span>const wxString& dn<span class="br0">)</span>;</span><br /> void ParseDN<span class="br0">(</span>wxWindow* parent, const wxString& dn, wxSizer* pSizer<span class="br0">)</span>;<br /> void ParseDN_by_prefix<span class="br0">(</span>wxWindow* parent, std::list<wxString>& tokens, wxString prefix, const wxString& name, wxSizer* pSizer, bool decode = false<span class="br0">)</span>;<br /> <br /><span class="re6">@@ -50,6 +51,7 @@ private:</span><br /> wxSizer* m_pSubjectSizer<span class="br0">{</span><span class="br0">}</span>;<br /> wxSizer* m_pIssuerSizer<span class="br0">{</span><span class="br0">}</span>;<br /> int line_height_<span class="br0">{</span><span class="br0">}</span>;<br /><span class="re8">+ unsigned int m_curSelect;</span><br /> <br /> void OnCertificateChoice<span class="br0">(</span>wxCommandEvent& event<span class="br0">)</span>;<br /> <span class="br0">}</span>;</div></pre><p>patch 可以由這兒抓: <a href="http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.18.0_trust_cert.patch" target="_blank">http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.18.0_trust_cert.patch</a> </p><p>這個 patch 不久前<a href="https://trac.filezilla-project.org/ticket/10842" target="_blank">送給作者</a>, 不過被否決了. 所以.... 有需要就自己處理吧, 或到 <a href="https://sourceforge.net/projects/filezillapv/" target="_blank">FileZillaPV</a> 去抓我做好的執行檔.</p>
Patch
FTP
Software
2016-05-28T20:50:15Z
tommy
-
FileZilla 3.7.3 Generic Proxy per site
https://blog.teatime.com.tw/1/post/461
<p>這是讓 <a href="https://filezilla-project.org/" target="_blank">FileZilla</a> 支援每個站點獨立設定要使用的 proxy 的修正.</p><pre class="diff"><div class="insertcode"><pre class="diff" style="font-family: monospace">diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/engine/ControlSocket.cpp filezilla-3.7.3/src/engine/ControlSocket.cpp<br /><span class="re3">--- filezilla-3.7.3.orig/src/engine/ControlSocket.cpp <span class="nu0">2013</span>-06-09 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">07.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/engine/ControlSocket.cpp <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.023788900</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">1163</span>,<span class="nu0">21</span> +<span class="nu0">1163</span>,<span class="nu0">44</span> @@</span><br /> wxString host;<br /> unsigned int port = <span class="nu0">0</span>;<br /> <br /><span class="re7">- const int proxy_type = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_TYPE<span class="br0">)</span>;</span><br /><span class="re7">- if <span class="br0">(</span>proxy_type > CProxySocket::unknown && proxy_type < CProxySocket::proxytype_count && !m_pCurrentServer->GetBypassProxy<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ int proxyType = <span class="nu0">0</span>;</span><br /><span class="re8">+ wxString proxyHost;</span><br /><span class="re8">+ unsigned int proxyPort;</span><br /><span class="re8">+ wxString proxyUser;</span><br /><span class="re8">+ wxString proxyPass;</span><br /><span class="re8">+</span><br /><span class="re8">+ if <span class="br0">(</span>m_pCurrentServer->GetProxyType<span class="br0">(</span><span class="br0">)</span> > CProxySocket::unknown &&</span><br /><span class="re8">+ m_pCurrentServer->GetProxyType<span class="br0">(</span><span class="br0">)</span> < CProxySocket::proxytype_count</span><br /><span class="re8">+ && m_pCurrentServer->GetProxyHost<span class="br0">(</span><span class="br0">)</span> != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ proxyType = m_pCurrentServer->GetProxyType<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyHost = m_pCurrentServer->GetProxyHost<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyPort = m_pCurrentServer->GetProxyPort<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyUser = m_pCurrentServer->GetProxyUser<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyPass = m_pCurrentServer->GetProxyPass<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else if <span class="br0">(</span>!m_pCurrentServer->GetBypassProxy<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ proxyType = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_TYPE<span class="br0">)</span>;</span><br /><span class="re8">+ proxyHost = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_HOST<span class="br0">)</span>;</span><br /><span class="re8">+ proxyPort = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_PORT<span class="br0">)</span>;</span><br /><span class="re8">+ proxyUser = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_USER<span class="br0">)</span>;</span><br /><span class="re8">+ proxyPass = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_PASS<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>proxyType > CProxySocket::unknown && proxyType < CProxySocket::proxytype_count<span class="br0">)</span></span><br /> <span class="br0">{</span><br /> LogMessage<span class="br0">(</span>::Status, _<span class="br0">(</span>"Connecting to %s through proxy"<span class="br0">)</span>, m_pCurrentServer->FormatHost<span class="br0">(</span><span class="br0">)</span>.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br /> <br /><span class="re7">- host = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_HOST<span class="br0">)</span>;</span><br /><span class="re7">- port = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_PORT<span class="br0">)</span>;</span><br /><span class="re8">+ host = proxyHost;</span><br /><span class="re8">+ port = proxyPort;</span><br /> <br /> delete m_pBackend;<br /> m_pProxyBackend = new CProxySocket<span class="br0">(</span>this, m_pSocket, this<span class="br0">)</span>;<br /> m_pBackend = m_pProxyBackend;<br /><span class="re7">- int res = m_pProxyBackend->Handshake<span class="br0">(</span><span class="br0">(</span>enum CProxySocket::ProxyType<span class="br0">)</span>proxy_type,</span><br /><span class="re8">+ int res = m_pProxyBackend->Handshake<span class="br0">(</span><span class="br0">(</span>enum CProxySocket::ProxyType<span class="br0">)</span>proxyType,</span><br /> m_pCurrentServer->GetHost<span class="br0">(</span><span class="br0">)</span>, m_pCurrentServer->GetPort<span class="br0">(</span><span class="br0">)</span>,<br /><span class="re7">- m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_USER<span class="br0">)</span>,</span><br /><span class="re7">- m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_PASS<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyUser,</span><br /><span class="re8">+ proxyPass<span class="br0">)</span>;</span><br /> <br /> if <span class="br0">(</span>res != EINPROGRESS<span class="br0">)</span><br /> <span class="br0">{</span><br /><span class="re6">@@ -<span class="nu0">1485</span>,<span class="nu0">4</span> +<span class="nu0">1508</span>,<span class="nu0">4</span> @@</span><br /> int CControlSocket::Chmod<span class="br0">(</span>const CChmodCommand&<span class="br0">)</span><br /> <span class="br0">{</span><br /> return FZ_REPLY_NOTSUPPORTED;<br /><span class="re7">-<span class="br0">}</span></span><br /><span class="kw1">\ No newline at end of file</span><br /><span class="re8">+<span class="br0">}</span></span><br />diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/engine/ftpcontrolsocket.cpp filezilla-3.7.3/src/engine/ftpcontrolsocket.cpp<br /><span class="re3">--- filezilla-3.7.3.orig/src/engine/ftpcontrolsocket.cpp <span class="nu0">2013</span>-06-09 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">07.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/engine/ftpcontrolsocket.cpp <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.029791700</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">4395</span>,<span class="nu0">7</span> +<span class="nu0">4395</span>,<span class="nu0">8</span> @@</span><br /> <br /> // Do not use FTP proxy if generic proxy is set<br /> int generic_proxy_type = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_TYPE<span class="br0">)</span>;<br /><span class="re7">- if <span class="br0">(</span><span class="br0">(</span>generic_proxy_type <= CProxySocket::unknown || generic_proxy_type >= CProxySocket::proxytype_count<span class="br0">)</span> &&</span><br /><span class="re8">+ if <span class="br0">(</span><span class="br0">(</span>server.GetProxyType<span class="br0">(</span><span class="br0">)</span> <= CProxySocket::unknown || server.GetProxyType<span class="br0">(</span><span class="br0">)</span> >= CProxySocket::proxytype_count || server.GetProxyHost<span class="br0">(</span><span class="br0">)</span> == _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span> &&</span><br /><span class="re8">+ <span class="br0">(</span>generic_proxy_type <= CProxySocket::unknown || generic_proxy_type >= CProxySocket::proxytype_count<span class="br0">)</span> &&</span><br /> <span class="br0">(</span>pData->ftp_proxy_type = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_FTP_PROXY_TYPE<span class="br0">)</span><span class="br0">)</span> && !server.GetBypassProxy<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /> <span class="br0">{</span><br /> pData->host = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_FTP_PROXY_HOST<span class="br0">)</span>;<br />diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/engine/server.cpp filezilla-3.7.3/src/engine/server.cpp<br /><span class="re3">--- filezilla-3.7.3.orig/src/engine/server.cpp <span class="nu0">2013</span>-01-<span class="nu0">14</span> <span class="nu0">12</span>:<span class="nu0">30</span>:<span class="nu0">09.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/engine/server.cpp <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.036796600</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">307</span>,<span class="nu0">6</span> +<span class="nu0">307</span>,<span class="nu0">11</span> @@</span><br /> m_timezoneOffset = op.m_timezoneOffset;<br /> m_pasvMode = op.m_pasvMode;<br /> m_maximumMultipleConnections = op.m_maximumMultipleConnections;<br /><span class="re8">+ m_proxyType = op.m_proxyType;</span><br /><span class="re8">+ m_proxyHost = op.m_proxyHost;</span><br /><span class="re8">+ m_proxyPort = op.m_proxyPort;</span><br /><span class="re8">+ m_proxyUser = op.m_proxyUser;</span><br /><span class="re8">+ m_proxyPass = op.m_proxyPass;</span><br /> m_encodingType = op.m_encodingType;<br /> m_customEncoding = op.m_customEncoding;<br /> m_postLoginCommands = op.m_postLoginCommands;<br /><span class="re6">@@ -<span class="nu0">350</span>,<span class="nu0">6</span> +<span class="nu0">355</span>,<span class="nu0">16</span> @@</span><br /> return false;<br /> else if <span class="br0">(</span>m_pasvMode != op.m_pasvMode<span class="br0">)</span><br /> return false;<br /><span class="re8">+ else if <span class="br0">(</span>m_proxyType != op.m_proxyType<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyHost != op.m_proxyHost<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyPort != op.m_proxyPort<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyUser != op.m_proxyUser<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyPass != op.m_proxyPass<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /> else if <span class="br0">(</span>m_encodingType != op.m_encodingType<span class="br0">)</span><br /> return false;<br /> else if <span class="br0">(</span>m_encodingType == ENCODING_CUSTOM<span class="br0">)</span><br /><span class="re6">@@ -<span class="nu0">436</span>,<span class="nu0">6</span> +<span class="nu0">451</span>,<span class="nu0">27</span> @@</span><br /> else if <span class="br0">(</span>m_pasvMode > op.m_pasvMode<span class="br0">)</span><br /> return false;<br /> <br /><span class="re8">+ if <span class="br0">(</span>m_proxyType < op.m_proxyType<span class="br0">)</span></span><br /><span class="re8">+ return true;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyType > op.m_proxyType<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ if <span class="br0">(</span>m_proxyHost < op.m_proxyHost<span class="br0">)</span></span><br /><span class="re8">+ return true;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyHost > op.m_proxyHost<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ if <span class="br0">(</span>m_proxyPort < op.m_proxyPort<span class="br0">)</span></span><br /><span class="re8">+ return true;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyPort > op.m_proxyPort<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ if <span class="br0">(</span>m_proxyUser < op.m_proxyUser<span class="br0">)</span></span><br /><span class="re8">+ return true;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyUser > op.m_proxyUser<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ if <span class="br0">(</span>m_proxyPass < op.m_proxyPass<span class="br0">)</span></span><br /><span class="re8">+ return true;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyPass > op.m_proxyPass<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+</span><br /> if <span class="br0">(</span>m_encodingType < op.m_encodingType<span class="br0">)</span><br /> return true;<br /> else if <span class="br0">(</span>m_encodingType > op.m_encodingType<span class="br0">)</span><br /><span class="re6">@@ -<span class="nu0">489</span>,<span class="nu0">6</span> +<span class="nu0">525</span>,<span class="nu0">16</span> @@</span><br /> return false;<br /> else if <span class="br0">(</span>m_pasvMode != op.m_pasvMode<span class="br0">)</span><br /> return false;<br /><span class="re8">+ else if <span class="br0">(</span>m_proxyType != op.m_proxyType<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyHost != op.m_proxyHost<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyPort != op.m_proxyPort<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyUser != op.m_proxyUser<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ else if <span class="br0">(</span>m_proxyPass != op.m_proxyPass<span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /> else if <span class="br0">(</span>m_encodingType != op.m_encodingType<span class="br0">)</span><br /> return false;<br /> else if <span class="br0">(</span>m_encodingType == ENCODING_CUSTOM<span class="br0">)</span><br /><span class="re6">@@ -<span class="nu0">635</span>,<span class="nu0">6</span> +<span class="nu0">681</span>,<span class="nu0">62</span> @@</span><br /> return m_maximumMultipleConnections;<br /> <span class="br0">}</span><br /> <br /><span class="re8">+int CServer::GetProxyType<span class="br0">(</span><span class="br0">)</span> const</span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ return m_proxyType;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+void CServer::SetProxyType<span class="br0">(</span>int type<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ m_proxyType = type;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+wxString CServer::GetProxyHost<span class="br0">(</span><span class="br0">)</span> const</span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ return m_proxyHost;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+bool CServer::SetProxyHost<span class="br0">(</span>wxString host<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ m_proxyHost = host;</span><br /><span class="re8">+ return true;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+unsigned int CServer::GetProxyPort<span class="br0">(</span><span class="br0">)</span> const</span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ return m_proxyPort;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+bool CServer::SetProxyPort<span class="br0">(</span>unsigned int port<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>port < 1 || port > <span class="nu0">65535</span><span class="br0">)</span></span><br /><span class="re8">+ return false;</span><br /><span class="re8">+ m_proxyPort = port;</span><br /><span class="re8">+ return true;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+wxString CServer::GetProxyUser<span class="br0">(</span><span class="br0">)</span> const</span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ return m_proxyUser;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+bool CServer::SetProxyUser<span class="br0">(</span>wxString user<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ m_proxyUser = user;</span><br /><span class="re8">+ return true;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+wxString CServer::GetProxyPass<span class="br0">(</span><span class="br0">)</span> const</span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ return m_proxyPass;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+bool CServer::SetProxyPass<span class="br0">(</span>wxString pass<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ m_proxyPass = pass;</span><br /><span class="re8">+ return true;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /> wxString CServer::FormatHost<span class="br0">(</span>bool always_omit_port /*=false*/<span class="br0">)</span> const<br /> <span class="br0">{</span><br /> wxString host = m_host;<br /><span class="re6">@@ -<span class="nu0">683</span>,<span class="nu0">6</span> +<span class="nu0">785</span>,<span class="nu0">11</span> @@</span><br /> m_timezoneOffset = <span class="nu0">0</span>;<br /> m_pasvMode = MODE_DEFAULT;<br /> m_maximumMultipleConnections = <span class="nu0">0</span>;<br /><span class="re8">+ m_proxyType = <span class="nu0">0</span>;</span><br /><span class="re8">+ m_proxyUser = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ m_proxyPort = <span class="nu0">8080</span>;</span><br /><span class="re8">+ m_proxyUser = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ m_proxyPass = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /> m_encodingType = ENCODING_AUTO;<br /> m_customEncoding = _T<span class="br0">(</span>""<span class="br0">)</span>;<br /> m_bypassProxy = false;<br />diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/engine/sftpcontrolsocket.cpp filezilla-3.7.3/src/engine/sftpcontrolsocket.cpp<br /><span class="re3">--- filezilla-3.7.3.orig/src/engine/sftpcontrolsocket.cpp <span class="nu0">2013</span>-06-09 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">07.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/engine/sftpcontrolsocket.cpp <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.044802800</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">486</span>,<span class="nu0">7</span> +<span class="nu0">486</span>,<span class="nu0">8</span> @@</span><br /> switch <span class="br0">(</span>pData->opState<span class="br0">)</span><br /> <span class="br0">{</span><br /> case connect_init:<br /><span class="re7">- if <span class="br0">(</span>m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_TYPE<span class="br0">)</span> && !m_pCurrentServer->GetBypassProxy<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ if <span class="br0">(</span><span class="br0">(</span>m_pCurrentServer->GetProxyType<span class="br0">(</span><span class="br0">)</span> && m_pCurrentServer->GetProxyHost<span class="br0">(</span><span class="br0">)</span> != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span> ||</span><br /><span class="re8">+ <span class="br0">(</span>m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_TYPE<span class="br0">)</span> && !m_pCurrentServer->GetBypassProxy<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span></span><br /> pData->opState = connect_proxy;<br /> else if <span class="br0">(</span>pData->pKeyFiles<span class="br0">)</span><br /> pData->opState = connect_keys;<br /><span class="re6">@@ -<span class="nu0">540</span>,<span class="nu0">37</span> +<span class="nu0">541</span>,<span class="nu0">59</span> @@</span><br /> <span class="br0">{</span><br /> case connect_proxy:<br /> <span class="br0">{</span><br /><span class="re7">- int type;</span><br /><span class="re7">- switch <span class="br0">(</span>m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_TYPE<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re7">- <span class="br0">{</span></span><br /><span class="re7">- case CProxySocket::HTTP:</span><br /><span class="re7">- type = <span class="nu0">1</span>;</span><br /><span class="re7">- break;</span><br /><span class="re7">- case CProxySocket::SOCKS5:</span><br /><span class="re7">- type = <span class="nu0">2</span>;</span><br /><span class="re7">- break;</span><br /><span class="re7">- default:</span><br /><span class="re7">- LogMessage<span class="br0">(</span>__TFILE__, __LINE__, this, Debug_Warning, _T<span class="br0">(</span>"Unsupported proxy type"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re7">- DoClose<span class="br0">(</span>FZ_REPLY_INTERNALERROR<span class="br0">)</span>;</span><br /><span class="re7">- return FZ_REPLY_ERROR;</span><br /><span class="re7">- <span class="br0">}</span></span><br /><span class="re7">-</span><br /><span class="re7">- wxString cmd = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"proxy %d \"%s\" %d"<span class="br0">)</span>, type,</span><br /><span class="re7">- m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_HOST<span class="br0">)</span>.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re7">- m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_PORT<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re7">- wxString user = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_USER<span class="br0">)</span>;</span><br /><span class="re7">- if <span class="br0">(</span>user != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re7">- cmd += _T<span class="br0">(</span>" \""<span class="br0">)</span> + user + _T<span class="br0">(</span>"\""<span class="br0">)</span>;</span><br /><span class="re7">-</span><br /><span class="re7">- wxString show = cmd;</span><br /><span class="re7">-</span><br /><span class="re7">- wxString pass = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_PASS<span class="br0">)</span>;</span><br /><span class="re7">- if <span class="br0">(</span>pass != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re7">- <span class="br0">{</span></span><br /><span class="re7">- cmd += _T<span class="br0">(</span>" \""<span class="br0">)</span> + pass + _T<span class="br0">(</span>"\""<span class="br0">)</span>;</span><br /><span class="re7">- show += _T<span class="br0">(</span>" \""<span class="br0">)</span> + wxString<span class="br0">(</span>'*', pass.Len<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> + _T<span class="br0">(</span>"\""<span class="br0">)</span>;</span><br /><span class="re7">- <span class="br0">}</span></span><br /><span class="re7">- res = Send<span class="br0">(</span>cmd, show<span class="br0">)</span>;</span><br /><span class="re8">+ int proxyType;</span><br /><span class="re8">+ wxString proxyHost;</span><br /><span class="re8">+ unsigned int proxyPort;</span><br /><span class="re8">+ wxString proxyUser;</span><br /><span class="re8">+ wxString proxyPass;</span><br /><span class="re8">+</span><br /><span class="re8">+ if <span class="br0">(</span>m_pCurrentServer->GetProxyType<span class="br0">(</span><span class="br0">)</span> && m_pCurrentServer->GetProxyHost<span class="br0">(</span><span class="br0">)</span> != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ proxyType = m_pCurrentServer->GetProxyType<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyHost = m_pCurrentServer->GetProxyHost<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyPort = m_pCurrentServer->GetProxyPort<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyUser = m_pCurrentServer->GetProxyUser<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ proxyPass = m_pCurrentServer->GetProxyPass<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else <span class="br0">{</span></span><br /><span class="re8">+ proxyType = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_TYPE<span class="br0">)</span>;</span><br /><span class="re8">+ proxyHost = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_HOST<span class="br0">)</span>;</span><br /><span class="re8">+ proxyPort = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOptionVal<span class="br0">(</span>OPTION_PROXY_PORT<span class="br0">)</span>;</span><br /><span class="re8">+ proxyUser = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_USER<span class="br0">)</span>;</span><br /><span class="re8">+ proxyPass = m_pEngine->GetOptions<span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_PROXY_PASS<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ int type;</span><br /><span class="re8">+ switch <span class="br0">(</span>proxyType<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ case CProxySocket::HTTP:</span><br /><span class="re8">+ type = <span class="nu0">1</span>;</span><br /><span class="re8">+ break;</span><br /><span class="re8">+ case CProxySocket::SOCKS5:</span><br /><span class="re8">+ type = <span class="nu0">2</span>;</span><br /><span class="re8">+ break;</span><br /><span class="re8">+ default:</span><br /><span class="re8">+ LogMessage<span class="br0">(</span>__TFILE__, __LINE__, this, Debug_Warning, _T<span class="br0">(</span>"Unsupported proxy type"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ DoClose<span class="br0">(</span>FZ_REPLY_INTERNALERROR<span class="br0">)</span>;</span><br /><span class="re8">+ return FZ_REPLY_ERROR;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ wxString cmd = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"proxy %d \"%s\" %d"<span class="br0">)</span>, type,</span><br /><span class="re8">+ proxyHost.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ proxyPort<span class="br0">)</span>;</span><br /><span class="re8">+ wxString user = proxyUser;</span><br /><span class="re8">+ if <span class="br0">(</span>user != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ cmd += _T<span class="br0">(</span>" \""<span class="br0">)</span> + user + _T<span class="br0">(</span>"\""<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString show = cmd;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString pass = proxyPass;</span><br /><span class="re8">+ if <span class="br0">(</span>pass != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ cmd += _T<span class="br0">(</span>" \""<span class="br0">)</span> + pass + _T<span class="br0">(</span>"\""<span class="br0">)</span>;</span><br /><span class="re8">+ show += _T<span class="br0">(</span>" \""<span class="br0">)</span> + wxString<span class="br0">(</span>'*', pass.Len<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> + _T<span class="br0">(</span>"\""<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ res = Send<span class="br0">(</span>cmd, show<span class="br0">)</span>;</span><br /> <span class="br0">}</span><br /> break;<br /> case connect_keys:<br />diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/include/server.h filezilla-3.7.3/src/include/server.h<br /><span class="re3">--- filezilla-3.7.3.orig/src/include/server.h <span class="nu0">2013</span>-01-<span class="nu0">14</span> <span class="nu0">12</span>:<span class="nu0">30</span>:<span class="nu0">08.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/include/server.h <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.049805500</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">107</span>,<span class="nu0">6</span> +<span class="nu0">107</span>,<span class="nu0">17</span> @@</span><br /> void SetPasvMode<span class="br0">(</span>enum PasvMode pasvMode<span class="br0">)</span>;<br /> void MaximumMultipleConnections<span class="br0">(</span>int maximum<span class="br0">)</span>;<br /> <br /><span class="re8">+ int GetProxyType<span class="br0">(</span><span class="br0">)</span> const;</span><br /><span class="re8">+ void SetProxyType<span class="br0">(</span>int type<span class="br0">)</span>;</span><br /><span class="re8">+ wxString GetProxyHost<span class="br0">(</span><span class="br0">)</span> const;</span><br /><span class="re8">+ bool SetProxyHost<span class="br0">(</span>wxString host<span class="br0">)</span>;</span><br /><span class="re8">+ unsigned int GetProxyPort<span class="br0">(</span><span class="br0">)</span> const;</span><br /><span class="re8">+ bool SetProxyPort<span class="br0">(</span>unsigned int port<span class="br0">)</span>;</span><br /><span class="re8">+ wxString GetProxyUser<span class="br0">(</span><span class="br0">)</span> const;</span><br /><span class="re8">+ bool SetProxyUser<span class="br0">(</span>wxString user<span class="br0">)</span>;</span><br /><span class="re8">+ wxString GetProxyPass<span class="br0">(</span><span class="br0">)</span> const;</span><br /><span class="re8">+ bool SetProxyPass<span class="br0">(</span>wxString pass<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /> wxString FormatHost<span class="br0">(</span>bool always_omit_port = false<span class="br0">)</span> const;<br /> wxString FormatServer<span class="br0">(</span>const bool always_include_prefix = false<span class="br0">)</span> const;<br /> <br /><span class="re6">@@ -<span class="nu0">158</span>,<span class="nu0">6</span> +<span class="nu0">169</span>,<span class="nu0">11</span> @@</span><br /> int m_timezoneOffset;<br /> enum PasvMode m_pasvMode;<br /> int m_maximumMultipleConnections;<br /><span class="re8">+ int m_proxyType;</span><br /><span class="re8">+ wxString m_proxyHost;</span><br /><span class="re8">+ unsigned int m_proxyPort;</span><br /><span class="re8">+ wxString m_proxyUser;</span><br /><span class="re8">+ wxString m_proxyPass;</span><br /> enum CharsetEncoding m_encodingType;<br /> wxString m_customEncoding;<br /> wxString m_name;<br />diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/interface/queue_storage.cpp filezilla-3.7.3/src/interface/queue_storage.cpp<br /><span class="re3">--- filezilla-3.7.3.orig/src/interface/queue_storage.cpp <span class="nu0">2012</span>-<span class="nu0">10</span>-<span class="nu0">25</span> <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">07.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/interface/queue_storage.cpp <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.056810800</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">58</span>,<span class="nu0">7</span> +<span class="nu0">58</span>,<span class="nu0">12</span> @@</span><br /> encoding,<br /> bypass_proxy,<br /> post_login_commands,<br /><span class="re7">- name</span><br /><span class="re8">+ name,</span><br /><span class="re8">+ proxy_type,</span><br /><span class="re8">+ proxy_host,</span><br /><span class="re8">+ proxy_port,</span><br /><span class="re8">+ proxy_user,</span><br /><span class="re8">+ proxy_pass</span><br /> <span class="br0">}</span>;<br /> <span class="br0">}</span><br /> <br /><span class="re6">@@ -<span class="nu0">78</span>,<span class="nu0">7</span> +<span class="nu0">83</span>,<span class="nu0">12</span> @@</span><br /> <span class="br0">{</span> _T<span class="br0">(</span>"encoding"<span class="br0">)</span>, text, 0 <span class="br0">}</span>,<br /> <span class="br0">{</span> _T<span class="br0">(</span>"bypass_proxy"<span class="br0">)</span>, integer, 0 <span class="br0">}</span>,<br /> <span class="br0">{</span> _T<span class="br0">(</span>"post_login_commands"<span class="br0">)</span>, text, 0 <span class="br0">}</span>,<br /><span class="re7">- <span class="br0">{</span> _T<span class="br0">(</span>"name"<span class="br0">)</span>, text, <span class="nu0">0</span> <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">{</span> _T<span class="br0">(</span>"name"<span class="br0">)</span>, text, <span class="nu0">0</span> <span class="br0">}</span>,</span><br /><span class="re8">+ <span class="br0">{</span> _T<span class="br0">(</span>"proxy_type"<span class="br0">)</span>, integer, <span class="nu0">0</span> <span class="br0">}</span>,</span><br /><span class="re8">+ <span class="br0">{</span> _T<span class="br0">(</span>"proxy_host"<span class="br0">)</span>, text, <span class="nu0">0</span> <span class="br0">}</span>,</span><br /><span class="re8">+ <span class="br0">{</span> _T<span class="br0">(</span>"proxy_port"<span class="br0">)</span>, integer, <span class="nu0">0</span> <span class="br0">}</span>,</span><br /><span class="re8">+ <span class="br0">{</span> _T<span class="br0">(</span>"proxy_user"<span class="br0">)</span>, text, <span class="nu0">0</span> <span class="br0">}</span>,</span><br /><span class="re8">+ <span class="br0">{</span> _T<span class="br0">(</span>"proxy_pass"<span class="br0">)</span>, text, <span class="nu0">0</span> <span class="br0">}</span></span><br /> <span class="br0">}</span>;<br /> <br /> namespace file_table_column_names<br /><span class="re6">@@ -<span class="nu0">647</span>,<span class="nu0">6</span> +<span class="nu0">657</span>,<span class="nu0">12</span> @@</span><br /> <span class="br0">}</span><br /> Bind<span class="br0">(</span>insertServerQuery_, server_table_column_names::max_connections, server.MaximumMultipleConnections<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br /> <br /><span class="re8">+ Bind<span class="br0">(</span>insertServerQuery_, server_table_column_names::proxy_type, static_cast<int><span class="br0">(</span>server.GetProxyType<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ Bind<span class="br0">(</span>insertServerQuery_, server_table_column_names::proxy_host, server.GetProxyHost<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ Bind<span class="br0">(</span>insertServerQuery_, server_table_column_names::proxy_port, static_cast<int><span class="br0">(</span>server.GetProxyPort<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ Bind<span class="br0">(</span>insertServerQuery_, server_table_column_names::proxy_user, server.GetProxyUser<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ Bind<span class="br0">(</span>insertServerQuery_, server_table_column_names::proxy_pass, server.GetProxyPass<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /> switch <span class="br0">(</span>server.GetEncodingType<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /> <span class="br0">{</span><br /> default:<br /><span class="re6">@@ -<span class="nu0">912</span>,<span class="nu0">6</span> +<span class="nu0">928</span>,<span class="nu0">21</span> @@</span><br /> return INVALID_DATA;<br /> server.MaximumMultipleConnections<span class="br0">(</span>maximumMultipleConnections<span class="br0">)</span>;<br /> <br /><span class="re8">+ int proxyType = GetColumnInt<span class="br0">(</span>selectServersQuery_, server_table_column_names::proxy_type<span class="br0">)</span>;</span><br /><span class="re8">+ server.SetProxyType<span class="br0">(</span>proxyType<span class="br0">)</span>;</span><br /><span class="re8">+ wxString proxyHost = GetColumnText<span class="br0">(</span>selectServersQuery_, server_table_column_names::proxy_host<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>!server.SetProxyHost<span class="br0">(</span>proxyHost<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ return INVALID_DATA;</span><br /><span class="re8">+ int proxyPort = GetColumnInt<span class="br0">(</span>selectServersQuery_, server_table_column_names::proxy_port<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>!server.SetProxyPort<span class="br0">(</span>proxyPort<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ return INVALID_DATA;</span><br /><span class="re8">+ wxString proxyUser = GetColumnText<span class="br0">(</span>selectServersQuery_, server_table_column_names::proxy_user<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>!server.SetProxyUser<span class="br0">(</span>proxyUser<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ return INVALID_DATA;</span><br /><span class="re8">+ wxString proxyPass = GetColumnText<span class="br0">(</span>selectServersQuery_, server_table_column_names::proxy_pass<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>!server.SetProxyPass<span class="br0">(</span>proxyPass<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ return INVALID_DATA;</span><br /><span class="re8">+</span><br /> wxString encodingType = GetColumnText<span class="br0">(</span>selectServersQuery_, server_table_column_names::encoding<span class="br0">)</span>;<br /> if <span class="br0">(</span>encodingType.empty<span class="br0">(</span><span class="br0">)</span> || encodingType == _T<span class="br0">(</span>"Auto"<span class="br0">)</span><span class="br0">)</span><br /> server.SetEncodingType<span class="br0">(</span>ENCODING_AUTO<span class="br0">)</span>;<br />diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/interface/resources/dialogs.xrc filezilla-3.7.3/src/interface/resources/dialogs.xrc<br /><span class="re3">--- filezilla-3.7.3.orig/src/interface/resources/dialogs.xrc <span class="nu0">2013</span>-07-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">11.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/interface/resources/dialogs.xrc <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.071819400</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">961</span>,<span class="nu0">7</span> +<span class="nu0">961</span>,<span class="nu0">7</span> @@</span><br /> <cellpos>3,0</cellpos><br /> <cellspan>0,2</cellspan><br /> </object><br /><span class="re7">- </span><br /><span class="re8">+</span><br /> <object class="sizeritem"><br /> <object class="wxStaticText"><br /> <label>&amp;Logon Type:</label><br /><span class="re6">@@ -<span class="nu0">1245</span>,<span class="nu0">6</span> +<span class="nu0">1245</span>,<span class="nu0">110</span> @@</span><br /> </object><br /> </object><br /> </object><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="notebookpage"></span><br /><span class="re8">+ <label>Generic proxy</label></span><br /><span class="re8">+ <object class="wxPanel"></span><br /><span class="re8">+ <object class="wxBoxSizer"></span><br /><span class="re8">+ <orient>wxVERTICAL</orient></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxStaticBoxSizer"></span><br /><span class="re8">+ <label>Generic proxy</label></span><br /><span class="re8">+ <orient>wxHORIZONTAL</orient></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxFlexGridSizer"></span><br /><span class="re8">+ <cols><span class="nu0">1</span></cols></span><br /><span class="re8">+ <vgap><span class="nu0">5</span></vgap></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxStaticText"></span><br /><span class="re8">+ <label>Type of generic proxy:</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxRadioButton" name="ID_PROXYTYPE_NONE"></span><br /><span class="re8">+ <label>&amp;None</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxRadioButton" name="ID_PROXYTYPE_HTTP"></span><br /><span class="re8">+ <label>&amp;HTTP/<span class="nu0">1.1</span> using CONNECT method</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxRadioButton" name="ID_PROXYTYPE_SOCKS5"></span><br /><span class="re8">+ <label>&amp;SOCKS <span class="nu0">5</span></label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxFlexGridSizer"></span><br /><span class="re8">+ <cols><span class="nu0">2</span></cols></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxStaticText"></span><br /><span class="re8">+ <label>P&amp;roxy host:</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxTextCtrl" name="ID_PROXY_HOST"/></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL|wxGROW</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxStaticText"></span><br /><span class="re8">+ <label>Proxy &amp;port:</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxTextCtrl" name="ID_PROXY_PORT"></span><br /><span class="re8">+ <size><span class="nu0">50</span>,-<span class="nu0">1</span></size></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxStaticText"></span><br /><span class="re8">+ <label>Proxy &amp;user:</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxTextCtrl" name="ID_PROXY_USER"/></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL|wxGROW</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxStaticText"></span><br /><span class="re8">+ <label>Pro&amp;xy password:</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxTextCtrl" name="ID_PROXY_PASS"></span><br /><span class="re8">+ <style>wxTE_PASSWORD</style></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <flag>wxALIGN_CENTRE_VERTICAL|wxGROW</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <vgap><span class="nu0">5</span></vgap></span><br /><span class="re8">+ <hgap><span class="nu0">5</span></hgap></span><br /><span class="re8">+ <growablecols><span class="nu0">1</span></growablecols></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <flag>wxGROW</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <growablecols><span class="nu0">0</span></growablecols></span><br /><span class="re8">+ <object class="sizeritem"></span><br /><span class="re8">+ <object class="wxStaticText"></span><br /><span class="re8">+ <label>Note: Using a generic proxy forces passive mode on FTP connections.</label></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <option><span class="nu0">1</span></option></span><br /><span class="re8">+ <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxGROW</flag></span><br /><span class="re8">+ <border><span class="nu0">5</span></border></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ <option><span class="nu0">1</span></option></span><br /><span class="re8">+ <flag>wxGROW</flag></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /><span class="re8">+ </object></span><br /> </object><br /> <object class="notebookpage"><br /> <label>Charset</label><br />diff --strip-trailing-cr -Nur filezilla-3.7.3.orig/src/interface/sitemanager_dialog.cpp filezilla-3.7.3/src/interface/sitemanager_dialog.cpp<br /><span class="re3">--- filezilla-3.7.3.orig/src/interface/sitemanager_dialog.cpp <span class="nu0">2013</span>-05-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">04.000000000</span> +0800</span><br /><span class="re4">+++ filezilla-3.7.3/src/interface/sitemanager_dialog.cpp <span class="nu0">2013</span>-<span class="nu0">10</span>-01 <span class="nu0">11</span>:<span class="nu0">30</span>:<span class="nu0">39.078825500</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">32</span>,<span class="nu0">6</span> +<span class="nu0">32</span>,<span class="nu0">9</span> @@</span><br /> EVT_BUTTON<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_BROWSE"<span class="br0">)</span>, CSiteManagerDialog::OnRemoteDirBrowse<span class="br0">)</span><br /> EVT_TREE_ITEM_ACTIVATED<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_SITETREE"<span class="br0">)</span>, CSiteManagerDialog::OnItemActivated<span class="br0">)</span><br /> EVT_CHECKBOX<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_LIMITMULTIPLE"<span class="br0">)</span>, CSiteManagerDialog::OnLimitMultipleConnectionsChanged<span class="br0">)</span><br /><span class="re8">+EVT_RADIOBUTTON<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_PROXYTYPE_NONE"<span class="br0">)</span>, CSiteManagerDialog::OnProxyChange<span class="br0">)</span></span><br /><span class="re8">+EVT_RADIOBUTTON<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_PROXYTYPE_HTTP"<span class="br0">)</span>, CSiteManagerDialog::OnProxyChange<span class="br0">)</span></span><br /><span class="re8">+EVT_RADIOBUTTON<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_PROXYTYPE_SOCKS5"<span class="br0">)</span>, CSiteManagerDialog::OnProxyChange<span class="br0">)</span></span><br /> EVT_RADIOBUTTON<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_CHARSET_AUTO"<span class="br0">)</span>, CSiteManagerDialog::OnCharsetChange<span class="br0">)</span><br /> EVT_RADIOBUTTON<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_CHARSET_UTF8"<span class="br0">)</span>, CSiteManagerDialog::OnCharsetChange<span class="br0">)</span><br /> EVT_RADIOBUTTON<span class="br0">(</span>XRCID<span class="br0">(</span>"ID_CHARSET_CUSTOM"<span class="br0">)</span>, CSiteManagerDialog::OnCharsetChange<span class="br0">)</span><br /><span class="re6">@@ -<span class="nu0">403</span>,<span class="nu0">6</span> +<span class="nu0">406</span>,<span class="nu0">10</span> @@</span><br /> XRCCTRL<span class="br0">(</span>*this, "ID_TRANSFERMODE_ACTIVE", wxRadioButton<span class="br0">)</span>->Update<span class="br0">(</span><span class="br0">)</span>;<br /> XRCCTRL<span class="br0">(</span>*this, "ID_TRANSFERMODE_PASSIVE", wxRadioButton<span class="br0">)</span>->Update<span class="br0">(</span><span class="br0">)</span>;<br /> <br /><span class="re8">+ XRCCTRL<span class="br0">(</span>*this, "ID_PROXYTYPE_NONE", wxRadioButton<span class="br0">)</span>->Update<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ XRCCTRL<span class="br0">(</span>*this, "ID_PROXYTYPE_HTTP", wxRadioButton<span class="br0">)</span>->Update<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ XRCCTRL<span class="br0">(</span>*this, "ID_PROXYTYPE_SOCKS5", wxRadioButton<span class="br0">)</span>->Update<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /> wxTreeItemId item = pTree->GetSelection<span class="br0">(</span><span class="br0">)</span>;<br /> if <span class="br0">(</span>!item.IsOk<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /> pTree->SelectItem<span class="br0">(</span>m_ownSites<span class="br0">)</span>;<br /><span class="re6">@@ -<span class="nu0">1396</span>,<span class="nu0">6</span> +<span class="nu0">1403</span>,<span class="nu0">19</span> @@</span><br /> else<br /> server.m_server.MaximumMultipleConnections<span class="br0">(</span>0<span class="br0">)</span>;<br /> <br /><span class="re8">+ if <span class="br0">(</span>XRCCTRL<span class="br0">(</span>*this, "ID_PROXYTYPE_HTTP", wxRadioButton<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ server.m_server.SetProxyType<span class="br0">(</span>1<span class="br0">)</span>;</span><br /><span class="re8">+ else if <span class="br0">(</span>XRCCTRL<span class="br0">(</span>*this, "ID_PROXYTYPE_SOCKS5", wxRadioButton<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ server.m_server.SetProxyType<span class="br0">(</span>2<span class="br0">)</span>;</span><br /><span class="re8">+ else</span><br /><span class="re8">+ server.m_server.SetProxyType<span class="br0">(</span>0<span class="br0">)</span>;</span><br /><span class="re8">+ server.m_server.SetProxyHost<span class="br0">(</span>XRCCTRL<span class="br0">(</span>*this, "ID_PROXY_HOST", wxTextCtrl<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ unsigned long proxyPort;</span><br /><span class="re8">+ XRCCTRL<span class="br0">(</span>*this, "ID_PROXY_PORT", wxTextCtrl<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span>.ToULong<span class="br0">(</span>&proxyPort<span class="br0">)</span>;</span><br /><span class="re8">+ server.m_server.SetProxyPort<span class="br0">(</span>proxyPort<span class="br0">)</span>;</span><br /><span class="re8">+ server.m_server.SetProxyUser<span class="br0">(</span>XRCCTRL<span class="br0">(</span>*this, "ID_PROXY_USER", wxTextCtrl<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ server.m_server.SetProxyPass<span class="br0">(</span>XRCCTRL<span class="br0">(</span>*this, "ID_PROXY_PASS", wxTextCtrl<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /> if <span class="br0">(</span>XRCCTRL<span class="br0">(</span>*this, "ID_CHARSET_UTF8", wxRadioButton<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /> server.m_server.SetEncodingType<span class="br0">(</span>ENCODING_UTF8<span class="br0">)</span>;<br /> else if <span class="br0">(</span>XRCCTRL<span class="br0">(</span>*this, "ID_CHARSET_CUSTOM", wxRadioButton<span class="br0">)</span>->GetValue<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /><span class="re6">@@ -<span class="nu0">1642</span>,<span class="nu0">6</span> +<span class="nu0">1662</span>,<span class="nu0">43</span> @@</span><br /> XRCCTRL<span class="br0">(</span>*this, "ID_MAXMULTIPLE&qu</pre></div></pre>
Patch
FTP
2013-10-01T13:23:59Z
tommy
-
讓 FileZilla 的 HTTP Proxy 支援 Digest 認證方式
https://blog.teatime.com.tw/1/post/437
<p><a href="http://filezilla-project.org/" target="_blank">FileZilla</a> 本身雖然支援 HTTP CONNECT 方式的 proxy, 不過, 它只使用 Basic 方式來認證, 如果碰到 Digest 方式的 proxy server, 就會得到 407 的錯誤而無法連線.</p><p>由於 Basic 的方式是把帳號密碼透過明碼的方式來傳送, 所以... 我不怎麼喜歡把認證方式由 Digest 改回 Basic, 所以... 就想辦法加上這個支援.</p><p>patch 如下:</p><pre class="diff"><div class="insertcode"><pre class="diff" style="font-family: monospace">diff --strip-trailing-cr -Nur a/src/engine/proxy.cpp b/src/engine/proxy.cpp<br /><span class="re3">--- a/src/engine/proxy.cpp <span class="nu0">2013</span>-01-<span class="nu0">28</span> <span class="nu0">17</span>:04:<span class="nu0">35.655438700</span> +0800</span><br /><span class="re4">+++ b/src/engine/proxy.cpp <span class="nu0">2013</span>-01-<span class="nu0">28</span> <span class="nu0">17</span>:04:<span class="nu0">44.290188300</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">1</span>,<span class="nu0">6</span> +<span class="nu0">1</span>,<span class="nu0">8</span> @@</span><br /> #include <filezilla.h><br /> #include "proxy.h"<br /> #include <errno.h><br /><span class="re8">+#include <wx/tokenzr.h></span><br /><span class="re8">+#include <nettle/md5-compat.h></span><br /> #include "ControlSocket.h"<br /> <br /> enum handshake_state<br /><span class="re6">@@ -<span class="nu0">25</span>,<span class="nu0">6</span> +<span class="nu0">27</span>,<span class="nu0">8</span> @@</span><br /> m_pSendBuffer = <span class="nu0">0</span>;<br /> m_pRecvBuffer = <span class="nu0">0</span>;<br /> <br /><span class="re8">+ m_doAuth = false;</span><br /><span class="re8">+</span><br /> m_proxyType = unknown;<br /> <br /> m_can_write = false;<br /><span class="re6">@@ -<span class="nu0">39</span>,<span class="nu0">6</span> +<span class="nu0">43</span>,<span class="nu0">42</span> @@</span><br /> delete <span class="br0">[</span><span class="br0">]</span> m_pRecvBuffer;<br /> <span class="br0">}</span><br /> <br /><span class="re8">+static void AppendSubHex<span class="br0">(</span>unsigned char val, wxString& result<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>val > <span class="nu0">9</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ result.Append<span class="br0">(</span><span class="br0">(</span>char<span class="br0">)</span><span class="br0">(</span>'a'+val-10<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else</span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ result.Append<span class="br0">(</span><span class="br0">(</span>char<span class="br0">)</span><span class="br0">(</span>'0'+val<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+static void AppendHex<span class="br0">(</span>unsigned char val, wxString& result<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ AppendSubHex<span class="br0">(</span><span class="br0">(</span>val >> 4<span class="br0">)</span> & 0xF, result<span class="br0">)</span>;</span><br /><span class="re8">+ AppendSubHex<span class="br0">(</span>val&0xF, result<span class="br0">)</span>;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+static wxString ComputeMD5<span class="br0">(</span>const char *buf, unsigned int len<span class="br0">)</span></span><br /><span class="re8">+<span class="br0">{</span></span><br /><span class="re8">+ MD5_CTX ctx;</span><br /><span class="re8">+ unsigned char signature<span class="br0">[</span>16<span class="br0">]</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ MD5Init<span class="br0">(</span>&ctx<span class="br0">)</span>;</span><br /><span class="re8">+ MD5Update<span class="br0">(</span>&ctx, <span class="br0">(</span>const unsigned char*<span class="br0">)</span>buf, len<span class="br0">)</span>;</span><br /><span class="re8">+ MD5Final<span class="br0">(</span>signature, &ctx<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString result;</span><br /><span class="re8">+ for <span class="br0">(</span>int j = <span class="nu0">0</span>; j < <span class="br0">(</span>int<span class="br0">)</span>sizeof signature; j++<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ AppendHex<span class="br0">(</span>signature<span class="br0">[</span>j<span class="br0">]</span>, result<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ return result;</span><br /><span class="re8">+<span class="br0">}</span></span><br /><span class="re8">+</span><br /> static wxString base64encode<span class="br0">(</span>const wxString& str<span class="br0">)</span><br /> <span class="br0">{</span><br /> // Code shamelessly taken from wxWidgets and adopted to encode UTF-8 strings.<br /><span class="re6">@@ -<span class="nu0">96</span>,<span class="nu0">39</span> +<span class="nu0">136</span>,<span class="nu0">12</span> @@</span><br /> <span class="br0">{</span><br /> m_handshakeState = http_wait;<br /> <br /><span class="re7">-#if wxUSE_UNICODE</span><br /><span class="re7">- wxWX2MBbuf challenge;</span><br /><span class="re7">-#else</span><br /><span class="re7">- const wxWX2MBbuf challenge;</span><br /><span class="re7">-#endif</span><br /><span class="re7">- int challenge_len;</span><br /><span class="re7">- if <span class="br0">(</span>user != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re7">- <span class="br0">{</span></span><br /><span class="re7">- challenge = base64encode<span class="br0">(</span>user + _T<span class="br0">(</span>":"<span class="br0">)</span> + pass<span class="br0">)</span>.mb_str<span class="br0">(</span>wxConvUTF8<span class="br0">)</span>;</span><br /><span class="re7">- challenge_len = strlen<span class="br0">(</span>challenge<span class="br0">)</span>;</span><br /><span class="re7">- <span class="br0">}</span></span><br /><span class="re7">- else</span><br /><span class="re7">- <span class="br0">{</span></span><br /><span class="re7">- challenge = <span class="br0">(</span>size_t<span class="br0">)</span><span class="nu0">0</span>;</span><br /><span class="re7">- challenge_len = <span class="nu0">0</span>;</span><br /><span class="re7">- <span class="br0">}</span></span><br /><span class="re7">-</span><br /> // Bit oversized, but be on the safe side<br /><span class="re7">- m_pSendBuffer = new char<span class="br0">[</span>70 + strlen<span class="br0">(</span>host_raw<span class="br0">)</span> * 2 + 2*5 + challenge_len + 23<span class="br0">]</span>;</span><br /><span class="re8">+ m_pSendBuffer = new char<span class="br0">[</span>70 + strlen<span class="br0">(</span>host_raw<span class="br0">)</span> * 2 + 2*5 + 23<span class="br0">]</span>;</span><br /> <br /><span class="re7">- if <span class="br0">(</span>!challenge<span class="br0">)</span></span><br /><span class="re7">- <span class="br0">{</span></span><br /><span class="re7">- m_sendBufferLen = sprintf<span class="br0">(</span>m_pSendBuffer, "CONNECT %s:%u HTTP/<span class="nu0">1.1</span>\r\nHost: %s:%u\r\nUser-Agent: FileZilla\r\n\r\n",</span><br /><span class="re7">- <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, port,</span><br /><span class="re7">- <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, port<span class="br0">)</span>;</span><br /><span class="re7">- <span class="br0">}</span></span><br /><span class="re7">- else</span><br /><span class="re7">- <span class="br0">{</span></span><br /><span class="re7">- m_sendBufferLen = sprintf<span class="br0">(</span>m_pSendBuffer, "CONNECT %s:%u HTTP/<span class="nu0">1.1</span>\r\nHost: %s:%u\r\nProxy-Authorization: Basic %s\r\nUser-Agent: FileZilla\r\n\r\n",</span><br /><span class="re7">- <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, port,</span><br /><span class="re7">- <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, port,</span><br /><span class="re7">- <span class="br0">(</span>const char*<span class="br0">)</span>challenge<span class="br0">)</span>;</span><br /><span class="re7">- <span class="br0">}</span></span><br /><span class="re8">+ m_sendBufferLen = sprintf<span class="br0">(</span>m_pSendBuffer, "CONNECT %s:%u HTTP/<span class="nu0">1.1</span>\r\nHost: %s:%u\r\nUser-Agent: FileZilla\r\n\r\n",</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, port,</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, port<span class="br0">)</span>;</span><br /> <br /> m_pRecvBuffer = new char<span class="br0">[</span>4096<span class="br0">]</span>;<br /> m_recvBufferLen = <span class="nu0">4096</span>;<br /><span class="re6">@@ -<span class="nu0">302</span>,<span class="nu0">12</span> +<span class="nu0">315</span>,<span class="nu0">319</span> @@</span><br /> if <span class="br0">(</span>!end<span class="br0">)</span><br /> continue;<br /> <br /><span class="re8">+ unsigned long int nContentLength = <span class="nu0">0</span>;</span><br /><span class="re8">+ bool bUseBasic = false;</span><br /><span class="re8">+ bool bUseDigest = false;</span><br /><span class="re8">+ wxString digestStr = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ wxString authStr = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ wxString header_str<span class="br0">(</span>m_pRecvBuffer, wxConvLocal, m_recvBufferPos<span class="br0">)</span>;</span><br /><span class="re8">+ wxStringTokenizer tkz<span class="br0">(</span>header_str, wxT<span class="br0">(</span>"\r\n"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ while <span class="br0">(</span>tkz.HasMoreTokens<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ wxString token = tkz.GetNextToken<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>token.Mid<span class="br0">(</span><span class="nu0">0</span>, <span class="nu0">15</span><span class="br0">)</span>.Lower<span class="br0">(</span><span class="br0">)</span> == _T<span class="br0">(</span>"content-length:"<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ token.Mid<span class="br0">(</span>15<span class="br0">)</span>.Trim<span class="br0">(</span>true<span class="br0">)</span>.Trim<span class="br0">(</span>false<span class="br0">)</span>.ToULong<span class="br0">(</span>&nContentLength<span class="br0">)</span>;</span><br /><span class="re8">+ continue;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>token.Mid<span class="br0">(</span><span class="nu0">0</span>, <span class="nu0">26</span><span class="br0">)</span>.Lower<span class="br0">(</span><span class="br0">)</span> == _T<span class="br0">(</span>"proxy-authenticate: basic "<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ bUseBasic = true;</span><br /><span class="re8">+ continue;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>token.Mid<span class="br0">(</span><span class="nu0">0</span>, <span class="nu0">27</span><span class="br0">)</span>.Lower<span class="br0">(</span><span class="br0">)</span> == _T<span class="br0">(</span>"proxy-authenticate: digest "<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ authStr = token.Mid<span class="br0">(</span>27<span class="br0">)</span>;</span><br /><span class="re8">+ bUseDigest = true;</span><br /><span class="re8">+ continue;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ // read body</span><br /><span class="re8">+ unsigned long int nBodyLength = <span class="nu0">0</span>;</span><br /><span class="re8">+ char *pBody = new char<span class="br0">[</span>nContentLength<span class="br0">]</span>;</span><br /><span class="re8">+ while <span class="br0">(</span>nBodyLength < nContentLength<span class="br0">)</span> <span class="br0">{</span></span><br /><span class="re8">+ int read;</span><br /><span class="re8">+</span><br /><span class="re8">+ do_read = nContentLength - nBodyLength;</span><br /><span class="re8">+</span><br /><span class="re8">+ read = m_pSocket->Read<span class="br0">(</span>pBody + nBodyLength, do_read, error<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>read == -<span class="nu0">1</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>error != EAGAIN<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ m_proxyState = noconn;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::close, error<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else</span><br /><span class="re8">+ m_can_read = false;</span><br /><span class="re8">+ continue;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>!read<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ m_proxyState = noconn;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::close, ECONNABORTED<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>m_pSendBuffer<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ m_proxyState = noconn;</span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Debug_Warning, _T<span class="br0">(</span>"Incoming data before requst fully sent"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::close, ECONNABORTED<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ nBodyLength += read;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /> end = strchr<span class="br0">(</span>m_pRecvBuffer, '\r'<span class="br0">)</span>;<br /> wxASSERT<span class="br0">(</span>end<span class="br0">)</span>;<br /> *end = <span class="nu0">0</span>;<br /> wxString reply<span class="br0">(</span>m_pRecvBuffer, wxConvUTF8<span class="br0">)</span>;<br /> m_pOwner->LogMessage<span class="br0">(</span>Response, _<span class="br0">(</span>"Proxy reply: %s"<span class="br0">)</span>, reply.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br /> <br /><span class="re8">+ if <span class="br0">(</span>reply.Left<span class="br0">(</span>12<span class="br0">)</span> == _T<span class="br0">(</span>"HTTP/1.1 401"<span class="br0">)</span> || reply.Left<span class="br0">(</span>12<span class="br0">)</span> == _T<span class="br0">(</span>"HTTP/1.1 407"<span class="br0">)</span> ||</span><br /><span class="re8">+ reply.Left<span class="br0">(</span>12<span class="br0">)</span> == _T<span class="br0">(</span>"HTTP/1.0 401"<span class="br0">)</span> || reply.Left<span class="br0">(</span><span class="nu0">12</span><span class="br0">)</span> == _T<span class="br0">(</span>"HTTP/<span class="nu0">1.0</span> <span class="nu0">407</span>"<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ if <span class="br0">(</span>m_doAuth || m_user == _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Debug_Warning, _<span class="br0">(</span>"already m_doAuth <span class="br0">(</span>%d<span class="br0">)</span>, or m_user is empty <span class="br0">(</span>%s<span class="br0">)</span>"<span class="br0">)</span>, m_doAuth, m_user.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ m_proxyState = noconn;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::close, ECONNRESET<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ if <span class="br0">(</span>bUseDigest<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ wxString realm = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ wxString nonce = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ wxString qop = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ wxStringTokenizer tkz2<span class="br0">(</span>authStr, wxT<span class="br0">(</span>","<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ while <span class="br0">(</span>tkz2.HasMoreTokens<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ wxString token2 = tkz2.GetNextToken<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ wxString name = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ wxString value = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ wxStringTokenizer tkz3<span class="br0">(</span>token2, wxT<span class="br0">(</span>"="<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ while <span class="br0">(</span>tkz3.HasMoreTokens<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ wxString token3 = tkz3.GetNextToken<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>name == _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ name = token3.Lower<span class="br0">(</span><span class="br0">)</span>.Trim<span class="br0">(</span>true<span class="br0">)</span>.Trim<span class="br0">(</span>false<span class="br0">)</span>;</span><br /><span class="re8">+ continue;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>token3.Left<span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> == _T<span class="br0">(</span>"\""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ value = token3.Mid<span class="br0">(</span>1, token3.Len<span class="br0">(</span><span class="br0">)</span>-2<span class="br0">)</span>.Trim<span class="br0">(</span>true<span class="br0">)</span>.Trim<span class="br0">(</span>false<span class="br0">)</span>;</span><br /><span class="re8">+ else</span><br /><span class="re8">+ value = token3.Trim<span class="br0">(</span>true<span class="br0">)</span>.Trim<span class="br0">(</span>false<span class="br0">)</span>;</span><br /><span class="re8">+ break;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>name == _T<span class="br0">(</span>"realm"<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ realm = value;</span><br /><span class="re8">+ else if <span class="br0">(</span>name == _T<span class="br0">(</span>"nonce"<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ nonce = value;</span><br /><span class="re8">+ else if <span class="br0">(</span>name == _T<span class="br0">(</span>"qop"<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ qop = value;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ if <span class="br0">(</span>realm == _T<span class="br0">(</span>""<span class="br0">)</span> || nonce == _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Debug_Warning, _T<span class="br0">(</span>"no realm or nonce"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ m_proxyState = conn;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::connection, 0<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ // HA1 = md5<span class="br0">(</span>username:realm:password<span class="br0">)</span></span><br /><span class="re8">+ // if qop = auth or no qop</span><br /><span class="re8">+ // HA2 = md5<span class="br0">(</span>method:digestURI<span class="br0">)</span></span><br /><span class="re8">+ // if qop = auth-int</span><br /><span class="re8">+ // HA2 = md5<span class="br0">(</span>method:digestURI:md5<span class="br0">(</span>body<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ // if qop = auth or auth-int</span><br /><span class="re8">+ // response = md5<span class="br0">(</span>HA1:nonce:nonceCount:clientNonce:qop:HA2<span class="br0">)</span></span><br /><span class="re8">+ // if no qop</span><br /><span class="re8">+ // response = md5<span class="br0">(</span>HA1:nonce:HA2<span class="br0">)</span></span><br /><span class="re8">+ wxString ha1, ha2, response;</span><br /><span class="re8">+ wxString s;</span><br /><span class="re8">+ bool bAuth = false;</span><br /><span class="re8">+ bool bAuthInt = false;</span><br /><span class="re8">+</span><br /><span class="re8">+ if <span class="br0">(</span>qop != _T<span class="br0">(</span>""<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ wxStringTokenizer tkz4<span class="br0">(</span>qop, wxT<span class="br0">(</span>","<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ while <span class="br0">(</span>tkz4.HasMoreTokens<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ wxString token4 = tkz4.GetNextToken<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>token4 == _T<span class="br0">(</span>"auth"<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ bAuth = true;</span><br /><span class="re8">+ if <span class="br0">(</span>token4 == _T<span class="br0">(</span>"auth-int"<span class="br0">)</span><span class="br0">)</span></span><br /><span class="re8">+ bAuthInt = true;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ s = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"%s:%s:%s"<span class="br0">)</span>, m_user.c_str<span class="br0">(</span><span class="br0">)</span>, realm.c_str<span class="br0">(</span><span class="br0">)</span>, m_pass.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ const wxWX2MBbuf s_raw = s.mb_str<span class="br0">(</span>wxConvUTF8<span class="br0">)</span>;</span><br /><span class="re8">+ ha1 = ComputeMD5<span class="br0">(</span><span class="br0">(</span>const char *<span class="br0">)</span>s_raw, strlen<span class="br0">(</span>s_raw<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString uri = _T<span class="br0">(</span>""<span class="br0">)</span>;</span><br /><span class="re8">+ if <span class="br0">(</span>qop == _T<span class="br0">(</span>""<span class="br0">)</span> || bAuth<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ uri = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"%s:%u"<span class="br0">)</span>, m_host.c_str<span class="br0">(</span><span class="br0">)</span>, m_port<span class="br0">)</span>;</span><br /><span class="re8">+ s = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"CONNECT:%s"<span class="br0">)</span>, uri.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ const wxWX2MBbuf s_raw = s.mb_str<span class="br0">(</span>wxConvUTF8<span class="br0">)</span>;</span><br /><span class="re8">+ ha2 = ComputeMD5<span class="br0">(</span><span class="br0">(</span>const char *<span class="br0">)</span>s_raw, strlen<span class="br0">(</span>s_raw<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else if <span class="br0">(</span>bAuthInt<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ uri = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"%s:%u"<span class="br0">)</span>, m_host.c_str<span class="br0">(</span><span class="br0">)</span>, m_port<span class="br0">)</span>;</span><br /><span class="re8">+ wxString bodyMD5 = ComputeMD5<span class="br0">(</span><span class="br0">(</span>const char *<span class="br0">)</span>pBody, nBodyLength<span class="br0">)</span>;</span><br /><span class="re8">+ s = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"CONNECT:%s:%s"<span class="br0">)</span>, uri.c_str<span class="br0">(</span><span class="br0">)</span>, bodyMD5.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ const wxWX2MBbuf s_raw = s.mb_str<span class="br0">(</span>wxConvLocal<span class="br0">)</span>;</span><br /><span class="re8">+ ha2 = ComputeMD5<span class="br0">(</span><span class="br0">(</span>const char *<span class="br0">)</span>s_raw, strlen<span class="br0">(</span>s_raw<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else</span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Debug_Warning, _T<span class="br0">(</span>"unknown qop: %s"<span class="br0">)</span>, qop.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ m_proxyState = conn;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::connection, 0<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ // we don't need body now</span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ if <span class="br0">(</span>bAuth || bAuthInt<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ wxString clientNonce = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"%04x%04x"<span class="br0">)</span>, GetRandomNumber<span class="br0">(</span>0, 0xffff<span class="br0">)</span>, GetRandomNumber<span class="br0">(</span>0, 0xffff<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ s = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"%s:%s:%s:%s:%s:%s"<span class="br0">)</span>,</span><br /><span class="re8">+ ha1.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ nonce.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ _T<span class="br0">(</span>"00000001"<span class="br0">)</span>,</span><br /><span class="re8">+ clientNonce.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ bAuth ? _T<span class="br0">(</span>"auth"<span class="br0">)</span> : _T<span class="br0">(</span>"auth-int"<span class="br0">)</span>,</span><br /><span class="re8">+ ha2.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ const wxWX2MBbuf s_raw = s.mb_str<span class="br0">(</span>wxConvLocal<span class="br0">)</span>;</span><br /><span class="re8">+ response = ComputeMD5<span class="br0">(</span><span class="br0">(</span>const char *<span class="br0">)</span>s_raw, strlen<span class="br0">(</span>s_raw<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ digestStr = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\", qop=%s, nc=00000001, cnonce=\"%s\""<span class="br0">)</span>,</span><br /><span class="re8">+ m_user.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ realm.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ nonce.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ uri.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ response.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ bAuth ? _T<span class="br0">(</span>"auth"<span class="br0">)</span> : _T<span class="br0">(</span>"auth-int"<span class="br0">)</span>,</span><br /><span class="re8">+ clientNonce.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ else</span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ s = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"%s:%s:%s"<span class="br0">)</span>,</span><br /><span class="re8">+ ha1.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ nonce.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ ha2.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ const wxWX2MBbuf s_raw = s.mb_str<span class="br0">(</span>wxConvLocal<span class="br0">)</span>;</span><br /><span class="re8">+ response = ComputeMD5<span class="br0">(</span><span class="br0">(</span>const char *<span class="br0">)</span>s_raw, strlen<span class="br0">(</span>s_raw<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ digestStr = wxString::Format<span class="br0">(</span>_T<span class="br0">(</span>"Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\""<span class="br0">)</span>,</span><br /><span class="re8">+ m_user.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ realm.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ nonce.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ uri.c_str<span class="br0">(</span><span class="br0">)</span>,</span><br /><span class="re8">+ response.c_str<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ m_doAuth = true;</span><br /><span class="re8">+ m_recvBufferPos = <span class="nu0">0</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ const wxWX2MBbuf host_raw = m_host.mb_str<span class="br0">(</span>wxConvUTF8<span class="br0">)</span>;</span><br /><span class="re8">+ const wxWX2MBbuf digest_raw = digestStr.mb_str<span class="br0">(</span>wxConvLocal<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ int challenge_len = digestStr.Len<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Status, _<span class="br0">(</span>"Sending CONNECT with Digest Authorization"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ // Bit oversized, but be on the safe side</span><br /><span class="re8">+ m_pSendBuffer = new char<span class="br0">[</span>70 + m_host.Len<span class="br0">(</span><span class="br0">)</span> * 2 + 2*5 + challenge_len * 2 + 23 + 40<span class="br0">]</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ m_sendBufferLen = sprintf<span class="br0">(</span>m_pSendBuffer, "CONNECT %s:%u HTTP/<span class="nu0">1.1</span>\r\nHost: %s:%u\r\nProxy-Authorization: %s\r\nUser-Agent: FileZilla\r\n\r\n",</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, m_port,</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, m_port,</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>digest_raw<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString host = m_pSocket->GetPeerIP<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ unsigned int port = m_pSocket->GetRemotePort<span class="br0">(</span>error<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ m_pSocket->Close<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ int res = m_pSocket->Connect<span class="br0">(</span>host, port<span class="br0">)</span>;</span><br /><span class="re8">+ // Treat success same as EINPROGRESS, we wait for connect notification in any case</span><br /><span class="re8">+ if <span class="br0">(</span>res && res != EINPROGRESS<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Debug_Warning, _T<span class="br0">(</span>"connect error?"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ m_proxyState = conn;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::connection, 0<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+</span><br /><span class="re8">+ if <span class="br0">(</span>bUseBasic<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ // we don't need body for this</span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+ m_doAuth = true;</span><br /><span class="re8">+ m_recvBufferPos = <span class="nu0">0</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+#if wxUSE_UNICODE</span><br /><span class="re8">+ wxWX2MBbuf challenge;</span><br /><span class="re8">+#else</span><br /><span class="re8">+ const wxWX2MBbuf challenge;</span><br /><span class="re8">+#endif</span><br /><span class="re8">+ const wxWX2MBbuf host_raw = m_host.mb_str<span class="br0">(</span>wxConvUTF8<span class="br0">)</span>;</span><br /><span class="re8">+ int challenge_len;</span><br /><span class="re8">+</span><br /><span class="re8">+ challenge = base64encode<span class="br0">(</span>m_user + _T<span class="br0">(</span>":"<span class="br0">)</span> + m_pass<span class="br0">)</span>.mb_str<span class="br0">(</span>wxConvUTF8<span class="br0">)</span>;</span><br /><span class="re8">+ challenge_len = strlen<span class="br0">(</span>challenge<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Status, _<span class="br0">(</span>"Sending CONNECT with Basic Authorization"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ // Bit oversized, but be on the safe side</span><br /><span class="re8">+ m_pSendBuffer = new char<span class="br0">[</span>70 + strlen<span class="br0">(</span>host_raw<span class="br0">)</span> * 2 + 2*5 + challenge_len + 23<span class="br0">]</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ m_sendBufferLen = sprintf<span class="br0">(</span>m_pSendBuffer, "CONNECT %s:%u HTTP/<span class="nu0">1.1</span>\r\nHost: %s:%u\r\nProxy-Authorization: Basic %s\r\nUser-Agent: FileZilla\r\n\r\n",</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, m_port,</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>host_raw, m_port,</span><br /><span class="re8">+ <span class="br0">(</span>const char*<span class="br0">)</span>challenge<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ wxString host = m_pSocket->GetPeerIP<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ unsigned int port = m_pSocket->GetRemotePort<span class="br0">(</span>error<span class="br0">)</span>;</span><br /><span class="re8">+</span><br /><span class="re8">+ m_pSocket->Close<span class="br0">(</span><span class="br0">)</span>;</span><br /><span class="re8">+ int res = m_pSocket->Connect<span class="br0">(</span>host, port<span class="br0">)</span>;</span><br /><span class="re8">+ // Treat success same as EINPROGRESS, we wait for connect notification in any case</span><br /><span class="re8">+ if <span class="br0">(</span>res && res != EINPROGRESS<span class="br0">)</span></span><br /><span class="re8">+ <span class="br0">{</span></span><br /><span class="re8">+ m_pOwner->LogMessage<span class="br0">(</span>Debug_Warning, _T<span class="br0">(</span>"connect error?"<span class="br0">)</span><span class="br0">)</span>;</span><br /><span class="re8">+ m_proxyState = conn;</span><br /><span class="re8">+ CSocketEvent *evt = new CSocketEvent<span class="br0">(</span>m_pEvtHandler, this, CSocketEvent::connection, 0<span class="br0">)</span>;</span><br /><span class="re8">+ CSocketEventDispatcher::Get<span class="br0">(</span><span class="br0">)</span>.SendEvent<span class="br0">(</span>evt<span class="br0">)</span>;</span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ return;</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ // other authentication method?</span><br /><span class="re8">+ <span class="br0">}</span></span><br /><span class="re8">+ delete <span class="br0">[</span><span class="br0">]</span> pBody;</span><br /><span class="re8">+</span><br /> if <span class="br0">(</span>reply.Left<span class="br0">(</span>10<span class="br0">)</span> != _T<span class="br0">(</span>"HTTP/1.1 2"<span class="br0">)</span> && reply.Left<span class="br0">(</span>10<span class="br0">)</span> != _T<span class="br0">(</span>"HTTP/1.0 2"<span class="br0">)</span><span class="br0">)</span><br /> <span class="br0">{</span><br /> m_proxyState = noconn;<br />diff --strip-trailing-cr -Nur a/src/engine/proxy.h b/src/engine/proxy.h<br /><span class="re3">--- a/src/engine/proxy.h <span class="nu0">2013</span>-01-<span class="nu0">28</span> <span class="nu0">17</span>:04:<span class="nu0">35.657440800</span> +0800</span><br /><span class="re4">+++ b/src/engine/proxy.h <span class="nu0">2013</span>-01-<span class="nu0">28</span> <span class="nu0">17</span>:04:<span class="nu0">44.293190900</span> +0800</span><br /><span class="re6">@@ -<span class="nu0">65</span>,<span class="nu0">6</span> +<span class="nu0">65</span>,<span class="nu0">8</span> @@</span><br /> int m_recvBufferPos;<br /> int m_recvBufferLen;<br /> <br /><span class="re8">+ bool m_doAuth;</span><br /><span class="re8">+</span><br /> void OnSocketEvent<span class="br0">(</span>CSocketEvent& event<span class="br0">)</span>;<br /> void OnReceive<span class="br0">(</span><span class="br0">)</span>;<br /> void OnSend<span class="br0">(</span><span class="br0">)</span>;</pre></div></pre><p><a href="http://trac.filezilla-project.org/ticket/8452" target="_blank">這個 patch 也有送給作者</a>.... 所以我就先不放我自己編的檔案了, 有需要就自己編譯看看或等作者納入這個 patch 吧. (如果作者不接受, 就等下一版我再放入 <a href="https://sourceforge.net/projects/filezillapv/" target="_blank">filezillapv</a> 中吧)</p>
Patch
FTP
2013-01-28T17:10:34Z
tommy
-
patch for FileZilla 3.4.0 win64 version
https://blog.teatime.com.tw/1/post/368
<p>雖然 ftp client 這東西, 似乎沒什麼必要特地使用 64 位元的版本, 不過.... 還是弄了一個 <a href="http://filezilla-project.org/" target="_blank">FileZilla</a> win64 的版本來試看看.</p><p>patch 的部份, 可以到<a href="http://trac.filezilla-project.org/ticket/7271" target="_blank">這兒下載</a>, 如果有修正的 patch, 應該也會傳到那兒去. 不過最後作者接不接受這個 patch, 我就不清楚了.</p><p>而要製作出 win64 的版本, 主要有下列要注意的地方:</p><ul><li>c/c++ compiler: <a href="http://sourceforge.net/projects/mingw-w64/" target="_blank">mingw64</a> (建議用 <a href="http://tdm-gcc.tdragon.net/" target="_blank">TDM-GCC</a> 的版本)</li><li><a href="http://www.mingw.org/wiki/msys" target="_blank">msys</a> 的部份, 可以參考 <a href="http://wiki.filezilla-project.org/Compiling_FileZilla_3_under_Windows" target="_blank">filezilla 的 wiki</a> 說明, 注意不要安裝任何 -dev 相關的東西, 避免使用到 32 位元的函式庫.</li><li>參考<a href="http://forum.filezilla-project.org/viewtopic.php?f=3&t=1227" target="_blank">舊的 filezilla 編譯說明</a>, 自行建立 64 位元的 <a href="http://www.gnu.org/software/libtool/" target="_blank">libtool</a>, <a href="http://www.gnu.org/software/autoconf/" target="_blank">autoconf</a>, <a href="http://www.gnu.org/software/automake/" target="_blank">automake</a>, <a href="http://www.gnu.org/software/libiconv/" target="_blank">libiconv</a>, <a href="http://www.gnu.org/software/gettext/" target="_blank">gettext</a> (請抓新的版本, 不要抓那篇說明的那些舊版本). </li><li><a href="http://www.gnu.org/software/libgcrypt/" target="_blank">libgcrypt</a> 請加上 --disable-asm 來製作, 因為 asm 部份的程式碼在 win64 使用是有問題的, 會造成程式 crash (可能是 segment fault).</li><li>安裝 <a href="http://www.gnupg.org/related_software/libgpg-error/" target="_blank">libgpg-error</a> 時, 執行 iconv --silence 可能會有問題, 建議改成 iconv -s (<a href="http://blog.teatime.com.tw/1/post/365" target="_blank">參考這篇</a>).</li><li><a href="http://www.gnu.org/software/gnutls/" target="_blank">gnutls</a> 似乎在 mingw64 下, 有些變數似乎是會變成用 unsigned 的方式來定義, 所以在 handshake 時會一直讀不到東西. 上頭的 patch 其中一個就是修正這個問題. </li><li><a href="http://www.wxwidgets.org/" target="_blank">wxWidgets</a> 2.8 並沒有對 win64 做處理, 有些地方的型別轉換會造成編譯時出錯 (當然把 64 位元的指標轉成 32 位元的指標, 也許在執行時也會出問題). 所以上頭最主要的 patch 是在修正這個問題. </li><li>FileZilla 在 resouce 的部份, processorArchitecture 指定為 x86, 要改成 * 或 amd64 才能正常運作, 否則會在<a href="http://blog.teatime.com.tw/1/post/367" target="_blank">執行時出現 0x000007b 的錯誤</a>.</li></ul><p>如果你只需要執行檔, 可以到 <a href="http://sourceforge.net/projects/filezillapv/files/Patched%20FileZilla%20Client/" target="_blank">FileZillaPV</a> 去抓, 如果有更新, 我應該也會傳一份上去.</p><p>如果要與 FileZilla 的作者討論這個 win64 的修正... 可以到<a href="http://forum.filezilla-project.org/viewtopic.php?f=3&t=19968" target="_blank">這兒</a>看看.</p><p>如果是自行編譯.... 在 fzshellext 的部份會出錯, 請忽略吧, 依據作者之前的說法, 64 位元的 fzshellexe 目前只能用 msvc 來產生. 所以... 直接用作者原本做的版本就可以了. </p>
程式設計
Patch
FTP
2011-04-07T14:41:14Z
tommy
-
奇怪的 pure-ftpd 錯誤: (?@?) [ERROR] Sorry, invalid address given
https://blog.teatime.com.tw/1/post/351
<p>今天在辦公室要連回家裡的 ftp 抓些檔案時, 突然發現無法連線的錯誤, 在 FileZilla 會看到連線之後, 出現 425 Sorry, invalid address given 的訊息. 找了半天也查不出原因. 不過.... 奇怪的是, 另一台電腦連線回去又可以正常連線. 所以... 看起來不像是 server 的問題, 而是 client 的問題.</p><p>不過... 這台不能連的機器, 昨天還可以正常連線, 為什麼今天就不能用呢?</p><p>後來在 Google 看到了<a href="http://blog.obsidianproject.co.uk/2009/10/pure-ftpd-error-sorry-invalid-address.html" target="_blank">這篇文章</a>, 指出 pure-ftpd 在反解 client 的 IP 出錯時, 會出現這個訊息. 依照說明, 加上 -H 參數 (如果用 Debian 系列, 在 /etc/pure-ftpd/conf/DontResolve 加上 yes 就可以了) 之後, 果然可以正常的連線了.</p><p>PS. 我記得反查失敗應該還是可以正常使用才對, 畢竟另一台電腦也應該反查不會有任何結果, 而宿舍的 ADSL 也應該一樣, 不過都可以正常連線. 只有今天早上才碰到這問題.... 也許是今天上層的 DNS 有點問題造成的吧. </p>
FTP
2010-08-16T14:24:03Z
tommy
-
修正 Pure-ftpd 1.0.22 在使用 TLS 協定時, 下傳檔案續傳不正確的問題.
https://blog.teatime.com.tw/1/post/326
<p>一個多月之前, <a href="http://www.pureftpd.org/project/pure-ftpd/" target="_blank">Pure-ftpd</a> 推出了新的 1.0.22 版, 對我來說, 其中最重大的改變就是支援在 TLS/SSL 時也對傳送的資料加密. 所以... 我馬上就裝起來用了. 不過... 隔天確發現下載的檔案都有問題, 不過我試了幾個小檔案, 發現又很正常. 後來想到這兒的網路狀況有點不好, 或許是斷線後續傳造成的, 再測試一下, 果然經過續傳後, 檔案大小在傳送後就不一樣了.</p><p>改了一下, 寫了一些 log, 發現在使用 TLS/SSL 下傳檔案時, 是透過 mmap_send() 去處理, 而一般的情形是用 sendfile_send() 來處理. 而且在 sendfile_send() 裡頭, 是這樣處理續傳位置的:</p><pre class="c"><div class="insertcode"><span class="co2">#ifndef SENDFILE_NONE</span><br /><span class="kw4">int</span> sendfile_send<span class="br0">(</span><span class="kw4">int</span> f, <span class="kw4">struct</span> stat st, <span class="kw4">double</span> <span class="sy0">*</span>started<span class="br0">)</span><br /><span class="br0">{</span><br /> off_t left;<br /> off_t o;<br /><span class="co2"># ifdef THROTTLING</span><br /> <span class="kw4">double</span> ended;<br /> off_t transmitted <span class="sy0">=</span> <span class="nu0">0</span>;<br /><span class="co2"># endif</span><br /> <br /> o <span class="sy0">=</span> restartat;<br /> <span class="kw1">while</span> <span class="br0">(</span>o < st.<span class="me1">st_size</span><span class="br0">)</span> <span class="br0">{</span></div></pre><p>但是在 mmap_send() 中是:</p><pre class="c"><div class="insertcode"><span class="kw4">int</span> mmap_send<span class="br0">(</span><span class="kw4">int</span> f, <span class="kw4">struct</span> stat st, <span class="kw4">double</span> <span class="sy0">*</span>started<span class="br0">)</span><br /><span class="br0">{</span><br /> off_t s;<br /> off_t skip;<br /> off_t o;<br /> <span class="kw4">char</span> <span class="sy0">*</span>p, <span class="sy0">*</span>buf;<br /> off_t left;<br /><span class="co2"># ifdef THROTTLING</span><br /> <span class="kw4">double</span> ended;<br /> off_t transmitted <span class="sy0">=</span> <span class="nu0">0</span>;<br /><span class="co2"># endif</span><br /> <br /> o <span class="sy0">=</span> restartat <span class="sy0">&</span> ~<span class="br0">(</span>map_size <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">)</span>;<br /> skip <span class="sy0">=</span> restartat <span class="sy0">-</span> o;<br /> <span class="kw1">while</span> <span class="br0">(</span>o < st.<span class="me1">st_size</span><span class="br0">)</span> <span class="br0">{</span></div></pre><p>至少在我家的 Debian 伺服器上頭, 上頭的運作是不正常的. 所以我就改了一下:</p><pre class="c"><div class="insertcode"><span class="kw4">int</span> mmap_send<span class="br0">(</span><span class="kw4">int</span> f, <span class="kw4">struct</span> stat st, <span class="kw4">double</span> <span class="sy0">*</span>started<span class="br0">)</span><br /><span class="br0">{</span><br /> off_t s;<br /> off_t skip;<br /> off_t o;<br /> <span class="kw4">char</span> <span class="sy0">*</span>p, <span class="sy0">*</span>buf;<br /> off_t left;<br /><span class="co2"># ifdef THROTTLING</span><br /> <span class="kw4">double</span> ended;<br /> off_t transmitted <span class="sy0">=</span> <span class="nu0">0</span>;<br /><span class="co2"># endif</span><br /> <br /><span class="co1">// twu2 20090523 begin</span><br /><span class="co1">// why change the restart pos?</span><br /><span class="co1">// o = restartat & ~(map_size - 1);</span><br /> o <span class="sy0">=</span> restartat;<br /><span class="co1">// twu2 20090523 end</span><br /> skip <span class="sy0">=</span> restartat <span class="sy0">-</span> o;</div></pre><p>直接就使用 restartat 的值, 這樣子處理之後, 至少在 Debian 裡頭是正常的.</p><p>這個 patch 的內容如下:</p><pre class="diff"><div class="insertcode">diff -Nur src.orig/ftpd.c src/ftpd.c<br /><span class="re3">--- src.orig/ftpd.c <span class="nu0">2009</span><span class="nu0">-04</span><span class="nu0">-26</span> <span class="nu0">19</span>:<span class="nu0">34</span>:<span class="nu0">04.000000000</span> <span class="nu0">+0800</span></span><br /><span class="re4">+++ src/ftpd.c <span class="nu0">2009</span><span class="nu0">-06</span><span class="nu0">-04</span> <span class="nu0">18</span>:<span class="nu0">55</span>:<span class="nu0">25.024105416</span> <span class="nu0">+0800</span></span><br /><span class="re6">@@ <span class="nu0">-3106</span>,<span class="nu0">7</span> <span class="nu0">+3106</span>,<span class="nu0">11</span> @@</span><br /> off_t transmitted = <span class="nu0">0</span>;<br /> # endif<br /> <br /><span class="re7">- o = restartat & ~<span class="br0">(</span>map_size - <span class="nu0">1</span><span class="br0">)</span>;</span><br /><span class="re8">+// twu2 <span class="nu0">20090523</span> begin</span><br /><span class="re8">+// why change the restart pos?</span><br /><span class="re8">+// o = restartat & ~<span class="br0">(</span>map_size - <span class="nu0">1</span><span class="br0">)</span>;</span><br /><span class="re8">+ o = restartat;</span><br /><span class="re8">+// twu2 <span class="nu0">20090523</span> end</span><br /> skip = restartat - o;<br /> while <span class="br0">(</span>o < st.st_size<span class="br0">)</span> <span class="br0">{</span><br /> # ifdef FTPWHO</div></pre><p>檔案可以在這兒抓: <a href="http://www.teatime.com.tw/~tommy/mypatch/pureftpd_1.0.22_tls_resume.patch" target="_blank">http://www.teatime.com.tw/~tommy/mypatch/pureftpd_1.0.22_tls_resume.patch</a> </p><p>有需要的可能要自行修改. 這個 patch 我也有送給作者.... 不過也許是我的英文太破了, 就如同之前送的 patch 一樣, 都沒有後續的消息, 看起來似乎也不會進到官方的程式中, 至少目前的 snapshot 版本還沒包含這個修正. </p>
Patch
FTP
2009-06-04T19:13:32Z
tommy
-
FileZilla 3.0.4 keepalive 功能
https://blog.teatime.com.tw/1/post/276
<p>在 <a href="http://filezilla-project.org/" target="_blank">FileZilla</a> 3.0.4 版中, 作者終於加上了 KeepAlive 的功能了. 原本以為, 我另外加上的那個 keepalive patch 就用不到了. 不過... 用了兩天後, 發現... 目前這個版本的 keepalive 還是有些問題.</p><p>首先是由於使用的指令的關係, 在 pure-ftpd 中, 仍然會照成斷線. 這個問題比較容易解決, 只要多加一個 STAT 指令, 就可以避免 pure-ftpd 的逾時設計了. 修正如下:</p><pre class="c"><div class="insertcode">diff -Nur filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>.<span class="me1">orig</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span><br />--- filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>.<span class="me1">orig</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> Tue Nov <span class="nu0">27</span> <span class="nu0">04</span>:<span class="nu0">42</span>:<span class="nu0">56</span> <span class="nu0">2007</span><br />+++ filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> Tue Nov <span class="nu0">27</span> <span class="nu0">20</span>:<span class="nu0">42</span>:<span class="nu0">42</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-4175</span>,<span class="nu0">7</span> <span class="nu0">+4175</span>,<span class="nu0">7</span> @@<br /> LogMessage<span class="br0">(</span>Status, _<span class="br0">(</span><span class="st0">"Sending keep-alive command"</span><span class="br0">)</span><span class="br0">)</span>;<br /> <br /> wxString cmd;<br />- <span class="kw4">int</span> i = rand<span class="br0">(</span><span class="br0">)</span> * <span class="nu0">3</span> / <span class="br0">(</span>RAND_MAX + <span class="nu0">1</span><span class="br0">)</span>;<br />+ <span class="kw4">int</span> i = rand<span class="br0">(</span><span class="br0">)</span> * <span class="nu0">4</span> / <span class="br0">(</span>RAND_MAX + <span class="nu0">1</span><span class="br0">)</span>;<br /> <span class="kw1">if</span> <span class="br0">(</span>!i<span class="br0">)</span><br /> cmd = _T<span class="br0">(</span><span class="st0">"NOOP"</span><span class="br0">)</span>;<br /> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">(</span>i == <span class="nu0">1</span><span class="br0">)</span><br />@@ <span class="nu0">-4185</span>,<span class="nu0">6</span> <span class="nu0">+4185</span>,<span class="nu0">8</span> @@<br /> <span class="kw1">else</span><br /> cmd = _T<span class="br0">(</span><span class="st0">"TYPE A"</span><span class="br0">)</span>;<br /> <span class="br0">}</span><br />+ <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">(</span>i == <span class="nu0">2</span><span class="br0">)</span><br />+ cmd = _T<span class="br0">(</span><span class="st0">"STAT"</span><span class="br0">)</span>;<br /> <span class="kw1">else</span><br /> cmd = _T<span class="br0">(</span><span class="st0">"PWD"</span><span class="br0">)</span>;</div></pre><p>Patch 可以由這兒抓取: <a href="http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.4_keepalive_for_pureftpd.patch" target="_blank">http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.4_keepalive_for_pureftpd.patch</a> </p><p>不過, 在加上上頭的 patch 之後, 還是發現有逾時的情形, 因為不好查, 所以, 就在顯示的訊息上頭, 先加上時間, 方便於除錯. 修正如下:</p><pre class="php"><div class="insertcode">diff -Nur filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>.orig/src/<span class="kw2">interface</span>/StatusView.cpp filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>/src/<span class="kw2">interface</span>/StatusView.cpp<br />--- filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>.orig/src/<span class="kw2">interface</span>/StatusView.cpp Tue Nov <span class="nu0">27</span> <span class="nu0">04</span>:<span class="nu0">42</span>:<span class="nu0">56</span> <span class="nu0">2007</span><br />+++ filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>/src/<span class="kw2">interface</span>/StatusView.cpp Thu Nov <span class="nu0">29</span> <span class="nu0">11</span>:<span class="nu0">10</span>:<span class="nu0">40</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-151</span>,<span class="nu0">6</span> <span class="nu0">+151</span>,<span class="nu0">9</span> @@<br /> <br /> m_pTextCtrl-><span class="me1">SetDefaultStyle</span><span class="br0">(</span>m_attributeCache<span class="br0">[</span>messagetype<span class="br0">]</span>.attr<span class="br0">)</span>;<br /> <br />+ wxDateTime now = wxDateTime::<span class="me2">Now</span><span class="br0">(</span><span class="br0">)</span>;<br />+ prefix += now.FormatISOTime<span class="br0">(</span><span class="br0">)</span>;<br />+ prefix += _T<span class="br0">(</span><span class="st0">" "</span><span class="br0">)</span>;<br /> prefix += m_attributeCache<span class="br0">[</span>messagetype<span class="br0">]</span>.prefix;<br /> <br /> int lineLength = m_attributeCache<span class="br0">[</span>messagetype<span class="br0">]</span>.len + message.Length<span class="br0">(</span><span class="br0">)</span>;</div></pre><p>Patch 可以由這兒抓取: <a href="http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.4_add_time_to_message.patch" target="_blank">http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.4_add_time_to_message.patch</a></p><p>經過上頭的修正之後, 發現系統在經過 30 分鐘的閒置後, 就停止送出 keepalive 的指令. 看一下程式碼, 果然有個檢查 30 分鐘的地方, 不知道是作者故意的設計, 還是 bug? 到 SourceForge submit 給作者, 看是否是真要如此設計. 在得到答案之前, 當然只好自己弄個 patch 來用. 修正如下:</p><pre class="c"><div class="insertcode">diff -Nur filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>.<span class="me1">orig</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span><br />--- filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>.<span class="me1">orig</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> Tue Nov <span class="nu0">27</span> <span class="nu0">04</span>:<span class="nu0">42</span>:<span class="nu0">56</span> <span class="nu0">2007</span><br />+++ filezilla<span class="nu0">-3.0</span><span class="nu0">.4</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> Thu Nov <span class="nu0">29</span> <span class="nu0">12</span>:<span class="nu0">33</span>:<span class="nu0">40</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-4204</span>,<span class="nu0">9</span> <span class="nu0">+4204</span>,<span class="nu0">11</span> @@<br /> <span class="kw1">if</span> <span class="br0">(</span>!m_lastCommandCompletionTime.<span class="me1">IsValid</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /> <span class="kw1">return</span>;<br /> <br />+<span class="coMULTI">/*<br /> wxTimeSpan span = wxDateTime::Now() - m_lastCommandCompletionTime;<br /> if (span.GetSeconds() >= (60 * 30))<br /> return;<br />+*/</span><br /> <br /> m_idleTimer.<span class="me1">Start</span><span class="br0">(</span><span class="nu0">30000</span>, <span class="kw2">true</span><span class="br0">)</span>;<br /> <span class="br0">}</span></div></pre><p>Patch 可以由這兒抓取: <a href="http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.4_keepalive_after_30_minutes.patch" target="_blank">http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.4_keepalive_after_30_minutes.patch</a></p><p>經過上頭的處理之後, 目前看起來運作就正常了. </p><p>如果需要 patch 過的執行檔, 請到 <a href="http://sourceforge.net/projects/filezillapv/" target="_blank">FileZillaPV</a> 專案去下載吧. </p><hr width="100%" size="2" />2007/11/30: <p>作者表示, 30 分鐘的限制是故意的設計. 所以... 如果有這種一直連線的需求, 就自己 patch 吧. </p><p> </p>
Patch
FTP
2007-11-29T13:10:50Z
tommy
-
FileZilla 3.0.3 patch for invalid hostname delay problem
https://blog.teatime.com.tw/1/post/270
<p>由於前一陣子宿舍的 ADSL 十分的不穩定, 每隔幾分鐘就會斷線一次, 就發現在 <a href="http://filezilla.sourceforge.net/" target="_blank">FileZilla</a> 3 傳檔的時候, 會因為斷線之後, 無法正確解析出 IP 時, 會馬上再次嘗試連線, 結果在不到一分鐘的時間內, 就達到 FileZilla3 允許設定的 99 次, 然後就會把該檔案放到失敗的 queue 當中, 不會再傳送了. 如果這時不小心把程式關了, 該檔案就消失在 queue 裡頭了.</p><p>不過, 自從九月的時候, 反應<a href="http://sourceforge.net/tracker/index.php?func=detail&aid=1795505&group_id=21558&atid=887596" target="_blank">這個問題</a>到現在, 仍然沒有解決. 在昨天 3.0.3 推出後, 就順便處理一下, 看起來似乎是可以正常使用.</p><p>這個修正如下:</p><pre class="cpp"><div class="insertcode">diff -Nur Filezilla3/src/engine/engineprivate.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/engine/engineprivate.<span class="me1">cpp</span><br />--- Filezilla3/src/engine/engineprivate.<span class="me1">cpp</span> Thu Nov <span class="nu0">8</span> <span class="nu0">15</span>:<span class="nu0">55</span>:<span class="nu0">07</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/engine/engineprivate.<span class="me1">cpp</span> Thu Nov <span class="nu0">8</span> <span class="nu0">15</span>:<span class="nu0">56</span>:<span class="nu0">54</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-219</span>,<span class="nu0">8</span> <span class="nu0">+219</span>,<span class="nu0">11</span> @@<br /> <br /> <span class="kw1">if</span> <span class="br0">(</span>m_pCurrentCommand->GetId<span class="br0">(</span><span class="br0">)</span> == cmd_connect<span class="br0">)</span><br /> <span class="br0">{</span><br />- <span class="kw1">if</span> <span class="br0">(</span>!<span class="br0">(</span>nErrorCode & ~<span class="br0">(</span>FZ_REPLY_ERROR | FZ_REPLY_DISCONNECTED | FZ_REPLY_TIMEOUT<span class="br0">)</span><span class="br0">)</span> && <br />- nErrorCode & <span class="br0">(</span>FZ_REPLY_ERROR | FZ_REPLY_DISCONNECTED<span class="br0">)</span> &&<br />+ <span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span><span class="br0">(</span>!m_pEventHandler->IsKindOf<span class="br0">(</span>CLASSINFO<span class="br0">(</span>wxFrame<span class="br0">)</span><span class="br0">)</span> &&<br />+ !<span class="br0">(</span>nErrorCode & ~<span class="br0">(</span>FZ_REPLY_ERROR | FZ_REPLY_DISCONNECTED | FZ_REPLY_TIMEOUT | FZ_REPLY_CRITICALERROR<span class="br0">)</span><span class="br0">)</span> &&<br />+ nErrorCode & <span class="br0">(</span>FZ_REPLY_ERROR | FZ_REPLY_DISCONNECTED | FZ_REPLY_CRITICALERROR<span class="br0">)</span><span class="br0">)</span> ||<br />+ <span class="br0">(</span>!<span class="br0">(</span>nErrorCode & ~<span class="br0">(</span>FZ_REPLY_ERROR | FZ_REPLY_DISCONNECTED | FZ_REPLY_TIMEOUT<span class="br0">)</span><span class="br0">)</span> && <br />+ nErrorCode & <span class="br0">(</span>FZ_REPLY_ERROR | FZ_REPLY_DISCONNECTED<span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> &&<br /> m_retryCount < m_pOptions->GetOptionVal<span class="br0">(</span>OPTION_RECONNECTCOUNT<span class="br0">)</span><span class="br0">)</span><br /> <span class="br0">{</span><br /> m_retryCount++;</div></pre><p>Patch 可以由這兒抓取: <a href="http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.3_delay_for_invalid_hostname.patch" target="_blank">http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.0.3_delay_for_invalid_hostname.patch</a></p><p>至於使用這個 patch 的執行檔, 請到 <a href="http://sourceforge.net/projects/filezillapv/" target="_blank">FileZillaPV</a> 去抓吧. </p>
Patch
FTP
2007-11-08T16:26:11Z
tommy
-
KeepAlive patch (version 3) for FileZilla 3.0.1
https://blog.teatime.com.tw/1/post/266
<p>修改之前的版本, 加上 QuickConnect 的處理.</p><p>修正如下:</p><pre class="cpp"><div class="insertcode">diff -Nur Filezilla3/src/engine/ControlSocket.<span class="me1">h</span> Filezilla3.<span class="me1">patch</span>/src/engine/ControlSocket.<span class="me1">h</span><br />--- Filezilla3/src/engine/ControlSocket.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">20</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/engine/ControlSocket.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-115</span>,<span class="nu0">6</span> <span class="nu0">+115</span>,<span class="nu0">8</span> @@<br /> <span class="kw2">virtual</span> <span class="kw4">int</span> Chmod<span class="br0">(</span><span class="kw4">const</span> CChmodCommand& command<span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> FZ_REPLY_NOTSUPPORTED; <span class="br0">}</span><br /> <span class="kw2">virtual</span> <span class="kw4">bool</span> Connected<span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span> = <span class="nu0">0</span>;<br /> <br />+ <span class="kw2">virtual</span> <span class="kw4">int</span> KeepAlive<span class="br0">(</span><span class="kw4">const</span> CKeepAliveCommand& command<span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> FZ_REPLY_OK; <span class="br0">}</span><br />+<br /> <span class="co1">// If m_pCurrentOpData is zero, this function returns the current command</span><br /> <span class="co1">// from the engine.</span><br /> <span class="kw2">enum</span> Command GetCurrentCommandId<span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span>;<br />diff -Nur Filezilla3/src/engine/FileZillaEngine.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/engine/FileZillaEngine.<span class="me1">cpp</span><br />--- Filezilla3/src/engine/FileZillaEngine.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">20</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/engine/FileZillaEngine.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-70</span>,<span class="nu0">6</span> <span class="nu0">+70</span>,<span class="nu0">9</span> @@<br /> <span class="kw1">case</span> cmd_chmod:<br /> res = Chmod<span class="br0">(</span>reinterpret_cast<const CChmodCommand&><span class="br0">(</span>command<span class="br0">)</span><span class="br0">)</span>;<br /> <span class="kw2">break</span>;<br />+ <span class="kw1">case</span> cmd_keepalive:<br />+ res = KeepAlive<span class="br0">(</span>reinterpret_cast<const CKeepAliveCommand &><span class="br0">(</span>command<span class="br0">)</span><span class="br0">)</span>;<br />+ <span class="kw2">break</span>;<br /> <span class="kw1">default</span>:<br /> <span class="kw1">return</span> FZ_REPLY_SYNTAXERROR;<br /> <span class="br0">}</span><br />diff -Nur Filezilla3/src/engine/commands.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/engine/commands.<span class="me1">cpp</span><br />--- Filezilla3/src/engine/commands.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">20</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/engine/commands.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-10</span>,<span class="nu0">6</span> <span class="nu0">+10</span>,<span class="nu0">16</span> @@<br /> <span class="kw1">return</span> m_Server;<br /> <span class="br0">}</span><br /> <br />+CKeepAliveCommand::<span class="me2">CKeepAliveCommand</span><span class="br0">(</span><span class="kw4">bool</span> keepAlive <span class="coMULTI">/*=true*/</span><span class="br0">)</span><br />+ : m_keepAlive<span class="br0">(</span>keepAlive<span class="br0">)</span><br />+<span class="br0">{</span><br />+<span class="br0">}</span><br />+<br />+<span class="kw4">bool</span> CKeepAliveCommand::<span class="me2">IsKeepAlive</span><span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span><br />+<span class="br0">{</span><br />+ <span class="kw1">return</span> m_keepAlive;<br />+<span class="br0">}</span><br />+<br /> CListCommand::<span class="me2">CListCommand</span><span class="br0">(</span><span class="kw4">bool</span> refresh <span class="coMULTI">/*=false*/</span><span class="br0">)</span><br /> : m_refresh<span class="br0">(</span>refresh<span class="br0">)</span><br /> <span class="br0">{</span><br />diff -Nur Filezilla3/src/engine/engineprivate.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/engine/engineprivate.<span class="me1">cpp</span><br />--- Filezilla3/src/engine/engineprivate.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">20</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/engine/engineprivate.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-525</span>,<span class="nu0">6</span> <span class="nu0">+525</span>,<span class="nu0">12</span> @@<br /> <span class="kw1">return</span> m_pControlSocket->Chmod<span class="br0">(</span>command<span class="br0">)</span>;<br /> <span class="br0">}</span><br /> <br />+<span class="kw4">int</span> CFileZillaEnginePrivate::<span class="me2">KeepAlive</span><span class="br0">(</span><span class="kw4">const</span> CKeepAliveCommand& command<span class="br0">)</span><br />+<span class="br0">{</span><br />+ m_pCurrentCommand = command.<span class="me1">Clone</span><span class="br0">(</span><span class="br0">)</span>;<br />+ <span class="kw1">return</span> m_pControlSocket->KeepAlive<span class="br0">(</span>command<span class="br0">)</span>;<br />+<span class="br0">}</span><br />+<br /> <span class="kw4">void</span> CFileZillaEnginePrivate::<span class="me2">SendDirectoryListingNotification</span><span class="br0">(</span><span class="kw4">const</span> CServerPath& path, <span class="kw4">bool</span> onList, <span class="kw4">bool</span> modified, <span class="kw4">bool</span> failed<span class="br0">)</span><br /> <span class="br0">{</span><br /> wxASSERT<span class="br0">(</span>m_pControlSocket<span class="br0">)</span>;<br />diff -Nur Filezilla3/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span><br />--- Filezilla3/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">20</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/engine/ftpcontrolsocket.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-24</span>,<span class="nu0">8</span> <span class="nu0">+24</span>,<span class="nu0">11</span> @@<br /> <span class="co2">#define LOGON_CUSTOMCOMMANDS 10</span><br /> <span class="co2">#define LOGON_DONE 11</span><br /> <br />+<span class="co2">#define KEEPALIVE_TIMER_ID wxID_HIGHEST + 5</span><br />+<br /> BEGIN_EVENT_TABLE<span class="br0">(</span>CFtpControlSocket, CRealControlSocket<span class="br0">)</span><br /> EVT_FZ_EXTERNALIPRESOLVE<span class="br0">(</span>wxID_ANY, CFtpControlSocket::<span class="me2">OnExternalIPAddress</span><span class="br0">)</span><br />+EVT_TIMER<span class="br0">(</span>wxID_ANY, CFtpControlSocket::<span class="me2">OnTimer</span><span class="br0">)</span><br /> END_EVENT_TABLE<span class="br0">(</span><span class="br0">)</span>;<br /> <br /> CRawTransferOpData::<span class="me2">CRawTransferOpData</span><span class="br0">(</span><span class="br0">)</span><br />@@ <span class="nu0">-137</span>,<span class="nu0">6</span> <span class="nu0">+140</span>,<span class="nu0">8</span> @@<br /> m_pTlsSocket = <span class="nu0">0</span>;<br /> m_protectDataChannel = <span class="kw2">false</span>;<br /> m_lastTypeBinary = <span class="nu0">-1</span>;<br />+ m_bEnableKeepAlive = <span class="kw2">false</span>;<br />+ m_keepAliveTimer.<span class="me1">SetOwner</span><span class="br0">(</span><span class="kw3">this</span>, KEEPALIVE_TIMER_ID<span class="br0">)</span>;<br /> <span class="br0">}</span><br /> <br /> CFtpControlSocket::~CFtpControlSocket<span class="br0">(</span><span class="br0">)</span><br />@@ <span class="nu0">-147</span>,<span class="nu0">12</span> <span class="nu0">+152</span>,<span class="nu0">16</span> @@<br /> <span class="br0">{</span><br /> LogMessage<span class="br0">(</span>Debug_Verbose, _T<span class="br0">(</span><span class="st0">"CFtpControlSocket::OnReceive()"</span><span class="br0">)</span><span class="br0">)</span>;<br /> <br />+ m_keepAliveStopWatch.<span class="me1">Start</span><span class="br0">(</span><span class="br0">)</span>;<br />+<br /> m_pBackend->Read<span class="br0">(</span>m_receiveBuffer + m_bufferLen, RECVBUFFERSIZE - m_bufferLen<span class="br0">)</span>;<br />- <br />+<br /> <span class="kw1">if</span> <span class="br0">(</span>m_pBackend->Error<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br /> <span class="br0">{</span><br /> <span class="kw1">if</span> <span class="br0">(</span>m_pBackend->LastError<span class="br0">(</span><span class="br0">)</span> != wxSOCKET_WOULDBLOCK<span class="br0">)</span><br /> <span class="br0">{</span><br />+ m_bEnableKeepAlive = <span class="kw2">false</span>;<br />+ m_keepAliveTimer.<span class="me1">Stop</span><span class="br0">(</span><span class="br0">)</span>;<br /> LogMessage<span class="br0">(</span>::<span class="me2">Error</span>, _<span class="br0">(</span><span class="st0">"Disconnected from server"</span><span class="br0">)</span><span class="br0">)</span>;<br /> DoClose<span class="br0">(</span><span class="br0">)</span>;<br /> <span class="br0">}</span><br />@@ <span class="nu0">-344</span>,<span class="nu0">6</span> <span class="nu0">+353</span>,<span class="nu0">7</span> @@<br /> <br /> <span class="kw1">if</span> <span class="br0">(</span>m_repliesToSkip<span class="br0">)</span><br /> <span class="br0">{</span><br />+ SetWait<span class="br0">(</span><span class="kw2">false</span><span class="br0">)</span>;<br /> LogMessage<span class="br0">(</span>Debug_Info, _T<span class="br0">(</span><span class="st0">"Skipping reply after cancelled operation."</span><span class="br0">)</span><span class="br0">)</span>;<br /> <span class="kw1">if</span> <span class="br0">(</span>m_Response<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span> != <span class="st0">'1'</span><span class="br0">)</span><br /> m_repliesToSkip--;<br />@@ <span class="nu0">-798</span>,<span class="nu0">6</span> <span class="nu0">+808</span>,<span class="nu0">7</span> @@<br /> LogMessage<span class="br0">(</span>::<span class="me2">Error</span>, _T<span class="br0">(</span><span class="st0">"Failed to convert command to 8 bit charset"</span><span class="br0">)</span><span class="br0">)</span>;<br /> <span class="kw1">return</span> <span class="kw2">false</span>;<br /> <span class="br0">}</span><br />+ m_keepAliveStopWatch.<span class="me1">Start</span><span class="br0">(</span><span class="br0">)</span>;<br /> <span class="kw4">unsigned</span> <span class="kw4">int</span> len = <span class="br0">(</span><span class="kw4">unsigned</span> <span class="kw4">int</span><span class="br0">)</span><span class="kw3">strlen</span><span class="br0">(</span>buffer<span class="br0">)</span>;<br /> <span class="kw4">bool</span> res = CRealControlSocket::<span class="me2">Send</span><span class="br0">(</span>buffer, len<span class="br0">)</span>;<br /> <span class="kw1">if</span> <span class="br0">(</span>res<span class="br0">)</span><br />@@ <span class="nu0">-3006</span>,<span class="nu0">6</span> <span class="nu0">+3017</span>,<span class="nu0">75</span> @@<br /> <span class="br0">}</span><br /> <br /> <span class="kw1">return</span> FZ_REPLY_WOULDBLOCK;<br />+<span class="br0">}</span><br />+<br />+<span class="kw4">int</span> CFtpControlSocket::<span class="me2">KeepAlive</span><span class="br0">(</span><span class="kw4">const</span> CKeepAliveCommand& command<span class="br0">)</span><br />+<span class="br0">{</span><br />+ LogMessage<span class="br0">(</span>Debug_Verbose, _T<span class="br0">(</span><span class="st0">"CFtpControlSocket::KeepAlive"</span><span class="br0">)</span><span class="br0">)</span>;<br />+<br />+ <span class="kw1">if</span> <span class="br0">(</span>command.<span class="me1">IsKeepAlive</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br />+ <span class="br0">{</span><br />+ <span class="kw1">if</span> <span class="br0">(</span>!m_bEnableKeepAlive<span class="br0">)</span><br />+ <span class="br0">{</span><br />+ m_bEnableKeepAlive = <span class="kw2">true</span>;<br />+ <span class="co1">// FIXME:</span><br />+ <span class="co1">// read keepalive option here</span><br />+ <span class="kw4">int</span> min_wait = <span class="nu0">30</span>;<br />+ <span class="kw4">int</span> max_wait = <span class="nu0">60</span>;<br />+ <span class="kw4">int</span> waitsecond = min_wait + <span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span><span class="br0">(</span><span class="kw3">rand</span><span class="br0">(</span><span class="br0">)</span>*<span class="br0">(</span>max_wait - min_wait<span class="br0">)</span>/<span class="br0">(</span>RAND_MAX<span class="nu0">+1</span><span class="br0">)</span><span class="br0">)</span>;<br />+ m_keepAliveTimer.<span class="me1">Start</span><span class="br0">(</span>waitsecond * <span class="nu0">1000</span><span class="br0">)</span>;<br />+ <span class="br0">}</span><br />+ <span class="br0">}</span><br />+ <span class="kw1">else</span><br />+ <span class="br0">{</span><br />+ <span class="kw1">if</span> <span class="br0">(</span>m_bEnableKeepAlive<span class="br0">)</span><br />+ <span class="br0">{</span><br />+ m_bEnableKeepAlive = <span class="kw2">false</span>;<br />+ m_keepAliveTimer.<span class="me1">Stop</span><span class="br0">(</span><span class="br0">)</span>;<br />+ <span class="br0">}</span><br />+ <span class="br0">}</span><br />+<br />+ m_bEnableKeepAlive = <span class="kw2">true</span>;<br />+ <span class="kw1">return</span> FZ_REPLY_OK;<br />+<span class="br0">}</span><br />+<br />+<span class="kw4">void</span> CFtpControlSocket::<span class="me2">DoKeepAlive</span><span class="br0">(</span><span class="br0">)</span><br />+<span class="br0">{</span><br />+ LogMessage<span class="br0">(</span>Debug_Verbose, _T<span class="br0">(</span><span class="st0">"CFtpControlSocket::DoKeepAlive"</span><span class="br0">)</span><span class="br0">)</span>;<br />+<br />+ <span class="co1">// ignore keepalive for last I/O for socket less than 15 seconds</span><br />+ <span class="kw1">if</span> <span class="br0">(</span>m_keepAliveStopWatch.<span class="kw3">Time</span><span class="br0">(</span><span class="br0">)</span> < <span class="nu0">15000</span><span class="br0">)</span><br />+ <span class="kw1">return</span>;<br />+ <span class="co1">// choose any command</span><br />+ wxString commands<span class="br0">[</span><span class="nu0">4</span><span class="br0">]</span> = <span class="br0">{</span>_T<span class="br0">(</span><span class="st0">"PWD"</span><span class="br0">)</span>,_T<span class="br0">(</span><span class="st0">"REST 0"</span><span class="br0">)</span>, _T<span class="br0">(</span><span class="st0">"NOOP"</span><span class="br0">)</span>, _T<span class="br0">(</span><span class="st0">"STAT"</span><span class="br0">)</span> <span class="br0">}</span>;<br />+ <span class="kw4">int</span> choice=<span class="br0">(</span><span class="kw3">rand</span><span class="br0">(</span><span class="br0">)</span>*<span class="nu0">4</span><span class="br0">)</span>/<span class="br0">(</span>RAND_MAX<span class="nu0">+1</span><span class="br0">)</span>;<br />+<br />+ m_repliesToSkip++;<br />+ Send<span class="br0">(</span>commands<span class="br0">[</span>choice<span class="br0">]</span><span class="br0">)</span>;<br />+ <span class="kw1">return</span>;<br />+<span class="br0">}</span><br />+<br />+<span class="kw4">void</span> CFtpControlSocket::<span class="me2">OnTimer</span><span class="br0">(</span>wxTimerEvent& event<span class="br0">)</span><br />+<span class="br0">{</span><br />+ <span class="kw1">if</span> <span class="br0">(</span>event.<span class="me1">GetId</span><span class="br0">(</span><span class="br0">)</span> == KEEPALIVE_TIMER_ID<span class="br0">)</span><br />+ <span class="br0">{</span><br />+ <span class="kw1">if</span> <span class="br0">(</span>m_keepAliveTimer.<span class="me1">IsRunning</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br />+ <span class="br0">{</span><br />+ m_keepAliveTimer.<span class="me1">Stop</span><span class="br0">(</span><span class="br0">)</span>;<br />+ <span class="kw1">if</span> <span class="br0">(</span>m_bEnableKeepAlive && IsConnected<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span><br />+ <span class="co1">// FIXME:</span><br />+ <span class="co1">// need to read the values from options...</span><br />+ <span class="kw4">int</span> min_wait = <span class="nu0">30</span>;<br />+ <span class="kw4">int</span> max_wait = <span class="nu0">60</span>;<br />+<br />+ <span class="kw4">int</span> waitsecond = min_wait + <span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span><span class="br0">(</span><span class="kw3">rand</span><span class="br0">(</span><span class="br0">)</span>*<span class="br0">(</span>max_wait - min_wait<span class="br0">)</span>/<span class="br0">(</span>RAND_MAX<span class="nu0">+1</span><span class="br0">)</span><span class="br0">)</span>;<br />+ m_keepAliveTimer.<span class="me1">Start</span><span class="br0">(</span>waitsecond * <span class="nu0">1000</span><span class="br0">)</span>;<br />+ DoKeepAlive<span class="br0">(</span><span class="br0">)</span>;<br />+ <span class="br0">}</span><br />+ <span class="br0">}</span><br />+ <span class="br0">}</span><br />+ <span class="kw1">else</span><br />+ CControlSocket::<span class="me2">OnTimer</span><span class="br0">(</span>event<span class="br0">)</span>;<br /> <span class="br0">}</span><br /> <br /> <span class="kw4">bool</span> CFtpControlSocket::<span class="me2">IsMisleadingListResponse</span><span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span><br />diff -Nur Filezilla3/src/engine/ftpcontrolsocket.<span class="me1">h</span> Filezilla3.<span class="me1">patch</span>/src/engine/ftpcontrolsocket.<span class="me1">h</span><br />--- Filezilla3/src/engine/ftpcontrolsocket.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">20</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/engine/ftpcontrolsocket.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-24</span>,<span class="nu0">6</span> <span class="nu0">+24</span>,<span class="nu0">12</span> @@<br /> <br /> <span class="kw2">protected</span>:<br /> <br />+ <span class="kw4">bool</span> m_bEnableKeepAlive;<br />+ wxTimer m_keepAliveTimer;<br />+ wxStopWatch m_keepAliveStopWatch;<br />+ <span class="kw2">virtual</span> <span class="kw4">int</span> KeepAlive<span class="br0">(</span><span class="kw4">const</span> CKeepAliveCommand& command<span class="br0">)</span>;<br />+ <span class="kw4">void</span> DoKeepAlive<span class="br0">(</span><span class="br0">)</span>;<br />+<br /> <span class="kw2">virtual</span> <span class="kw4">int</span> ResetOperation<span class="br0">(</span><span class="kw4">int</span> nErrorCode<span class="br0">)</span>;<br /> <br /> <span class="kw2">virtual</span> <span class="kw4">int</span> Connect<span class="br0">(</span><span class="kw4">const</span> CServer &server<span class="br0">)</span>;<br />@@ <span class="nu0">-128</span>,<span class="nu0">6</span> <span class="nu0">+134</span>,<span class="nu0">7</span> @@<br /> <br /> DECLARE_EVENT_TABLE<span class="br0">(</span><span class="br0">)</span>;<br /> <span class="kw4">void</span> OnExternalIPAddress<span class="br0">(</span>fzExternalIPResolveEvent& event<span class="br0">)</span>;<br />+ <span class="kw4">void</span> OnTimer<span class="br0">(</span>wxTimerEvent& event<span class="br0">)</span>;<br /> <span class="br0">}</span>;<br /> <br /> <span class="kw2">class</span> CIOThread;<br />diff -Nur Filezilla3/src/include/commands.<span class="me1">h</span> Filezilla3.<span class="me1">patch</span>/src/include/commands.<span class="me1">h</span><br />--- Filezilla3/src/include/commands.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">12</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/include/commands.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-19</span>,<span class="nu0">6</span> <span class="nu0">+19</span>,<span class="nu0">7</span> @@<br /> cmd_rename,<br /> cmd_chmod,<br /> cmd_raw,<br />+ cmd_keepalive,<br /> <br /> <span class="co1">// Only used internally</span><br /> cmd_cwd,<br />@@ <span class="nu0">-74</span>,<span class="nu0">6</span> <span class="nu0">+75</span>,<span class="nu0">15</span> @@<br /> <span class="kw4">const</span> CServer GetServer<span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span>;<br /> <span class="kw2">protected</span>:<br /> CServer m_Server;<br />+<span class="br0">}</span>;<br />+<br />+DECLARE_COMMAND<span class="br0">(</span>CKeepAliveCommand, cmd_keepalive<span class="br0">)</span><br />+ CKeepAliveCommand<span class="br0">(</span><span class="kw4">bool</span> keepAlive = <span class="kw2">true</span><span class="br0">)</span>;<br />+<br />+ <span class="kw4">bool</span> IsKeepAlive<span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span>;<br />+<br />+<span class="kw2">protected</span>:<br />+ <span class="kw4">bool</span> m_keepAlive;<br /> <span class="br0">}</span>;<br /> <br /> DECLARE_COMMAND<span class="br0">(</span>CDisconnectCommand, cmd_disconnect<span class="br0">)</span><br />diff -Nur Filezilla3/src/include/engineprivate.<span class="me1">h</span> Filezilla3.<span class="me1">patch</span>/src/include/engineprivate.<span class="me1">h</span><br />--- Filezilla3/src/include/engineprivate.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">12</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/include/engineprivate.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">05</span>:<span class="nu0">49</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-69</span>,<span class="nu0">6</span> <span class="nu0">+69</span>,<span class="nu0">7</span> @@<br /> <span class="kw4">int</span> Mkdir<span class="br0">(</span><span class="kw4">const</span> CMkdirCommand& command<span class="br0">)</span>;<br /> <span class="kw4">int</span> <span class="kw3">Rename</span><span class="br0">(</span><span class="kw4">const</span> CRenameCommand& command<span class="br0">)</span>;<br /> <span class="kw4">int</span> Chmod<span class="br0">(</span><span class="kw4">const</span> CChmodCommand& command<span class="br0">)</span>;<br />+ <span class="kw4">int</span> KeepAlive<span class="br0">(</span><span class="kw4">const</span> CKeepAliveCommand& command<span class="br0">)</span>;<br /> <br /> <span class="kw4">int</span> ContinueConnect<span class="br0">(</span><span class="br0">)</span>;<br /> <br />diff -Nur Filezilla3/src/interface/Mainfrm.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/interface/Mainfrm.<span class="me1">cpp</span><br />--- Filezilla3/src/interface/Mainfrm.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">08</span>:<span class="nu0">54</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/interface/Mainfrm.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">09</span>:<span class="nu0">18</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-932</span>,<span class="nu0">7</span> <span class="nu0">+932</span>,<span class="nu0">10</span> @@<br /> <br /> CServerPath path;<br /> path.<span class="me1">SetSafePath</span><span class="br0">(</span>COptions::<span class="me2">Get</span><span class="br0">(</span><span class="br0">)</span>->GetOption<span class="br0">(</span>OPTION_LASTSERVERPATH<span class="br0">)</span><span class="br0">)</span>;<br />- m_pState->Connect<span class="br0">(</span>server, <span class="kw2">false</span>, path<span class="br0">)</span>;<br />+ <span class="co1">// FIXME:</span><br />+ <span class="co1">// read keepalive from option</span><br />+ <span class="kw4">bool</span> keepAlive = <span class="kw2">true</span>;<br />+ m_pState->Connect<span class="br0">(</span>server, <span class="kw2">false</span>, keepAlive, path<span class="br0">)</span>;<br /> <span class="br0">}</span><br /> <br /> <span class="kw4">void</span> CMainFrame::<span class="me2">OnRefresh</span><span class="br0">(</span>wxCommandEvent &event<span class="br0">)</span><br />@@ <span class="nu0">-1456</span>,<span class="nu0">7</span> <span class="nu0">+1459</span>,<span class="nu0">10</span> @@<br /> <span class="kw1">return</span>;<br /> <span class="br0">}</span><br /> <br />- m_pState->Connect<span class="br0">(</span>pData->m_server, <span class="kw2">true</span>, pData->m_remoteDir<span class="br0">)</span>;<br />+ <span class="co1">// FIXME:</span><br />+ <span class="co1">// read keepalive from option</span><br />+ <span class="kw4">bool</span> keepAlive = <span class="kw2">true</span>;<br />+ m_pState->Connect<span class="br0">(</span>pData->m_server, <span class="kw2">true</span>, keepAlive, pData->m_remoteDir<span class="br0">)</span>;<br /> <br /> <span class="kw1">if</span> <span class="br0">(</span>pData->m_localDir != _T<span class="br0">(</span><span class="st0">""</span><span class="br0">)</span><span class="br0">)</span><br /> m_pState->SetLocalDir<span class="br0">(</span>pData->m_localDir<span class="br0">)</span>;<br />diff -Nur Filezilla3/src/interface/quickconnectbar.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/interface/quickconnectbar.<span class="me1">cpp</span><br />--- Filezilla3/src/interface/quickconnectbar.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">08</span>:<span class="nu0">54</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/interface/quickconnectbar.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">09</span>:<span class="nu0">18</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-108</span>,<span class="nu0">7</span> <span class="nu0">+108</span>,<span class="nu0">10</span> @@<br /> <span class="kw1">return</span>;<br /> <span class="br0">}</span><br /> <br />- <span class="kw1">if</span> <span class="br0">(</span>!m_pState->Connect<span class="br0">(</span>server, <span class="kw2">true</span><span class="br0">)</span><span class="br0">)</span><br />+ <span class="co1">// FIXME:</span><br />+ <span class="co1">// read keepalive from option</span><br />+ <span class="kw4">bool</span> keepAlive = <span class="kw2">true</span>;<br />+ <span class="kw1">if</span> <span class="br0">(</span>!m_pState->Connect<span class="br0">(</span>server, <span class="kw2">true</span>, keepAlive<span class="br0">)</span><span class="br0">)</span><br /> <span class="kw1">return</span>;<br /> <br /> CRecentServerList::<span class="me2">SetMostRecentServer</span><span class="br0">(</span>server<span class="br0">)</span>;<br />diff -Nur Filezilla3/src/interface/state.<span class="me1">cpp</span> Filezilla3.<span class="me1">patch</span>/src/interface/state.<span class="me1">cpp</span><br />--- Filezilla3/src/interface/state.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">08</span>:<span class="nu0">54</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/interface/state.<span class="me1">cpp</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">09</span>:<span class="nu0">18</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-259</span>,<span class="nu0">7</span> <span class="nu0">+259</span>,<span class="nu0">7</span> @@<br /> NotifyHandlers<span class="br0">(</span>STATECHANGE_APPLYFILTER<span class="br0">)</span>;<br /> <span class="br0">}</span><br /> <br />-<span class="kw4">bool</span> CState::<span class="me2">Connect</span><span class="br0">(</span><span class="kw4">const</span> CServer& server, <span class="kw4">bool</span> askBreak, <span class="kw4">const</span> CServerPath& path <span class="coMULTI">/*=CServerPath()*/</span><span class="br0">)</span><br />+<span class="kw4">bool</span> CState::<span class="me2">Connect</span><span class="br0">(</span><span class="kw4">const</span> CServer& server, <span class="kw4">bool</span> askBreak, <span class="kw4">bool</span> keepAlive <span class="coMULTI">/*=false*/</span>, <span class="kw4">const</span> CServerPath& path <span class="coMULTI">/*=CServerPath()*/</span><span class="br0">)</span><br /> <span class="br0">{</span><br /> <span class="kw1">if</span> <span class="br0">(</span>!m_pEngine<span class="br0">)</span><br /> <span class="kw1">return</span> <span class="kw2">false</span>;<br />@@ <span class="nu0">-273</span>,<span class="nu0">6</span> <span class="nu0">+273</span>,<span class="nu0">8</span> @@<br /> <br /> m_pCommandQueue->ProcessCommand<span class="br0">(</span><span class="kw3">new</span> CConnectCommand<span class="br0">(</span>server<span class="br0">)</span><span class="br0">)</span>;<br /> m_pCommandQueue->ProcessCommand<span class="br0">(</span><span class="kw3">new</span> CListCommand<span class="br0">(</span>path<span class="br0">)</span><span class="br0">)</span>;<br />+ <span class="kw1">if</span> <span class="br0">(</span>keepAlive<span class="br0">)</span><br />+ m_pCommandQueue->ProcessCommand<span class="br0">(</span><span class="kw3">new</span> CKeepAliveCommand<span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span><span class="br0">)</span>;<br /> <br /> COptions::<span class="me2">Get</span><span class="br0">(</span><span class="br0">)</span>->SetLastServer<span class="br0">(</span>server<span class="br0">)</span>;<br /> COptions::<span class="me2">Get</span><span class="br0">(</span><span class="br0">)</span>->SetOption<span class="br0">(</span>OPTION_LASTSERVERPATH, path.<span class="me1">GetSafePath</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br />diff -Nur Filezilla3/src/interface/state.<span class="me1">h</span> Filezilla3.<span class="me1">patch</span>/src/interface/state.<span class="me1">h</span><br />--- Filezilla3/src/interface/state.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">08</span>:<span class="nu0">54</span> <span class="nu0">2007</span><br />+++ Filezilla3.<span class="me1">patch</span>/src/interface/state.<span class="me1">h</span> Mon Sep <span class="nu0">24</span> <span class="nu0">22</span>:<span class="nu0">09</span>:<span class="nu0">18</span> <span class="nu0">2007</span><br />@@ <span class="nu0">-40</span>,<span class="nu0">7</span> <span class="nu0">+40</span>,<span class="nu0">7</span> @@<br /> <span class="kw4">static</span> <span class="kw4">bool</span> LocalDirHasParent<span class="br0">(</span><span class="kw4">const</span> wxString& dir<span class="br0">)</span>;<br /> <span class="kw4">static</span> <span class="kw4">bool</span> LocalDirIsWriteable<span class="br0">(</span><span class="kw4">const</span> wxString& dir<span class="br0">)</span>;<br /> <br />- <span class="kw4">bool</span> Connect<span class="br0">(</span><span class="kw4">const</span> CServer& server, <span class="kw4">bool</span> askBreak, <span class="kw4">const</span> CServerPath& path = CServerPath<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br />+ <span class="kw4">bool</span> Connect<span class="br0">(</span><span class="kw4">const</span> CServer& server, <span class="kw4">bool</span> askBreak, <span class="kw4">bool</span> keepAlive = <span class="kw2">false</span>, <span class="kw4">const</span> CServerPath& path = CServerPath<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br /> <br /> <span class="kw4">bool</span> SetRemoteDir<span class="br0">(</span><span class="kw4">const</span> CDirectoryListing *m_pDirectoryListing, <span class="kw4">bool</span> modified = <span class="kw2">false</span><span class="br0">)</span>;<br /> <span class="kw4">const</span> CDirectoryListing *GetRemoteDir<span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span>;</div></pre><p> Patch 可以由這兒抓取: <a href="http://www.teatime.com.tw/%7Etommy/mypatch/filezilla3_keepalive.patch" target="_blank">http://www.teatime.com.tw/~tommy/mypatch/filezilla3_keepalive.patch</a> <a href="http://www.teatime.com.tw/%7Etommy/mypatch/filezilla3_keepalive.patch" target="_blank"> </a> <br />製作出來的 Windows 執行檔可以由這兒抓: <a href="http://www.teatime.com.tw/~tommy/files/filezilla/filezilla301.7z" target="_blank">http://www.teatime.com.tw/~tommy/files/filezilla/filezilla301.7z</a> </p><p>有需要的就自己抓回去用吧. </p>
Patch
FTP
2007-09-24T22:50:57Z
tommy