[PATCH] RFC2640 Support for FileZilla 2.2.11?

Moderator: Project members

Post Reply
Message
Author
twu2
425 Can't open data connection
Posts: 45
Joined: 2005-02-26 16:54

[PATCH] RFC2640 Support for FileZilla 2.2.11?

#1 Post by twu2 » 2005-02-26 17:10

Here is a simple patch for filezilla 2.2.11 to support RFC-2640. (maybe....)

If the FEAT response show UTF8 support, this patch will encode all control socket command/response form Windows ANSI codepage to UTF-8, and encode the list result from UTF-8 to Windows ANSI codepage.

I've tested this patch for Chinese Windows XP (CP950, Big5) to a UTF-8 ftp server. It work for me.

http://www.teatime.com.tw/~tommy/filezi ... 2640.patch

Code: Select all

diff -Nur source.orig\FtpControlSocket.cpp source.patched\FtpControlSocket.cpp
--- source.orig\FtpControlSocket.cpp	Sat Jan 15 19:46:52 2005
+++ source.patched\FtpControlSocket.cpp	Sun Feb 27 00:53:06 2005
@@ -146,6 +146,8 @@
 	m_useZlib = false;
 	m_zlibSupported = false;
 	m_zlibLevel = 8;
+
+	m_bUTF8 = false;
 }
 
 CFtpControlSocket::~CFtpControlSocket()
@@ -552,8 +554,10 @@
 	{ // authentication succeeded, we're now get the response to the CWD command
 		if (GetReplyCode() == 2) // we're logged on
 		{
-			if (Send("FEAT"))
+			if (Send("FEAT")) {
+				m_bUTF8 = false;
 				m_Operation.nOpState = CONNECT_FEAT;
+			}
 			return;
 		}
 		else
@@ -581,8 +585,10 @@
 			DoClose();
 			return;
 		case LO: //LO means we are logged on
-			if (Send("FEAT"))
+			if (Send("FEAT")) {
+				m_bUTF8 = false;
 				m_Operation.nOpState = CONNECT_FEAT;
+			}
 			return;
 		}
 	}
