pscp 項目上傳中文文件亂碼問題

pscp 項目上傳中文文件亂碼問題

putty工程是一個開源項目,可用於遠程連接Linux 機器。其中pscp項目是其中的一個子項目,可用於加密地文件傳輸,類似於Linux系統中的scp命令,但在windows系統中運行pscp.exe,傳輸中文名字的文件到遠程機器中時,遠程機器的文件名會出現亂碼,這是由於windows系統中使用ANSI字符編碼和遠程機器使用UTF-8字符編碼不同導致的。

下面介紹如果修改pscp源碼,使其支持中文文件的傳輸

1.下載putty 工程

putty工程源代碼下載:https://the.earth.li/~sgtatham/putty/latest/putty-src.zip

2.用VS 打開工程putty-0.70\windows\VS2012\putty.sln

3.編譯項目pscp

如果出現報錯:無法找到文件“version.h”

請先修改項目屬性,屬性->配置屬性->VC++目錄,在包含目錄中添加路徑 $(ProjectDir)..\..\..\

4.添加兩個文件,winencode.h和winencode.c 增加字符編碼轉換的函數

winencode.h

#ifndef PUTTY_ENCODE_H
#define PUTTY_ENCODE_H

#include <Windows.h>

#ifdef __cplusplus  
extern "C" {
#endif

	/**
	* ansi轉utf16
	* @srcStr		源字符串
	* @destLen		目標字符串長度(不是size),不包括('\0')
	* @return		目標字符串指針,帶(L'\0')結尾
	*/
	wchar_t* ansi_2_utf16(const char* srcStr, int *destLen);


	/**
	* utf16轉ansi
	* @srcStr		源字符串
	* @destLen		目標字符串長度,不包括('\0')
	* @return		目標字符串指針,帶(L'\0')結尾
	*/
	char* utf16_2_ansi(const wchar_t* srcStr, int *destLen);

	char* utf16_2_utf8(const wchar_t* srcStr, int *destLen);

	wchar_t* utf8_2_utf16(const char* srcStr, int *destLen);

	char* ansi_2_utf8(const char* srcStr, int *destLen);

	char* utf8_2_ansi(const char* srcStr, int *destLen);

#ifdef __cplusplus  
}
#endif
#endif

winencode.c

#include "winencode.h"


wchar_t* ansi_2_utf16(const char* srcStr, int *destLen)
{

	// 獲取轉換後長度(已經包括'\0')
	int len = MultiByteToWideChar(CP_ACP, 0, srcStr, -1, 0, 0);
	len += (len == 0);
	wchar_t* rst = (wchar_t*)malloc(len * 2);
	// 轉換
	len = MultiByteToWideChar(CP_ACP, 0, srcStr, -1, rst, len);
	len += (len == 0);
	rst[len - 1] = '\0';

	if (destLen)
		*destLen = len - 1;
	return rst;

}

char* utf16_2_ansi(const wchar_t* srcStr, int *destLen)
{

	// 獲取轉換後長度(已經包括'\0')
	int len = WideCharToMultiByte(CP_ACP, 0, srcStr, -1, 0, 0, NULL, NULL);
	len += (len == 0);
	char* rst = (char*)malloc(len);
	// 轉換
	len = WideCharToMultiByte(CP_ACP, 0, srcStr, -1, rst, len, NULL, NULL);
	len += (len == 0);
	rst[len - 1] = '\0';

	if (destLen)
		*destLen = len - 1;
	return rst;

}

wchar_t* utf8_2_utf16(const char* srcStr, int *destLen)
{
	// 獲取轉換後長度(已經包括'\0')
	int len = MultiByteToWideChar(CP_UTF8, 0, srcStr, -1, 0, 0);
	len += (len == 0);
	wchar_t* rst = (wchar_t*)malloc(len * 2);
	// 轉換
	len = MultiByteToWideChar(CP_UTF8, 0, srcStr, -1, rst, len);
	len += (len == 0);
	rst[len - 1] = '\0';

	if (destLen)
		*destLen = len - 1;
	return rst;
}

char* utf16_2_utf8(const wchar_t* srcStr, int *destLen)
{

	// 獲取轉換後長度(已經包括'\0')
	int len = WideCharToMultiByte(CP_UTF8, 0, srcStr, -1, 0, 0, NULL, NULL);
	len += (len == 0);
	char* rst = (char*)malloc(len);
	// 轉換
	len = WideCharToMultiByte(CP_UTF8, 0, srcStr, -1, rst, len, NULL, NULL);
	len += (len == 0);
	rst[len - 1] = '\0';

	if (destLen)
		*destLen = len - 1;
	return rst;
}

char* ansi_2_utf8(const char* srcStr, int *destLen)
{

	wchar_t* utf16Str = ansi_2_utf16(srcStr, 0);
	char* utf8Str = utf16_2_utf8(utf16Str, destLen);
	free(utf16Str);
	return utf8Str;
}

char* utf8_2_ansi(const char* srcStr, int *destLen)
{
	wchar_t* utf16Str = utf8_2_utf16(srcStr, 0);
	char* ansiStr = utf16_2_ansi(utf16Str, destLen);
	free(utf16Str);
	return ansiStr;
}

5. 修改文件sftp.c
    添加頭文件 #include "winencode.h"
    修改fxp_open_send()函數

/*
 * Open a file.
 */
struct sftp_request *fxp_open_send(const char *path, int type,
                                   struct fxp_attrs *attrs)
{
    struct sftp_request *req = sftp_alloc_request();
    struct sftp_packet *pktout;
	char * utf8_path;
	utf8_path = ansi_2_utf8(path, 0);
    pktout = sftp_pkt_init(SSH_FXP_OPEN);
    sftp_pkt_adduint32(pktout, req->id);
    sftp_pkt_addstring(pktout, utf8_path);
    sftp_pkt_adduint32(pktout, type);
	free(utf8_path);
    if (attrs)
        sftp_pkt_addattrs(pktout, *attrs);
    else
        sftp_pkt_adduint32(pktout, 0); /* empty ATTRS structure */
    sftp_send(pktout);
    return req;
}

6.編譯運行即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章