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;
}