• R/O
  • SSH
  • HTTPS

ttssh2: Commit


Commit MetaInfo

Revision11021 (tree)
Time2023-10-22 13:13:04
Authorzmatsuo

Log Message

SCP送受信ダイアログのファイル名に漢字等が含まれていると送受信できない問題を修正

- [ファイル] - [SSH SCP...] SCPダイアログからの送受信
- ダイアログ、ファイル名の扱いをUnicode化

- エラーメッセージなども正しく表示されなかったので修正

- ANSI版ダウンロードディレクトリ TTTSet.FileDir を廃止

- TTTSet.reserve_FileDir へリネーム
- TTTSet.FileDirW のみ使用

Change Summary

Incremental Difference

--- trunk/teraterm/common/ttlib.c (revision 11020)
+++ trunk/teraterm/common/ttlib.c (revision 11021)
@@ -237,7 +237,7 @@
237237 return TRUE;
238238 }
239239
240-BOOL ExtractFileName(PCHAR PathName, PCHAR FileName, int destlen)
240+BOOL ExtractFileName(const char *PathName, PCHAR FileName, int destlen)
241241 {
242242 int i, j;
243243
@@ -249,7 +249,7 @@
249249 return (strlen(FileName)>0);
250250 }
251251
252-BOOL ExtractDirName(PCHAR PathName, PCHAR DirName)
252+BOOL ExtractDirName(const char *PathName, PCHAR DirName)
253253 {
254254 int i, j;
255255
--- trunk/teraterm/common/ttlib.h (revision 11020)
+++ trunk/teraterm/common/ttlib.h (revision 11021)
@@ -52,8 +52,8 @@
5252 BOOL GetFileNamePos(const char *PathName, int *DirLen, int *FNPos);
5353 BOOL GetFileNamePosU8(const char *PathName, int *DirLen, int *FNPos);
5454 BOOL GetFileNamePosW(const wchar_t *PathName, size_t *DirLen, size_t *FNPos);
55-DllExport BOOL ExtractFileName(PCHAR PathName, PCHAR FileName, int destlen);
56-DllExport BOOL ExtractDirName(PCHAR PathName, PCHAR DirName);
55+DllExport BOOL ExtractFileName(const char *PathName, PCHAR FileName, int destlen);
56+DllExport BOOL ExtractDirName(const char *PathName, PCHAR DirName);
5757 wchar_t *ExtractDirNameW(const wchar_t *PathName);
5858 wchar_t *ExtractFileNameW(const wchar_t *PathName);
5959 void FitFileName(PCHAR FileName, int destlen, const char *DefExt);
--- trunk/teraterm/common/tttypes.h (revision 11020)
+++ trunk/teraterm/common/tttypes.h (revision 11021)
@@ -347,7 +347,7 @@
347347 WORD XmodemOpt, XmodemBin;
348348 int ZmodemDataLen, ZmodemWinSize;
349349 int QVWinSize;
350- char FileDir[MAXPATHLEN]; // switch FileDirW
350+ char reserve_FileDir[256]; // switch FileDirW
351351 char FileSendFilter[128];
352352 WORD Language;
353353 char DelimList[52];
@@ -541,7 +541,7 @@
541541 WORD LogLockExclusive;
542542 WORD KermitOpt;
543543 WORD FontQuality;
544- char ScpSendDir[MAXPATHLEN];
544+ char ScpSendDir[MAXPATHLEN]; // SCP 送信先(ホストのディレクトリ)
545545 char reserver_BGImageFilePath[MAX_PATH];
546546 int LogRotate; // enum rotate_mode LogRotate;
547547 DWORD LogRotateSize;
--- trunk/teraterm/teraterm/ttdde.c (revision 11020)
+++ trunk/teraterm/teraterm/ttdde.c (revision 11021)
@@ -450,7 +450,8 @@
450450 break;
451451 }
452452 case CmdChangeDir:
453- strncpy_s(ts.FileDir, sizeof(ts.FileDir),ParamFileName, _TRUNCATE);
453+ free(ts.FileDirW);
454+ ts.FileDirW = ToWcharU8(ParamFileName);
454455 break;
455456 case CmdClearScreen:
456457 switch (ParamFileName[0]) {
--- trunk/teraterm/ttpdlg/ttdlg.c (revision 11020)
+++ trunk/teraterm/ttpdlg/ttdlg.c (revision 11021)
@@ -1891,7 +1891,6 @@
18911891 if (DoesFolderExistW(FileDirExpanded)) {
18921892 free(ts->FileDirW);
18931893 ts->FileDirW = new_dir;
1894- WideCharToACP_t(ts->FileDirW, ts->FileDir, sizeof(ts->FileDir));
18951894 OK = TRUE;
18961895 }
18971896 else {
--- trunk/teraterm/ttpset/ttset.c (revision 11020)
+++ trunk/teraterm/ttpset/ttset.c (revision 11021)
@@ -1175,7 +1175,6 @@
11751175 free(ts->FileDirW);
11761176 ts->FileDirW = GetDownloadFolderW();
11771177 }
1178- WideCharToACP_t(ts->FileDirW, ts->FileDir, sizeof(ts->FileDir));
11791178
11801179 /* filter on file send (2007.6.5 maya) */
11811180 GetPrivateProfileString(Section, "FileSendFilter", "",
@@ -3770,7 +3769,9 @@
37703769 if (dir != NULL && wcslen(dir) > 0 && DoesFolderExistW(dir)) {
37713770 free(ts->FileDirW);
37723771 ts->FileDirW = _wcsdup(dir);
3772+#if 0
37733773 WideCharToACP_t(ts->FileDirW, ts->FileDir, sizeof(ts->FileDir));
3774+#endif
37743775 }
37753776 free(dir);
37763777 }
--- trunk/ttssh2/ttxssh/ssh.c (revision 11020)
+++ trunk/ttssh2/ttxssh/ssh.c (revision 11021)
@@ -43,21 +43,18 @@
4343 #include <openssl/rsa.h>
4444 #include <openssl/dsa.h>
4545 #include <openssl/md5.h>
46+
4647 #include <limits.h>
4748 #include <malloc.h>
4849 #include <string.h>
50+#if !defined(_CRTDBG_MAP_ALLOC)
51+#define _CRTDBG_MAP_ALLOC
52+#endif
4953 #include <stdlib.h>
54+#include <crtdbg.h>
5055 #include <process.h>
5156 #include <time.h>
5257 #include <commctrl.h>
53-#include "buffer.h"
54-#include "ssh.h"
55-#include "crypt.h"
56-#include "fwd.h"
57-#include "sftp.h"
58-#include "kex.h"
59-#include "dlglib.h"
60-
6158 #include <sys/types.h>
6259 #include <sys/stat.h>
6360 #include <sys/utime.h>
@@ -69,6 +66,16 @@
6966 #include <fcntl.h>
7067 #endif
7168
69+
70+#include "buffer.h"
71+#include "ssh.h"
72+#include "crypt.h"
73+#include "fwd.h"
74+#include "sftp.h"
75+#include "kex.h"
76+#include "dlglib.h"
77+#include "win32helper.h"
78+
7279 #ifndef MAX
7380 # define MAX(a,b) (((a)>(b))?(a):(b))
7481 # define MIN(a,b) (((a)<(b))?(a):(b))
@@ -4196,22 +4203,55 @@
41964203 }
41974204 }
41984205
4206+static int accessU8(const char *pathU8, int mode)
4207+{
4208+ wchar_t *pathW = ToWcharU8(pathU8);
4209+ int r = _waccess(pathW, mode);
4210+ free(pathW);
4211+ return r;
4212+}
4213+
4214+DWORD hFormatMessageW(DWORD error, wchar_t **message)
4215+{
4216+ LPWSTR lpMsgBuf;
4217+ DWORD r =
4218+ FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
4219+ NULL,
4220+ error,
4221+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
4222+ (LPWSTR)&lpMsgBuf,
4223+ 0,
4224+ NULL);
4225+ if (r == 0) {
4226+ *message = NULL;
4227+ return GetLastError();
4228+ }
4229+ *message = _wcsdup(lpMsgBuf);
4230+ LocalFree(lpMsgBuf);
4231+ return NO_ERROR;
4232+}
4233+
41994234 /**
42004235 * SCP support
42014236 *
4202- * @param sendfile UTF-8
4203- * @param dstfile UTF-8
4204- * @param direction
4237+ * @param sendfile ファイル名,UTF-8
4238+ * @param dstfile ファイル名,UTF-8
4239+ * TOREMOTE のとき、
4240+ * NULL のとき、ホームフォルダ
4241+ * 相対パス、ホームフォルダからの相対?
4242+ * 絶対パス
4243+ * TOLOCAL のとき
4244+ * NULL のとき、ダウンロードフォルダ
4245+ * 相対パス、カレントフォルダからの相対?
4246+ * 絶対パス
4247+ * @param direction TOREMOTE copy local to remote
4248+ * FROMREMOTE copy remote to local
4249+ *
42054250 */
4206-int SSH_scp_transaction(PTInstVar pvar, char *sendfile, char *dstfile, enum scp_dir direction)
4251+int SSH_scp_transaction(PTInstVar pvar, const char *sendfile, const char *dstfile, enum scp_dir direction)
42074252 {
4208- buffer_t *msg;
4209- char *s;
4210- unsigned char *outmsg;
4211- int len;
42124253 Channel_t *c = NULL;
42134254 FILE *fp = NULL;
4214- struct __stat64 st;
42154255
42164256 // ソケットがクローズされている場合は何もしない。
42174257 if (pvar->socket == INVALID_SOCKET)
@@ -4235,25 +4275,22 @@
42354275 }
42364276
42374277 if (direction == TOREMOTE) { // copy local to remote
4278+ struct __stat64 st;
42384279 fp = fopenU8(sendfile, "rb");
42394280 if (fp == NULL) {
4240- char buf[1024];
4241- int len;
4242- UTIL_get_lang_msg("MSG_SSH_SCP_FILEOPEN_READ_ERROR", pvar,
4243- "Can't open file for reading:");
4244- _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%s ", pvar->UIMsg);
4245- len = strlen(buf);
4246- FormatMessage(
4247- FORMAT_MESSAGE_FROM_SYSTEM,
4248- NULL,
4249- GetLastError(),
4250- 0,
4251- buf+len,
4252- sizeof(buf)-len,
4253- NULL);
4254- UTIL_get_lang_msg("MSG_SSH_SCP_FILEOPEN_ERROR_TITLE", pvar,
4255- "TTSSH: file open error");
4256- MessageBox(NULL, buf, pvar->UIMsg, MB_OK | MB_ICONERROR);
4281+ static const TTMessageBoxInfoW info = {
4282+ "TTSSH",
4283+ "MSG_SSH_SCP_FILEOPEN_ERROR_TITLE", L"TTSSH: file open error",
4284+ "MSG_SSH_SCP_FILEOPEN_READ_ERROR", L"Can't open file for reading: %s %s",
4285+ MB_OK | MB_ICONERROR
4286+ };
4287+ DWORD error = GetLastError();
4288+ wchar_t *err_str;
4289+ hFormatMessageW(error, &err_str);
4290+ wchar_t *fname = ToWcharU8(sendfile);
4291+ TTMessageBoxW(NULL, &info, pvar->ts->UILanguageFileW, err_str, fname);
4292+ free(fname);
4293+ free(err_str);
42574294 goto error;
42584295 }
42594296
@@ -4276,14 +4313,18 @@
42764313
42774314 if (dstfile == NULL || dstfile[0] == '\0') { // local file path is empty.
42784315 char *fn;
4279- char FileDirExpanded[MAX_PATH];
4316+ wchar_t *FileDirExpanded;
4317+ char *FileDirExpandedU8;
42804318
42814319 fn = strrchr(sendfile, '/');
42824320 if (fn && fn[1] == '\0')
42834321 goto error;
42844322
4285- ExpandEnvironmentStrings(pvar->ts->FileDir, FileDirExpanded, sizeof(FileDirExpanded));
4286- _snprintf_s(c->scp.localfilefull, sizeof(c->scp.localfilefull), _TRUNCATE, "%s\\%s", FileDirExpanded, fn ? fn : sendfile);
4323+ hExpandEnvironmentStringsW(pvar->ts->FileDirW, &FileDirExpanded);
4324+ FileDirExpandedU8 = ToU8W(FileDirExpanded);
4325+ _snprintf_s(c->scp.localfilefull, sizeof(c->scp.localfilefull), _TRUNCATE, "%s\\%s", FileDirExpandedU8, fn ? fn : sendfile);
4326+ free(FileDirExpanded);
4327+ free(FileDirExpandedU8);
42874328 ExtractFileName(c->scp.localfilefull, c->scp.localfile, sizeof(c->scp.localfile)); // file name only
42884329 } else {
42894330 _snprintf_s(c->scp.localfilefull, sizeof(c->scp.localfilefull), _TRUNCATE, "%s", dstfile);
@@ -4290,48 +4331,49 @@
42904331 ExtractFileName(dstfile, c->scp.localfile, sizeof(c->scp.localfile)); // file name only
42914332 }
42924333
4293- if (_access(c->scp.localfilefull, 0x00) == 0) {
4294- char buf[512];
4334+ if (accessU8(c->scp.localfilefull, 0x00) == 0) {
42954335 int dlgresult;
4296- if (_access(c->scp.localfilefull, 0x02) == -1) { // 0x02 == writable
4297- UTIL_get_lang_msg("MSG_SSH_SCP_FILEOPEN_READONLY_ERROR", pvar,
4298- "`%s' file is read only.");
4299- _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->UIMsg, c->scp.localfilefull);
4300- UTIL_get_lang_msg("MSG_SSH_SCP_FILEOPEN_ERROR_TITLE", pvar,
4301- "TTSSH: file open error");
4302- MessageBox(NULL, buf, pvar->UIMsg, MB_OK | MB_ICONERROR);
4336+ if (accessU8(c->scp.localfilefull, 0x02) == -1) { // 0x02 == writable
4337+ static const TTMessageBoxInfoW info = {
4338+ "TTSSH",
4339+ "MSG_SSH_SCP_FILEOPEN_ERROR_TITLE", L"TTSSH: file open error",
4340+ "MSG_SSH_SCP_FILEOPEN_READONLY_ERROR", L"`%s' file is read only.",
4341+ MB_OK | MB_ICONERROR
4342+ };
4343+ wchar_t *fname = ToWcharU8(c->scp.localfilefull);
4344+ TTMessageBoxW(NULL, &info, pvar->ts->UILanguageFileW, fname);
4345+ free(fname);
43034346 goto error;
43044347 }
4305- UTIL_get_lang_msg("MSG_SSH_SCP_FILEOPEN_OVERWRITE_CONFIRM", pvar,
4306- "`%s' file exists.\noverwrite it?");
4307- _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->UIMsg, c->scp.localfilefull);
4308- UTIL_get_lang_msg("MSG_SSH_SCP_CONFIRM_TITLE", pvar,
4309- "TTSSH: confirm");
4310- dlgresult = MessageBox(NULL, buf, pvar->UIMsg, MB_YESNO | MB_ICONQUESTION);
4348+ static const TTMessageBoxInfoW info = {
4349+ "TTSSH",
4350+ "MSG_SSH_SCP_CONFIRM_TITLE", L"TTSSH: confirm",
4351+ "MSG_SSH_SCP_FILEOPEN_OVERWRITE_CONFIRM", L"`%s' file exists.\noverwrite it?",
4352+ MB_YESNO | MB_ICONQUESTION
4353+ };
4354+ wchar_t *fname = ToWcharU8(c->scp.localfilefull);
4355+ dlgresult = TTMessageBoxW(NULL, &info, pvar->ts->UILanguageFileW, fname);
4356+ free(fname);
43114357 if (dlgresult == IDNO) {
43124358 goto error;
43134359 }
43144360 }
43154361
4316- fp = fopen(c->scp.localfilefull, "wb");
4362+ fp = fopenU8(c->scp.localfilefull, "wb");
43174363 if (fp == NULL) {
4318- char buf[1024];
4319- int len;
4320- UTIL_get_lang_msg("MSG_SSH_SCP_FILEOPEN_WRITE_ERROR", pvar,
4321- "Can't open file for writing:");
4322- _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%s ", pvar->UIMsg);
4323- len = strlen(buf);
4324- FormatMessage(
4325- FORMAT_MESSAGE_FROM_SYSTEM,
4326- NULL,
4327- GetLastError(),
4328- 0,
4329- buf+len,
4330- sizeof(buf)-len,
4331- NULL);
4332- UTIL_get_lang_msg("MSG_SSH_SCP_FILEOPEN_ERROR_TITLE", pvar,
4333- "TTSSH: file open error");
4334- MessageBox(NULL, buf, pvar->UIMsg, MB_OK | MB_ICONERROR);
4364+ static const TTMessageBoxInfoW info = {
4365+ "TTSSH",
4366+ "MSG_SSH_SCP_FILEOPEN_ERROR_TITLE", L"TTSSH: file open error",
4367+ "MSG_SSH_SCP_FILEOPEN_WRITE_ERROR", L"Can't open file for writing: %s %s",
4368+ MB_OK | MB_ICONERROR
4369+ };
4370+ DWORD error = GetLastError();
4371+ wchar_t *err_str;
4372+ hFormatMessageW(error, &err_str);
4373+ wchar_t *fname = ToWcharU8(c->scp.localfilefull);
4374+ TTMessageBoxW(NULL, &info, pvar->ts->UILanguageFileW, err_str, fname);
4375+ free(fname);
4376+ free(err_str);
43354377 goto error;
43364378 }
43374379
@@ -4342,21 +4384,28 @@
43424384 c->scp.dir = direction;
43434385 c->scp.state = SCP_INIT;
43444386
4345- // session open
4346- msg = buffer_init();
4347- if (msg == NULL) {
4348- goto error;
4387+ {
4388+ buffer_t *msg;
4389+ char *s;
4390+ unsigned char *outmsg;
4391+ int len;
4392+
4393+ // session open
4394+ msg = buffer_init();
4395+ if (msg == NULL) {
4396+ goto error;
4397+ }
4398+ s = "session";
4399+ buffer_put_string(msg, s, strlen(s)); // ctype
4400+ buffer_put_int(msg, c->self_id); // self(channel number)
4401+ buffer_put_int(msg, c->local_window); // local_window
4402+ buffer_put_int(msg, c->local_maxpacket); // local_maxpacket
4403+ len = buffer_len(msg);
4404+ outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN, len);
4405+ memcpy(outmsg, buffer_ptr (msg), len);
4406+ finish_send_packet(pvar);
4407+ buffer_free(msg);
43494408 }
4350- s = "session";
4351- buffer_put_string(msg, s, strlen(s)); // ctype
4352- buffer_put_int(msg, c->self_id); // self(channel number)
4353- buffer_put_int(msg, c->local_window); // local_window
4354- buffer_put_int(msg, c->local_maxpacket); // local_maxpacket
4355- len = buffer_len(msg);
4356- outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN, len);
4357- memcpy(outmsg, buffer_ptr (msg), len);
4358- finish_send_packet(pvar);
4359- buffer_free(msg);
43604409
43614410 g_scp_sending = TRUE;
43624411
@@ -7426,7 +7475,8 @@
74267475
74277476 BOOL handle_SSH2_userauth_passwd_changereq(PTInstVar pvar)
74287477 {
7429- int len, ret;
7478+ int len;
7479+ INT_PTR ret;
74307480 char *data;
74317481 buffer_t *msg = NULL;
74327482 char *s, *username;
@@ -8094,7 +8144,7 @@
80948144 size_t buflen;
80958145 } scp_dlg_parm_t;
80968146
8097-static LRESULT CALLBACK ssh_scp_dlg_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
8147+static INT_PTR CALLBACK ssh_scp_dlg_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
80988148 {
80998149 static int closed = 0;
81008150
@@ -8181,21 +8231,13 @@
81818231 return 0;
81828232 }
81838233
8184-/* dlglib に全く同じものがあるのでそちらを利用する */
8185-#if 0
8186-void InitDlgProgress(HWND HDlg, int id_Progress, int *CurProgStat) {
8187- HWND HProg;
8188- HProg = GetDlgItem(HDlg, id_Progress);
8189-
8190- *CurProgStat = 0;
8191-
8192- SendMessage(HProg, PBM_SETRANGE, (WPARAM)0, MAKELPARAM(0, 100));
8193- SendMessage(HProg, PBM_SETSTEP, (WPARAM)1, 0);
8194- SendMessage(HProg, PBM_SETPOS, (WPARAM)0, 0);
8195-
8196- return;
8234+static BOOL SetDlgItemTextU8(HWND hDlg, int nIDDlgItem, const char *strU8)
8235+{
8236+ wchar_t *strW = ToWcharU8(strU8);
8237+ BOOL retval = SetDlgItemTextW(hDlg, nIDDlgItem, strW);
8238+ free(strW);
8239+ return retval;
81978240 }
8198-#endif
81998241
82008242 static unsigned __stdcall ssh_scp_thread(void *p)
82018243 {
@@ -8215,8 +8257,7 @@
82158257 buflen = min(c->remote_window, 8192*4); // max 32KB
82168258 buf = malloc(buflen);
82178259
8218- //SendMessage(GetDlgItem(hWnd, IDC_FILENAME), WM_SETTEXT, 0, (LPARAM)c->scp.localfile);
8219- SendMessage(GetDlgItem(hWnd, IDC_FILENAME), WM_SETTEXT, 0, (LPARAM)c->scp.localfilefull);
8260+ SetDlgItemTextU8(hWnd, IDC_FILENAME, c->scp.localfilefull);
82208261
82218262 InitDlgProgress(hWnd, IDC_PROGBAR, &ProgStat);
82228263
@@ -8351,8 +8392,8 @@
83518392 HANDLE thread;
83528393 unsigned int tid;
83538394
8354- hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS),
8355- pvar->cv->HWin, (DLGPROC)ssh_scp_dlg_proc);
8395+ hDlgWnd = TTCreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS),
8396+ pvar->cv->HWin, ssh_scp_dlg_proc);
83568397 if (hDlgWnd != NULL) {
83578398 static const DlgTextInfo text_info[] = {
83588399 { 0, "DLG_SCP_PROGRESS_TITLE_SENDFILE" },
@@ -8697,8 +8738,8 @@
86978738
86988739 // 進捗ウィンドウ
86998740 c->scp.pvar = pvar;
8700- hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS),
8701- pvar->cv->HWin, (DLGPROC)ssh_scp_dlg_proc);
8741+ hDlgWnd = TTCreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS),
8742+ pvar->cv->HWin, ssh_scp_dlg_proc);
87028743 if (hDlgWnd != NULL) {
87038744 static const DlgTextInfo text_info[] = {
87048745 { 0, "DLG_SCP_PROGRESS_TITLE_RECEIVEFILE" },
@@ -8709,7 +8750,7 @@
87098750 SetI18nDlgStrsW(hDlgWnd, "TTSSH", text_info, _countof(text_info), pvar->ts->UILanguageFileW);
87108751
87118752 c->scp.progress_window = hDlgWnd;
8712- SendMessage(GetDlgItem(hDlgWnd, IDC_FILENAME), WM_SETTEXT, 0, (LPARAM)c->scp.localfilefull);
8753+ SetDlgItemTextU8(hDlgWnd, IDC_FILENAME, c->scp.localfilefull);
87138754 ShowWindow(hDlgWnd, SW_SHOW);
87148755 }
87158756
@@ -8830,7 +8871,7 @@
88308871 error:
88318872 { // error
88328873 char msg[2048];
8833- unsigned int i, max;
8874+ unsigned int max;
88348875 int offset, resp;
88358876
88368877 resp = data[0];
@@ -8843,14 +8884,12 @@
88438884 offset = 0;
88448885 }
88458886
8846- if (buflen > sizeof(msg))
8847- max = sizeof(msg);
8887+ if (buflen > sizeof(msg) - 1)
8888+ max = sizeof(msg) - 1;
88488889 else
88498890 max = buflen - offset;
8850- for (i = 0 ; i < max ; i++) {
8851- msg[i] = data[i + offset];
8852- }
8853- msg[i] = '\0';
8891+ memcpy(msg, &data[offset], max);
8892+ msg[max] = '\0';
88548893
88558894 // よく分からないエラーの場合は、自身でチャネルをクローズする。
88568895 // .bashrc に"stty stop undef"が定義されていると、TTSSHが落ちる問題への暫定処置。
@@ -8863,9 +8902,12 @@
88638902 //ssh2_channel_send_close(pvar, c);
88648903 }
88658904
8866- UTIL_get_lang_msg("MSG_SSH_SCP_ERROR_TITLE", pvar,
8867- "TTSSH: SCP error");
8868- MessageBox(NULL, msg, pvar->UIMsg, MB_OK | MB_ICONEXCLAMATION);
8905+ wchar_t uimsgW[MAX_UIMSG];
8906+ UTIL_get_lang_msgW("MSG_SSH_SCP_ERROR_TITLE", pvar,
8907+ L"TTSSH: SCP error", uimsgW);
8908+ wchar_t *msgW = ToWcharU8(msg);
8909+ MessageBoxW(pvar->cv->HWin, msgW, uimsgW, MB_OK | MB_ICONEXCLAMATION);
8910+ free(msgW);
88698911 }
88708912 }
88718913
--- trunk/ttssh2/ttxssh/ssh.h (revision 11020)
+++ trunk/ttssh2/ttxssh/ssh.h (revision 11021)
@@ -480,7 +480,7 @@
480480 int SSH_start_scp(PTInstVar pvar, char *sendfile, char *dstfile);
481481 int SSH_scp_sending_status(void);
482482 int SSH_start_scp_receive(PTInstVar pvar, char *filename);
483-int SSH_scp_transaction(PTInstVar pvar, char *sendfile, char *dstfile, enum scp_dir direction);
483+int SSH_scp_transaction(PTInstVar pvar, const char *sendfile, const char *dstfile, enum scp_dir direction);
484484 int SSH_sftp_transaction(PTInstVar pvar);
485485
486486 /* auxiliary SSH2 interfaces for pkt.c */
--- trunk/ttssh2/ttxssh/ttxssh.c (revision 11020)
+++ trunk/ttssh2/ttxssh/ttxssh.c (revision 11021)
@@ -104,6 +104,7 @@
104104 #include "win32helper.h"
105105 #include "comportinfo.h"
106106 #include "asprintf.h"
107+#include "ttcommdlg.h"
107108
108109 #include "libputty.h"
109110
@@ -3283,6 +3284,28 @@
32833284 return (datalength); // success
32843285 }
32853286
3287+/**
3288+ * SCPのパスを保存する
3289+ *
3290+ * TODO
3291+ * - tsに書き戻してしまってよい?
3292+ * - Unicode化する
3293+ */
3294+static void SavePaths(HWND dlg, TTTSet *pts)
3295+{
3296+ // 送信パスを ts->ScpSendDir に保存
3297+ char sendfiledir[MAX_PATH];
3298+ GetDlgItemTextA(dlg, IDC_SENDFILE_TO, sendfiledir, _countof(sendfiledir));
3299+ strncpy_s(pts->ScpSendDir, sizeof(pts->ScpSendDir), sendfiledir, _TRUNCATE);
3300+
3301+#if 0
3302+ // 受信パスを ts->FileDir に保存
3303+ char recvdir[MAX_PATH];
3304+ GetDlgItemTextA(dlg, IDC_RECVFILE_TO, recvdir, _countof(recvdir));
3305+ strncpy_s(pvar->ts->FileDir, sizeof(pvar->ts->FileDir), recvdir, _TRUNCATE);
3306+#endif
3307+}
3308+
32863309 //
32873310 // SCP dialog
32883311 //
@@ -3289,45 +3312,28 @@
32893312 static INT_PTR CALLBACK TTXScpDialog(HWND dlg, UINT msg, WPARAM wParam,
32903313 LPARAM lParam)
32913314 {
3292- static char sendfile[MAX_PATH] = "";
3293- static char sendfiledir[MAX_PATH] = "";
3294- static char recvdir[MAX_PATH] = "";
3295- HWND hWnd;
3296- HDROP hDrop;
3297- UINT uFileNo;
3298- char szFileName[256];
3299- int i;
3300-
33013315 switch (msg) {
3302- case WM_INITDIALOG:
3303- {
3304- static const DlgTextInfo text_info[] = {
3305- { 0, "DLG_SCP_TITLE" },
3306- { IDC_SENDFILE_FROM_LABEL, "DLG_SCP_SENDFILE_FROM" },
3307- { IDC_SENDFILE_TO_LABEL, "DLG_SCP_SENDFILE_TO" },
3308- { IDC_SENDFILE_NOTE, "DLG_SCP_SENDFILE_DRAG" },
3309- { IDOK, "DLG_SCP_SENDFILE_SEND" },
3310- { IDCANCEL, "DLG_SCP_SENDFILE_CANCEL" },
3311- { IDC_RECEIVEFILE_FROM_LABEL, "DLG_SCP_RECEIVEFILE_FROM" },
3312- { IDC_RECVFILE_TO_LABEL, "DLG_SCP_RECEIVEFILE_TO" },
3313- { IDC_RECV, "DLG_SCP_RECEIVEFILE_RECEIVE" },
3314- };
3315- SetI18nDlgStrsW(dlg, "TTSSH", text_info, _countof(text_info), pvar->ts->UILanguageFileW);
3316- }
3316+ case WM_INITDIALOG: {
3317+ static const DlgTextInfo text_info[] = {
3318+ { 0, "DLG_SCP_TITLE" },
3319+ { IDC_SENDFILE_FROM_LABEL, "DLG_SCP_SENDFILE_FROM" },
3320+ { IDC_SENDFILE_TO_LABEL, "DLG_SCP_SENDFILE_TO" },
3321+ { IDC_SENDFILE_NOTE, "DLG_SCP_SENDFILE_DRAG" },
3322+ { IDOK, "DLG_SCP_SENDFILE_SEND" },
3323+ { IDCANCEL, "DLG_SCP_SENDFILE_CANCEL" },
3324+ { IDC_RECEIVEFILE_FROM_LABEL, "DLG_SCP_RECEIVEFILE_FROM" },
3325+ { IDC_RECVFILE_TO_LABEL, "DLG_SCP_RECEIVEFILE_TO" },
3326+ { IDC_RECV, "DLG_SCP_RECEIVEFILE_RECEIVE" },
3327+ };
3328+ SetI18nDlgStrsW(dlg, "TTSSH", text_info, _countof(text_info), pvar->ts->UILanguageFileW);
33173329
33183330 DragAcceptFiles(dlg, TRUE);
33193331
33203332 // SCPファイル送信先を表示する
3321- if (sendfiledir[0] == '\0') {
3322- _snprintf_s(sendfiledir, sizeof(sendfiledir), _TRUNCATE, pvar->ts->ScpSendDir); // home directory
3323- }
3324- SendMessage(GetDlgItem(dlg, IDC_SENDFILE_TO), WM_SETTEXT, 0, (LPARAM)sendfiledir);
3333+ SetDlgItemTextA(dlg, IDC_SENDFILE_TO, pvar->ts->ScpSendDir);
33253334
33263335 // SCPファイル受信先を表示する
3327- if (recvdir[0] == '\0') {
3328- _snprintf_s(recvdir, sizeof(recvdir), _TRUNCATE, "%s", pvar->ts->FileDir);
3329- }
3330- SendMessage(GetDlgItem(dlg, IDC_RECVFILE_TO), WM_SETTEXT, 0, (LPARAM)recvdir);
3336+ SetDlgItemTextW(dlg, IDC_RECVFILE_TO, pvar->ts->FileDirW);
33313337
33323338 #ifdef SFTP_DEBUG
33333339 ShowWindow(GetDlgItem(dlg, IDC_SFTP_TEST), SW_SHOW);
@@ -3335,126 +3341,109 @@
33353341 CenterWindow(dlg, GetParent(dlg));
33363342
33373343 return TRUE;
3344+ }
33383345
3339- case WM_DROPFILES:
3340- {
3341- hDrop = (HDROP)wParam;
3342- uFileNo = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL, 0);
3343- for(i = 0; i < (int)uFileNo; i++) {
3344- DragQueryFile(hDrop, i, szFileName, sizeof(szFileName));
3345-
3346+ case WM_DROPFILES: {
3347+ HDROP hDrop = (HDROP)wParam;
3348+ UINT uFileNo = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL, 0);
3349+ if (uFileNo > 0) {
3350+ const UINT len = DragQueryFileW(hDrop, 0, NULL, 0);
3351+ if (len == 0) {
3352+ DragFinish(hDrop);
3353+ return TRUE;
3354+ }
3355+ wchar_t *filename = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1));
3356+ DragQueryFileW(hDrop, 0, filename, len + 1);
3357+ filename[len] = '\0';
33463358 // update edit box
3347- hWnd = GetDlgItem(dlg, IDC_SENDFILE_EDIT);
3348- SendMessage(hWnd, WM_SETTEXT , 0, (LPARAM)szFileName);
3359+ SetDlgItemTextW(dlg, IDC_SENDFILE_EDIT, filename);
3360+ free(filename);
33493361 }
33503362 DragFinish(hDrop);
3351- }
33523363 return TRUE;
3364+ }
33533365
33543366 case WM_COMMAND:
33553367 switch (wParam) {
3356- case IDC_SENDFILE_SELECT | (BN_CLICKED << 16):
3357- {
3358- OPENFILENAME ofn;
3368+ case IDC_SENDFILE_SELECT | (BN_CLICKED << 16): {
3369+ TTOPENFILENAMEW ofn = {0};
33593370
3360- ZeroMemory(&ofn, sizeof(ofn));
3361- ofn.lStructSize = get_OPENFILENAME_SIZE();
33623371 ofn.hwndOwner = dlg;
33633372 #if 0
33643373 get_lang_msg("FILEDLG_SELECT_LOGVIEW_APP_FILTER", ts.UIMsg, sizeof(ts.UIMsg),
33653374 "exe(*.exe)\\0*.exe\\0all(*.*)\\0*.*\\0\\0", ts.UILanguageFile);
33663375 #endif
3367- ofn.lpstrFilter = "all(*.*)\0*.*\0\0";
3368- ofn.lpstrFile = sendfile;
3369- ofn.nMaxFile = sizeof(sendfile);
3370-#if 0
3371- get_lang_msg("FILEDLG_SELECT_LOGVIEW_APP_TITLE", uimsg, sizeof(uimsg),
3372- "Choose a executing file with launching logging file", ts.UILanguageFile);
3373-#endif
3376+ ofn.lpstrFilter = L"all(*.*)\0*.*\0\0";
33743377 UTIL_get_lang_msg("DLG_SCP_SELECT_FILE_TITLE", pvar,
33753378 "Choose a sending file with SCP");
3376- ofn.lpstrTitle = pvar->UIMsg;
3377-
3379+ wchar_t *UIMsgW;
3380+ GetI18nStrWW("TTSSH", "DLG_SCP_SELECT_FILE_TITLE", L"Choose a sending file with SCP", pvar->ts->UILanguageFileW, &UIMsgW);
3381+ ofn.lpstrTitle = UIMsgW;
33783382 ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
33793383 ofn.Flags |= OFN_FORCESHOWHIDDEN;
3380- if (GetOpenFileName(&ofn) != 0) {
3381- hWnd = GetDlgItem(dlg, IDC_SENDFILE_EDIT);
3382- SendMessage(hWnd, WM_SETTEXT , 0, (LPARAM)sendfile);
3384+ wchar_t *filename;
3385+ if (TTGetOpenFileNameW(&ofn, &filename)) {
3386+ SetDlgItemTextW(dlg, IDC_SENDFILE_EDIT, filename);
3387+ free(filename);
33833388 }
3384- }
3389+ free(UIMsgW);
3390+
33853391 return TRUE;
3386- case IDC_RECVDIR_SELECT | (BN_CLICKED << 16):
3387- {
3388- wchar_t *buf, *buf2, uimsg[MAX_UIMSG];
3389- hGetDlgItemTextW(dlg, IDC_RECVFILE_TO, &buf);
3392+ }
3393+ case IDC_RECVDIR_SELECT | (BN_CLICKED << 16): {
3394+ wchar_t *cur_dir, *new_dir, uimsg[MAX_UIMSG];
3395+ hGetDlgItemTextW(dlg, IDC_RECVFILE_TO, &cur_dir);
33903396 UTIL_get_lang_msgW("DLG_SCP_SELECT_DEST_TITLE", pvar,
33913397 L"Choose destination directory", uimsg);
3392- if (doSelectFolderW(dlg, buf, uimsg, &buf2)) {
3393- WideCharToACP_t(buf2, recvdir, sizeof(recvdir));
3394- SetDlgItemTextA(dlg, IDC_RECVFILE_TO, recvdir);
3395- free(buf2);
3398+ if (doSelectFolderW(dlg, cur_dir, uimsg, &new_dir)) {
3399+ SetDlgItemTextW(dlg, IDC_RECVFILE_TO, new_dir);
3400+ free(new_dir);
33963401 }
3397- free(buf);
3402+ free(cur_dir);
33983403 }
33993404 return TRUE;
34003405 }
34013406
34023407 switch (LOWORD(wParam)) {
3403- case IDOK: // ファイル送信
3404- hWnd = GetDlgItem(dlg, IDC_SENDFILE_EDIT);
3405- SendMessage(hWnd, WM_GETTEXT , sizeof(sendfile), (LPARAM)sendfile);
3406- if (sendfile[0] != '\0') {
3407- // 送信パスを取り出し、ts->ScpSendDir も合わせて更新する。
3408- hWnd = GetDlgItem(dlg, IDC_SENDFILE_TO);
3409- SendMessage(hWnd, WM_GETTEXT , sizeof(sendfiledir), (LPARAM)sendfiledir);
3410- strncpy_s(pvar->ts->ScpSendDir, sizeof(pvar->ts->ScpSendDir), sendfiledir, _TRUNCATE);
3408+ case IDOK: { // ファイル送信
3409+ wchar_t *filenameW;
3410+ hGetDlgItemTextW(dlg, IDC_SENDFILE_EDIT, &filenameW);
3411+ if (filenameW != NULL) {
3412+ // 送信パス
3413+ wchar_t *sendfiledirW;
3414+ hGetDlgItemTextW(dlg, IDC_SENDFILE_TO, &sendfiledirW);
34113415
3412- // 受信パスを取り出し、ts->FileDir も合わせて更新する。
3413- hWnd = GetDlgItem(dlg, IDC_RECVFILE_TO);
3414- SendMessage(hWnd, WM_GETTEXT , sizeof(recvdir), (LPARAM)recvdir);
3415- strncpy_s(pvar->ts->FileDir, sizeof(pvar->ts->FileDir), recvdir, _TRUNCATE);
3416+ char *sendfiledirU8 = ToU8W(sendfiledirW);
3417+ char *filenameU8 = ToU8W(filenameW);
3418+ SSH_start_scp(pvar, filenameU8, sendfiledirU8);
3419+ //SSH_scp_transaction(pvar, "bigfile30.bin", "", FROMREMOTE);
3420+ free(filenameU8);
3421+ free(sendfiledirU8);
3422+ free(sendfiledirW);
3423+ free(filenameW);
34163424
3417- SSH_start_scp(pvar, sendfile, sendfiledir);
3418- //SSH_scp_transaction(pvar, "bigfile30.bin", "", FROMREMOTE);
3425+ SavePaths(dlg, pvar->ts);
3426+
34193427 EndDialog(dlg, 1); // dialog close
34203428 return TRUE;
34213429 }
34223430 return FALSE;
3431+ }
34233432
3424- case IDCANCEL:
3425- // 送信パスを取り出し、ts->ScpSendDir も合わせて更新する。
3426- hWnd = GetDlgItem(dlg, IDC_SENDFILE_TO);
3427- SendMessage(hWnd, WM_GETTEXT , sizeof(sendfiledir), (LPARAM)sendfiledir);
3428- strncpy_s(pvar->ts->ScpSendDir, sizeof(pvar->ts->ScpSendDir), sendfiledir, _TRUNCATE);
3433+ case IDCANCEL: {
3434+ SavePaths(dlg, pvar->ts);
34293435
3430- // 受信パスを取り出し、ts->FileDir も合わせて更新する。
3431- hWnd = GetDlgItem(dlg, IDC_RECVFILE_TO);
3432- SendMessage(hWnd, WM_GETTEXT , sizeof(recvdir), (LPARAM)recvdir);
3433- strncpy_s(pvar->ts->FileDir, sizeof(pvar->ts->FileDir), recvdir, _TRUNCATE);
3434-
34353436 EndDialog(dlg, 0); // dialog close
34363437 return TRUE;
3438+ }
34373439
3438- case IDC_RECV: // ファイル受信
3439- hWnd = GetDlgItem(dlg, IDC_RECVFILE);
3440- SendMessage(hWnd, WM_GETTEXT , sizeof(szFileName), (LPARAM)szFileName);
3441- if (szFileName[0] != '\0') {
3442- char recvpath[MAX_PATH] = "";
3443- char* fn = strrchr(szFileName, '/');
3444- char recvfn[sizeof(szFileName)];
3445- char recvdir_expanded[MAX_PATH];
3446-
3447- // 送信パスを取り出し、ts->ScpSendDir も合わせて更新する。
3448- hWnd = GetDlgItem(dlg, IDC_SENDFILE_TO);
3449- SendMessage(hWnd, WM_GETTEXT , sizeof(sendfiledir), (LPARAM)sendfiledir);
3450- strncpy_s(pvar->ts->ScpSendDir, sizeof(pvar->ts->ScpSendDir), sendfiledir, _TRUNCATE);
3451-
3452- // 受信パスを取り出し、ts->FileDir も合わせて更新する。
3453- hWnd = GetDlgItem(dlg, IDC_RECVFILE_TO);
3454- SendMessage(hWnd, WM_GETTEXT , sizeof(recvdir), (LPARAM)recvdir);
3455- ExpandEnvironmentStrings(recvdir, recvdir_expanded, sizeof(recvdir_expanded));
3456- strncpy_s(pvar->ts->FileDir, sizeof(pvar->ts->FileDir), recvdir, _TRUNCATE);
3457-
3440+ case IDC_RECV: {
3441+ // ファイル受信
3442+ wchar_t *FileNameW;
3443+ hGetDlgItemTextW(dlg, IDC_RECVFILE, &FileNameW);
3444+ if (FileNameW != NULL) {
3445+ // 受信ファイルからパスを取り除く
3446+ wchar_t *fn = wcsrchr(FileNameW, L'/');
34583447 if (fn) {
34593448 fn++;
34603449 if (*fn == '\0') {
@@ -3462,16 +3451,40 @@
34623451 }
34633452 }
34643453 else {
3465- fn = szFileName;
3454+ fn = FileNameW;
34663455 }
3467- strncpy_s(recvfn, sizeof(recvfn), fn, _TRUNCATE);
3468- replaceInvalidFileNameChar(recvfn, '_');
3469- _snprintf_s(recvpath, sizeof(recvpath), _TRUNCATE, "%s\\%s", recvdir_expanded, recvfn);
3470- SSH_scp_transaction(pvar, szFileName, recvpath, FROMREMOTE);
3456+ wchar_t *recvfn = replaceInvalidFileNameCharW(fn, '_');
3457+
3458+ // 受信パス
3459+ wchar_t *recvdirW;
3460+ hGetDlgItemTextW(dlg, IDC_RECVFILE_TO, &recvdirW);
3461+ wchar_t *recvdir_expanded;
3462+ hExpandEnvironmentStringsW(recvdirW, &recvdir_expanded);
3463+
3464+ wchar_t *recvpathW;
3465+ if (recvdir_expanded[0] != 0) {
3466+ aswprintf(&recvpathW, L"%s\\%s", recvdir_expanded, recvfn);
3467+ } else {
3468+ recvpathW = _wcsdup(recvfn);
3469+ }
3470+ char *recvpathU8 = ToU8W(recvpathW);
3471+ char *FileNameU8 = ToU8W(FileNameW);
3472+ SSH_scp_transaction(pvar, FileNameU8, recvpathU8, FROMREMOTE);
3473+ free(FileNameW);
3474+ free(recvfn);
3475+ free(recvdirW);
3476+ free(recvdir_expanded);
3477+ free(recvpathW);
3478+ free(recvpathU8);
3479+ free(FileNameU8);
3480+
3481+ SavePaths(dlg, pvar->ts);
3482+
34713483 EndDialog(dlg, 1); // dialog close
34723484 return TRUE;
34733485 }
34743486 return FALSE;
3487+ }
34753488
34763489 case IDC_SFTP_TEST:
34773490 SSH_sftp_transaction(pvar);
Show on old repository browser