| 77 |
SCP_INIT, SCP_TIMESTAMP, SCP_FILEINFO, SCP_DATA, SCP_CLOSING, |
SCP_INIT, SCP_TIMESTAMP, SCP_FILEINFO, SCP_DATA, SCP_CLOSING, |
| 78 |
}; |
}; |
| 79 |
|
|
| 80 |
|
enum scp_dir { |
| 81 |
|
TOLOCAL, FROMREMOTE, |
| 82 |
|
}; |
| 83 |
|
|
| 84 |
typedef struct bufchain { |
typedef struct bufchain { |
| 85 |
buffer_t *msg; |
buffer_t *msg; |
| 86 |
struct bufchain *next; |
struct bufchain *next; |
| 87 |
} bufchain_t; |
} bufchain_t; |
| 88 |
|
|
| 89 |
typedef struct scp { |
typedef struct scp { |
| 90 |
enum scp_state state; // SCP state |
enum scp_dir dir; // transfer direction |
| 91 |
|
enum scp_state state; // SCP state |
| 92 |
char sendfile[MAX_PATH]; // sending filename |
char sendfile[MAX_PATH]; // sending filename |
| 93 |
char sendfilefull[MAX_PATH]; // sending filename fullpath |
char sendfilefull[MAX_PATH]; // sending filename fullpath |
| 94 |
FILE *sendfp; // file pointer |
FILE *sendfp; // file pointer |
| 264 |
|
|
| 265 |
if (c->type == TYPE_SCP) { |
if (c->type == TYPE_SCP) { |
| 266 |
c->scp.state = SCP_CLOSING; |
c->scp.state = SCP_CLOSING; |
| 267 |
|
fclose(c->scp.sendfp); |
| 268 |
|
if (c->scp.progress != NULL) { |
| 269 |
|
DestroyWindow(c->scp.progress); |
| 270 |
|
c->scp.progress = NULL; |
| 271 |
|
} |
| 272 |
if (c->scp.thread != (HANDLE)-1L) { |
if (c->scp.thread != (HANDLE)-1L) { |
| 273 |
WaitForSingleObject(c->scp.thread, INFINITE); |
WaitForSingleObject(c->scp.thread, INFINITE); |
| 274 |
CloseHandle(c->scp.thread); |
CloseHandle(c->scp.thread); |
| 275 |
c->scp.thread = (HANDLE)-1L; |
c->scp.thread = (HANDLE)-1L; |
| 276 |
} |
} |
|
if (c->scp.progress != NULL) { |
|
|
DestroyWindow(c->scp.progress); |
|
|
c->scp.progress = NULL; |
|
|
} |
|
|
fclose(c->scp.sendfp); |
|
| 277 |
} |
} |
| 278 |
|
|
| 279 |
memset(c, 0, sizeof(Channel_t)); |
memset(c, 0, sizeof(Channel_t)); |
| 3363 |
// |
// |
| 3364 |
// (2007.12.21 yutaka) |
// (2007.12.21 yutaka) |
| 3365 |
// |
// |
| 3366 |
int SSH_start_scp(PTInstVar pvar, char *sendfile) |
static int SSH_scp_transaction(PTInstVar pvar, char *sendfile, enum scp_dir direction) |
| 3367 |
{ |
{ |
| 3368 |
buffer_t *msg; |
buffer_t *msg; |
| 3369 |
char *s; |
char *s; |
| 3380 |
if (SSHv1(pvar)) // SSH1サポートはTBD |
if (SSHv1(pvar)) // SSH1サポートはTBD |
| 3381 |
goto error; |
goto error; |
| 3382 |
|
|
|
fp = fopen(sendfile, "rb"); |
|
|
if (fp == NULL) |
|
|
goto error; |
|
|
|
|
| 3383 |
// チャネル設定 |
// チャネル設定 |
| 3384 |
c = ssh2_channel_new(CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT, TYPE_SCP, -1); |
c = ssh2_channel_new(CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT, TYPE_SCP, -1); |
| 3385 |
if (c == NULL) { |
if (c == NULL) { |
| 3388 |
notify_fatal_error(pvar, pvar->ts->UIMsg); |
notify_fatal_error(pvar, pvar->ts->UIMsg); |
| 3389 |
goto error; |
goto error; |
| 3390 |
} |
} |
| 3391 |
|
|
| 3392 |
|
if (direction == TOLOCAL) { // copy local to remote |
| 3393 |
|
fp = fopen(sendfile, "rb"); |
| 3394 |
|
if (fp == NULL) |
| 3395 |
|
goto error; |
| 3396 |
|
|
| 3397 |
|
strncpy_s(c->scp.sendfilefull, sizeof(c->scp.sendfilefull), sendfile, _TRUNCATE); // full path |
| 3398 |
|
ExtractFileName(sendfile, c->scp.sendfile, sizeof(c->scp.sendfile)); // file name only |
| 3399 |
|
c->scp.sendfp = fp; // file pointer |
| 3400 |
|
|
| 3401 |
|
if (_stat(c->scp.sendfilefull, &st) == 0) { |
| 3402 |
|
c->scp.filestat = st; |
| 3403 |
|
} else { |
| 3404 |
|
goto error; |
| 3405 |
|
} |
| 3406 |
|
} else { // copy remote to local |
| 3407 |
|
fp = fopen(sendfile, "wb"); |
| 3408 |
|
if (fp == NULL) |
| 3409 |
|
goto error; |
| 3410 |
|
|
| 3411 |
|
strncpy_s(c->scp.sendfilefull, sizeof(c->scp.sendfilefull), sendfile, _TRUNCATE); |
| 3412 |
|
strncpy_s(c->scp.sendfile, sizeof(c->scp.sendfile), sendfile, _TRUNCATE); |
| 3413 |
|
} |
| 3414 |
|
|
| 3415 |
// setup SCP data |
// setup SCP data |
| 3416 |
|
c->scp.dir = direction; |
| 3417 |
c->scp.state = SCP_INIT; |
c->scp.state = SCP_INIT; |
|
strncpy_s(c->scp.sendfilefull, sizeof(c->scp.sendfilefull), sendfile, _TRUNCATE); // full path |
|
|
ExtractFileName(sendfile, c->scp.sendfile, sizeof(c->scp.sendfile)); // file name only |
|
|
c->scp.sendfp = fp; // file pointer |
|
|
if (_stat(c->scp.sendfilefull, &st) == 0) { |
|
|
c->scp.filestat = st; |
|
|
} else { |
|
|
goto error; |
|
|
} |
|
| 3418 |
|
|
| 3419 |
// session open |
// session open |
| 3420 |
msg = buffer_init(); |
msg = buffer_init(); |
| 3443 |
return FALSE; |
return FALSE; |
| 3444 |
} |
} |
| 3445 |
|
|
| 3446 |
|
int SSH_start_scp(PTInstVar pvar, char *sendfile) |
| 3447 |
|
{ |
| 3448 |
|
return SSH_scp_transaction(pvar, sendfile, TOLOCAL); |
| 3449 |
|
} |
| 3450 |
|
|
| 3451 |
|
|
| 3452 |
///////////////////////////////////////////////////////////////////////////// |
///////////////////////////////////////////////////////////////////////////// |
| 3453 |
// |
// |
| 6856 |
|
|
| 6857 |
if (c->type == TYPE_SCP) { |
if (c->type == TYPE_SCP) { |
| 6858 |
char sbuf[MAX_PATH + 30]; |
char sbuf[MAX_PATH + 30]; |
| 6859 |
_snprintf_s(sbuf, sizeof(sbuf), _TRUNCATE, "scp -t %s", c->scp.sendfile); |
if (c->scp.dir == TOLOCAL) { |
| 6860 |
|
_snprintf_s(sbuf, sizeof(sbuf), _TRUNCATE, "scp -t %s", c->scp.sendfile); |
| 6861 |
|
|
| 6862 |
|
} else { |
| 6863 |
|
_snprintf_s(sbuf, sizeof(sbuf), _TRUNCATE, "scp -f %s", c->scp.sendfile); |
| 6864 |
|
|
| 6865 |
|
} |
| 6866 |
buffer_put_string(msg, sbuf, strlen(sbuf)); |
buffer_put_string(msg, sbuf, strlen(sbuf)); |
| 6867 |
goto done; |
goto done; |
| 6868 |
} |
} |
| 7190 |
do { |
do { |
| 7191 |
// Cancelボタンが押下されたらウィンドウが消える。 |
// Cancelボタンが押下されたらウィンドウが消える。 |
| 7192 |
if (IsWindowVisible(hWnd) == 0) |
if (IsWindowVisible(hWnd) == 0) |
| 7193 |
goto abort; |
goto cancel_abort; |
| 7194 |
|
|
| 7195 |
// ファイルから読み込んだデータはかならずサーバへ送信する。 |
// ファイルから読み込んだデータはかならずサーバへ送信する。 |
| 7196 |
ret = fread(buf, 1, sizeof(buf), c->scp.sendfp); |
ret = fread(buf, 1, sizeof(buf), c->scp.sendfp); |
| 7236 |
c->scp.state = SCP_DATA; |
c->scp.state = SCP_DATA; |
| 7237 |
return 0; |
return 0; |
| 7238 |
|
|
| 7239 |
abort: |
cancel_abort: |
| 7240 |
ssh2_channel_send_close(pvar, c); |
ssh2_channel_send_close(pvar, c); |
| 7241 |
|
|
| 7242 |
#if 0 |
abort: |
| 7243 |
// デッドロック回避のため、自分でハンドルをクローズする。 |
|
|
CloseHandle(c->scp.thread); |
|
|
c->scp.thread = (HANDLE)-1L; |
|
|
//ssh2_channel_delete(c); // free channel |
|
|
#endif |
|
| 7244 |
return 0; |
return 0; |
| 7245 |
} |
} |
| 7246 |
|
|
| 7247 |
|
|
| 7248 |
|
static void SSH2_scp_tolocal(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen) |
| 7249 |
|
{ |
| 7250 |
|
if (c->scp.state == SCP_INIT) { |
| 7251 |
|
char buf[128]; |
| 7252 |
|
|
| 7253 |
|
_snprintf_s(buf, sizeof(buf), _TRUNCATE, "T%lu 0 %lu 0\n", |
| 7254 |
|
(unsigned long)c->scp.filestat.st_mtime, (unsigned long)c->scp.filestat.st_atime); |
| 7255 |
|
|
| 7256 |
|
c->scp.state = SCP_TIMESTAMP; |
| 7257 |
|
SSH2_send_channel_data(pvar, c, buf, strlen(buf)); |
| 7258 |
|
|
| 7259 |
|
} else if (c->scp.state == SCP_TIMESTAMP) { |
| 7260 |
|
char buf[128]; |
| 7261 |
|
|
| 7262 |
|
_snprintf_s(buf, sizeof(buf), _TRUNCATE, "C0644 %lld %s\n", |
| 7263 |
|
(long long)c->scp.filestat.st_size, c->scp.sendfile); |
| 7264 |
|
|
| 7265 |
|
c->scp.state = SCP_FILEINFO; |
| 7266 |
|
SSH2_send_channel_data(pvar, c, buf, strlen(buf)); |
| 7267 |
|
|
| 7268 |
|
} else if (c->scp.state == SCP_FILEINFO) { |
| 7269 |
|
HWND hDlgWnd; |
| 7270 |
|
HANDLE thread; |
| 7271 |
|
unsigned int tid; |
| 7272 |
|
|
| 7273 |
|
c->scp.pvar = pvar; |
| 7274 |
|
|
| 7275 |
|
hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS), |
| 7276 |
|
pvar->cv->HWin, (DLGPROC)ssh_scp_dlg_proc); |
| 7277 |
|
if (hDlgWnd != NULL) { |
| 7278 |
|
c->scp.progress = hDlgWnd; |
| 7279 |
|
ShowWindow(hDlgWnd, SW_SHOW); |
| 7280 |
|
} |
| 7281 |
|
|
| 7282 |
|
thread = (HANDLE)_beginthreadex(NULL, 0, ssh_scp_thread, c, 0, &tid); |
| 7283 |
|
if (thread == (HANDLE)-1) { |
| 7284 |
|
// TODO: |
| 7285 |
|
} |
| 7286 |
|
c->scp.thread = thread; |
| 7287 |
|
|
| 7288 |
|
|
| 7289 |
|
} else if (c->scp.state == SCP_DATA) { |
| 7290 |
|
// 送信完了 |
| 7291 |
|
ssh2_channel_send_close(pvar, c); |
| 7292 |
|
//ssh2_channel_delete(c); // free channel |
| 7293 |
|
|
| 7294 |
|
//MessageBox(NULL, "SCP sending done.", "TTSSH", MB_OK); |
| 7295 |
|
} |
| 7296 |
|
} |
| 7297 |
|
|
| 7298 |
|
static void SSH2_scp_response(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen) |
| 7299 |
|
{ |
| 7300 |
|
if (buflen == 1 && data[0] == '\0') { // OK |
| 7301 |
|
if (c->scp.dir == TOLOCAL) { |
| 7302 |
|
SSH2_scp_tolocal(pvar, c, data, buflen); |
| 7303 |
|
} else { |
| 7304 |
|
//SSH2_scp_fromremote(pvar, c, data, buflen); |
| 7305 |
|
} |
| 7306 |
|
|
| 7307 |
|
} else { // error |
| 7308 |
|
char msg[2048]; |
| 7309 |
|
unsigned int i, max; |
| 7310 |
|
|
| 7311 |
|
if (buflen > sizeof(msg)) |
| 7312 |
|
max = sizeof(msg); |
| 7313 |
|
else |
| 7314 |
|
max = buflen - 1; |
| 7315 |
|
for (i = 0 ; i < max ; i++) { |
| 7316 |
|
msg[i] = data[i + 1]; |
| 7317 |
|
} |
| 7318 |
|
msg[i] = '\0'; |
| 7319 |
|
|
| 7320 |
|
ssh2_channel_send_close(pvar, c); |
| 7321 |
|
//ssh2_channel_delete(c); // free channel |
| 7322 |
|
|
| 7323 |
|
MessageBox(NULL, msg, "TTSSH: SCP error", MB_OK | MB_ICONEXCLAMATION); |
| 7324 |
|
} |
| 7325 |
|
} |
| 7326 |
|
|
| 7327 |
|
|
| 7328 |
static BOOL handle_SSH2_channel_data(PTInstVar pvar) |
static BOOL handle_SSH2_channel_data(PTInstVar pvar) |
| 7329 |
{ |
{ |
| 7330 |
int len; |
int len; |
| 7374 |
FWD_received_data(pvar, c->local_num, data, str_len); |
FWD_received_data(pvar, c->local_num, data, str_len); |
| 7375 |
|
|
| 7376 |
} else if (c->type == TYPE_SCP) { // SCP |
} else if (c->type == TYPE_SCP) { // SCP |
| 7377 |
if (str_len == 1 && data[0] == '\0') { // OK |
SSH2_scp_response(pvar, c, data, str_len); |
|
|
|
|
if (c->scp.state == SCP_INIT) { |
|
|
char buf[128]; |
|
|
|
|
|
_snprintf_s(buf, sizeof(buf), _TRUNCATE, "T%lu 0 %lu 0\n", |
|
|
(unsigned long)c->scp.filestat.st_mtime, (unsigned long)c->scp.filestat.st_atime); |
|
|
|
|
|
c->scp.state = SCP_TIMESTAMP; |
|
|
SSH2_send_channel_data(pvar, c, buf, strlen(buf)); |
|
|
|
|
|
} else if (c->scp.state == SCP_TIMESTAMP) { |
|
|
char buf[128]; |
|
|
|
|
|
_snprintf_s(buf, sizeof(buf), _TRUNCATE, "C0644 %lld %s\n", |
|
|
(long long)c->scp.filestat.st_size, c->scp.sendfile); |
|
|
|
|
|
c->scp.state = SCP_FILEINFO; |
|
|
SSH2_send_channel_data(pvar, c, buf, strlen(buf)); |
|
|
|
|
|
} else if (c->scp.state == SCP_FILEINFO) { |
|
|
HWND hDlgWnd; |
|
|
HANDLE thread; |
|
|
unsigned int tid; |
|
|
|
|
|
c->scp.pvar = pvar; |
|
|
|
|
|
hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS), |
|
|
pvar->cv->HWin, (DLGPROC)ssh_scp_dlg_proc); |
|
|
if (hDlgWnd != NULL) { |
|
|
c->scp.progress = hDlgWnd; |
|
|
ShowWindow(hDlgWnd, SW_SHOW); |
|
|
} |
|
|
|
|
|
thread = (HANDLE)_beginthreadex(NULL, 0, ssh_scp_thread, c, 0, &tid); |
|
|
if (thread == (HANDLE)-1) { |
|
|
// TODO: |
|
|
} |
|
|
c->scp.thread = thread; |
|
|
|
|
|
|
|
|
} else if (c->scp.state == SCP_DATA) { |
|
|
// 送信完了 |
|
|
ssh2_channel_send_close(pvar, c); |
|
|
//ssh2_channel_delete(c); // free channel |
|
|
|
|
|
//MessageBox(NULL, "SCP sending done.", "TTSSH", MB_OK); |
|
|
} |
|
|
|
|
|
} else { // error |
|
|
char msg[2048]; |
|
|
unsigned int i, max; |
|
|
|
|
|
if (str_len > sizeof(msg)) |
|
|
max = sizeof(msg); |
|
|
else |
|
|
max = str_len - 1; |
|
|
for (i = 0 ; i < max ; i++) { |
|
|
msg[i] = data[i + 1]; |
|
|
} |
|
|
msg[i] = '\0'; |
|
|
|
|
|
ssh2_channel_send_close(pvar, c); |
|
|
//ssh2_channel_delete(c); // free channel |
|
|
|
|
|
MessageBox(NULL, msg, "TTSSH: SCP error", MB_OK | MB_ICONEXCLAMATION); |
|
|
} |
|
| 7378 |
} |
} |
| 7379 |
|
|
| 7380 |
//debug_print(200, data, strlen); |
//debug_print(200, data, strlen); |