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.编译运行即可

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