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);elsesftp_pkt_adduint32(pktout, 0); /* empty ATTRS structure */sftp_send(pktout);return req;
}