[Ttssh2-commit] [4930] SFTP:

svnno****@sourc***** svnno****@sourc*****
2012年 5月 4日 (金) 23:39:22 JST


Revision: 4930
          http://sourceforge.jp/projects/ttssh2/svn/view?view=rev&revision=4930
Author:   yutakapon
Date:     2012-05-04 23:39:22 +0900 (Fri, 04 May 2012)
Log Message:
-----------
SFTP:
  - コマンドラインコンソール(モードレスダイアログ)を追加した。これが将来的にFFFTPやWinSCPの2ペイン方式になる(予定)。
  - インタラクティブループに入る前のパス送信処理を追加した。

※一人言
SCPを実装したときもそうだったが、WindowsアプリはUNIXプログラムのようにブロックさせないようにしなければならないため、
1つのコマンドを送受信するだけでも、状態遷移管理をしなければならず、ロジックが煩雑になる。
SFTP用の別プロセスを起こして、Tera Term(TTSSH)本体とプロセス間通信するようにしたほうがよいのかも。

Modified Paths:
--------------
    trunk/ttssh2/ttxssh/resource.h
    trunk/ttssh2/ttxssh/sftp.c
    trunk/ttssh2/ttxssh/ssh.h
    trunk/ttssh2/ttxssh/ttxssh.rc

-------------- next part --------------
Modified: trunk/ttssh2/ttxssh/resource.h
===================================================================
--- trunk/ttssh2/ttxssh/resource.h	2012-05-03 16:17:09 UTC (rev 4929)
+++ trunk/ttssh2/ttxssh/resource.h	2012-05-04 14:39:22 UTC (rev 4930)
@@ -14,6 +14,7 @@
 #define IDD_SSHAUTH                     106
 #define IDD_SSHSCP_PROGRESS             107
 #define IDD_SSHPASSWD_INPUT             108
+#define IDD_SFTP_DIALOG                 109
 #define IDD_HOSTDLG                     600
 #define IDC_HOSTTCPIP                   601
 #define IDD_SSHDIFFERENTKEY             601
@@ -116,6 +117,7 @@
 #define IDC_SENDFILE_EDIT               1069
 #define IDC_PASSWD                      1069
 #define IDC_ECDSA521_TYPE               1069
+#define IDC_SFTP_EDIT                   1069
 #define IDC_STATIC1                     1070
 #define IDC_COMPRESSLABEL               1070
 #define IDC_SSHVERSIONS                 1070
@@ -194,13 +196,14 @@
 #define IDC_EDIT2                       1208
 #define IDC_NEW_PASSWD                  1208
 #define IDC_SENDFILE_TO                 1208
+#define IDC_SFTP_CONSOLE                1208
 #define IDC_PUTTY_VERSION               1209
 
 // Next default values for new objects
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        109
+#define _APS_NEXT_RESOURCE_VALUE        110
 #define _APS_NEXT_COMMAND_VALUE         40001
 #define _APS_NEXT_CONTROL_VALUE         1210
 #define _APS_NEXT_SYMED_VALUE           101

Modified: trunk/ttssh2/ttxssh/sftp.c
===================================================================
--- trunk/ttssh2/ttxssh/sftp.c	2012-05-03 16:17:09 UTC (rev 4929)
+++ trunk/ttssh2/ttxssh/sftp.c	2012-05-04 14:39:22 UTC (rev 4930)
@@ -51,6 +51,22 @@
 #include <sys/stat.h>
 #include <assert.h>
 
+
+#define WM_USER_CONSOLE (WM_USER + 1)
+
+static void sftp_console_message(PTInstVar pvar, Channel_t *c, char *fmt, ...)
+{
+	char tmp[1024];
+	va_list arg;
+
+	va_start(arg, fmt);
+	_vsnprintf(tmp, sizeof(tmp), fmt, arg);
+	va_end(arg);
+
+	SendMessage(c->sftp.console_window, WM_USER_CONSOLE, 0, (LPARAM)tmp);
+	notify_verbose_message(pvar, tmp, LOG_LEVEL_VERBOSE);
+}
+
 static void sftp_do_syslog(PTInstVar pvar, int level, char *fmt, ...)
 {
 	char tmp[1024];
@@ -148,8 +164,23 @@
 	return;
 }
 