@@ -696,6 +702,17 @@
 			{
 				if (!m_RecvBuffer.empty() && m_RecvBuffer.back()!=_T("") )
 				{
+					if (m_bUTF8) {
+						// convert from UTF-8 to ANSI
+						int len = MultiByteToWideChar(CP_UTF8, 0, m_RecvBuffer.back(), -1, NULL, 0);
+						char *p1 = new char[len * 2 + 1];
+						char *p2 = new char[len * 2 + 1];
+						MultiByteToWideChar(CP_UTF8, 0, m_RecvBuffer.back(), -1 , (LPWSTR)p1, len*2);
+						WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+						m_RecvBuffer.back() = p2;
+						delete [] p1;
+						delete [] p2;
+					}
 					ShowStatus(m_RecvBuffer.back(), 3);
 					//Check for multi-line responses
 					if (m_RecvBuffer.back().GetLength()>3)
@@ -832,8 +849,22 @@
 	
 	ShowStatus(str,2);
 	str+="\r\n";
-	LPCSTR lpszAsciiSend=T2CA(str);
-	int res = CAsyncSocketEx::Send(lpszAsciiSend,strlen(lpszAsciiSend));
+	int res;
+	if (m_bUTF8) {
+		// Convert ANSI to UTF-8
+		int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+		char *p1 = new char[len * 2 + 1];
+		char *p2 = new char[len * 2 + 1];
+		MultiByteToWideChar(CP_ACP, 0, str, -1 , (LPWSTR)p1, len*2);
+		WideCharToMultiByte(CP_UTF8, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+		res = CAsyncSocketEx::Send(p2, strlen(p2));
+		delete [] p1;
+		delete [] p2;
+	}
+	else {
+		LPCSTR lpszAsciiSend=T2CA(str);
+		res = CAsyncSocketEx::Send(lpszAsciiSend,strlen(lpszAsciiSend));
+	}
 	if (!res)
 	{
 		if (GetLastError()!=WSAEWOULDBLOCK)
@@ -4875,6 +4906,9 @@
 		line.MakeUpper();
 		if (line == _T(" MODE Z") || line.Left(8) == _T(" MODE Z "))
 			m_zlibSupported = true;
+		if (line == _T(" UTF8") || line.Left(8) == _T(" UTF8 ")) {
+			m_bUTF8 = true;
+		}
 	}
 }
 
diff -Nur source.orig\FtpControlSocket.h source.patched\FtpControlSocket.h
--- source.orig\FtpControlSocket.h	Mon Jun 07 22:59:10 2004
+++ source.patched\FtpControlSocket.h	Sun Feb 27 00:15:08 2005
@@ -130,6 +130,8 @@
 	bool m_zlibSupported;
 	int m_zlibLevel;
 
+	bool m_bUTF8;
+
 private:
 	BOOL m_bCheckForTimeout;
 };
diff -Nur source.orig\FtpListResult.cpp source.patched\FtpListResult.cpp
--- source.orig\FtpListResult.cpp	Sun Feb 27 00:35:57 2005
+++ source.patched\FtpListResult.cpp	Sun Feb 27 00:41:10 2005
@@ -142,11 +142,12 @@
 
 #endif
 
-CFtpListResult::CFtpListResult(t_server server)
+CFtpListResult::CFtpListResult(t_server server, bool bUTF8)
 {
 	listhead=curpos=0;
 	
 	m_server = server;
+	m_bUTF8 = bUTF8;
 
 	pos=0;
 
@@ -369,8 +370,23 @@
 	while (line)
 	{
 		int tmp;
-		char *tmpline=new char[strlen(line)+1];
-		strcpy(tmpline, line);
+		char *tmpline;
+
+		if (m_bUTF8) {
+			// convert from UTF-8 to ANSI
+			int len = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
+			char *p1 = new char[len * 2 + 1];
+			char *p2 = new char[len * 2 + 1];
+			MultiByteToWideChar(CP_UTF8, 0, line, -1 , (LPWSTR)p1, len*2);
+			WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+			tmpline = p2;
+			delete [] p1;
+			//delete [] p2;
+		}
+		else {
+			tmpline=new char[strlen(line)+1];
+			strcpy(tmpline, line);
+		}
 		if (parseLine(tmpline, strlen(tmpline), direntry, tmp))
 		{
 			delete [] tmpline;
@@ -541,8 +557,23 @@
 			break;
 		}			
 		int tmp;
-		char *tmpline = new char[strlen(line)+1];
-		strcpy(tmpline, line);
+		char *tmpline;
+
+		if (m_bUTF8) {
+			// convert from UTF-8 to ANSI
+			int len = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
+			char *p1 = new char[len * 2 + 1];
+			char *p2 = new char[len * 2 + 1];
+			MultiByteToWideChar(CP_UTF8, 0, line, -1 , (LPWSTR)p1, len*2);
+			WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+			tmpline = p2;
+			delete [] p1;
+			//delete [] p2;
+		}
+		else {
+			tmpline=new char[strlen(line)+1];
+			strcpy(tmpline, line);
+		}
 		if (parseLine(tmpline, strlen(tmpline), direntry, tmp))
 		{
 			delete [] tmpline;
diff -Nur source.orig\FtpListResult.h source.patched\FtpListResult.h
--- source.orig\FtpListResult.h	Fri Jan 14 14:50:46 2005
+++ source.patched\FtpListResult.h	Sun Feb 27 00:16:17 2005
@@ -55,9 +55,10 @@
 {
 public:
 	t_server m_server;
+	bool m_bUTF8;
 	void SendToMessageLog(HWND hWnd, UINT nMsg);
 	void AddData(char *data,int size);
-	CFtpListResult(t_server server);
+	CFtpListResult(t_server server, bool bUTF8 = false);
 	~CFtpListResult();
 	t_directory::t_direntry *getList(int &num, CTime EntryTime);
 
diff -Nur source.orig\TransferSocket.cpp source.patched\TransferSocket.cpp
--- source.orig\TransferSocket.cpp	Sun Feb 20 12:30:52 2005
+++ source.patched\TransferSocket.cpp	Sun Feb 27 00:14:15 2005
@@ -79,7 +79,7 @@
 	m_pSslLayer = NULL;
 	m_pGssLayer = NULL;
 
-	m_pListResult = new CFtpListResult(pOwner->m_CurrentServer);
+	m_pListResult = new CFtpListResult(pOwner->m_CurrentServer, pOwner->m_bUTF8);
 	m_LastUpdateTime.QuadPart = 0;
 
 	memset(&m_zlibStream, 0, sizeof(m_zlibStream));

User avatar
botg
Site Admin
Posts: 35509
Joined: 2004-02-23 20:49
First name: Tim
Last name: Kosse

#2 Post by botg » 2005-02-26 19:15

Thanks. Can you please check if your patch compiles with a unicode build of FileZilla? (Target provided in project files)
You only convert from UTF8 to wide char and then back to the local char set, where in a unicode build you've to skip the last step.

twu2
425 Can't open data connection
Posts: 45
Joined: 2005-02-26 16:54

#3 Post by twu2 » 2005-02-27 05:31

botg wrote:Thanks. Can you please check if your patch compiles with a unicode build of FileZilla? (Target provided in project files)
You only convert from UTF8 to wide char and then back to the local char set, where in a unicode build you've to skip the last step.
My patch didn't work for unicode build now, I'll try to modify it.

But, I also find there are some errors in unicode build of FileZilla even without my patch.

Because the ftp command and response (also list data) are sent/received use ascii code, not unicode.
The current unicode code in FileZilla will convert it from ascii to unicode for each byte.

But for a MBCS string, we can't convert it to unicode byte by byte, should convert it to unicode for whole string, or at least a whole MBCS word.

So, in unicode build, in FtpListResult.cpp and FtpControlSocket.cpp, we should convert it to unicode until we get the whole line, not convert them each byte.

I've tried to make some change for this, it will show Chinese word correct in unicode build, but it also made Filezilla very unstable, core-dump randomly.

twu2
425 Can't open data connection
Posts: 45
Joined: 2005-02-26 16:54

#4 Post by twu2 » 2005-02-27 13:44

finally, I finished the patch for both unicode build and ansi build.

I also find why unicode build so unstable for me.

For StatusCtrl.cpp

Code: Select all

	char *buffer = new char[rtfstr.GetLength() + 5]; //Make it large enough to hold unicode data
	strcpy(buffer + 4, T2CA(rtfstr));
	*(int *)buffer = 0;
There are 3 new operator to allocate memory, the size just rtfstr.GetLength() + 5, but for T2CA(rtfstr), the size may large than the length of rtfstr. So I change the code here as

Code: Select all

	char *buffer = new char[rtfstr.GetLength()*2 + 5]; //Make it large enough to hold unicode data
	strcpy(buffer + 4, T2CA(rtfstr));
	*(int *)buffer = 0;
After that, the unicode build work fine for me now.

here is the patch, I've test under Chinese Windows XP, it work for me for both unicode and ansi version.
http://www.teatime.com.tw/~tommy/filezi ... 2640.patch

Code: Select all

diff -Nur source.orig\FtpControlSocket.cpp source.patched\FtpControlSocket.cpp
--- source.orig\FtpControlSocket.cpp	Sat Jan 15 19:46:52 2005
+++ source.patched\FtpControlSocket.cpp	Sun Feb 27 20:31:06 2005
@@ -146,6 +146,8 @@
 	m_useZlib = false;
 	m_zlibSupported = false;
 	m_zlibLevel = 8;
+
+	m_bUTF8 = false;
 }
 
 CFtpControlSocket::~CFtpControlSocket()
@@ -459,7 +461,7 @@
 			 m_Operation.nOpState == CONNECT_GSS_NEEDPASS ||
 			 m_Operation.nOpState == CONNECT_GSS_NEEDUSER)
 	{
-		if (!m_RecvBuffer.empty() && m_RecvBuffer.front() != _T(""))
+		if (!m_RecvBuffer.empty() && m_RecvBuffer.front() != "")
 		{
 			//Incoming reply from server during async is not allowed
 			DoClose();
@@ -474,7 +476,7 @@
 	}
 	else if (m_Operation.nOpState == CONNECT_SYST)
 	{
-		if (GetReplyCode() == 2 && m_RecvBuffer.front().GetLength() > 7 && m_RecvBuffer.front().Mid(3, 4) == _T(" MVS"))
+		if (GetReplyCode() == 2 && m_RecvBuffer.front().GetLength() > 7 && m_RecvBuffer.front().Mid(3, 4) == " MVS")
 		{
 			if (m_CurrentServer.nServerType & FZ_SERVERTYPE_FTP)
 				m_CurrentServer.nServerType |= FZ_SERVERTYPE_SUB_FTP_MVS;
@@ -552,8 +554,10 @@
 	{ // authentication succeeded, we're now get the response to the CWD command
 		if (GetReplyCode() == 2) // we're logged on
 		{
-			if (Send("FEAT"))
+			if (Send("FEAT")) {
+				m_bUTF8 = false;
 				m_Operation.nOpState = CONNECT_FEAT;
+			}
 			return;
 		}
 		else
@@ -581,8 +585,10 @@
 			DoClose();
 			return;
 		case LO: //LO means we are logged on
-			if (Send("FEAT"))
+			if (Send("FEAT")) {
+				m_bUTF8 = false;
 				m_Operation.nOpState = CONNECT_FEAT;
+			}
 			return;
 		}
 	}
@@ -659,6 +665,7 @@
 			temp="PASS "+m_CurrentServer.pass+"@"+CCrypt::decrypt(COptions::GetOption(OPTION_FWPASS));
 			break;
 	}
+	m_bUTF8 = false;
 	// send command, get response
 	if(!Send(temp))
 		return;
@@ -679,7 +686,7 @@
 			LogMessage(__FILE__, __LINE__, this,FZ_LOG_INFO, _T("Socket has been closed, don't process receive") );
 			return;
 		}
-		m_MultiLine=_T("");
+		m_MultiLine="";
 		CString str;
 		str.Format(IDS_STATUSMSG_CONNECTEDWITH, m_ServerName);
 		ShowStatus(str,0);
@@ -694,13 +701,25 @@
 		{
 			if ((buffer[i]=='\r')||(buffer[i]=='\n')||(buffer[i]==0))
 			{
-				if (!m_RecvBuffer.empty() && m_RecvBuffer.back()!=_T("") )
+				if (!m_RecvBuffer.empty() && m_RecvBuffer.back()!="" )
 				{
-					ShowStatus(m_RecvBuffer.back(), 3);
+					if (m_bUTF8) {
+						// convert from UTF-8 to ANSI
+						int len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_RecvBuffer.back(), -1, NULL, 0);
+						char *p1 = new char[len * 2 + 1];
+						char *p2 = new char[len * 2 + 1];
+						MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_RecvBuffer.back(), -1 , (LPWSTR)p1, len*2);
+						WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+						m_RecvBuffer.back() = p2;
+						delete [] p1;
+						delete [] p2;
+					}
+					CString temp_str = m_RecvBuffer.back();
+					ShowStatus(temp_str, 3);
 					//Check for multi-line responses
 					if (m_RecvBuffer.back().GetLength()>3)
 					{
-						if (m_MultiLine != _T(""))
+						if (m_MultiLine != "")
 						{
 							if (m_RecvBuffer.back().Left(4) != m_MultiLine)
 							{
@@ -709,7 +728,7 @@
 							}
 							else // end of multi-line found
  							{
- 								m_MultiLine = _T("");
+ 								m_MultiLine = "";
  								m_pOwner->PostThreadMessage(m_pOwner->m_nInternalMessageID,FZAPI_THREADMSG_PROCESSREPLY,0);
  							}
 						}
@@ -725,7 +744,7 @@
 					}
 					else
 						m_RecvBuffer.pop_back();
-					m_RecvBuffer.push_back(_T(""));
+					m_RecvBuffer.push_back("");
 				}
 			}
 			else
@@ -733,7 +752,7 @@
 				//The command may only be 2000 chars long. This ensures that a malicious user can't
 				//send extremely large commands to fill the memory of the server
 				if (m_RecvBuffer.empty())
-					m_RecvBuffer.push_back(_T(""));
+					m_RecvBuffer.push_back("");
 				if (m_RecvBuffer.back().GetLength()<2000)
 					m_RecvBuffer.back()+=buffer[i];
 			}
@@ -811,7 +830,7 @@
 	{
 		if (!m_pOwner->IsConnected())
 		{
-			m_MultiLine=_T("");
+			m_MultiLine="";
 			m_pOwner->SetConnected(TRUE);
 			CString str;
 			str.Format(m_pSslLayer ? IDS_STATUSMSG_CONNECTEDWITHSSL : IDS_STATUSMSG_CONNECTEDWITH, m_ServerName);
@@ -832,8 +851,36 @@
 	
 	ShowStatus(str,2);
 	str+="\r\n";
-	LPCSTR lpszAsciiSend=T2CA(str);
-	int res = CAsyncSocketEx::Send(lpszAsciiSend,strlen(lpszAsciiSend));
+	int res;
+	if (m_bUTF8) {
+#if defined(_UNICODE)
+		// Convert unicode to ascii first
+		LPCSTR lpszAsciiSend=T2CA(str);
+		// Convert Unicode to UTF-8
+		int len = MultiByteToWideChar(CP_ACP, 0, lpszAsciiSend, -1, NULL, 0);
+		char *p1 = new char[len * 2 + 1];
+		char *p2 = new char[len * 2 + 1];
+		MultiByteToWideChar(CP_ACP, 0, lpszAsciiSend, -1 , (LPWSTR)p1, len*2);
+		WideCharToMultiByte(CP_UTF8, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+		res = CAsyncSocketEx::Send(p2, strlen(p2));
+		delete [] p1;
+		delete [] p2;
+#else
+		// Convert ANSI to UTF-8
+		int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+		char *p1 = new char[len * 2 + 1];
+		char *p2 = new char[len * 2 + 1];
+		MultiByteToWideChar(CP_ACP, 0, str, -1 , (LPWSTR)p1, len*2);
+		WideCharToMultiByte(CP_UTF8, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+		res = CAsyncSocketEx::Send(p2, strlen(p2));
+		delete [] p1;
+		delete [] p2;
+#endif
+	}
+	else {
+		LPCSTR lpszAsciiSend=T2CA(str);
+		res = CAsyncSocketEx::Send(lpszAsciiSend,strlen(lpszAsciiSend));
+	}
 	if (!res)
 	{
 		if (GetLastError()!=WSAEWOULDBLOCK)
@@ -878,6 +925,8 @@
 	m_zlibSupported = false;
 	m_zlibLevel = 0;
 
+	m_bUTF8 = false;
+
 	CControlSocket::Close();
 }
 
@@ -2075,9 +2124,9 @@
 				{
 					int res=GetReplyCode();
 					if (res == 2 || res == 3 || //Creation successful
-						m_RecvBuffer.front()==_T("550 Directory already exists") )//Creation was successful, although someone else did the work for us
+						m_RecvBuffer.front()=="550 Directory already exists" )//Creation was successful, although someone else did the work for us
 					{
-						if (m_RecvBuffer.front()==_T("550 Directory already exists") )
+						if (m_RecvBuffer.front()=="550 Directory already exists" )
 							printf("OK");
 						CServerPath path2=pData->MKDCurrent;
 						if (path2.HasParent())
@@ -2204,8 +2253,9 @@
 				}
 
 				CServerPath path;
+				CString temp_str = m_RecvBuffer.front().Mid(pos1+1,pos2-pos1-1);
 				path.SetServer(m_CurrentServer);
-				if (!path.SetPath(m_RecvBuffer.front().Mid(pos1+1,pos2-pos1-1)))
+				if (!path.SetPath(temp_str))
 				{
 					LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Can't parse path, CServerPath::SetPath() failed."));
 					nReplyError = FZ_REPLY_ERROR;
@@ -2297,8 +2347,8 @@
 			
 			if (pData->bPasv)
 			{
-				int i=m_RecvBuffer.front().Find( _T("(") );
-				int j=j=m_RecvBuffer.front().Find( _T(")") );
+				int i=m_RecvBuffer.front().Find( "(" );
+				int j=j=m_RecvBuffer.front().Find( ")" );
 				// extract connect port number and IP from string returned by server
 				if (i==-1 || j==-1 || (i+11)>=j)
 				{
@@ -2400,7 +2450,7 @@
 				m_Operation.nOpState=FILETRANSFER_LIST_LIST;
 			break;
 		case FILETRANSFER_LIST_LIST:
-			if (!m_RecvBuffer.front().CompareNoCase(_T("550 No members found.")) && (m_CurrentServer.nServerType & FZ_SERVERTYPE_SUB_FTP_MVS))
+			if (!m_RecvBuffer.front().CompareNoCase("550 No members found.") && (m_CurrentServer.nServerType & FZ_SERVERTYPE_SUB_FTP_MVS))
 			{
 				ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
 
@@ -2610,8 +2660,8 @@
 			{
 				if (pData->bPasv)
 				{
-					int i=m_RecvBuffer.front().Find( _T("(") );
-					int j=j=m_RecvBuffer.front().Find( _T(")") );
+					int i=m_RecvBuffer.front().Find( "(" );
+					int j=j=m_RecvBuffer.front().Find( ")" );
 					// extract connect port number and IP from string returned by server
 					if(i==-1 || j==-1 || (GetFamily() == AF_INET && (i+11) >= j))
 					{
@@ -4269,7 +4319,7 @@
 		CMakeDirData *pData=(CMakeDirData *)m_Operation.pData;
 		int res=GetReplyCode();
 		if (res==2 || res==3 || //Creation successful
-		m_RecvBuffer.front()==_T("550 Directory already exists") )//Creation was successful, although someone else did the work for us
+		m_RecvBuffer.front()=="550 Directory already exists" )//Creation was successful, although someone else did the work for us
 		{ //Create dir entry in parent dir
 			CServerPath path2=pData->Current;
 			if (path2.HasParent())
@@ -4637,7 +4687,7 @@
 	case FZ_ASYNCREQUEST_GSS_AUTHFAILED:
 		if (m_Operation.nOpMode!=CSMODE_CONNECT || m_Operation.nOpState!=CONNECT_GSS_FAILED)
 			break;
-		if (!m_RecvBuffer.empty() && m_RecvBuffer.front()!= _T(""))
+		if (!m_RecvBuffer.empty() && m_RecvBuffer.front()!= "")
 		{
 			DoClose();
 			break; 
@@ -4868,13 +4918,16 @@
 	return TRUE;
 }
 
-void CFtpControlSocket::DiscardLine(CString line)
+void CFtpControlSocket::DiscardLine(CStringA line)
 {
 	if (m_Operation.nOpMode == CSMODE_CONNECT && m_Operation.nOpState == CONNECT_FEAT)
 	{
 		line.MakeUpper();
-		if (line == _T(" MODE Z") || line.Left(8) == _T(" MODE Z "))
+		if (line == " MODE Z" || line.Left(8) == " MODE Z ")
 			m_zlibSupported = true;
+		if (line == " UTF8" || line.Left(8) == " UTF8 ") {
+			m_bUTF8 = true;
+		}
 	}
 }
 
diff -Nur source.orig\FtpControlSocket.h source.patched\FtpControlSocket.h
--- source.orig\FtpControlSocket.h	Mon Jun 07 22:59:10 2004
+++ source.patched\FtpControlSocket.h	Sun Feb 27 17:10:18 2005
@@ -110,17 +110,17 @@
 	
 	BOOL ParsePwdReply(CString reply);
 
-	void DiscardLine(CString line);
+	void DiscardLine(CStringA line);
 	bool NeedModeCommand();
 	bool NeedOptsCommand();
 
 	CFile *m_pDataFile;
 	CTransferSocket *m_pTransferSocket;
-	CString m_MultiLine;
+	CStringA m_MultiLine;
 	CTime m_LastSendTime;
 	
 	CString m_ServerName;
-	std::list<CString> m_RecvBuffer;
+	std::list<CStringA> m_RecvBuffer;
 	CTime m_LastRecvTime;
 	class CListData;
 	class CFileTransferData;
@@ -129,6 +129,8 @@
 	bool m_useZlib;
 	bool m_zlibSupported;
 	int m_zlibLevel;
+
+	bool m_bUTF8;
 
 private:
 	BOOL m_bCheckForTimeout;
diff -Nur source.orig\FtpListResult.cpp source.patched\FtpListResult.cpp
--- source.orig\FtpListResult.cpp	Sun Feb 27 00:35:57 2005
+++ source.patched\FtpListResult.cpp	Sun Feb 27 21:04:21 2005
@@ -142,11 +142,12 @@
 
 #endif
 
-CFtpListResult::CFtpListResult(t_server server)
+CFtpListResult::CFtpListResult(t_server server, bool bUTF8)
 {
 	listhead=curpos=0;
 	
 	m_server = server;
+	m_bUTF8 = bUTF8;
 
 	pos=0;
 
@@ -369,8 +370,23 @@
 	while (line)
 	{
 		int tmp;
-		char *tmpline=new char[strlen(line)+1];
-		strcpy(tmpline, line);
+		char *tmpline;
+
+		if (m_bUTF8) {
+			// convert from UTF-8 to ANSI
+			int len = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
+			char *p1 = new char[len * 2 + 1];
+			char *p2 = new char[len * 2 + 1];
+			MultiByteToWideChar(CP_UTF8, 0, line, -1 , (LPWSTR)p1, len*2);
+			WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+			tmpline = p2;
+			delete [] p1;
+			//delete [] p2;
+		}
+		else {
+			tmpline=new char[strlen(line)+1];
+			strcpy(tmpline, line);
+		}
 		if (parseLine(tmpline, strlen(tmpline), direntry, tmp))
 		{
 			delete [] tmpline;
@@ -541,8 +557,23 @@
 			break;
 		}			
 		int tmp;
-		char *tmpline = new char[strlen(line)+1];
-		strcpy(tmpline, line);
+		char *tmpline;
+
+		if (m_bUTF8) {
+			// convert from UTF-8 to ANSI
+			int len = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
+			char *p1 = new char[len * 2 + 1];
+			char *p2 = new char[len * 2 + 1];
+			MultiByteToWideChar(CP_UTF8, 0, line, -1 , (LPWSTR)p1, len*2);
+			WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+			tmpline = p2;
+			delete [] p1;
+			//delete [] p2;
+		}
+		else {
+			tmpline=new char[strlen(line)+1];
+			strcpy(tmpline, line);
+		}
 		if (parseLine(tmpline, strlen(tmpline), direntry, tmp))
 		{
 			delete [] tmpline;
@@ -2129,12 +2160,31 @@
 
 void CFtpListResult::copyStr(CString &target, int pos, const char *source, int len) const
 {
+#if defined(_UNICODE)
+	if (pos != 0) {
+		int i;
+		LPTSTR pBuffer = target.GetBuffer(pos + len);
+		ASSERT(pBuffer);
+		for (i = 0; i < len; i++)
+			pBuffer[pos + i] = source[i];
+		target.ReleaseBuffer(pos + len);
+	}
+	else {
+		USES_CONVERSION;
+		char *p = new char[len+1];
+		memcpy(p, source, len);
+		p[len] = '\0';
+		target = A2CT(p);
+		delete [] p;
+	}
+#else
 	int i;
 	LPTSTR pBuffer = target.GetBuffer(pos + len);
 	ASSERT(pBuffer);
 	for (i = 0; i < len; i++)
 		pBuffer[pos + i] = source[i];
 	target.ReleaseBuffer(pos + len);
+#endif
 }
 
 BOOL CFtpListResult::parseAsIBM(const char *line, const int linelen, t_directory::t_direntry &direntry)
diff -Nur source.orig\FtpListResult.h source.patched\FtpListResult.h
--- source.orig\FtpListResult.h	Fri Jan 14 14:50:46 2005
+++ source.patched\FtpListResult.h	Sun Feb 27 00:16:17 2005
@@ -55,9 +55,10 @@
 {
 public:
 	t_server m_server;
+	bool m_bUTF8;
 	void SendToMessageLog(HWND hWnd, UINT nMsg);
 	void AddData(char *data,int size);
-	CFtpListResult(t_server server);
+	CFtpListResult(t_server server, bool bUTF8 = false);
 	~CFtpListResult();
 	t_directory::t_direntry *getList(int &num, CTime EntryTime);
 
diff -Nur source.orig\StatusCtrl.cpp source.patched\StatusCtrl.cpp
--- source.orig\StatusCtrl.cpp	Wed Oct 27 16:18:18 2004
+++ source.patched\StatusCtrl.cpp	Sun Feb 27 20:54:51 2005
@@ -135,7 +135,7 @@
 
 	rtfstr += "} ";
 
-	char *buffer = new char[rtfstr.GetLength() + 5];
+	char *buffer = new char[rtfstr.GetLength()*2 + 5];
 	strcpy(buffer + 4, T2CA(rtfstr));
 	*(int *)buffer = 0;
 
@@ -279,7 +279,7 @@
 	CString rtfstr = m_RTFHeader;
 	rtfstr += "} ";
 
-	char *buffer = new char[rtfstr.GetLength() + 5];
+	char *buffer = new char[rtfstr.GetLength()*2 + 5];
 	strcpy(buffer + 4, T2CA(rtfstr));
 	*(int *)buffer = 0;
 
@@ -324,7 +324,7 @@
 		__time64_t t = _time64(0);
 		if (!strftime(buf, 100, "[%H:%M:%S] ", _localtime64(&t)))
 			buf[0] = 0;
-		CString stime = A2CT(buf);
+		stime = A2CT(buf);
 	}
 
 	CString str;
@@ -371,7 +371,7 @@
 	
 	rtfstr += "} ";
 
-	char *buffer = new char[rtfstr.GetLength() + 5]; //Make it large enough to hold unicode data
+	char *buffer = new char[rtfstr.GetLength()*2 + 5]; //Make it large enough to hold unicode data
 	strcpy(buffer + 4, T2CA(rtfstr));
 	*(int *)buffer = 0;
 
diff -Nur source.orig\TransferSocket.cpp source.patched\TransferSocket.cpp
--- source.orig\TransferSocket.cpp	Sun Feb 20 12:30:52 2005
+++ source.patched\TransferSocket.cpp	Sun Feb 27 00:14:15 2005
@@ -79,7 +79,7 @@
 	m_pSslLayer = NULL;
 	m_pGssLayer = NULL;
 
-	m_pListResult = new CFtpListResult(pOwner->m_CurrentServer);
+	m_pListResult = new CFtpListResult(pOwner->m_CurrentServer, pOwner->m_bUTF8);
 	m_LastUpdateTime.QuadPart = 0;
 
 	memset(&m_zlibStream, 0, sizeof(m_zlibStream));
PS. I change some variable and function to use CStringA, not CString, because the response string receive from ftp server is not an unicode string. It's easy for me to convert the string from multi-byte to unicode line by line, not byte by byte.

User avatar
botg
Site Admin
Posts: 35509
Joined: 2004-02-23 20:49
First name: Tim
Last name: Kosse

#5 Post by botg » 2005-02-28 12:29

Thanks.

I had to modify the patch slightly, though. In unicode mode, you were converting the input data from UTF8 into Unicode and then back to the local MBCS charset, which is a lossy conversion.
I've modified the code so that the data will not be converted multiple times. For this I did add the new function CFtpControlSocket::GetReply().

Btw, I had a hard to to apply your patch, GNU patch did not find the input files. The recommended way to create patches is to use cvs diff -u > my.patch

twu2
425 Can't open data connection
Posts: 45
Joined: 2005-02-26 16:54

#6 Post by twu2 » 2005-02-28 16:16

Sorry, I didn't get soruce code from cvs, I use the source code zip file.
I generate the patch use GNU diff tool win32 version.

I made a smaller one patch, this one won't convert to ANSI under unicode build. And I also change m_RecvBuffer back to CString, just using another CStringA variable m_RecvBufferA to keep the incoming buffer, then convert it from UTF-8 to ANSI/Unicode after got EOL. Then assign this string to m_RecvBuffer.back().

Also for FtpListResult.cpp, I move all convert code to copyStr() only.

Here is new patch:
http://www.teatime.com.tw/~tommy/filezi ... 2640.patch

And I also put a zip file include this patch, and the original files and patched files here:
http://www.teatime.com.tw/~tommy/filezilla_patch.zip

Code: Select all

diff -Nur source.orig\FtpControlSocket.cpp source\FtpControlSocket.cpp
--- source.orig\FtpControlSocket.cpp	Sat Jan 15 19:46:52 2005
+++ source\FtpControlSocket.cpp	Mon Feb 28 23:38:41 2005
@@ -146,6 +146,9 @@
 	m_useZlib = false;
 	m_zlibSupported = false;
 	m_zlibLevel = 8;
+
+	m_bUTF8 = false;
+	m_RecvBufferA = "";
 }
 
 CFtpControlSocket::~CFtpControlSocket()
@@ -552,8 +555,10 @@
 	{ // authentication succeeded, we're now get the response to the CWD command
 		if (GetReplyCode() == 2) // we're logged on
 		{
-			if (Send("FEAT"))
+			if (Send("FEAT")) {
+				m_bUTF8 = false;
 				m_Operation.nOpState = CONNECT_FEAT;
+			}
 			return;
 		}
 		else
@@ -581,8 +586,10 @@
 			DoClose();
 			return;
 		case LO: //LO means we are logged on
-			if (Send("FEAT"))
+			if (Send("FEAT")) {
+				m_bUTF8 = false;
 				m_Operation.nOpState = CONNECT_FEAT;
+			}
 			return;
 		}
 	}
@@ -659,6 +666,7 @@
 			temp="PASS "+m_CurrentServer.pass+"@"+CCrypt::decrypt(COptions::GetOption(OPTION_FWPASS));
 			break;
 	}
+	m_bUTF8 = false;
 	// send command, get response
 	if(!Send(temp))
 		return;
@@ -694,8 +702,32 @@
 		{
 			if ((buffer[i]=='\r')||(buffer[i]=='\n')||(buffer[i]==0))
 			{
-				if (!m_RecvBuffer.empty() && m_RecvBuffer.back()!=_T("") )
+				if (!m_RecvBuffer.empty() && m_RecvBufferA!="" )
 				{
+					if (m_bUTF8) {
+#if defined(_UNICODE)
+						// convert from UTF-8 to Unicode
+						int len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_RecvBufferA, -1, NULL, 0);
+						wchar_t *p2 = new wchar_t[len * 2 + 1];
+						MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_RecvBufferA, -1, (LPWSTR)p2, len*2);
+						m_RecvBuffer.back() = p2;
+						delete [] p2;
+#else
+						// convert from UTF-8 to ANSI
+						int len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_RecvBufferA, -1, NULL, 0);
+						char *p1 = new char[len * 2 + 1];
+						char *p2 = new char[len * 2 + 1];
+						MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)m_RecvBufferA, -1 , (LPWSTR)p1, len*2);
+						WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+						m_RecvBuffer.back() = p2;
+						delete [] p1;
+						delete [] p2;
+#endif
+					}
+					else {
+						USES_CONVERSION;
+						m_RecvBuffer.back() = A2CT(m_RecvBufferA);
+					}
 					ShowStatus(m_RecvBuffer.back(), 3);
 					//Check for multi-line responses
 					if (m_RecvBuffer.back().GetLength()>3)
@@ -726,16 +758,19 @@
 					else
 						m_RecvBuffer.pop_back();
 					m_RecvBuffer.push_back(_T(""));
+					m_RecvBufferA = "";
 				}
 			}
 			else
 			{
 				//The command may only be 2000 chars long. This ensures that a malicious user can't
 				//send extremely large commands to fill the memory of the server
-				if (m_RecvBuffer.empty())
+				if (m_RecvBuffer.empty()) {
 					m_RecvBuffer.push_back(_T(""));
-				if (m_RecvBuffer.back().GetLength()<2000)
-					m_RecvBuffer.back()+=buffer[i];
+					m_RecvBufferA = "";
+				}
+				if (m_RecvBufferA.GetLength()<2000)
+					m_RecvBufferA+=buffer[i];
 			}
 		}
 		if (numread<BUFFERSIZE)
@@ -832,8 +867,31 @@
 	
 	ShowStatus(str,2);
 	str+="\r\n";
-	LPCSTR lpszAsciiSend=T2CA(str);
-	int res = CAsyncSocketEx::Send(lpszAsciiSend,strlen(lpszAsciiSend));
+	int res;
+	if (m_bUTF8) {
+#if defined(_UNICODE)
+		// Convert Unicode to UTF-8
+		int len = str.GetLength() * 6;
+		char *p1 = new char[len + 1];
+		WideCharToMultiByte(CP_UTF8, 0, str, -1, p1, len, NULL, NULL);
+		res = CAsyncSocketEx::Send(p1, strlen(p1));
+		delete [] p1;
+#else
+		// Convert ANSI to UTF-8
+		int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+		char *p1 = new char[len * 2 + 1];
+		char *p2 = new char[len * 2 + 1];
+		MultiByteToWideChar(CP_ACP, 0, str, -1 , (LPWSTR)p1, len*2);
+		WideCharToMultiByte(CP_UTF8, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+		res = CAsyncSocketEx::Send(p2, strlen(p2));
+		delete [] p1;
+		delete [] p2;
+#endif
+	}
+	else {
+		LPCSTR lpszAsciiSend=T2CA(str);
+		res = CAsyncSocketEx::Send(lpszAsciiSend,strlen(lpszAsciiSend));
+	}
 	if (!res)
 	{
 		if (GetLastError()!=WSAEWOULDBLOCK)
@@ -871,13 +929,16 @@
 		nError |= FZ_REPLY_ERROR;
 	ResetOperation(FZ_REPLY_ERROR|FZ_REPLY_DISCONNECTED|nError);
 	m_RecvBuffer.clear();
-	m_MultiLine = "";
+	m_MultiLine = _T("");
+	m_RecvBufferA = "";
 	m_bDidRejectCertificate = FALSE;
 
 	m_useZlib = false;
 	m_zlibSupported = false;
 	m_zlibLevel = 0;
 
+	m_bUTF8 = false;
+
 	CControlSocket::Close();
 }
 
@@ -4875,6 +4936,8 @@
 		line.MakeUpper();
 		if (line == _T(" MODE Z") || line.Left(8) == _T(" MODE Z "))
 			m_zlibSupported = true;
+		if (line == _T(" UTF8") || line.Left(8) == _T(" UTF8 "))
+			m_bUTF8 = true;
 	}
 }
 
diff -Nur source.orig\FtpControlSocket.h source\FtpControlSocket.h
--- source.orig\FtpControlSocket.h	Mon Jun 07 22:59:10 2004
+++ source\FtpControlSocket.h	Mon Feb 28 23:25:03 2005
@@ -120,6 +120,7 @@
 	CTime m_LastSendTime;
 	
 	CString m_ServerName;
+	CStringA m_RecvBufferA;
 	std::list<CString> m_RecvBuffer;
 	CTime m_LastRecvTime;
 	class CListData;
@@ -129,6 +130,8 @@
 	bool m_useZlib;
 	bool m_zlibSupported;
 	int m_zlibLevel;
+
+	bool m_bUTF8;
 
 private:
 	BOOL m_bCheckForTimeout;
diff -Nur source.orig\FtpListResult.cpp source\FtpListResult.cpp
--- source.orig\FtpListResult.cpp	Sun Feb 27 00:35:57 2005
+++ source\FtpListResult.cpp	Mon Feb 28 23:47:52 2005
@@ -142,11 +142,12 @@
 
 #endif
 
-CFtpListResult::CFtpListResult(t_server server)
+CFtpListResult::CFtpListResult(t_server server, bool bUTF8)
 {
 	listhead=curpos=0;
 	
 	m_server = server;
+	m_bUTF8 = bUTF8;
 
 	pos=0;
 
@@ -2129,12 +2130,71 @@
 
 void CFtpListResult::copyStr(CString &target, int pos, const char *source, int len) const
 {
-	int i;
-	LPTSTR pBuffer = target.GetBuffer(pos + len);
-	ASSERT(pBuffer);
-	for (i = 0; i < len; i++)
-		pBuffer[pos + i] = source[i];
-	target.ReleaseBuffer(pos + len);
+#if defined(_UNICODE)
+	if (m_bUTF8) {
+		char *p = new char[len+1];
+		memcpy(p, source, len);
+		p[len] = '\0';
+		// convert from UTF-8 to Unicode
+		int len = MultiByteToWideChar(CP_UTF8, 0, p, -1, NULL, 0);
+		wchar_t *p2 = new wchar_t[len * 2 + 1];
+		MultiByteToWideChar(CP_UTF8, 0, p, -1 , (LPWSTR)p2, len*2);
+		int i;
+		int ulen = wcslen(p2);
+		LPTSTR pBuffer = target.GetBuffer(pos + ulen);
+		ASSERT(pBuffer);
+		for (i = 0; i < ulen; i++)
+			pBuffer[pos + i] = p2[i];
+		target.ReleaseBuffer(pos + ulen);
+		delete [] p;
+		delete [] p2;
+	}
+	else {
+		USES_CONVERSION;
+		char *p = new char[len+1];
+		memcpy(p, source, len);
+		p[len] = '\0';
+		CString tempstr = A2CT(p);
+		int i;
+		int ulen = tempstr.GetLength();
+		LPTSTR pBuffer = target.GetBuffer(pos + ulen);
+		ASSERT(pBuffer);
+		for (i = 0; i < ulen; i++)
+			pBuffer[pos + i] = tempstr[i];
+		target.ReleaseBuffer(pos + ulen);
+		delete [] p;
+	}
+#else
+	if (m_bUTF8) {
+		char *p = new char[len+1];
+		memcpy(p, source, len);
+		p[len] = '\0';
+		// convert from UTF-8 to ANSI
+		int len = MultiByteToWideChar(CP_UTF8, 0, p, -1, NULL, 0);
+		char *p1 = new char[len * 2 + 1];
+		char *p2 = new char[len * 2 + 1];
+		MultiByteToWideChar(CP_UTF8, 0, p, -1 , (LPWSTR)p1, len*2);
+		WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
+		int i;
+		int ulen = strlen(p2);
+		LPTSTR pBuffer = target.GetBuffer(pos + ulen);
+		ASSERT(pBuffer);
+		for (i = 0; i < ulen; i++)
+			pBuffer[pos + i] = p2[i];
+		target.ReleaseBuffer(pos + ulen);
+		delete [] p;
+		delete [] p1;
+		delete [] p2;
+	}
+	else {
+		int i;
+		LPTSTR pBuffer = target.GetBuffer(pos + len);
+		ASSERT(pBuffer);
+		for (i = 0; i < len; i++)
+			pBuffer[pos + i] = source[i];
+		target.ReleaseBuffer(pos + len);
+	}
+#endif
 }
 
 BOOL CFtpListResult::parseAsIBM(const char *line, const int linelen, t_directory::t_direntry &direntry)
diff -Nur source.orig\FtpListResult.h source\FtpListResult.h
--- source.orig\FtpListResult.h	Fri Jan 14 14:50:46 2005
+++ source\FtpListResult.h	Sun Feb 27 00:16:17 2005
@@ -55,9 +55,10 @@
 {
 public:
 	t_server m_server;
+	bool m_bUTF8;
 	void SendToMessageLog(HWND hWnd, UINT nMsg);
 	void AddData(char *data,int size);
-	CFtpListResult(t_server server);
+	CFtpListResult(t_server server, bool bUTF8 = false);
 	~CFtpListResult();
 	t_directory::t_direntry *getList(int &num, CTime EntryTime);
 
diff -Nur source.orig\StatusCtrl.cpp source\StatusCtrl.cpp
--- source.orig\StatusCtrl.cpp	Wed Oct 27 16:18:18 2004
+++ source\StatusCtrl.cpp	Sun Feb 27 20:54:51 2005
@@ -135,7 +135,7 @@
 
 	rtfstr += "} ";
 
-	char *buffer = new char[rtfstr.GetLength() + 5];
+	char *buffer = new char[rtfstr.GetLength()*2 + 5];
 	strcpy(buffer + 4, T2CA(rtfstr));
 	*(int *)buffer = 0;
 
@@ -279,7 +279,7 @@
 	CString rtfstr = m_RTFHeader;
 	rtfstr += "} ";
 
-	char *buffer = new char[rtfstr.GetLength() + 5];
+	char *buffer = new char[rtfstr.GetLength()*2 + 5];
 	strcpy(buffer + 4, T2CA(rtfstr));
 	*(int *)buffer = 0;
 
@@ -324,7 +324,7 @@
 		__time64_t t = _time64(0);
 		if (!strftime(buf, 100, "[%H:%M:%S] ", _localtime64(&t)))
 			buf[0] = 0;
-		CString stime = A2CT(buf);
+		stime = A2CT(buf);
 	}
 
 	CString str;
@@ -371,7 +371,7 @@
 	
 	rtfstr += "} ";
 
-	char *buffer = new char[rtfstr.GetLength() + 5]; //Make it large enough to hold unicode data
+	char *buffer = new char[rtfstr.GetLength()*2 + 5]; //Make it large enough to hold unicode data
 	strcpy(buffer + 4, T2CA(rtfstr));
 	*(int *)buffer = 0;
 
diff -Nur source.orig\TransferSocket.cpp source\TransferSocket.cpp
--- source.orig\TransferSocket.cpp	Sun Feb 20 12:30:52 2005
+++ source\TransferSocket.cpp	Sun Feb 27 00:14:15 2005
@@ -79,7 +79,7 @@
 	m_pSslLayer = NULL;
 	m_pGssLayer = NULL;
 
-	m_pListResult = new CFtpListResult(pOwner->m_CurrentServer);
+	m_pListResult = new CFtpListResult(pOwner->m_CurrentServer, pOwner->m_bUTF8);
 	m_LastUpdateTime.QuadPart = 0;
 
 	memset(&m_zlibStream, 0, sizeof(m_zlibStream));

User avatar
botg
Site Admin
Posts: 35509
Joined: 2004-02-23 20:49
First name: Tim
Last name: Kosse

#7 Post by botg » 2005-02-28 19:02

Thanks, though I did already apply your previous patch with some modifications. Please use the version in CVS for further modifications.

twu2
425 Can't open data connection
Posts: 45
Joined: 2005-02-26 16:54

#8 Post by twu2 » 2005-03-01 01:11

Thanks.

I checkout from CVS today, it's work now for both unicode build and ansi build.
But I found in FtpListResult.cpp, we still convert to ansi first, then convert to unicode in unicode build, this may lost something.

so here is the patch for this file.

Code: Select all

diff -Nur source/FtpListResult.cpp source.patch/FtpListResult.cpp
--- source/FtpListResult.cpp	2005-03-01 08:57:42.000000000 +0800
+++ source.patch/FtpListResult.cpp	2005-03-01 09:03:09.000000000 +0800
@@ -370,26 +370,8 @@
 	while (line)
 	{
 		int tmp;
-		char *tmpline;
-		if (m_bUTF8)
-		{
-			// convert from UTF-8 to ANSI
-			// First get the length
-			int len = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
-			// Now allocate buffer and convert to unicode
-			char *p1 = new char[len * 2 + 1];
-			MultiByteToWideChar(CP_UTF8, 0, line, -1 , (LPWSTR)p1, len * 2);
-			// Convert back to local charset
-			char *p2 = new char[len * 2 + 1];
-			WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
-			tmpline = p2;
-			delete [] p1;
-		}
-		else
-		{
-			tmpline = new char[strlen(line) + 1];
-			strcpy(tmpline, line);
-		}
+		char *tmpline = new char[strlen(line) + 1];
+		strcpy(tmpline, line);
 		if (parseLine(tmpline, strlen(tmpline), direntry, tmp))
 		{
 			delete [] tmpline;
@@ -560,26 +542,8 @@
 			break;
 		}			
 		int tmp;
-		char *tmpline;
-		if (m_bUTF8)
-		{
-			// convert from UTF-8 to ANSI
-			// First get the length
-			int len = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
-			// Now allocate buffer and convert to unicode
-			char *p1 = new char[len * 2 + 1];
-			MultiByteToWideChar(CP_UTF8, 0, line, -1 , (LPWSTR)p1, len * 2);
-			// Convert back to local charset
-			char *p2 = new char[len * 2 + 1];
-			WideCharToMultiByte(CP_ACP, 0,(LPCWSTR)p1, -1, p2, len*2, NULL, NULL);
-			tmpline = p2;
-			delete [] p1;
-		}
-		else
-		{
-			tmpline = new char[strlen(line) + 1];
-			strcpy(tmpline, line);
-		}
+		char *tmpline = new char[strlen(line) + 1];
+		strcpy(tmpline, line);
 		if (parseLine(tmpline, strlen(tmpline), direntry, tmp))
 		{
 			delete [] tmpline;
@@ -2166,33 +2130,37 @@
 
 void CFtpListResult::copyStr(CString &target, int pos, const char *source, int len) const
 {
-#if defined(_UNICODE)
-	if (pos != 0)
-	{
-		int i;
-		LPTSTR pBuffer = target.GetBuffer(pos + len);
-		ASSERT(pBuffer);
-		for (i = 0; i < len; i++)
-			pBuffer[pos + i] = source[i];
-		target.ReleaseBuffer(pos + len);
+	USES_CONVERSION;
+	CString tempstr;
+
+	char *p = new char[len+1];
+	memcpy(p, source, len);
+	p[len] = '\0';
+	if (m_bUTF8)
+	{
+		// convert from UTF-8 to ANSI
+		int len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)p, -1, NULL, 0);
+		if (len != 0)
+		{
+			LPWSTR p1 = new WCHAR[len + 1];
+			MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)p, -1 , (LPWSTR)p1, len*2);
+			tempstr = W2CT(p1);
+			delete [] p1;
+		}
+		else
+			tempstr = A2CT(p);
 	}
 	else
-	{
-		USES_CONVERSION;
-		char *p = new char[len+1];
-		memcpy(p, source, len);
-		p[len] = '\0';
-		target = A2CT(p);
-		delete [] p;
-	}
-#else 
+		tempstr = A2CT(p);
+	delete [] p;
+
 	int i;
-	LPTSTR pBuffer = target.GetBuffer(pos + len);
+	int ulen = tempstr.GetLength();
+	LPTSTR pBuffer = target.GetBuffer(pos + ulen);
 	ASSERT(pBuffer);
-	for (i = 0; i < len; i++)
-		pBuffer[pos + i] = source[i];
-	target.ReleaseBuffer(pos + len);
-#endif
+	for (i = 0; i < ulen; i++)
+		pBuffer[pos + i] = tempstr[i];
+	target.ReleaseBuffer(pos + ulen);
 }
 
 BOOL CFtpListResult::parseAsIBM(const char *line, const int linelen, t_directory::t_direntry &direntry)

eyebex
226 Transfer OK
Posts: 171
Joined: 2004-04-02 15:24

#9 Post by eyebex » 2005-03-01 09:08

@twu2: why don't you post your patches to the sourceforge patch tracker (http://sourceforge.net/tracker/?atid=37 ... unc=browse) instead of this forum? it would be much more convenient for others to have all patches in ONE place.

User avatar
botg
Site Admin
Posts: 35509
Joined: 2004-02-23 20:49
First name: Tim
Last name: Kosse

#10 Post by botg » 2005-03-07 13:26

Thanks twu2, I've applied the last patch.

twu2
425 Can't open data connection
Posts: 45
Joined: 2005-02-26 16:54

#11 Post by twu2 » 2005-03-08 05:17

Thanks.

I've test the code in CVS, the unicode build work fine for me, I can see Chinese filename and Japan filename for the same server now.

Post Reply