+static void sftp_send_string_request(PTInstVar pvar, Channel_t *c, unsigned int id, unsigned int code,
+									 char *s, unsigned int len)
+{
+	buffer_t *msg;
+
+	sftp_buffer_alloc(&msg);
+	buffer_put_char(msg, code);
+	buffer_put_int(msg, id);
+	buffer_put_string(msg, s, len);
+	sftp_send_msg(pvar, c, msg);
+	sftp_syslog(pvar, "Sent message fd %d T:%u I:%u", c->remote_id, code, id);
+	sftp_buffer_free(msg);
+}
+
+
 // SFTP\x92ʐM\x8AJ\x8En\x91O\x82̃l\x83S\x83V\x83G\x81[\x83V\x83\x87\x83\x93
-// based on do_init()#sftp-client.c
+// based on do_init()#sftp-client.c(OpenSSH 6.0)
 void sftp_do_init(PTInstVar pvar, Channel_t *c)
 {
 	buffer_t *msg;
@@ -224,15 +255,205 @@
 		// TODO:
 	}
 
+	sftp_syslog(pvar, "Connected to SFTP server.");
+
 error:
 	return;
 }
 
-// SFTP\x8E\xF3\x90M\x8F\x88\x97\x9D -\x83\x81\x83C\x83\x93\x83\x8B\x81[\x83`\x83\x93-
+// \x83p\x83X\x82̑\x97\x90M
+// based on do_realpath()#sftp-client.c(OpenSSH 6.0)
+static void sftp_do_realpath(PTInstVar pvar, Channel_t *c, char *path)
+{
+	unsigned int id;
+
+	strncpy_s(c->sftp.path, sizeof(c->sftp.path), path, _TRUNCATE);
+	id = c->sftp.msg_id++;
+	sftp_send_string_request(pvar, c, id, SSH2_FXP_REALPATH, path, strlen(path));
+}
+
+/* Convert from SSH2_FX_ status to text error message */
+static const char *fx2txt(int status)
+{       
+    switch (status) {
+    case SSH2_FX_OK:
+        return("No error");
+    case SSH2_FX_EOF:
+        return("End of file");
+    case SSH2_FX_NO_SUCH_FILE:
+        return("No such file or directory");
+    case SSH2_FX_PERMISSION_DENIED:
+        return("Permission denied");
+    case SSH2_FX_FAILURE:
+        return("Failure");
+    case SSH2_FX_BAD_MESSAGE:
+        return("Bad message");
+    case SSH2_FX_NO_CONNECTION:
+        return("No connection");
+    case SSH2_FX_CONNECTION_LOST:
+        return("Connection lost");
+    case SSH2_FX_OP_UNSUPPORTED:
+        return("Operation unsupported");
+    default:
+        return("Unknown status");
+    }
+    /* NOTREACHED */
+}
+
+static char *sftp_do_realpath_recv(PTInstVar pvar, Channel_t *c, buffer_t *msg)
+{
+	unsigned int type, expected_id, count, id;
+	char *filename = NULL, *longname;
+
+	type = buffer_get_char(msg);
+	id = buffer_get_int(msg);
+
+	expected_id = c->sftp.msg_id - 1; 
+	if (id != expected_id) {
+		sftp_syslog(pvar, "ID mismatch (%u != %u)", id, expected_id);
+		goto error;
+	}
+
+	if (type == SSH2_FXP_STATUS) {
+		unsigned int status = buffer_get_int(msg);
+
+		sftp_syslog(pvar, "Couldn't canonicalise: %s", fx2txt(status));
+		goto error;
+	} else if (type != SSH2_FXP_NAME) {
+        sftp_syslog(pvar, "Expected SSH2_FXP_NAME(%u) packet, got %u",
+            SSH2_FXP_NAME, type);
+		goto error;
+	}
+
+	count = buffer_get_int(msg);
+	if (count != 1) {
+		sftp_syslog(pvar, "Got multiple names (%d) from SSH_FXP_REALPATH", count);
+		goto error;
+	}
+
+	filename = buffer_get_string_msg(msg, NULL);
+	longname = buffer_get_string_msg(msg, NULL);
+	//a = decode_attrib(&msg);
+
+	sftp_console_message(pvar, c, "SSH_FXP_REALPATH %s -> %s", c->sftp.path, filename);
+
+	free(longname);
+
+error:
+	return (filename);
+}
+
+
+/*
+ * SFTP \x83R\x83}\x83\x93\x83h\x83\x89\x83C\x83\x93\x83R\x83\x93\x83\\x81[\x83\x8B
+ */
+static WNDPROC hEditProc;
+
+static LRESULT CALLBACK EditProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+	switch (uMsg) {
+		case WM_KEYDOWN:
+		if ((int)wParam == VK_RETURN) {
+			char buf[512];
+
+			GetWindowText(hwnd, buf, sizeof(buf));
+			SetWindowText(hwnd, "");
+			if (buf[0] != '\0') {
+				SendDlgItemMessage(GetParent(hwnd), IDC_SFTP_CONSOLE, EM_REPLACESEL, 0, (LPARAM) buf);
+				SendDlgItemMessage(GetParent(hwnd), IDC_SFTP_CONSOLE, EM_REPLACESEL, 0,
+								   (LPARAM) (char FAR *) "\r\n");
+			}
+		}
+		break;
+	default:
+		return (CallWindowProc(hEditProc, hwnd, uMsg, wParam, lParam));
+	}
+
+	return 0L;
+}
+
+static LRESULT CALLBACK OnSftpConsoleDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+	static HFONT DlgDragDropFont = NULL;
+	LOGFONT logfont;
+	HFONT font;
+	HWND hEdit;
+
+	switch (msg) {
+		case WM_INITDIALOG:
+			font = (HFONT)SendMessage(hDlgWnd, WM_GETFONT, 0, 0);
+			GetObject(font, sizeof(LOGFONT), &logfont);
+			DlgDragDropFont = NULL;
+
+			hEdit = GetDlgItem(hDlgWnd, IDC_SFTP_EDIT);
+			SetFocus(hEdit);
+
+			// \x83G\x83f\x83B\x83b\x83g\x83R\x83\x93\x83g\x83\x8D\x81[\x83\x8B\x82̃T\x83u\x83N\x83\x89\x83X\x89\xBB
+			hEditProc = (WNDPROC)GetWindowLong(hEdit, GWL_WNDPROC);
+			SetWindowLong(hEdit, GWL_WNDPROC, (LONG)EditProc);
+
+			return TRUE;
+
+		case WM_COMMAND:
+			switch (LOWORD(wp)) {
+				case IDOK:
+					break;
+
+				case IDCANCEL:
+					if (DlgDragDropFont != NULL) {
+						DeleteObject(DlgDragDropFont);
+					}
+					EndDialog(hDlgWnd, IDCANCEL);
+					DestroyWindow(hDlgWnd);
+					break;
+
+				default:
+					return FALSE;
+			}
+
+		case WM_USER_CONSOLE:
+			SendDlgItemMessage(hDlgWnd, IDC_SFTP_CONSOLE, EM_REPLACESEL, 0, (LPARAM) lp);
+			SendDlgItemMessage(hDlgWnd, IDC_SFTP_CONSOLE, EM_REPLACESEL, 0,
+							   (LPARAM) (char FAR *) "\r\n");
+			return TRUE;
+
+#if 0
+		case WM_SIZE:
+			{
+				// \x8DĔz\x92u
+				int dlg_w, dlg_h;
+				RECT rc_dlg;
+				RECT rc;
+				POINT p;
+
+				// \x90V\x82\xB5\x82\xA2\x83_\x83C\x83A\x83\x8D\x83O\x82̃T\x83C\x83Y\x82𓾂\xE9
+				GetClientRect(hDlgWnd, &rc_dlg);
+				dlg_w = rc_dlg.right;
+				dlg_h = rc_dlg.bottom;
+
+				// \x83R\x83}\x83\x93\x83h\x83v\x83\x8D\x83\x93\x83v\x83g
+				GetWindowRect(GetDlgItem(hDlgWnd, IDC_SFTP_EDIT), &rc);
+				p.x = rc.left;
+				p.y = rc.top;
+				ScreenToClient(hDlgWnd, &p);
+				SetWindowPos(GetDlgItem(hDlgWnd, IDC_SFTP_EDIT), 0,
+ 							 0, 0, dlg_w, p.y,
+							 SWP_NOSIZE | SWP_NOZORDER);
+			}
+			return TRUE;
+#endif
+
+		default:
+			return FALSE;
+	}
+	return TRUE;
+}
+
+// SFTP\x8E\xF3\x90M\x8F\x88\x97\x9D -\x83X\x83e\x81[\x83g\x83}\x83V\x81[\x83\x93-
 void sftp_response(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen)
 {
 	buffer_t *msg;
-	int state;
+	HWND hDlgWnd;
 
 	/*
 	 * Allocate buffer
@@ -240,10 +461,26 @@
 	sftp_buffer_alloc(&msg);
 	sftp_get_msg(pvar, c, data, buflen, &msg);
 
-	state = c->sftp.state;
-	if (state == SFTP_INIT) {
+	if (c->sftp.state == SFTP_INIT) {
 		sftp_do_init_recv(pvar, c, msg);
-		sftp_syslog(pvar, "Connected to SFTP server.");
+
+		// \x83R\x83\x93\x83\\x81[\x83\x8B\x82\xF0\x8BN\x93\xAE\x82\xB7\x82\xE9\x81B
+		hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SFTP_DIALOG), 
+				pvar->cv->HWin, (DLGPROC)OnSftpConsoleDlgProc);	
+		if (hDlgWnd != NULL) {
+			c->sftp.console_window = hDlgWnd;
+			ShowWindow(hDlgWnd, SW_SHOW);
+		}
+
+		sftp_do_realpath(pvar, c, ".");
+		c->sftp.state = SFTP_CONNECTED;
+
+	} else if (c->sftp.state == SFTP_CONNECTED) {
+		char *remote_path;
+		remote_path = sftp_do_realpath_recv(pvar, c, msg);
+
+		c->sftp.state = SFTP_REALPATH;
+
 	}
 
 	/*

Modified: trunk/ttssh2/ttxssh/ssh.h
===================================================================
--- trunk/ttssh2/ttxssh/ssh.h	2012-05-03 16:17:09 UTC (rev 4929)
+++ trunk/ttssh2/ttxssh/ssh.h	2012-05-04 14:39:22 UTC (rev 4930)
@@ -659,11 +659,12 @@
 } scp_t;
 
 enum sftp_state {
-	SFTP_INIT, 
+	SFTP_INIT, SFTP_CONNECTED, SFTP_REALPATH, 
 };
 
 typedef struct sftp {
 	enum sftp_state state;
+	HWND console_window;
 	unsigned int transfer_buflen;
 	unsigned int num_requests;
 	unsigned int version;
@@ -675,6 +676,7 @@
 	unsigned int exts;
 	unsigned long long limit_kbps;
 	//struct bwlimit bwlimit_in, bwlimit_out;
+	char path[1024];
 } sftp_t;
 
 typedef struct channel {

Modified: trunk/ttssh2/ttxssh/ttxssh.rc
===================================================================
--- trunk/ttssh2/ttxssh/ttxssh.rc	2012-05-03 16:17:09 UTC (rev 4929)
+++ trunk/ttssh2/ttxssh/ttxssh.rc	2012-05-04 14:39:22 UTC (rev 4930)
@@ -13,6 +13,52 @@
 #undef APSTUDIO_READONLY_SYMBOLS
 
 /////////////////////////////////////////////////////////////////////////////
+// \x93\xFA\x96{\x8C\xEA resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_SFTP_DIALOG DIALOGEX 0, 0, 266, 150
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "TTSSH: SFTP console"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    EDITTEXT        IDC_SFTP_EDIT,7,7,252,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_SFTP_CONSOLE,7,33,252,110,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO 
+BEGIN
+    IDD_SFTP_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 259
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 143
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+#endif    // \x93\xFA\x96{\x8C\xEA resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
 // \x89p\x8C\xEA (\x95č\x91) resources
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)



Ttssh2-commit メーリングリストの案内