X-Git-Url: http://git.sourceforge.jp/view?p=ffftp%2Fffftp.git;a=blobdiff_plain;f=getput.c;h=28c2471de5eb3666ea6fab767deb4c5f076ad984;hp=7cf67a29cbe8b62074ed9b992bd9acb351b87447;hb=28c3554bd94b9b4f6dcc78175755e8fd24f8e237;hpb=791b047f2c0c10f5d5cc09db8d642191c5c23a83 diff --git a/getput.c b/getput.c index 7cf67a2..28c2471 100644 --- a/getput.c +++ b/getput.c @@ -1,6 +1,6 @@ -/*============================================================================= +/*============================================================================= * -* ƒ_ƒEƒ“ƒ[ƒh^ƒAƒbƒvƒ[ƒh +* ダウンロード/アップロード * =============================================================================== / Copyright (C) 1997-2007 Sota. All rights reserved. @@ -27,11 +27,11 @@ / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /============================================================================*/ -/* ‚±‚̃\[ƒX‚͈ꕔAWS_FTP Version 93.12.05 ‚̃\[ƒX‚ðŽQl‚É‚µ‚Ü‚µ‚½B */ -/* ƒXƒŒƒbƒh‚̍쐬^I—¹‚ÉŠÖ‚µ‚āA”óŒû“aì¬‚̃pƒbƒ`‚ð‘g‚ݍž‚Ý‚Ü‚µ‚½B */ +/* このソースは一部、WS_FTP Version 93.12.05 のソースを参考にしました。 */ +/* スレッドの作成/終了に関して、樋口殿作成のパッチを組み込みました。 */ /* - ˆê•”A‚‘¬‰»‚Ì‚½‚߂̃R[ƒh’ljÁ by H.Shirouzu at 2002/10/02 + 一部、高速化のためのコード追加 by H.Shirouzu at 2002/10/02 */ #define STRICT @@ -41,7 +41,9 @@ #include #include #include -#include +// IPv6対応 +//#include +#include #include #include #include @@ -57,26 +59,26 @@ #define SOCKBUF_SIZE (256 * 1024) /* End */ -#ifdef DISABLE_NETWORK_BUFFERS +#ifdef DISABLE_TRANSFER_NETWORK_BUFFERS #undef BUFSIZE -#define BUFSIZE (64 * 1024) // RWIN’lˆÈ‰º‚ŏ[•ª‚È‘å‚«‚³‚ª–]‚Ü‚µ‚¢‚ÆŽv‚í‚ê‚éB +#define BUFSIZE (64 * 1024) // RWIN値以下で充分な大きさが望ましいと思われる。 #undef SET_BUFFER_SIZE #endif -#define TIMER_DISPLAY 1 /* •\Ž¦XV—pƒ^ƒCƒ}‚ÌID */ -#define DISPLAY_TIMING 500 /* •\Ž¦XVŽžŠÔ 0.5•b */ +#define TIMER_DISPLAY 1 /* 表示更新用タイマのID */ +#define DISPLAY_TIMING 500 /* 表示更新時間 0.5秒 */ #define ERR_MSG_LEN 1024 -/* íœŠm”Fƒ_ƒCƒAƒƒO‚̏î•ñ */ +/* 削除確認ダイアログの情報 */ typedef struct { int Cur; TRANSPACKET *Pkt; } MIRRORDELETEINFO; -/*===== ƒvƒƒgƒ^ƒCƒv =====*/ +/*===== プロトタイプ =====*/ static void DispTransPacket(TRANSPACKET *Pkt); static void EraseTransFileList(void); @@ -86,55 +88,92 @@ static int DownLoadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork); static int DownLoadPassive(TRANSPACKET *Pkt, int *CancelCheckWork); static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *CancelCheckWork); static void DispDownloadFinishMsg(TRANSPACKET *Pkt, int iRetCode); -static int DispUpDownErrDialog(int ResID, HWND hWnd, char *Fname); -static BOOL CALLBACK UpDownErrorDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +// 再転送対応 +//static int DispUpDownErrDialog(int ResID, HWND hWnd, char *Fname); +static int DispUpDownErrDialog(int ResID, HWND hWnd, TRANSPACKET *Pkt); +// 64ビット対応 +//static BOOL CALLBACK UpDownErrorDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +static INT_PTR CALLBACK UpDownErrorDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); static int SetDownloadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int *Mode, int *CancelCheckWork); -static BOOL CALLBACK NoResumeWndProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); +// 64ビット対応 +//static BOOL CALLBACK NoResumeWndProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); +static INT_PTR CALLBACK NoResumeWndProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); static int DoUpLoad(SOCKET cSkt, TRANSPACKET *Pkt); static int UpLoadNonPassive(TRANSPACKET *Pkt); static int UpLoadPassive(TRANSPACKET *Pkt); static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt); -static int TermCodeConvAndSend(TERMCODECONVINFO *tInfo, SOCKET Skt, char *Data, int Size, int Ascii); +// 同時接続対応 +//static int TermCodeConvAndSend(TERMCODECONVINFO *tInfo, SOCKET Skt, char *Data, int Size, int Ascii); +static int TermCodeConvAndSend(TERMCODECONVINFO *tInfo, SOCKET Skt, char *Data, int Size, int Ascii, int *CancelCheckWork); static void DispUploadFinishMsg(TRANSPACKET *Pkt, int iRetCode); static int SetUploadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int *Mode); static LRESULT CALLBACK TransDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam); static void DispTransferStatus(HWND hWnd, int End, TRANSPACKET *Pkt); static void DispTransFileInfo(TRANSPACKET *Pkt, char *Title, int SkipButton, int Info); -static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max); +// IPv6対応 +//static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max); +static int GetAdrsAndPort(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max); +static int GetAdrsAndPortIPv4(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max); +static int GetAdrsAndPortIPv6(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max); static int IsSpecialDevice(char *Fname); static int MirrorDelNotify(int Cur, int Notify, TRANSPACKET *Pkt); -static BOOL CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); +// 64ビット対応 +//static BOOL CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); +static INT_PTR CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); static void SetErrorMsg(char *fmt, ...); +// 同時接続対応 +static char* GetErrMsg(); -/*===== ƒ[ƒJƒ‹‚ȃ[ƒN =====*/ +/*===== ローカルなワーク =====*/ -static HANDLE hTransferThread; +// 同時接続対応 +//static HANDLE hTransferThread; +static HANDLE hTransferThread[MAX_DATA_CONNECTION]; static int fTransferThreadExit = FALSE; -static HANDLE hRunMutex; /* “]‘—ƒXƒŒƒbƒhŽÀsƒ~ƒ…[ƒeƒbƒNƒX */ -static HANDLE hListAccMutex; /* “]‘—ƒtƒ@ƒCƒ‹ƒAƒNƒZƒX—pƒ~ƒ…[ƒeƒbƒNƒX */ - -static int TransFiles = 0; /* “]‘—‘Ò‚¿ƒtƒ@ƒCƒ‹” */ -static TRANSPACKET *TransPacketBase = NULL; /* “]‘—ƒtƒ@ƒCƒ‹ƒŠƒXƒg */ - -static int Canceled; /* ’†Ž~ƒtƒ‰ƒO YES/NO */ -static int ClearAll; /* ‘S‚Ä’†Ž~ƒtƒ‰ƒO YES/NO */ - -static int ForceAbort; /* “]‘—’†Ž~ƒtƒ‰ƒO */ - /* ‚±‚̃tƒ‰ƒO‚̓XƒŒƒbƒh‚ðI—¹‚³‚¹‚é‚Æ‚«‚ÉŽg‚¤ */ - -static LONGLONG AllTransSizeNow; /* ¡‰ñ‚Ì“]‘—‚Å“]‘—‚µ‚½ƒTƒCƒY */ -static time_t TimeStart; /* “]‘—ŠJŽnŽžŠÔ */ - -static int KeepDlg = NO; /* “]‘—’†ƒ_ƒCƒAƒƒO‚ðÁ‚³‚È‚¢‚©‚Ç‚¤‚© (YES/NO) */ -static int MoveToForeground = NO; /* ƒEƒCƒ“ƒhƒE‚ð‘O–ʂɈړ®‚·‚é‚©‚Ç‚¤‚© (YES/NO) */ - -static char CurDir[FMAX_PATH+1] = { "" }; -static char ErrMsg[ERR_MSG_LEN+7]; - -/*===== ŠO•”ŽQÆ =====*/ - -/* Ý’è’l */ +static HANDLE hRunMutex; /* 転送スレッド実行ミューテックス */ +static HANDLE hListAccMutex; /* 転送ファイルアクセス用ミューテックス */ + +static int TransFiles = 0; /* 転送待ちファイル数 */ +static TRANSPACKET *TransPacketBase = NULL; /* 転送ファイルリスト */ +// 同時接続対応 +static TRANSPACKET *NextTransPacketBase = NULL; + +// 同時接続対応 +//static int Canceled; /* 中止フラグ YES/NO */ +static int Canceled[MAX_DATA_CONNECTION]; /* 中止フラグ YES/NO */ +static int ClearAll; /* 全て中止フラグ YES/NO */ + +static int ForceAbort; /* 転送中止フラグ */ + /* このフラグはスレッドを終了させるときに使う */ + +// 同時接続対応 +//static LONGLONG AllTransSizeNow; /* 今回の転送で転送したサイズ */ +//static time_t TimeStart; /* 転送開始時間 */ +static LONGLONG AllTransSizeNow[MAX_DATA_CONNECTION]; /* 今回の転送で転送したサイズ */ +static time_t TimeStart[MAX_DATA_CONNECTION]; /* 転送開始時間 */ + +static int KeepDlg = NO; /* 転送中ダイアログを消さないかどうか (YES/NO) */ +static int MoveToForeground = NO; /* ウインドウを前面に移動するかどうか (YES/NO) */ + +// 同時接続対応 +//static char CurDir[FMAX_PATH+1] = { "" }; +static char CurDir[MAX_DATA_CONNECTION][FMAX_PATH+1]; +// 同時接続対応 +//static char ErrMsg[ERR_MSG_LEN+7]; +static char ErrMsg[MAX_DATA_CONNECTION+1][ERR_MSG_LEN+7]; +static DWORD ErrMsgThreadId[MAX_DATA_CONNECTION+1]; +static HANDLE hErrMsgMutex; + +// 同時接続対応 +static int WaitForMainThread = NO; +// 再転送対応 +static int TransferErrorMode = EXIST_OVW; +static int TransferErrorNotify = NO; + +/*===== 外部参照 =====*/ + +/* 設定値 */ extern int SaveTimeStamp; extern int RmEOF; // extern int TimeOut; @@ -145,74 +184,100 @@ extern int FolderAttr; extern int FolderAttrNum; -/*----- ƒtƒ@ƒCƒ‹“]‘—ƒXƒŒƒbƒh‚ð‹N“®‚·‚é ---------------------------------------- +/*----- ファイル転送スレッドを起動する ---------------------------------------- * * Parameter -* ‚È‚µ +* なし * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ int MakeTransferThread(void) { DWORD dwID; + int i; hListAccMutex = CreateMutex( NULL, FALSE, NULL ); hRunMutex = CreateMutex( NULL, TRUE, NULL ); + // 同時接続対応 + hErrMsgMutex = CreateMutex( NULL, FALSE, NULL ); ClearAll = NO; ForceAbort = NO; fTransferThreadExit = FALSE; - hTransferThread = (HANDLE)_beginthreadex(NULL, 0, TransferThread, 0, 0, &dwID); - if (hTransferThread == NULL) - return(FAIL); /* XXX */ + // 同時接続対応 +// hTransferThread = (HANDLE)_beginthreadex(NULL, 0, TransferThread, 0, 0, &dwID); +// if (hTransferThread == NULL) +// return(FFFTP_FAIL); /* XXX */ + for(i = 0; i < MAX_DATA_CONNECTION; i++) + { + hTransferThread[i] = (HANDLE)_beginthreadex(NULL, 0, TransferThread, (void*)i, 0, &dwID); + if(hTransferThread[i] == NULL) + return FFFTP_FAIL; + } - return(SUCCESS); + return(FFFTP_SUCCESS); } -/*----- ƒtƒ@ƒCƒ‹“]‘—ƒXƒŒƒbƒh‚ðI—¹‚·‚é ---------------------------------------- +/*----- ファイル転送スレッドを終了する ---------------------------------------- * * Parameter -* ‚È‚µ +* なし * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ void CloseTransferThread(void) { - Canceled = YES; + int i; + // 同時接続対応 +// Canceled = YES; + for(i = 0; i < MAX_DATA_CONNECTION; i++) + Canceled[i] = YES; ClearAll = YES; ForceAbort = YES; fTransferThreadExit = TRUE; - while(WaitForSingleObject(hTransferThread, 10) == WAIT_TIMEOUT) + // 同時接続対応 +// while(WaitForSingleObject(hTransferThread, 10) == WAIT_TIMEOUT) +// { +// BackgrndMessageProc(); +// Canceled = YES; +// } +// CloseHandle(hTransferThread); + for(i = 0; i < MAX_DATA_CONNECTION; i++) { - BackgrndMessageProc(); - Canceled = YES; + while(WaitForSingleObject(hTransferThread[i], 10) == WAIT_TIMEOUT) + { + BackgrndMessageProc(); + Canceled[i] = YES; + } + CloseHandle(hTransferThread[i]); } - CloseHandle(hTransferThread); ReleaseMutex( hRunMutex ); CloseHandle( hListAccMutex ); CloseHandle( hRunMutex ); + // 同時接続対応 + CloseHandle( hErrMsgMutex ); return; } -/*----- “]‘—‚·‚éƒtƒ@ƒCƒ‹î•ñ‚ðƒŠƒXƒg‚ɒljÁ‚·‚é -------------------------------- +/*----- 転送するファイル情報をリストに追加する -------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* TRANSPACKET **Base : ƒŠƒXƒg‚̐擪 +* TRANSPACKET *Pkt : 転送ファイル情報 +* TRANSPACKET **Base : リストの先頭 * * Return Value -* int ƒXƒe[ƒ^ƒX -* SUCCESS/FAIL +* int ステータス +* FFFTP_SUCCESS/FFFTP_FAIL *----------------------------------------------------------------------------*/ int AddTmpTransFileList(TRANSPACKET *Pkt, TRANSPACKET **Base) @@ -221,7 +286,7 @@ int AddTmpTransFileList(TRANSPACKET *Pkt, TRANSPACKET **Base) TRANSPACKET *Prev; int Sts; - Sts = FAIL; + Sts = FFFTP_FAIL; if((Pos = malloc(sizeof(TRANSPACKET))) != NULL) { memcpy(Pos, Pkt, sizeof(TRANSPACKET)); @@ -236,19 +301,19 @@ int AddTmpTransFileList(TRANSPACKET *Pkt, TRANSPACKET **Base) Prev = Prev->Next; Prev->Next = Pos; } - Sts = SUCCESS; + Sts = FFFTP_SUCCESS; } return(Sts); } -/*----- “]‘—‚·‚éƒtƒ@ƒCƒ‹î•ñƒŠƒXƒg‚ðƒNƒŠƒA‚·‚é -------------------------------- +/*----- 転送するファイル情報リストをクリアする -------------------------------- * * Parameter -* TRANSPACKET **Base : ƒŠƒXƒg‚̐擪 +* TRANSPACKET **Base : リストの先頭 * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ void EraseTmpTransFileList(TRANSPACKET **Base) @@ -268,15 +333,15 @@ void EraseTmpTransFileList(TRANSPACKET **Base) } -/*----- “]‘—‚·‚éƒtƒ@ƒCƒ‹î•ñƒŠƒXƒg‚©‚ç‚P‚‚̏î•ñ‚ðŽæ‚菜‚­ -------------------- +/*----- 転送するファイル情報リストから1つの情報を取り除く -------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* TRANSPACKET **Base : ƒŠƒXƒg‚̐擪 +* TRANSPACKET *Pkt : 転送ファイル情報 +* TRANSPACKET **Base : リストの先頭 * * Return Value -* int ƒXƒe[ƒ^ƒX -* SUCCESS/FAIL +* int ステータス +* FFFTP_SUCCESS/FFFTP_FAIL *----------------------------------------------------------------------------*/ int RemoveTmpTransFileListItem(TRANSPACKET **Base, int Num) @@ -285,13 +350,13 @@ int RemoveTmpTransFileListItem(TRANSPACKET **Base, int Num) TRANSPACKET *Prev; int Sts; - Sts = FAIL; + Sts = FFFTP_FAIL; Pos = *Base; if(Num == 0) { *Base = Pos->Next; free(Pos); - Sts = SUCCESS; + Sts = FFFTP_SUCCESS; } else { @@ -303,7 +368,7 @@ int RemoveTmpTransFileListItem(TRANSPACKET **Base, int Num) { Prev->Next = Pos->Next; free(Pos); - Sts = SUCCESS; + Sts = FFFTP_SUCCESS; break; } } @@ -312,22 +377,39 @@ int RemoveTmpTransFileListItem(TRANSPACKET **Base, int Num) } -/*----- “]‘—‚·‚éƒtƒ@ƒCƒ‹î•ñ‚ð“]‘—ƒtƒ@ƒCƒ‹ƒŠƒXƒg‚É“o˜^‚·‚é -------------------- +/*----- 転送するファイル情報を転送ファイルリストに登録する -------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ +* TRANSPACKET *Pkt : 転送ファイル情報 * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ void AddTransFileList(TRANSPACKET *Pkt) { + // 同時接続対応 + TRANSPACKET *Pos; + DispTransPacket(Pkt); - WaitForSingleObject(hListAccMutex, INFINITE); + // 同時接続対応 +// WaitForSingleObject(hListAccMutex, INFINITE); + while(WaitForSingleObject(hListAccMutex, 0) == WAIT_TIMEOUT) + { + WaitForMainThread = YES; + BackgrndMessageProc(); + Sleep(1); + } - if(AddTmpTransFileList(Pkt, &TransPacketBase) == SUCCESS) + // 同時接続対応 + Pos = TransPacketBase; + if(Pos != NULL) + { + while(Pos->Next != NULL) + Pos = Pos->Next; + } + if(AddTmpTransFileList(Pkt, &TransPacketBase) == FFFTP_SUCCESS) { if((strncmp(Pkt->Cmd, "RETR", 4) == 0) || (strncmp(Pkt->Cmd, "STOR", 4) == 0)) @@ -336,30 +418,47 @@ void AddTransFileList(TRANSPACKET *Pkt) PostMessage(GetMainHwnd(), WM_CHANGE_COND, 0, 0); } } + // 同時接続対応 + if(NextTransPacketBase == NULL) + { + if(Pos) + NextTransPacketBase = Pos->Next; + else + NextTransPacketBase = TransPacketBase; + } ReleaseMutex(hListAccMutex); + // 同時接続対応 + WaitForMainThread = NO; return; } -/*----- “]‘—ƒtƒ@ƒCƒ‹î•ñ‚ð“]‘—ƒtƒ@ƒCƒ‹ƒŠƒXƒg‚ɒljÁ‚·‚é ------------------------ +/*----- 転送ファイル情報を転送ファイルリストに追加する ------------------------ * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* TRANSPACKET **Base : ƒŠƒXƒg‚̐擪 +* TRANSPACKET *Pkt : 転送ファイル情報 +* TRANSPACKET **Base : リストの先頭 * * Return Value -* ‚È‚µ +* なし * * Note -* PktŽ©‘Ì‚ðƒŠƒXƒg‚ɘAŒ‹‚·‚é +* Pkt自体をリストに連結する *----------------------------------------------------------------------------*/ void AppendTransFileList(TRANSPACKET *Pkt) { TRANSPACKET *Pos; - WaitForSingleObject(hListAccMutex, INFINITE); + // 同時接続対応 +// WaitForSingleObject(hListAccMutex, INFINITE); + while(WaitForSingleObject(hListAccMutex, 0) == WAIT_TIMEOUT) + { + WaitForMainThread = YES; + BackgrndMessageProc(); + Sleep(1); + } if(TransPacketBase == NULL) TransPacketBase = Pkt; @@ -370,6 +469,9 @@ void AppendTransFileList(TRANSPACKET *Pkt) Pos = Pos->Next; Pos->Next = Pkt; } + // 同時接続対応 + if(NextTransPacketBase == NULL) + NextTransPacketBase = Pkt; while(Pkt != NULL) { @@ -385,17 +487,19 @@ void AppendTransFileList(TRANSPACKET *Pkt) } ReleaseMutex(hListAccMutex); + // 同時接続対応 + WaitForMainThread = NO; return; } -/*----- “]‘—ƒtƒ@ƒCƒ‹î•ñ‚ð•\Ž¦‚·‚é -------------------------------------------- +/*----- 転送ファイル情報を表示する -------------------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ +* TRANSPACKET *Pkt : 転送ファイル情報 * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ static void DispTransPacket(TRANSPACKET *Pkt) @@ -419,13 +523,13 @@ static void DispTransPacket(TRANSPACKET *Pkt) } -/*----- “]‘—ƒtƒ@ƒCƒ‹ƒŠƒXƒg‚ðƒNƒŠƒA‚·‚é ---------------------------------------- +/*----- 転送ファイルリストをクリアする ---------------------------------------- * * Parameter -* ‚È‚µ +* なし * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ static void EraseTransFileList(void) @@ -437,30 +541,46 @@ static void EraseTransFileList(void) NotDel = NULL; - WaitForSingleObject(hListAccMutex, INFINITE); + // 同時接続対応 +// WaitForSingleObject(hListAccMutex, INFINITE); + while(WaitForSingleObject(hListAccMutex, 0) == WAIT_TIMEOUT) + { + WaitForMainThread = YES; + BackgrndMessageProc(); + Sleep(1); + } New = TransPacketBase; while(New != NULL) { - /* ÅŒã‚Ì"BACKCUR"‚Í•K—v‚Ȃ̂ŏÁ‚³‚È‚¢ */ + /* 最後の"BACKCUR"は必要なので消さない */ if(strcmp(New->Cmd, "BACKCUR") == 0) { if(NotDel != NULL) - free(NotDel); + // 同時接続対応 +// free(NotDel); + strcpy(NotDel->Cmd, ""); NotDel = New; New = New->Next; - NotDel->Next = NULL; + // 同時接続対応 +// NotDel->Next = NULL; } else { Next = New->Next; - free(New); + // 同時接続対応 +// free(New); + strcpy(New->Cmd, ""); New = Next; } } TransPacketBase = NotDel; + // 同時接続対応 + NextTransPacketBase = NotDel; TransFiles = 0; PostMessage(GetMainHwnd(), WM_CHANGE_COND, 0, 0); ReleaseMutex(hListAccMutex); + // 同時接続対応 + WaitForMainThread = NO; strcpy(Pkt.Cmd, "GOQUIT"); AddTransFileList(&Pkt); @@ -468,13 +588,13 @@ static void EraseTransFileList(void) } -/*----- “]‘—’†ƒ_ƒCƒAƒƒO‚ðÁ‚³‚È‚¢‚悤‚É‚·‚é‚©‚Ç‚¤‚©‚ðÝ’è -------------------- +/*----- 転送中ダイアログを消さないようにするかどうかを設定 -------------------- * * Parameter -* int Sw : “]‘—’†ƒ_ƒCƒAƒƒO‚ðÁ‚³‚È‚¢‚©‚Ç‚¤‚© (YES/NO) +* int Sw : 転送中ダイアログを消さないかどうか (YES/NO) * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ void KeepTransferDialog(int Sw) @@ -484,13 +604,13 @@ void KeepTransferDialog(int Sw) } -/*----- Œ»Ý“]‘—’†‚©‚Ç‚¤‚©‚ð•Ô‚· ---------------------------------------------- +/*----- 現在転送中かどうかを返す ---------------------------------------------- * * Parameter -* ‚È‚µ +* なし * * Return Value -* int ƒXƒe[ƒ^ƒX (YES/NO=“]‘—’†‚Å‚Í‚È‚¢) +* int ステータス (YES/NO=転送中ではない) *----------------------------------------------------------------------------*/ int AskTransferNow(void) @@ -499,13 +619,13 @@ int AskTransferNow(void) } -/*----- “]‘—‚·‚éƒtƒ@ƒCƒ‹‚̐”‚ð•Ô‚· -------------------------------------------- +/*----- 転送するファイルの数を返す -------------------------------------------- * * Parameter -* ‚È‚µ +* なし * * Return Value -* int “]‘—‚·‚éƒtƒ@ƒCƒ‹‚̐” +* int 転送するファイルの数 *----------------------------------------------------------------------------*/ int AskTransferFileNum(void) @@ -514,13 +634,13 @@ int AskTransferFileNum(void) } -/*----- “]‘—’†ƒEƒCƒ“ƒhƒE‚ð‘O–ʂɏo‚· ------------------------------------------ +/*----- 転送中ウインドウを前面に出す ------------------------------------------ * * Parameter -* ‚È‚µ +* なし * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ void GoForwardTransWindow(void) @@ -530,29 +650,33 @@ void GoForwardTransWindow(void) } -/*----- “]‘—ƒ\ƒPƒbƒg‚̃JƒŒƒ“ƒgƒfƒBƒŒƒNƒgƒŠî•ñ‚ð‰Šú‰» ------------------------ +/*----- 転送ソケットのカレントディレクトリ情報を初期化 ------------------------ * * Parameter -* ‚È‚µ +* なし * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ void InitTransCurDir(void) { - strcpy(CurDir, ""); + // 同時接続対応 +// strcpy(CurDir, ""); + int i; + for(i = 0; i < MAX_DATA_CONNECTION; i++) + strcpy(CurDir[i], ""); return; } -/*----- ƒtƒ@ƒCƒ‹“]‘—ƒXƒŒƒbƒh‚̃ƒCƒ“ƒ‹[ƒv ------------------------------------ +/*----- ファイル転送スレッドのメインループ ------------------------------------ * * Parameter -* void *Dummy : Žg‚í‚È‚¢ +* void *Dummy : 使わない * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ static ULONG WINAPI TransferThread(void *Dummy) @@ -562,15 +686,31 @@ static ULONG WINAPI TransferThread(void *Dummy) char Tmp[FMAX_PATH+1]; int CwdSts; int GoExit; - int Down; - int Up; +// int Down; +// int Up; + static int Down; + static int Up; int DelNotify; + int ThreadCount; + SOCKET CmdSkt; + SOCKET NewCmdSkt; + SOCKET TrnSkt; + RECT WndRect; + int i; + DWORD LastUsed; hWndTrans = NULL; Down = NO; Up = NO; GoExit = NO; DelNotify = NO; + // 同時接続対応 + // ソケットは各転送スレッドが管理 + ThreadCount = (int)Dummy; + CmdSkt = INVALID_SOCKET; + NewCmdSkt = INVALID_SOCKET; + TrnSkt = INVALID_SOCKET; + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST); while((TransPacketBase != NULL) || (WaitForSingleObject(hRunMutex, 200) == WAIT_TIMEOUT)) @@ -578,29 +718,130 @@ static ULONG WINAPI TransferThread(void *Dummy) if(fTransferThreadExit == TRUE) break; - WaitForSingleObject(hListAccMutex, INFINITE); - memset(ErrMsg, NUL, ERR_MSG_LEN+7); + if(WaitForMainThread == YES) + { + BackgrndMessageProc(); + Sleep(100); + continue; + } + +// WaitForSingleObject(hListAccMutex, INFINITE); + while(WaitForSingleObject(hListAccMutex, 0) == WAIT_TIMEOUT) + { + BackgrndMessageProc(); + Sleep(1); + } +// memset(ErrMsg, NUL, ERR_MSG_LEN+7); + memset(GetErrMsg(), NUL, ERR_MSG_LEN+7); - Canceled = NO; +// Canceled = NO; + Canceled[ThreadCount] = NO; - if(TransPacketBase != NULL) + while(TransPacketBase != NULL && strcmp(TransPacketBase->Cmd, "") == 0) { - ReleaseMutex(hListAccMutex); + Pos = TransPacketBase; + TransPacketBase = TransPacketBase->Next; + free(Pos); + } + NewCmdSkt = AskCmdCtrlSkt(); + if(AskReuseCmdSkt() == YES && ThreadCount == 0) + { + if(TransPacketBase && ThreadCount < AskMaxThreadCount()) + TrnSkt = AskTrnCtrlSkt(); + } + else + { + if(TransPacketBase && NewCmdSkt != INVALID_SOCKET && ThreadCount < AskMaxThreadCount()) + { + if(TrnSkt == INVALID_SOCKET || NewCmdSkt != CmdSkt) + { + ReleaseMutex(hListAccMutex); + ReConnectTrnSkt(&TrnSkt, &Canceled[ThreadCount]); + // 同時ログイン数制限対策 + if(TrnSkt != INVALID_SOCKET) + LastUsed = timeGetTime(); + else + { + // 同時ログイン数制限に引っかかった可能性あり + // 負荷を下げるために約10秒間待機 + i = 10000; + while(NewCmdSkt != CmdSkt && i > 0) + { + BackgrndMessageProc(); + Sleep(1); + i--; + } + } +// WaitForSingleObject(hListAccMutex, INFINITE); + while(WaitForSingleObject(hListAccMutex, 0) == WAIT_TIMEOUT) + { + BackgrndMessageProc(); + Sleep(1); + } + } + } + else + { + if(TrnSkt != INVALID_SOCKET) + { + // 同時ログイン数制限対策 + // 10秒間は再利用を許可 + if(timeGetTime() - LastUsed > 10000) + { + ReleaseMutex(hListAccMutex); + SendData(TrnSkt, "QUIT\r\n", 6, 0, &Canceled[ThreadCount]); + DoClose(TrnSkt); + TrnSkt = INVALID_SOCKET; +// WaitForSingleObject(hListAccMutex, INFINITE); + while(WaitForSingleObject(hListAccMutex, 0) == WAIT_TIMEOUT) + { + BackgrndMessageProc(); + Sleep(1); + } + } + } + } + } + CmdSkt = NewCmdSkt; +// if(TransPacketBase != NULL) + if(TrnSkt != INVALID_SOCKET && NextTransPacketBase != NULL) + { + if(strcmp(NextTransPacketBase->Cmd, "GOQUIT") == 0 && NextTransPacketBase != TransPacketBase) + { + ReleaseMutex(hListAccMutex); + BackgrndMessageProc(); + Sleep(1); + continue; + } + Pos = NextTransPacketBase; + NextTransPacketBase = NextTransPacketBase->Next; + // ディレクトリ操作は非同期で行わない +// ReleaseMutex(hListAccMutex); if(hWndTrans == NULL) { - if((strncmp(TransPacketBase->Cmd, "RETR", 4) == 0) || - (strncmp(TransPacketBase->Cmd, "STOR", 4) == 0) || - (strncmp(TransPacketBase->Cmd, "MKD", 3) == 0) || - (strncmp(TransPacketBase->Cmd, "L-", 2) == 0) || - (strncmp(TransPacketBase->Cmd, "R-", 2) == 0)) +// if((strncmp(TransPacketBase->Cmd, "RETR", 4) == 0) || +// (strncmp(TransPacketBase->Cmd, "STOR", 4) == 0) || +// (strncmp(TransPacketBase->Cmd, "MKD", 3) == 0) || +// (strncmp(TransPacketBase->Cmd, "L-", 2) == 0) || +// (strncmp(TransPacketBase->Cmd, "R-", 2) == 0)) + if((strncmp(Pos->Cmd, "RETR", 4) == 0) || + (strncmp(Pos->Cmd, "STOR", 4) == 0) || + (strncmp(Pos->Cmd, "MKD", 3) == 0) || + (strncmp(Pos->Cmd, "L-", 2) == 0) || + (strncmp(Pos->Cmd, "R-", 2) == 0)) { hWndTrans = CreateDialog(GetFtpInst(), MAKEINTRESOURCE(transfer_dlg), HWND_DESKTOP, (DLGPROC)TransDlgProc); if(MoveToForeground == YES) SetForegroundWindow(hWndTrans); ShowWindow(hWndTrans, SW_SHOWNOACTIVATE); + GetWindowRect(hWndTrans, &WndRect); + SetWindowPos(hWndTrans, NULL, WndRect.left, WndRect.top + (WndRect.bottom - WndRect.top) * ThreadCount - (WndRect.bottom - WndRect.top) * (AskMaxThreadCount() - 1) / 2, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } } - TransPacketBase->hWndTrans = hWndTrans; +// TransPacketBase->hWndTrans = hWndTrans; + Pos->hWndTrans = hWndTrans; + Pos->ctrl_skt = TrnSkt; + Pos->ThreadCount = ThreadCount; if(hWndTrans != NULL) { @@ -612,60 +853,85 @@ static ULONG WINAPI TransferThread(void *Dummy) } if(hWndTrans != NULL) - SendMessage(hWndTrans, WM_SET_PACKET, 0, (LPARAM)TransPacketBase); +// SendMessage(hWndTrans, WM_SET_PACKET, 0, (LPARAM)TransPacketBase); + SendMessage(hWndTrans, WM_SET_PACKET, 0, (LPARAM)Pos); - /* ƒ_ƒEƒ“ƒ[ƒh */ - if(strncmp(TransPacketBase->Cmd, "RETR", 4) == 0) + /* ダウンロード */ +// if(strncmp(TransPacketBase->Cmd, "RETR", 4) == 0) + if(strncmp(Pos->Cmd, "RETR", 4) == 0) { - /* •s³‚ȃpƒX‚ðŒŸo */ - if(CheckPathViolation(TransPacketBase) == NO) + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため +// ReleaseMutex(hListAccMutex); + /* 不正なパスを検出 */ +// if(CheckPathViolation(TransPacketBase) == NO) + if(CheckPathViolation(Pos) == NO) { - /* ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢‚½‚߂̏ˆ— */ - if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == SUCCESS) + /* フルパスを使わないための処理 */ +// if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == FFFTP_SUCCESS) + if(MakeNonFullPath(Pos, CurDir[Pos->ThreadCount], Tmp) == FFFTP_SUCCESS) { - if(strncmp(TransPacketBase->Cmd, "RETR-S", 6) == 0) +// if(strncmp(TransPacketBase->Cmd, "RETR-S", 6) == 0) + if(strncmp(Pos->Cmd, "RETR-S", 6) == 0) { - /* ƒTƒCƒY‚Æ“ú•t‚ðŽæ“¾ */ - DoSIZE(TransPacketBase->RemoteFile, &TransPacketBase->Size); - DoMDTM(TransPacketBase->RemoteFile, &TransPacketBase->Time); - strcpy(TransPacketBase->Cmd, "RETR "); + /* サイズと日付を取得 */ +// DoSIZE(TransPacketBase->RemoteFile, &TransPacketBase->Size); +// DoMDTM(TransPacketBase->RemoteFile, &TransPacketBase->Time); +// strcpy(TransPacketBase->Cmd, "RETR "); + DoSIZE(TrnSkt, Pos->RemoteFile, &Pos->Size, &Canceled[Pos->ThreadCount]); + DoMDTM(TrnSkt, Pos->RemoteFile, &Pos->Time, &Canceled[Pos->ThreadCount]); + strcpy(Pos->Cmd, "RETR "); } Down = YES; // if(DoDownLoad(AskTrnCtrlSkt(), TransPacketBase, NO) == 429) // { -// if(ReConnectTrnSkt() == SUCCESS) - DoDownLoad(AskTrnCtrlSkt(), TransPacketBase, NO, &Canceled); +// if(ReConnectTrnSkt() == FFFTP_SUCCESS) +// DoDownLoad(AskTrnCtrlSkt(), TransPacketBase, NO, &Canceled); + DoDownLoad(TrnSkt, Pos, NO, &Canceled[Pos->ThreadCount]); // } } } + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため + ReleaseMutex(hListAccMutex); } - /* ƒAƒbƒvƒ[ƒh */ - else if(strncmp(TransPacketBase->Cmd, "STOR", 4) == 0) + /* アップロード */ +// else if(strncmp(TransPacketBase->Cmd, "STOR", 4) == 0) + else if(strncmp(Pos->Cmd, "STOR", 4) == 0) { - /* ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢‚½‚߂̏ˆ— */ - if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == SUCCESS) + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため +// ReleaseMutex(hListAccMutex); + /* フルパスを使わないための処理 */ +// if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == FFFTP_SUCCESS) + if(MakeNonFullPath(Pos, CurDir[Pos->ThreadCount], Tmp) == FFFTP_SUCCESS) { Up = YES; // if(DoUpLoad(AskTrnCtrlSkt(), TransPacketBase) == 429) // { -// if(ReConnectTrnSkt() == SUCCESS) - DoUpLoad(AskTrnCtrlSkt(), TransPacketBase); +// if(ReConnectTrnSkt() == FFFTP_SUCCESS) +// DoUpLoad(AskTrnCtrlSkt(), TransPacketBase); + DoUpLoad(TrnSkt, Pos); // } } + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため + ReleaseMutex(hListAccMutex); } - /* ƒtƒHƒ‹ƒ_ì¬iƒ[ƒJƒ‹‚Ü‚½‚̓zƒXƒgj */ - else if(strncmp(TransPacketBase->Cmd, "MKD", 3) == 0) + /* フォルダ作成(ローカルまたはホスト) */ +// else if(strncmp(TransPacketBase->Cmd, "MKD", 3) == 0) + else if(strncmp(Pos->Cmd, "MKD", 3) == 0) { - DispTransFileInfo(TransPacketBase, MSGJPN078, FALSE, YES); +// DispTransFileInfo(TransPacketBase, MSGJPN078, FALSE, YES); + DispTransFileInfo(Pos, MSGJPN078, FALSE, YES); - if(strlen(TransPacketBase->RemoteFile) > 0) +// if(strlen(TransPacketBase->RemoteFile) > 0) + if(strlen(Pos->RemoteFile) > 0) { - /* ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢‚½‚߂̏ˆ— */ + /* フルパスを使わないための処理 */ CwdSts = FTP_COMPLETE; - strcpy(Tmp, TransPacketBase->RemoteFile); - if(ProcForNonFullpath(Tmp, CurDir, hWndTrans, 1) == FAIL) +// strcpy(Tmp, TransPacketBase->RemoteFile); + strcpy(Tmp, Pos->RemoteFile); +// if(ProcForNonFullpath(Tmp, CurDir, hWndTrans, 1) == FFFTP_FAIL) + if(ProcForNonFullpath(TrnSkt, Tmp, CurDir[Pos->ThreadCount], hWndTrans, &Canceled[Pos->ThreadCount]) == FFFTP_FAIL) { ClearAll = YES; CwdSts = FTP_ERROR; @@ -674,149 +940,217 @@ static ULONG WINAPI TransferThread(void *Dummy) if(CwdSts == FTP_COMPLETE) { Up = YES; - CommandProcTrn(NULL, "MKD %s", Tmp); - /* ‚·‚łɃtƒHƒ‹ƒ_‚ª‚ ‚éê‡‚à‚ ‚é‚̂ŁA */ - /* ‚±‚±‚ł̓Gƒ‰[ƒ`ƒFƒbƒN‚Í‚µ‚È‚¢ */ +// CommandProcTrn(NULL, "MKD %s", Tmp); + CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "MKD %s", Tmp); + /* すでにフォルダがある場合もあるので、 */ + /* ここではエラーチェックはしない */ if(FolderAttr) - CommandProcTrn(NULL, "%s %03d %s", AskHostChmodCmd(), FolderAttrNum, Tmp); +// CommandProcTrn(NULL, "%s %03d %s", AskHostChmodCmd(), FolderAttrNum, Tmp); + CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "%s %03d %s", AskHostChmodCmd(), FolderAttrNum, Tmp); } } - else if(strlen(TransPacketBase->LocalFile) > 0) +// else if(strlen(TransPacketBase->LocalFile) > 0) + else if(strlen(Pos->LocalFile) > 0) { Down = YES; - DoLocalMKD(TransPacketBase->LocalFile); +// DoLocalMKD(TransPacketBase->LocalFile); + DoLocalMKD(Pos->LocalFile); } + ReleaseMutex(hListAccMutex); } - /* ƒfƒBƒŒƒNƒgƒŠì¬ií‚ɃzƒXƒg‘¤j */ - else if(strncmp(TransPacketBase->Cmd, "R-MKD", 5) == 0) + /* ディレクトリ作成(常にホスト側) */ +// else if(strncmp(TransPacketBase->Cmd, "R-MKD", 5) == 0) + else if(strncmp(Pos->Cmd, "R-MKD", 5) == 0) { - DispTransFileInfo(TransPacketBase, MSGJPN079, FALSE, YES); +// DispTransFileInfo(TransPacketBase, MSGJPN079, FALSE, YES); + DispTransFileInfo(Pos, MSGJPN079, FALSE, YES); - /* ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢‚½‚߂̏ˆ— */ - if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == SUCCESS) + /* フルパスを使わないための処理 */ +// if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == FFFTP_SUCCESS) + if(MakeNonFullPath(Pos, CurDir[Pos->ThreadCount], Tmp) == FFFTP_SUCCESS) { Up = YES; - CommandProcTrn(NULL, "%s%s", TransPacketBase->Cmd+2, TransPacketBase->RemoteFile); +// CommandProcTrn(NULL, "%s%s", TransPacketBase->Cmd+2, TransPacketBase->RemoteFile); + CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "%s%s", Pos->Cmd+2, Pos->RemoteFile); if(FolderAttr) - CommandProcTrn(NULL, "%s %03d %s", AskHostChmodCmd(), FolderAttrNum, TransPacketBase->RemoteFile); +// CommandProcTrn(NULL, "%s %03d %s", AskHostChmodCmd(), FolderAttrNum, TransPacketBase->RemoteFile); + CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "%s %03d %s", AskHostChmodCmd(), FolderAttrNum, Pos->RemoteFile); } + ReleaseMutex(hListAccMutex); } - /* ƒfƒBƒŒƒNƒgƒŠíœií‚ɃzƒXƒg‘¤j */ - else if(strncmp(TransPacketBase->Cmd, "R-RMD", 5) == 0) + /* ディレクトリ削除(常にホスト側) */ +// else if(strncmp(TransPacketBase->Cmd, "R-RMD", 5) == 0) + else if(strncmp(Pos->Cmd, "R-RMD", 5) == 0) { - DispTransFileInfo(TransPacketBase, MSGJPN080, FALSE, YES); +// DispTransFileInfo(TransPacketBase, MSGJPN080, FALSE, YES); + DispTransFileInfo(Pos, MSGJPN080, FALSE, YES); - DelNotify = MirrorDelNotify(WIN_REMOTE, DelNotify, TransPacketBase); +// DelNotify = MirrorDelNotify(WIN_REMOTE, DelNotify, TransPacketBase); + DelNotify = MirrorDelNotify(WIN_REMOTE, DelNotify, Pos); if((DelNotify == YES) || (DelNotify == YES_ALL)) { - /* ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢‚½‚߂̏ˆ— */ - if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == SUCCESS) + /* フルパスを使わないための処理 */ +// if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == FFFTP_SUCCESS) + if(MakeNonFullPath(Pos, CurDir[Pos->ThreadCount], Tmp) == FFFTP_SUCCESS) { Up = YES; - CommandProcTrn(NULL, "%s%s", TransPacketBase->Cmd+2, TransPacketBase->RemoteFile); +// CommandProcTrn(NULL, "%s%s", TransPacketBase->Cmd+2, TransPacketBase->RemoteFile); + CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "%s%s", Pos->Cmd+2, Pos->RemoteFile); } } + ReleaseMutex(hListAccMutex); } - /* ƒtƒ@ƒCƒ‹íœií‚ɃzƒXƒg‘¤j */ - else if(strncmp(TransPacketBase->Cmd, "R-DELE", 6) == 0) + /* ファイル削除(常にホスト側) */ +// else if(strncmp(TransPacketBase->Cmd, "R-DELE", 6) == 0) + else if(strncmp(Pos->Cmd, "R-DELE", 6) == 0) { - DispTransFileInfo(TransPacketBase, MSGJPN081, FALSE, YES); +// DispTransFileInfo(TransPacketBase, MSGJPN081, FALSE, YES); + DispTransFileInfo(Pos, MSGJPN081, FALSE, YES); - DelNotify = MirrorDelNotify(WIN_REMOTE, DelNotify, TransPacketBase); +// DelNotify = MirrorDelNotify(WIN_REMOTE, DelNotify, TransPacketBase); + DelNotify = MirrorDelNotify(WIN_REMOTE, DelNotify, Pos); if((DelNotify == YES) || (DelNotify == YES_ALL)) { - /* ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢‚½‚߂̏ˆ— */ - if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == SUCCESS) + /* フルパスを使わないための処理 */ +// if(MakeNonFullPath(TransPacketBase, CurDir, Tmp) == FFFTP_SUCCESS) + if(MakeNonFullPath(Pos, CurDir[Pos->ThreadCount], Tmp) == FFFTP_SUCCESS) { Up = YES; - CommandProcTrn(NULL, "%s%s", TransPacketBase->Cmd+2, TransPacketBase->RemoteFile); +// CommandProcTrn(NULL, "%s%s", TransPacketBase->Cmd+2, TransPacketBase->RemoteFile); + CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "%s%s", Pos->Cmd+2, Pos->RemoteFile); } } + ReleaseMutex(hListAccMutex); } - /* ƒfƒBƒŒƒNƒgƒŠì¬ií‚Ƀ[ƒJƒ‹‘¤j */ - else if(strncmp(TransPacketBase->Cmd, "L-MKD", 5) == 0) + /* ディレクトリ作成(常にローカル側) */ +// else if(strncmp(TransPacketBase->Cmd, "L-MKD", 5) == 0) + else if(strncmp(Pos->Cmd, "L-MKD", 5) == 0) { - DispTransFileInfo(TransPacketBase, MSGJPN082, FALSE, YES); +// DispTransFileInfo(TransPacketBase, MSGJPN082, FALSE, YES); + DispTransFileInfo(Pos, MSGJPN082, FALSE, YES); Down = YES; - DoLocalMKD(TransPacketBase->LocalFile); +// DoLocalMKD(TransPacketBase->LocalFile); + DoLocalMKD(Pos->LocalFile); + ReleaseMutex(hListAccMutex); } - /* ƒfƒBƒŒƒNƒgƒŠíœií‚Ƀ[ƒJƒ‹‘¤j */ - else if(strncmp(TransPacketBase->Cmd, "L-RMD", 5) == 0) + /* ディレクトリ削除(常にローカル側) */ +// else if(strncmp(TransPacketBase->Cmd, "L-RMD", 5) == 0) + else if(strncmp(Pos->Cmd, "L-RMD", 5) == 0) { - DispTransFileInfo(TransPacketBase, MSGJPN083, FALSE, YES); +// DispTransFileInfo(TransPacketBase, MSGJPN083, FALSE, YES); + DispTransFileInfo(Pos, MSGJPN083, FALSE, YES); - DelNotify = MirrorDelNotify(WIN_LOCAL, DelNotify, TransPacketBase); +// DelNotify = MirrorDelNotify(WIN_LOCAL, DelNotify, TransPacketBase); + DelNotify = MirrorDelNotify(WIN_LOCAL, DelNotify, Pos); if((DelNotify == YES) || (DelNotify == YES_ALL)) { Down = YES; - DoLocalRMD(TransPacketBase->LocalFile); +// DoLocalRMD(TransPacketBase->LocalFile); + DoLocalRMD(Pos->LocalFile); } + ReleaseMutex(hListAccMutex); } - /* ƒtƒ@ƒCƒ‹íœií‚Ƀ[ƒJƒ‹‘¤j */ - else if(strncmp(TransPacketBase->Cmd, "L-DELE", 6) == 0) + /* ファイル削除(常にローカル側) */ +// else if(strncmp(TransPacketBase->Cmd, "L-DELE", 6) == 0) + else if(strncmp(Pos->Cmd, "L-DELE", 6) == 0) { - DispTransFileInfo(TransPacketBase, MSGJPN084, FALSE, YES); +// DispTransFileInfo(TransPacketBase, MSGJPN084, FALSE, YES); + DispTransFileInfo(Pos, MSGJPN084, FALSE, YES); - DelNotify = MirrorDelNotify(WIN_LOCAL, DelNotify, TransPacketBase); +// DelNotify = MirrorDelNotify(WIN_LOCAL, DelNotify, TransPacketBase); + DelNotify = MirrorDelNotify(WIN_LOCAL, DelNotify, Pos); if((DelNotify == YES) || (DelNotify == YES_ALL)) { Down = YES; - DoLocalDELE(TransPacketBase->LocalFile); +// DoLocalDELE(TransPacketBase->LocalFile); + DoLocalDELE(Pos->LocalFile); } + ReleaseMutex(hListAccMutex); } - /* ƒJƒŒƒ“ƒgƒfƒBƒŒƒNƒgƒŠ‚ðÝ’è */ - else if(strcmp(TransPacketBase->Cmd, "SETCUR") == 0) + /* カレントディレクトリを設定 */ +// else if(strcmp(TransPacketBase->Cmd, "SETCUR") == 0) + else if(strcmp(Pos->Cmd, "SETCUR") == 0) { - if(AskShareProh() == YES) +// if(AskShareProh() == YES) + if(AskReuseCmdSkt() == NO || AskShareProh() == YES) { - if(strcmp(CurDir, TransPacketBase->RemoteFile) != 0) +// if(strcmp(CurDir, TransPacketBase->RemoteFile) != 0) + if(strcmp(CurDir[Pos->ThreadCount], Pos->RemoteFile) != 0) { - if(CommandProcTrn(NULL, "CWD %s", TransPacketBase->RemoteFile)/100 != FTP_COMPLETE) +// if(CommandProcTrn(NULL, "CWD %s", TransPacketBase->RemoteFile)/100 != FTP_COMPLETE) + if(CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "CWD %s", Pos->RemoteFile)/100 != FTP_COMPLETE) { DispCWDerror(hWndTrans); ClearAll = YES; } } } - strcpy(CurDir, TransPacketBase->RemoteFile); +// strcpy(CurDir, TransPacketBase->RemoteFile); + strcpy(CurDir[Pos->ThreadCount], Pos->RemoteFile); + ReleaseMutex(hListAccMutex); } - /* ƒJƒŒƒ“ƒgƒfƒBƒŒƒNƒgƒŠ‚ð–ß‚· */ - else if(strcmp(TransPacketBase->Cmd, "BACKCUR") == 0) + /* カレントディレクトリを戻す */ +// else if(strcmp(TransPacketBase->Cmd, "BACKCUR") == 0) + else if(strcmp(Pos->Cmd, "BACKCUR") == 0) { - if(AskShareProh() == NO) +// if(AskShareProh() == NO) + if(AskReuseCmdSkt() == YES && AskShareProh() == NO) { - if(strcmp(CurDir, TransPacketBase->RemoteFile) != 0) - CommandProcTrn(NULL, "CWD %s", TransPacketBase->RemoteFile); - strcpy(CurDir, TransPacketBase->RemoteFile); +// if(strcmp(CurDir, TransPacketBase->RemoteFile) != 0) +// CommandProcTrn(NULL, "CWD %s", TransPacketBase->RemoteFile); +// strcpy(CurDir, TransPacketBase->RemoteFile); + if(strcmp(CurDir[Pos->ThreadCount], Pos->RemoteFile) != 0) + CommandProcTrn(TrnSkt, NULL, &Canceled[Pos->ThreadCount], "CWD %s", Pos->RemoteFile); + strcpy(CurDir[Pos->ThreadCount], Pos->RemoteFile); } + ReleaseMutex(hListAccMutex); } - /* Ž©“®I—¹‚Ì‚½‚ß‚Ì’Ê’m */ - else if(strcmp(TransPacketBase->Cmd, "GOQUIT") == 0) + /* 自動終了のための通知 */ +// else if(strcmp(TransPacketBase->Cmd, "GOQUIT") == 0) + else if(strcmp(Pos->Cmd, "GOQUIT") == 0) { + ReleaseMutex(hListAccMutex); GoExit = YES; } + else + ReleaseMutex(hListAccMutex); - /*===== ‚P‚‚̏ˆ—I‚í‚è =====*/ + /*===== 1つの処理終わり =====*/ if(ForceAbort == NO) { - WaitForSingleObject(hListAccMutex, INFINITE); +// WaitForSingleObject(hListAccMutex, INFINITE); + while(WaitForSingleObject(hListAccMutex, 0) == WAIT_TIMEOUT) + { + BackgrndMessageProc(); + Sleep(1); + } if(ClearAll == YES) +// EraseTransFileList(); + { + for(i = 0; i < MAX_DATA_CONNECTION; i++) + Canceled[i] = YES; EraseTransFileList(); + Pos = NULL; + } else { - if((strncmp(TransPacketBase->Cmd, "RETR", 4) == 0) || - (strncmp(TransPacketBase->Cmd, "STOR", 4) == 0)) +// if((strncmp(TransPacketBase->Cmd, "RETR", 4) == 0) || +// (strncmp(TransPacketBase->Cmd, "STOR", 4) == 0)) + if((strncmp(Pos->Cmd, "RETR", 4) == 0) || + (strncmp(Pos->Cmd, "STOR", 4) == 0)) { - TransFiles--; +// TransFiles--; + if(TransFiles > 0) + TransFiles--; PostMessage(GetMainHwnd(), WM_CHANGE_COND, 0, 0); } - Pos = TransPacketBase; - TransPacketBase = TransPacketBase->Next; - free(Pos); +// Pos = TransPacketBase; +// TransPacketBase = TransPacketBase->Next; +// free(Pos); } ClearAll = NO; ReleaseMutex(hListAccMutex); @@ -828,8 +1162,14 @@ static ULONG WINAPI TransferThread(void *Dummy) ReleaseMutex(hListAccMutex); } } + if(hWndTrans != NULL) + SendMessage(hWndTrans, WM_SET_PACKET, 0, 0); + if(Pos != NULL) + strcpy(Pos->Cmd, ""); + LastUsed = timeGetTime(); } - else +// else + else if(TransPacketBase == NULL) { DelNotify = NO; @@ -841,57 +1181,97 @@ static ULONG WINAPI TransferThread(void *Dummy) DestroyWindow(hWndTrans); hWndTrans = NULL; - if(GoExit == YES) - { - SoundPlay(SND_TRANS); - - if(AskAutoExit() == NO) - { - if(Down == YES) - PostMessage(GetMainHwnd(), WM_REFRESH_LOCAL_FLG, 0, 0); - if(Up == YES) - PostMessage(GetMainHwnd(), WM_REFRESH_REMOTE_FLG, 0, 0); - } - Down = NO; - Up = NO; - } +// if(GoExit == YES) +// { +// SoundPlay(SND_TRANS); +// +// if(AskAutoExit() == NO) +// { +// if(Down == YES) +// PostMessage(GetMainHwnd(), WM_REFRESH_LOCAL_FLG, 0, 0); +// if(Up == YES) +// PostMessage(GetMainHwnd(), WM_REFRESH_REMOTE_FLG, 0, 0); +// } +// Down = NO; +// Up = NO; +// } } } BackgrndMessageProc(); +// Sleep(1); + Sleep(100); if(GoExit == YES) { + SoundPlay(SND_TRANS); + if(AskAutoExit() == NO) + { + if(Down == YES) + PostMessage(GetMainHwnd(), WM_REFRESH_LOCAL_FLG, 0, 0); + if(Up == YES) + PostMessage(GetMainHwnd(), WM_REFRESH_REMOTE_FLG, 0, 0); + } + Down = NO; + Up = NO; PostMessage(GetMainHwnd(), WM_COMMAND, MAKEWPARAM(MENU_AUTO_EXIT, 0), 0); GoExit = NO; } + + // 再転送対応 + TransferErrorMode = AskTransferErrorMode(); + TransferErrorNotify = AskTransferErrorNotify(); + } + else + { + ReleaseMutex(hListAccMutex); + if(hWndTrans != NULL) + { + DestroyWindow(hWndTrans); + hWndTrans = NULL; + } + BackgrndMessageProc(); + if(ThreadCount < AskMaxThreadCount()) + Sleep(1); + else + Sleep(100); + } + } + if(AskReuseCmdSkt() == NO || ThreadCount > 0) + { + if(TrnSkt != INVALID_SOCKET) + { + SendData(TrnSkt, "QUIT\r\n", 6, 0, &Canceled[ThreadCount]); + DoClose(TrnSkt); } } return 0; } -/*----- ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢ƒtƒ@ƒCƒ‹ƒAƒNƒZƒX‚̏€”õ ------------------------------ +/*----- フルパスを使わないファイルアクセスの準備 ------------------------------ * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒpƒPƒbƒg -* char *Cur : ƒJƒŒƒ“ƒgƒfƒBƒŒƒNƒgƒŠ -* char *Tmp : ì‹Æ—pƒGƒŠƒA +* TRANSPACKET *Pkt : 転送パケット +* char *Cur : カレントディレクトリ +* char *Tmp : 作業用エリア * * Return Value -* int ƒXƒe[ƒ^ƒX(SUCCESS/FAIL) +* int ステータス(FFFTP_SUCCESS/FFFTP_FAIL) * * Note -* ƒtƒ‹ƒpƒX‚ðŽg‚í‚È‚¢Žž‚́A -* ‚±‚̃‚ƒWƒ…[ƒ‹“à‚Å CWD ‚ðs‚È‚¢A -* Pkt->RemoteFile ‚Ƀtƒ@ƒCƒ‹–¼‚Ì‚ÝŽc‚·BiƒpƒX–¼‚͏Á‚·j +* フルパスを使わない時は、 +* このモジュール内で CWD を行ない、 +* Pkt->RemoteFile にファイル名のみ残す。(パス名は消す) *----------------------------------------------------------------------------*/ +// 同時接続対応 static int MakeNonFullPath(TRANSPACKET *Pkt, char *Cur, char *Tmp) { int Sts; - Sts = ProcForNonFullpath(Pkt->RemoteFile, Cur, Pkt->hWndTrans, 1); - if(Sts == FAIL) +// Sts = ProcForNonFullpath(Pkt->RemoteFile, Cur, Pkt->hWndTrans, 1); + Sts = ProcForNonFullpath(Pkt->ctrl_skt, Pkt->RemoteFile, Cur, Pkt->hWndTrans, &Canceled[Pkt->ThreadCount]); + if(Sts == FFFTP_FAIL) ClearAll = YES; return(Sts); @@ -900,19 +1280,19 @@ static int MakeNonFullPath(TRANSPACKET *Pkt, char *Cur, char *Tmp) -/*----- ƒ_ƒEƒ“ƒ[ƒh‚ðs‚È‚¤ -------------------------------------------------- +/*----- ダウンロードを行なう -------------------------------------------------- * * Parameter -* SOCKET cSkt : ƒRƒ“ƒgƒ[ƒ‹ƒ\ƒPƒbƒg -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* int DirList : ƒfƒBƒŒƒNƒgƒŠƒŠƒXƒg‚̃_ƒEƒ“ƒ[ƒh(YES/NO) +* SOCKET cSkt : コントロールソケット +* TRANSPACKET *Pkt : 転送ファイル情報 +* int DirList : ディレクトリリストのダウンロード(YES/NO) * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード * * Note -* ‚±‚̃‚ƒWƒ…[ƒ‹‚́Aƒtƒ@ƒCƒ‹ˆê——‚̎擾‚È‚Ç‚ðs‚È‚¤Û‚ɃƒCƒ“‚̃XƒŒƒbƒh -* ‚©‚ç‚àŒÄ‚΂ê‚éBƒƒCƒ“‚̃XƒŒƒbƒh‚©‚çŒÄ‚΂ê‚鎞‚Í Pkt->hWndTrans == NULLB +* このモジュールは、ファイル一覧の取得などを行なう際にメインのスレッド +* からも呼ばれる。メインのスレッドから呼ばれる時は Pkt->hWndTrans == NULL。 *----------------------------------------------------------------------------*/ int DoDownLoad(SOCKET cSkt, TRANSPACKET *Pkt, int DirList, int *CancelCheckWork) @@ -937,7 +1317,9 @@ int DoDownLoad(SOCKET cSkt, TRANSPACKET *Pkt, int DirList, int *CancelCheckWork) { if(Pkt->hWndTrans != NULL) { - AllTransSizeNow = 0; + // 同時接続対応 +// AllTransSizeNow = 0; + AllTransSizeNow[Pkt->ThreadCount] = 0; if(DirList == NO) DispTransFileInfo(Pkt, MSGJPN086, TRUE, YES); @@ -945,7 +1327,13 @@ int DoDownLoad(SOCKET cSkt, TRANSPACKET *Pkt, int DirList, int *CancelCheckWork) DispTransFileInfo(Pkt, MSGJPN087, FALSE, NO); } - if(BackgrndMessageProc() == NO) + // SFTP対応 +// if(BackgrndMessageProc() == NO) + if(IsSFTPAttached(Pkt->ctrl_skt)) + { + // TODO: + } + else if(BackgrndMessageProc() == NO) { if(AskPasvMode() != YES) iRetCode = DownLoadNonPassive(Pkt, CancelCheckWork); @@ -968,13 +1356,13 @@ int DoDownLoad(SOCKET cSkt, TRANSPACKET *Pkt, int DirList, int *CancelCheckWork) } -/*----- ’ʏ탂[ƒh‚Ńtƒ@ƒCƒ‹‚ðƒ_ƒEƒ“ƒ[ƒh ------------------------------------ +/*----- 通常モードでファイルをダウンロード ------------------------------------ * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ +* TRANSPACKET *Pkt : 転送ファイル情報 * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード *----------------------------------------------------------------------------*/ static int DownLoadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork) @@ -985,7 +1373,10 @@ static int DownLoadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork) SOCKET listen_socket = INVALID_SOCKET; // data listen socket char Buf[1024]; int CreateMode; - struct sockaddr_in saSockAddr1; + // IPv6対応 +// struct sockaddr_in saSockAddr1; + struct sockaddr_in saSockAddrIPv4; + struct sockaddr_in6 saSockAddrIPv6; char Reply[ERR_MSG_LEN+7]; if((listen_socket = GetFTPListenSocket(Pkt->ctrl_skt, CancelCheckWork)) != INVALID_SOCKET) @@ -996,10 +1387,24 @@ static int DownLoadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork) iRetCode = command(Pkt->ctrl_skt, Reply, CancelCheckWork, "%s", Buf); if(iRetCode/100 == FTP_PRELIM) { - if(SocksGet2ndBindReply(listen_socket, &data_socket) == FAIL) + // 同時接続対応 +// if(SocksGet2ndBindReply(listen_socket, &data_socket) == FFFTP_FAIL) + if(SocksGet2ndBindReply(listen_socket, &data_socket, CancelCheckWork) == FFFTP_FAIL) { - iLength = sizeof(saSockAddr1); - data_socket = do_accept(listen_socket, (struct sockaddr *)&saSockAddr1, (int *)&iLength); + // IPv6対応 +// iLength = sizeof(saSockAddr1); +// data_socket = do_accept(listen_socket, (struct sockaddr *)&saSockAddr1, (int *)&iLength); + switch(AskCurNetType()) + { + case NTYPE_IPV4: + iLength=sizeof(saSockAddrIPv4); + data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv4, (int *)&iLength); + break; + case NTYPE_IPV6: + iLength=sizeof(saSockAddrIPv6); + data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv6, (int *)&iLength); + break; + } if(shutdown(listen_socket, 1) != 0) ReportWSError("shutdown listen", WSAGetLastError()); @@ -1012,12 +1417,36 @@ static int DownLoadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork) iRetCode = 500; } else - DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port)); + // IPv6対応 +// DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port)); + { + switch(AskCurNetType()) + { + case NTYPE_IPV4: + DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddrIPv4.sin_addr), ntohs(saSockAddrIPv4.sin_port)); + break; + case NTYPE_IPV6: + DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet6_ntoa(saSockAddrIPv6.sin6_addr), ntohs(saSockAddrIPv6.sin6_port)); + break; + } + } } if(data_socket != INVALID_SOCKET) { - iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため + ReleaseMutex(hListAccMutex); + // FTPS対応 +// iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); + if(IsSSLAttached(Pkt->ctrl_skt)) + { + if(AttachSSL(data_socket, Pkt->ctrl_skt, CancelCheckWork)) + iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); + else + iRetCode = 500; + } + else + iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); // data_socket = DoClose(data_socket); } } @@ -1043,13 +1472,13 @@ static int DownLoadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork) } -/*----- Passiveƒ‚[ƒh‚Ńtƒ@ƒCƒ‹‚ðƒ_ƒEƒ“ƒ[ƒh --------------------------------- +/*----- Passiveモードでファイルをダウンロード --------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ +* TRANSPACKET *Pkt : 転送ファイル情報 * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード *----------------------------------------------------------------------------*/ static int DownLoadPassive(TRANSPACKET *Pkt, int *CancelCheckWork) @@ -1058,18 +1487,34 @@ static int DownLoadPassive(TRANSPACKET *Pkt, int *CancelCheckWork) SOCKET data_socket = INVALID_SOCKET; // data channel socket char Buf[1024]; int CreateMode; - char Adrs[20]; + // IPv6対応 +// char Adrs[20]; + char Adrs[40]; int Port; int Flg; char Reply[ERR_MSG_LEN+7]; - iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "PASV"); + // IPv6対応 +// iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "PASV"); + switch(AskCurNetType()) + { + case NTYPE_IPV4: + iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "PASV"); + break; + case NTYPE_IPV6: + iRetCode = command(Pkt->ctrl_skt, Buf, CancelCheckWork, "EPSV"); + break; + } if(iRetCode/100 == FTP_COMPLETE) { - if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == SUCCESS) + // IPv6対応 +// if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == FFFTP_SUCCESS) + if(GetAdrsAndPort(Pkt->ctrl_skt, Buf, Adrs, &Port, 39) == FFFTP_SUCCESS) { if((data_socket = connectsock(Adrs, Port, MSGJPN091, CancelCheckWork)) != INVALID_SOCKET) { + // 変数が未初期化のバグ修正 + Flg = 1; if(setsockopt(data_socket, IPPROTO_TCP, TCP_NODELAY, (LPSTR)&Flg, sizeof(Flg)) == SOCKET_ERROR) ReportWSError("setsockopt", WSAGetLastError()); @@ -1079,7 +1524,19 @@ static int DownLoadPassive(TRANSPACKET *Pkt, int *CancelCheckWork) iRetCode = command(Pkt->ctrl_skt, Reply, CancelCheckWork, "%s", Buf); if(iRetCode/100 == FTP_PRELIM) { - iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため + ReleaseMutex(hListAccMutex); + // FTPS対応 +// iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); + if(IsSSLAttached(Pkt->ctrl_skt)) + { + if(AttachSSL(data_socket, Pkt->ctrl_skt, CancelCheckWork)) + iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); + else + iRetCode = 500; + } + else + iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); // data_socket = DoClose(data_socket); } else @@ -1112,20 +1569,20 @@ static int DownLoadPassive(TRANSPACKET *Pkt, int *CancelCheckWork) } -/*----- ƒ_ƒEƒ“ƒ[ƒh‚ÌŽÀs ---------------------------------------------------- +/*----- ダウンロードの実行 ---------------------------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* SOCKET dSkt : ƒf[ƒ^ƒ\ƒPƒbƒg -* int CreateMode : ƒtƒ@ƒCƒ‹ì¬ƒ‚[ƒh (CREATE_ALWAYS/OPEN_ALWAYS) +* TRANSPACKET *Pkt : 転送ファイル情報 +* SOCKET dSkt : データソケット +* int CreateMode : ファイル作成モード (CREATE_ALWAYS/OPEN_ALWAYS) * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード * * Note -* “]‘—‚ÌŒo‰ß•\Ž¦‚Í -* ƒ_ƒCƒAƒƒO‚ðo‚·(Pkt->hWndTrans!=NULL)ê‡AƒCƒ“ƒ^[ƒoƒ‹ƒ^ƒCƒ}‚ÅŒo‰ß‚ð•\Ž¦‚·‚é -* ƒ_ƒCƒAƒƒO‚ðo‚³‚È‚¢ê‡A‚±‚̃‹[ƒ`ƒ“‚©‚çDispDownloadSize()‚ðŒÄ‚Ô +* 転送の経過表示は +* ダイアログを出す(Pkt->hWndTrans!=NULL)場合、インターバルタイマで経過を表示する +* ダイアログを出さない場合、このルーチンからDispDownloadSize()を呼ぶ *----------------------------------------------------------------------------*/ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *CancelCheckWork) @@ -1155,8 +1612,8 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc /* End */ #endif -#ifdef DISABLE_NETWORK_BUFFERS - // ”O‚Ì‚½‚ߎóMƒoƒbƒtƒ@‚𖳌ø‚É‚·‚éB + // 念のため受信バッファを無効にする +#ifdef DISABLE_TRANSFER_NETWORK_BUFFERS int buf_size = 0; setsockopt(dSkt, SOL_SOCKET, SO_RCVBUF, (char *)&buf_size, sizeof(buf_size)); #endif @@ -1169,30 +1626,41 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc dwFileAttributes = GetFileAttributes(Pkt->LocalFile); if (dwFileAttributes != INVALID_FILE_ATTRIBUTES && (dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { - // “Ç‚ÝŽæ‚èê—p + // 読み取り専用 if (MessageBox(GetMainHwnd(), MSGJPN296, MSGJPN086, MB_YESNO) == IDYES) { - // ‘®«‚ð‰ðœ + // 属性を解除 SetFileAttributes(Pkt->LocalFile, dwFileAttributes ^ FILE_ATTRIBUTE_READONLY); } } if((iFileHandle = CreateFile(Pkt->LocalFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &Sec, CreateMode, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { - // UTF-8‘Ήž + // UTF-8対応 + char Buf3[(BUFSIZE + 3) * 4]; + CODECONVINFO cInfo2; int ProcessedBOM = NO; + // 4GB超対応(kaokunさん提供) + DWORD High = 0; if(CreateMode == OPEN_ALWAYS) - SetFilePointer(iFileHandle, 0, 0, FILE_END); + // 4GB超対応(kaokunさん提供) +// SetFilePointer(iFileHandle, 0, 0, FILE_END); + SetFilePointer(iFileHandle, 0, &High, FILE_END); if(Pkt->hWndTrans != NULL) { - TimeStart = time(NULL); + // 同時接続対応 +// TimeStart = time(NULL); + TimeStart[Pkt->ThreadCount] = time(NULL); SetTimer(Pkt->hWndTrans, TIMER_DISPLAY, DISPLAY_TIMING, NULL); } InitCodeConvInfo(&cInfo); cInfo.KanaCnv = Pkt->KanaCnv; - /*===== ƒtƒ@ƒCƒ‹‚ðŽóM‚·‚郋[ƒv =====*/ + InitCodeConvInfo(&cInfo2); + cInfo2.KanaCnv = Pkt->KanaCnv; + + /*===== ファイルを受信するループ =====*/ while((Pkt->Abort == ABORT_NONE) && (ForceAbort == NO)) { // FD_ZERO(&ReadFds); @@ -1239,7 +1707,7 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc break; } - /* Š¿ŽšƒR[ƒh•ÏŠ· */ + /* 漢字コード変換 */ if(Pkt->KanjiCode != KANJI_NOCNV) { cInfo.Str = Buf; @@ -1248,29 +1716,45 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc cInfo.BufSize = BUFSIZE+3; do { - // ‚±‚±‚Å‘S‚ÄUTF-8‚Ö•ÏŠ·‚·‚é - // TODO: SJISˆÈŠO‚à’¼ÚUTF-8‚Ö•ÏŠ· + // ここで全てUTF-8へ変換する + // TODO: SJIS以外も直接UTF-8へ変換 // if(Pkt->KanjiCode == KANJI_JIS) // Continue = ConvJIStoSJIS(&cInfo); // else // Continue = ConvEUCtoSJIS(&cInfo); - char Buf3[(BUFSIZE + 3) * 4]; - CODECONVINFO cInfo2; switch(Pkt->KanjiCode) { case KANJI_SJIS: switch(Pkt->KanjiCodeDesired) { case KANJI_SJIS: - memcpy(Buf3, cInfo.Str, cInfo.StrLen); - cInfo2.OutLen = cInfo.StrLen; - Continue = NO; +// memcpy(Buf3, cInfo.Str, cInfo.StrLen); +// cInfo2.OutLen = cInfo.StrLen; +// Continue = NO; + // カナ変換のため + Continue = ConvSJIStoJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvJIStoSJIS(&cInfo2); break; case KANJI_JIS: + Continue = ConvSJIStoJIS(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; break; case KANJI_EUC: + Continue = ConvSJIStoEUC(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; break; case KANJI_UTF8N: + Continue = ConvSJIStoUTF8N(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { memcpy(Buf3, "\xEF\xBB\xBF", 3); @@ -1280,7 +1764,7 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc break; } Continue = ConvSJIStoUTF8N(&cInfo); - memcpy(Buf3, Buf2, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; } @@ -1290,17 +1774,38 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc { case KANJI_SJIS: Continue = ConvJIStoSJIS(&cInfo); - memcpy(Buf3, Buf2, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; case KANJI_JIS: - memcpy(Buf3, cInfo.Str, cInfo.StrLen); - cInfo2.OutLen = cInfo.StrLen; - Continue = NO; +// memcpy(Buf3, cInfo.Str, cInfo.StrLen); +// cInfo2.OutLen = cInfo.StrLen; +// Continue = NO; + // カナ変換のため + Continue = ConvJIStoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); break; case KANJI_EUC: + Continue = ConvJIStoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); break; case KANJI_UTF8N: + Continue = ConvJIStoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { memcpy(Buf3, "\xEF\xBB\xBF", 3); @@ -1310,8 +1815,6 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc break; } Continue = ConvJIStoSJIS(&cInfo); - InitCodeConvInfo(&cInfo2); - cInfo2.KanaCnv = NO; cInfo2.Str = cInfo.Buf; cInfo2.StrLen = cInfo.OutLen; cInfo2.Buf = Buf3; @@ -1325,17 +1828,38 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc { case KANJI_SJIS: Continue = ConvEUCtoSJIS(&cInfo); - memcpy(Buf3, Buf2, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; case KANJI_JIS: + Continue = ConvEUCtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); break; case KANJI_EUC: - memcpy(Buf3, cInfo.Str, cInfo.StrLen); - cInfo2.OutLen = cInfo.StrLen; - Continue = NO; +// memcpy(Buf3, cInfo.Str, cInfo.StrLen); +// cInfo2.OutLen = cInfo.StrLen; +// Continue = NO; + // カナ変換のため + Continue = ConvEUCtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); break; case KANJI_UTF8N: + Continue = ConvEUCtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { memcpy(Buf3, "\xEF\xBB\xBF", 3); @@ -1345,8 +1869,6 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc break; } Continue = ConvEUCtoSJIS(&cInfo); - InitCodeConvInfo(&cInfo2); - cInfo2.KanaCnv = NO; cInfo2.Str = cInfo.Buf; cInfo2.StrLen = cInfo.OutLen; cInfo2.Buf = Buf3; @@ -1356,6 +1878,50 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc } break; case KANJI_UTF8N: + switch(Pkt->KanjiCodeDesired) + { + case KANJI_SJIS: + Continue = ConvUTF8NtoSJIS(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Str, cInfo.StrLen); + cInfo2.OutLen = cInfo.StrLen; + Continue = NO; + break; + case KANJI_UTF8BOM: + if(ProcessedBOM == NO) + { + memcpy(Buf3, "\xEF\xBB\xBF", 3); + cInfo2.OutLen = 3; + Continue = YES; + ProcessedBOM = YES; + break; + } + memcpy(Buf3, cInfo.Str, cInfo.StrLen); + cInfo2.OutLen = cInfo.StrLen; + Continue = NO; + break; + } + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { if(memcmp(Buf, "\xEF\xBB\xBF", 3) == 0) @@ -1366,7 +1932,7 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc cInfo2.OutLen = 0; switch(Pkt->KanjiCodeDesired) { - case KANJI_UTF8N: + case KANJI_UTF8BOM: memcpy(Buf3, "\xEF\xBB\xBF", 3); cInfo2.OutLen = 3; break; @@ -1379,18 +1945,35 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc { case KANJI_SJIS: Continue = ConvUTF8NtoSJIS(&cInfo); - memcpy(Buf3, Buf2, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; case KANJI_JIS: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); break; case KANJI_EUC: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); break; case KANJI_UTF8N: memcpy(Buf3, cInfo.Str, cInfo.StrLen); cInfo2.OutLen = cInfo.StrLen; Continue = NO; break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Str, cInfo.StrLen); + cInfo2.OutLen = cInfo.StrLen; + Continue = NO; + break; } break; } @@ -1408,10 +1991,12 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc Pkt->ExistSize += iNumBytes; if(Pkt->hWndTrans != NULL) - AllTransSizeNow += iNumBytes; + // 同時接続対応 +// AllTransSizeNow += iNumBytes; + AllTransSizeNow[Pkt->ThreadCount] += iNumBytes; else { - /* “]‘—ƒ_ƒCƒAƒƒO‚ðo‚³‚È‚¢Žž‚ÌŒo‰ß•\Ž¦ */ + /* 転送ダイアログを出さない時の経過表示 */ DispDownloadSize(Pkt->ExistSize); } @@ -1419,30 +2004,208 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc ForceAbort = YES; } - /* ‘‚«Žc‚µ‚½ƒf[ƒ^‚ð‘‚«ž‚Þ */ + /* 書き残したデータを書き込む */ if(Pkt->KanjiCode != KANJI_NOCNV) { cInfo.Buf = Buf2; cInfo.BufSize = BUFSIZE+3; FlushRestData(&cInfo); - if(WriteFile(iFileHandle, Buf2, cInfo.OutLen, &Writed, NULL) == FALSE) - Pkt->Abort = ABORT_DISKFULL; - } - - /* ƒOƒ‰ƒt•\Ž¦‚ðXV */ - if(Pkt->hWndTrans != NULL) - { - KillTimer(Pkt->hWndTrans, TIMER_DISPLAY); - DispTransferStatus(Pkt->hWndTrans, YES, Pkt); - TimeStart = time(NULL) - TimeStart + 1; - } - else - { - /* “]‘—ƒ_ƒCƒAƒƒO‚ðo‚³‚È‚¢Žž‚ÌŒo‰ß•\Ž¦‚ðÁ‚· */ - DispDownloadSize(-1); + switch(Pkt->KanjiCode) + { + case KANJI_SJIS: + switch(Pkt->KanjiCodeDesired) + { + case KANJI_SJIS: + // カナ変換のため + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvJIStoSJIS(&cInfo2); + break; + case KANJI_JIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_EUC: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + } + break; + case KANJI_JIS: + switch(Pkt->KanjiCodeDesired) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + // カナ変換のため + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + } + break; + case KANJI_EUC: + switch(Pkt->KanjiCodeDesired) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + // カナ変換のため + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + } + break; + case KANJI_UTF8N: + switch(Pkt->KanjiCodeDesired) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + } + break; + case KANJI_UTF8BOM: + switch(Pkt->KanjiCodeDesired) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + } + break; + } +// if(WriteFile(iFileHandle, Buf2, cInfo.OutLen, &Writed, NULL) == FALSE) + if(WriteFile(iFileHandle, Buf3, cInfo2.OutLen, &Writed, NULL) == FALSE) + Pkt->Abort = ABORT_DISKFULL; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + FlushRestData(&cInfo2); + if(WriteFile(iFileHandle, Buf3, cInfo2.OutLen, &Writed, NULL) == FALSE) + Pkt->Abort = ABORT_DISKFULL; } - /* ƒtƒ@ƒCƒ‹‚̃^ƒCƒ€ƒXƒ^ƒ“ƒv‚ð‡‚í‚¹‚é */ + /* グラフ表示を更新 */ + if(Pkt->hWndTrans != NULL) + { + KillTimer(Pkt->hWndTrans, TIMER_DISPLAY); + DispTransferStatus(Pkt->hWndTrans, YES, Pkt); + // 同時接続対応 +// TimeStart = time(NULL) - TimeStart + 1; + TimeStart[Pkt->ThreadCount] = time(NULL) - TimeStart[Pkt->ThreadCount] + 1; + } + else + { + /* 転送ダイアログを出さない時の経過表示を消す */ + DispDownloadSize(-1); + } + + /* ファイルのタイムスタンプを合わせる */ if((SaveTimeStamp == YES) && ((Pkt->Time.dwLowDateTime != 0) || (Pkt->Time.dwHighDateTime != 0))) { @@ -1469,10 +2232,10 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc if(ForceAbort == NO) { - /* Abort‚ðƒzƒXƒg‚É“`‚¦‚é */ + /* Abortをホストに伝える */ if(Pkt->Abort != ABORT_NONE && iFileHandle != INVALID_HANDLE_VALUE) { - SendData(Pkt->ctrl_skt, "\xFF\xF4\xFF", 3, MSG_OOB, CancelCheckWork); /* MSG_OOB‚É’ˆÓ */ + SendData(Pkt->ctrl_skt, "\xFF\xF4\xFF", 3, MSG_OOB, CancelCheckWork); /* MSG_OOBに注意 */ SendData(Pkt->ctrl_skt, "\xF2", 1, 0, CancelCheckWork); command(Pkt->ctrl_skt, NULL, CancelCheckWork, "ABOR"); } @@ -1497,14 +2260,14 @@ static int DownLoadFile(TRANSPACKET *Pkt, SOCKET dSkt, int CreateMode, int *Canc } -/*----- ƒ_ƒEƒ“ƒ[ƒhI—¹^’†Ž~Žž‚̃ƒbƒZ[ƒW‚ð•\Ž¦ ---------------------------- +/*----- ダウンロード終了/中止時のメッセージを表示 ---------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* int iRetCode : ‰ž“šƒR[ƒh +* TRANSPACKET *Pkt : 転送ファイル情報 +* int iRetCode : 応答コード * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ static void DispDownloadFinishMsg(TRANSPACKET *Pkt, int iRetCode) @@ -1518,34 +2281,65 @@ static void DispDownloadFinishMsg(TRANSPACKET *Pkt, int iRetCode) strcpy(Fname, Pkt->RemoteFile); #if defined(HAVE_OPENVMS) - /* OpenVMS‚̏ꍇA‹óƒfƒBƒŒƒNƒgƒŠ‚ÖˆÚ“®‚·‚é‚Æ550 File not found‚É‚È‚Á‚Ä - * ƒGƒ‰[ƒ_ƒCƒAƒƒO‚âƒGƒ‰[ƒƒbƒZ[ƒW‚ªo‚é‚̂ʼn½‚à‚µ‚È‚¢ */ + /* OpenVMSの場合、空ディレクトリへ移動すると550 File not foundになって + * エラーダイアログやエラーメッセージが出るので何もしない */ if (AskHostType() == HTYPE_VMS) return; #endif +#if defined(HAVE_TANDEM) + /* HP Nonstop Server の場合、ファイルのない subvol へ移動すると550 File not found + * になるが問題ないのでエラーダイアログやエラーメッセージを出さないため */ + if (AskHostType() == HTYPE_TANDEM) + return; +#endif if((strncmp(Pkt->Cmd, "NLST", 4) == 0) || (strncmp(Pkt->Cmd, "LIST", 4) == 0)) { SetTaskMsg(MSGJPN097); strcpy(Fname, MSGJPN098); } - else if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) - SetTaskMsg(MSGJPN099, TimeStart, Pkt->ExistSize/TimeStart); + // 同時接続対応 +// else if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) +// SetTaskMsg(MSGJPN099, TimeStart, Pkt->ExistSize/TimeStart); + else if((Pkt->hWndTrans != NULL) && (TimeStart[Pkt->ThreadCount] != 0)) + SetTaskMsg(MSGJPN099, TimeStart[Pkt->ThreadCount], Pkt->ExistSize/TimeStart[Pkt->ThreadCount]); else SetTaskMsg(MSGJPN100); if(Pkt->Abort != ABORT_USER) { - if(DispUpDownErrDialog(downerr_dlg, Pkt->hWndTrans, Fname) == NO) - ClearAll = YES; + // 全て中止を選択後にダイアログが表示されるバグ対策 +// if(DispUpDownErrDialog(downerr_dlg, Pkt->hWndTrans, Fname) == NO) + // 再転送対応 +// if(Canceled[Pkt->ThreadCount] == NO && ClearAll == NO && DispUpDownErrDialog(downerr_dlg, Pkt->hWndTrans, Fname) == NO) +// ClearAll = YES; + if(Canceled[Pkt->ThreadCount] == NO && ClearAll == NO) + { + if(strncmp(Pkt->Cmd, "RETR", 4) == 0 || strncmp(Pkt->Cmd, "STOR", 4) == 0) + { + if(TransferErrorNotify == YES && DispUpDownErrDialog(downerr_dlg, Pkt->hWndTrans, Pkt) == NO) + ClearAll = YES; + else + { + Pkt->Mode = TransferErrorMode; + AddTransFileList(Pkt); + } + } + } } } else { if((strncmp(Pkt->Cmd, "NLST", 4) == 0) || (strncmp(Pkt->Cmd, "LIST", 4) == 0)) SetTaskMsg(MSGJPN101, Pkt->ExistSize); - else if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) - SetTaskMsg(MSGJPN102, TimeStart, Pkt->ExistSize/TimeStart); + // 同時接続対応 +// else if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) +// SetTaskMsg(MSGJPN102, TimeStart, Pkt->ExistSize/TimeStart); + else if((Pkt->hWndTrans != NULL) && (TimeStart[Pkt->ThreadCount] != 0)) + // "0 B/S"と表示されるバグを修正 + // 原因は%dにあたる部分に64ビット値が渡されているため +// SetTaskMsg(MSGJPN102, TimeStart[Pkt->ThreadCount], Pkt->ExistSize/TimeStart[Pkt->ThreadCount]); + SetTaskMsg(MSGJPN102, (LONG)TimeStart[Pkt->ThreadCount], (LONG)(Pkt->ExistSize/TimeStart[Pkt->ThreadCount])); else SetTaskMsg(MSGJPN103, Pkt->ExistSize); } @@ -1554,78 +2348,110 @@ static void DispDownloadFinishMsg(TRANSPACKET *Pkt, int iRetCode) } -/*----- ƒ_ƒEƒ“ƒ[ƒh^ƒAƒbƒvƒ[ƒhƒGƒ‰[‚̃_ƒCƒAƒƒO‚ð•\Ž¦ -------------------- +/*----- ダウンロード/アップロードエラーのダイアログを表示 -------------------- * * Parameter -* int RedID : ƒ_ƒCƒAƒƒOƒ{ƒbƒNƒX‚̃Šƒ\[ƒXID -* HWND hWnd : ‘‚«ž‚Ý’†ƒ_ƒCƒAƒƒO‚̃EƒCƒ“ƒhƒE -* char *Fname : ƒtƒ@ƒCƒ‹–¼ +* int RedID : ダイアログボックスのリソースID +* HWND hWnd : 書き込み中ダイアログのウインドウ +* char *Fname : ファイル名 * * Return Value -* int ƒXƒe[ƒ^ƒX (YES=’†Ž~/NO=‘S‚Ä’†Ž~) +* int ステータス (YES=中止/NO=全て中止) *----------------------------------------------------------------------------*/ -static int DispUpDownErrDialog(int ResID, HWND hWnd, char *Fname) +// 再転送対応 +//static int DispUpDownErrDialog(int ResID, HWND hWnd, char *Fname) +static int DispUpDownErrDialog(int ResID, HWND hWnd, TRANSPACKET *Pkt) { if(hWnd == NULL) hWnd = GetMainHwnd(); SoundPlay(SND_ERROR); - return(DialogBoxParam(GetFtpInst(), MAKEINTRESOURCE(ResID), hWnd, UpDownErrorDialogProc, (LPARAM)Fname)); + // 再転送対応 +// return(DialogBoxParam(GetFtpInst(), MAKEINTRESOURCE(ResID), hWnd, UpDownErrorDialogProc, (LPARAM)Fname)); + return(DialogBoxParam(GetFtpInst(), MAKEINTRESOURCE(ResID), hWnd, UpDownErrorDialogProc, (LPARAM)Pkt)); } -/*----- ƒ_ƒEƒ“ƒ[ƒhƒGƒ‰[^ƒAƒbƒvƒ[ƒhƒGƒ‰[ƒ_ƒCƒAƒƒO‚̃R[ƒ‹ƒoƒbƒN -------- +/*----- ダウンロードエラー/アップロードエラーダイアログのコールバック -------- * * Parameter -* HWND hDlg : ƒEƒCƒ“ƒhƒEƒnƒ“ƒhƒ‹ -* UINT message : ƒƒbƒZ[ƒW”ԍ† -* WPARAM wParam : ƒƒbƒZ[ƒW‚Ì WPARAM ˆø” -* LPARAM lParam : ƒƒbƒZ[ƒW‚Ì LPARAM ˆø” +* HWND hDlg : ウインドウハンドル +* UINT message : メッセージ番号 +* WPARAM wParam : メッセージの WPARAM 引数 +* LPARAM lParam : メッセージの LPARAM 引数 * * Return Value * BOOL TRUE/FALSE *----------------------------------------------------------------------------*/ -static BOOL CALLBACK UpDownErrorDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +// 64ビット対応 +//static BOOL CALLBACK UpDownErrorDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +static INT_PTR CALLBACK UpDownErrorDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { + static TRANSPACKET *Pkt; + static const RADIOBUTTON DownExistButton[] = { + { DOWN_EXIST_OVW, EXIST_OVW }, + { DOWN_EXIST_RESUME, EXIST_RESUME }, + { DOWN_EXIST_IGNORE, EXIST_IGNORE } + }; + #define DOWNEXISTBUTTONS (sizeof(DownExistButton)/sizeof(RADIOBUTTON)) + switch (message) { case WM_INITDIALOG : - SendDlgItemMessage(hDlg, UPDOWN_ERR_FNAME, WM_SETTEXT, 0, (LPARAM)lParam); - SendDlgItemMessage(hDlg, UPDOWN_ERR_MSG, WM_SETTEXT, 0, (LPARAM)ErrMsg); + Pkt = (TRANSPACKET *)lParam; +// SendDlgItemMessage(hDlg, UPDOWN_ERR_FNAME, WM_SETTEXT, 0, (LPARAM)lParam); + SendDlgItemMessage(hDlg, UPDOWN_ERR_FNAME, WM_SETTEXT, 0, (LPARAM)Pkt->RemoteFile); + // 同時接続対応 +// SendDlgItemMessage(hDlg, UPDOWN_ERR_MSG, WM_SETTEXT, 0, (LPARAM)ErrMsg); + SendDlgItemMessage(hDlg, UPDOWN_ERR_MSG, WM_SETTEXT, 0, (LPARAM)GetErrMsg()); + + if((Pkt->Type == TYPE_A) || (Pkt->ExistSize <= 0)) + EnableWindow(GetDlgItem(hDlg, DOWN_EXIST_RESUME), FALSE); + + SetRadioButtonByValue(hDlg, TransferErrorMode, DownExistButton, DOWNEXISTBUTTONS); return(TRUE); case WM_COMMAND : switch(GET_WM_COMMAND_ID(wParam, lParam)) { + case IDOK_ALL : + TransferErrorNotify = NO; + /* ここに break はない */ + case IDOK : + TransferErrorMode = AskRadioButtonValue(hDlg, DownExistButton, DOWNEXISTBUTTONS); EndDialog(hDlg, YES); break; case IDCANCEL : EndDialog(hDlg, NO); break; + + case IDHELP : +// hHelpWin = HtmlHelp(NULL, AskHelpFilePath(), HH_HELP_CONTEXT, IDH_HELP_TOPIC_0000009); + break; } - return(TRUE); + return(TRUE); } - return(FALSE); + return(FALSE); } -/*----- ƒ_ƒEƒ“ƒ[ƒh‚̃ŠƒWƒ…[ƒ€‚̏€”õ‚ðs‚¤ ---------------------------------- +/*----- ダウンロードのリジュームの準備を行う ---------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* iont ProcMode : ˆ—ƒ‚[ƒh(EXIST_xxx) -* LONGLONG Size : ƒ[ƒhÏ‚݂̃tƒ@ƒCƒ‹‚̃TƒCƒY -* int *Mode : ƒtƒ@ƒCƒ‹ì¬ƒ‚[ƒh (CREATE_xxxx) +* TRANSPACKET *Pkt : 転送ファイル情報 +* iont ProcMode : 処理モード(EXIST_xxx) +* LONGLONG Size : ロード済みのファイルのサイズ +* int *Mode : ファイル作成モード (CREATE_xxxx) * * Return Value -* int “]‘—‚ðs‚¤‚©‚Ç‚¤‚©(YES/NO=‚±‚̃tƒ@ƒCƒ‹‚𒆎~/NO_ALL=‘S‚Ä’†Ž~) +* int 転送を行うかどうか(YES/NO=このファイルを中止/NO_ALL=全て中止) * * Note -* Pkt->ExistSize‚̃Zƒbƒg‚ðs‚È‚¤ +* Pkt->ExistSizeのセットを行なう *----------------------------------------------------------------------------*/ static int SetDownloadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int *Mode, int *CancelCheckWork) @@ -1645,7 +2471,7 @@ static int SetDownloadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int iRetCode = command(Pkt->ctrl_skt, Reply, CancelCheckWork, "REST %s", MakeNumString(Size, Tmp, FALSE)); if(iRetCode/100 < FTP_RETRY) { - /* ƒŠƒWƒ…[ƒ€ */ + /* リジューム */ if(Pkt->hWndTrans != NULL) Pkt->ExistSize = Size; *Mode = OPEN_ALWAYS; @@ -1655,7 +2481,7 @@ static int SetDownloadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int Com = DialogBox(GetFtpInst(), MAKEINTRESOURCE(noresume_dlg), Pkt->hWndTrans, NoResumeWndProc); if(Com != YES) { - if(Com == NO_ALL) /* ‘S‚Ä’†Ž~ */ + if(Com == NO_ALL) /* 全て中止 */ ClearAll = YES; Pkt->Abort = ABORT_USER; } @@ -1665,19 +2491,21 @@ static int SetDownloadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int } -/*----- resumeƒGƒ‰[ƒ_ƒCƒAƒƒO‚̃R[ƒ‹ƒoƒbƒN ---------------------------------- +/*----- resumeエラーダイアログのコールバック ---------------------------------- * * Parameter -* HWND hDlg : ƒEƒCƒ“ƒhƒEƒnƒ“ƒhƒ‹ -* UINT message : ƒƒbƒZ[ƒW”ԍ† -* WPARAM wParam : ƒƒbƒZ[ƒW‚Ì WPARAM ˆø” -* LPARAM lParam : ƒƒbƒZ[ƒW‚Ì LPARAM ˆø” +* HWND hDlg : ウインドウハンドル +* UINT message : メッセージ番号 +* WPARAM wParam : メッセージの WPARAM 引数 +* LPARAM lParam : メッセージの LPARAM 引数 * * Return Value * BOOL TRUE/FALSE *----------------------------------------------------------------------------*/ -static BOOL CALLBACK NoResumeWndProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) +// 64ビット対応 +//static BOOL CALLBACK NoResumeWndProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) +static INT_PTR CALLBACK NoResumeWndProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { @@ -1706,14 +2534,14 @@ static BOOL CALLBACK NoResumeWndProc(HWND hDlg, UINT iMessage, WPARAM wParam, LP -/*----- ƒAƒbƒvƒ[ƒh‚ðs‚È‚¤ -------------------------------------------------- +/*----- アップロードを行なう -------------------------------------------------- * * Parameter -* SOCKET cSkt : ƒRƒ“ƒgƒ[ƒ‹ƒ\ƒPƒbƒg -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ +* SOCKET cSkt : コントロールソケット +* TRANSPACKET *Pkt : 転送ファイル情報 * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード *----------------------------------------------------------------------------*/ static int DoUpLoad(SOCKET cSkt, TRANSPACKET *Pkt) @@ -1725,12 +2553,14 @@ static int DoUpLoad(SOCKET cSkt, TRANSPACKET *Pkt) if(Pkt->Mode != EXIST_IGNORE) { - if(CheckFileReadable(Pkt->LocalFile) == SUCCESS) + if(CheckFileReadable(Pkt->LocalFile) == FFFTP_SUCCESS) { if(Pkt->Type == TYPE_I) Pkt->KanjiCode = KANJI_NOCNV; - iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled, "TYPE %c", Pkt->Type); + // 同時接続対応 +// iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled, "TYPE %c", Pkt->Type); + iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled[Pkt->ThreadCount], "TYPE %c", Pkt->Type); if(iRetCode/100 < FTP_RETRY) { if(Pkt->Mode == EXIST_UNIQUE) @@ -1739,7 +2569,13 @@ static int DoUpLoad(SOCKET cSkt, TRANSPACKET *Pkt) if(Pkt->hWndTrans != NULL) DispTransFileInfo(Pkt, MSGJPN104, TRUE, YES); - if(BackgrndMessageProc() == NO) + // SFTP対応 +// if(BackgrndMessageProc() == NO) + if(IsSFTPAttached(Pkt->ctrl_skt)) + { + // TODO: + } + else if(BackgrndMessageProc() == NO) { if(AskPasvMode() != YES) iRetCode = UpLoadNonPassive(Pkt); @@ -1752,9 +2588,11 @@ static int DoUpLoad(SOCKET cSkt, TRANSPACKET *Pkt) else SetErrorMsg(Reply); - /* ‘®«•ÏX */ + /* 属性変更 */ if((Pkt->Attr != -1) && ((iRetCode/100) == FTP_COMPLETE)) - command(Pkt->ctrl_skt, Reply, &Canceled, "%s %03X %s", AskHostChmodCmd(), Pkt->Attr, Pkt->RemoteFile); + // 同時接続対応 +// command(Pkt->ctrl_skt, Reply, &Canceled, "%s %03X %s", AskHostChmodCmd(), Pkt->Attr, Pkt->RemoteFile); + command(Pkt->ctrl_skt, Reply, &Canceled[Pkt->ThreadCount], "%s %03X %s", AskHostChmodCmd(), Pkt->Attr, Pkt->RemoteFile); } else { @@ -1775,13 +2613,13 @@ static int DoUpLoad(SOCKET cSkt, TRANSPACKET *Pkt) } -/*----- ’ʏ탂[ƒh‚Ńtƒ@ƒCƒ‹‚ðƒAƒbƒvƒ[ƒh ------------------------------------ +/*----- 通常モードでファイルをアップロード ------------------------------------ * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ +* TRANSPACKET *Pkt : 転送ファイル情報 * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード *----------------------------------------------------------------------------*/ static int UpLoadNonPassive(TRANSPACKET *Pkt) @@ -1791,25 +2629,56 @@ static int UpLoadNonPassive(TRANSPACKET *Pkt) SOCKET data_socket = INVALID_SOCKET; // data channel socket SOCKET listen_socket = INVALID_SOCKET; // data listen socket char Buf[1024]; - struct sockaddr_in saSockAddr1; + // IPv6対応 +// struct sockaddr_in saSockAddr1; + struct sockaddr_in saSockAddrIPv4; + struct sockaddr_in6 saSockAddrIPv6; int Resume; char Reply[ERR_MSG_LEN+7]; - if((listen_socket = GetFTPListenSocket(Pkt->ctrl_skt, &Canceled)) != INVALID_SOCKET) + // 同時接続対応 +// if((listen_socket = GetFTPListenSocket(Pkt->ctrl_skt, &Canceled)) != INVALID_SOCKET) + if((listen_socket = GetFTPListenSocket(Pkt->ctrl_skt, &Canceled[Pkt->ThreadCount])) != INVALID_SOCKET) { SetUploadResume(Pkt, Pkt->Mode, Pkt->ExistSize, &Resume); if(Resume == NO) +#if defined(HAVE_TANDEM) + if(AskHostType() == HTYPE_TANDEM && AskOSS() == NO && Pkt->Type != TYPE_A) { + if( Pkt->PriExt == DEF_PRIEXT && Pkt->SecExt == DEF_SECEXT && Pkt->MaxExt == DEF_MAXEXT) { + // EXTENTがデフォルトのときはコードのみ + sprintf(Buf, "%s%s,%d", Pkt->Cmd, Pkt->RemoteFile, Pkt->FileCode); + } else { + sprintf(Buf, "%s%s,%d,%d,%d,%d", Pkt->Cmd, Pkt->RemoteFile, Pkt->FileCode, Pkt->PriExt, Pkt->SecExt, Pkt->MaxExt); + } + } else +#endif sprintf(Buf, "%s%s", Pkt->Cmd, Pkt->RemoteFile); else sprintf(Buf, "%s%s", "APPE ", Pkt->RemoteFile); - iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled, "%s", Buf); + // 同時接続対応 +// iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled, "%s", Buf); + iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled[Pkt->ThreadCount], "%s", Buf); if((iRetCode/100) == FTP_PRELIM) { - if(SocksGet2ndBindReply(listen_socket, &data_socket) == FAIL) + // 同時接続対応 +// if(SocksGet2ndBindReply(listen_socket, &data_socket) == FFFTP_FAIL) + if(SocksGet2ndBindReply(listen_socket, &data_socket, &Canceled[Pkt->ThreadCount]) == FFFTP_FAIL) { - iLength=sizeof(saSockAddr1); - data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddr1, (int *)&iLength); + // IPv6対応 +// iLength=sizeof(saSockAddr1); +// data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddr1, (int *)&iLength); + switch(AskCurNetType()) + { + case NTYPE_IPV4: + iLength=sizeof(saSockAddrIPv4); + data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv4, (int *)&iLength); + break; + case NTYPE_IPV6: + iLength=sizeof(saSockAddrIPv6); + data_socket = do_accept(listen_socket,(struct sockaddr *)&saSockAddrIPv6, (int *)&iLength); + break; + } if(shutdown(listen_socket, 1) != 0) ReportWSError("shutdown listen", WSAGetLastError()); @@ -1822,12 +2691,36 @@ static int UpLoadNonPassive(TRANSPACKET *Pkt) iRetCode = 500; } else - DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port)); + // IPv6対応 +// DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddr1.sin_addr), ntohs(saSockAddr1.sin_port)); + { + switch(AskCurNetType()) + { + case NTYPE_IPV4: + DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet_ntoa(saSockAddrIPv4.sin_addr), ntohs(saSockAddrIPv4.sin_port)); + break; + case NTYPE_IPV6: + DoPrintf("Skt=%u : accept from %s port %u", data_socket, inet6_ntoa(saSockAddrIPv6.sin6_addr), ntohs(saSockAddrIPv6.sin6_port)); + break; + } + } } if(data_socket != INVALID_SOCKET) { - iRetCode = UpLoadFile(Pkt, data_socket); + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため + ReleaseMutex(hListAccMutex); + // FTPS対応 +// iRetCode = UpLoadFile(Pkt, data_socket); + if(IsSSLAttached(Pkt->ctrl_skt)) + { + if(AttachSSL(data_socket, Pkt->ctrl_skt, &Canceled[Pkt->ThreadCount])) + iRetCode = UpLoadFile(Pkt, data_socket); + else + iRetCode = 500; + } + else + iRetCode = UpLoadFile(Pkt, data_socket); data_socket = DoClose(data_socket); } } @@ -1850,13 +2743,13 @@ static int UpLoadNonPassive(TRANSPACKET *Pkt) } -/*----- Passiveƒ‚[ƒh‚Ńtƒ@ƒCƒ‹‚ðƒAƒbƒvƒ[ƒh --------------------------------- +/*----- Passiveモードでファイルをアップロード --------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ +* TRANSPACKET *Pkt : 転送ファイル情報 * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード *----------------------------------------------------------------------------*/ static int UpLoadPassive(TRANSPACKET *Pkt) @@ -1864,32 +2757,76 @@ static int UpLoadPassive(TRANSPACKET *Pkt) int iRetCode; SOCKET data_socket = INVALID_SOCKET; // data channel socket char Buf[1024]; - char Adrs[20]; + // IPv6対応 +// char Adrs[20]; + char Adrs[40]; int Port; int Flg; int Resume; char Reply[ERR_MSG_LEN+7]; - iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled, "PASV"); + // 同時接続対応 +// iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled, "PASV"); + // IPv6対応 +// iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled[Pkt->ThreadCount], "PASV"); + switch(AskCurNetType()) + { + case NTYPE_IPV4: + iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled[Pkt->ThreadCount], "PASV"); + break; + case NTYPE_IPV6: + iRetCode = command(Pkt->ctrl_skt, Buf, &Canceled[Pkt->ThreadCount], "EPSV"); + break; + } if(iRetCode/100 == FTP_COMPLETE) { - if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == SUCCESS) + // IPv6対応 +// if(GetAdrsAndPort(Buf, Adrs, &Port, 19) == FFFTP_SUCCESS) + if(GetAdrsAndPort(Pkt->ctrl_skt, Buf, Adrs, &Port, 39) == FFFTP_SUCCESS) { - if((data_socket = connectsock(Adrs, Port, MSGJPN109, &Canceled)) != INVALID_SOCKET) + // 同時接続対応 +// if((data_socket = connectsock(Adrs, Port, MSGJPN109, &Canceled)) != INVALID_SOCKET) + if((data_socket = connectsock(Adrs, Port, MSGJPN109, &Canceled[Pkt->ThreadCount])) != INVALID_SOCKET) { + // 変数が未初期化のバグ修正 + Flg = 1; if(setsockopt(data_socket, IPPROTO_TCP, TCP_NODELAY, (LPSTR)&Flg, sizeof(Flg)) == SOCKET_ERROR) ReportWSError("setsockopt", WSAGetLastError()); SetUploadResume(Pkt, Pkt->Mode, Pkt->ExistSize, &Resume); if(Resume == NO) +#if defined(HAVE_TANDEM) + if(AskHostType() == HTYPE_TANDEM && AskOSS() == NO && Pkt->Type != TYPE_A) { + if( Pkt->PriExt == DEF_PRIEXT && Pkt->SecExt == DEF_SECEXT && Pkt->MaxExt == DEF_MAXEXT) { + // EXTENTがデフォルトのときはコードのみ + sprintf(Buf, "%s%s,%d", Pkt->Cmd, Pkt->RemoteFile, Pkt->FileCode); + } else { + sprintf(Buf, "%s%s,%d,%d,%d,%d", Pkt->Cmd, Pkt->RemoteFile, Pkt->FileCode, Pkt->PriExt, Pkt->SecExt, Pkt->MaxExt); + } + } else +#endif sprintf(Buf, "%s%s", Pkt->Cmd, Pkt->RemoteFile); else sprintf(Buf, "%s%s", "APPE ", Pkt->RemoteFile); - iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled, "%s", Buf); + // 同時接続対応 +// iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled, "%s", Buf); + iRetCode = command(Pkt->ctrl_skt, Reply, &Canceled[Pkt->ThreadCount], "%s", Buf); if(iRetCode/100 == FTP_PRELIM) { - iRetCode = UpLoadFile(Pkt, data_socket); + // 一部TYPE、STOR(RETR)、PORT(PASV)を並列に処理できないホストがあるため + ReleaseMutex(hListAccMutex); + // FTPS対応 +// iRetCode = UpLoadFile(Pkt, data_socket); + if(IsSSLAttached(Pkt->ctrl_skt)) + { + if(AttachSSL(data_socket, Pkt->ctrl_skt, &Canceled[Pkt->ThreadCount])) + iRetCode = UpLoadFile(Pkt, data_socket); + else + iRetCode = 500; + } + else + iRetCode = UpLoadFile(Pkt, data_socket); data_socket = DoClose(data_socket); } @@ -1923,18 +2860,18 @@ static int UpLoadPassive(TRANSPACKET *Pkt) } -/*----- ƒAƒbƒvƒ[ƒh‚ÌŽÀs ---------------------------------------------------- +/*----- アップロードの実行 ---------------------------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* SOCKET dSkt : ƒf[ƒ^ƒ\ƒPƒbƒg +* TRANSPACKET *Pkt : 転送ファイル情報 +* SOCKET dSkt : データソケット * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード * * Note -* “]‘—‚ÌŒo‰ß•\Ž¦‚́AƒCƒ“ƒ^[ƒoƒ‹ƒ^ƒCƒ}‚ÅŒo‰ß‚ð•\Ž¦‚·‚é -* “]‘—ƒ_ƒCƒAƒƒO‚ðo‚³‚È‚¢‚ŃAƒbƒvƒ[ƒh‚·‚邱‚Æ‚Í‚È‚¢ +* 転送の経過表示は、インターバルタイマで経過を表示する +* 転送ダイアログを出さないでアップロードすることはない *----------------------------------------------------------------------------*/ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) @@ -1965,8 +2902,8 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) /* End */ #endif -#ifdef DISABLE_NETWORK_BUFFERS - // ”O‚Ì‚½‚ß‘—Mƒoƒbƒtƒ@‚𖳌ø‚É‚·‚éB + // 念のため送信バッファを無効にする +#ifdef DISABLE_TRANSFER_NETWORK_BUFFERS int buf_size = 0; setsockopt(dSkt, SOL_SOCKET, SO_SNDBUF, (char *)&buf_size, sizeof(buf_size)); #endif @@ -1980,7 +2917,9 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) if((iFileHandle = CreateFile(Pkt->LocalFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, &Sec, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { - // UTF-8‘Ήž + // UTF-8対応 + char Buf3[(BUFSIZE + 3) * 4]; + CODECONVINFO cInfo2; int ProcessedBOM = NO; if(Pkt->hWndTrans != NULL) { @@ -1991,8 +2930,11 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) Low = (DWORD)LOW32(Pkt->ExistSize); SetFilePointer(iFileHandle, Low, &High, FILE_BEGIN); - AllTransSizeNow = 0; - TimeStart = time(NULL); + // 同時接続対応 +// AllTransSizeNow = 0; +// TimeStart = time(NULL); + AllTransSizeNow[Pkt->ThreadCount] = 0; + TimeStart[Pkt->ThreadCount] = time(NULL); SetTimer(Pkt->hWndTrans, TIMER_DISPLAY, DISPLAY_TIMING, NULL); } @@ -2000,7 +2942,10 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) cInfo.KanaCnv = Pkt->KanaCnv; InitTermCodeConvInfo(&tInfo); - /*===== ƒtƒ@ƒCƒ‹‚𑗐M‚·‚郋[ƒv =====*/ + InitCodeConvInfo(&cInfo2); + cInfo2.KanaCnv = Pkt->KanaCnv; + + /*===== ファイルを送信するループ =====*/ while((Pkt->Abort == ABORT_NONE) && (ForceAbort == NO) && (ReadFile(iFileHandle, Buf, BUFSIZE, &iNumBytes, NULL) == TRUE)) @@ -2008,7 +2953,7 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) if(iNumBytes == 0) break; - /* EOFœ‹Ž */ + /* EOF除去 */ EofPos = NULL; if((RmEOF == YES) && (Pkt->Type == TYPE_A)) { @@ -2016,7 +2961,7 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) iNumBytes = EofPos - Buf; } - /* Š¿ŽšƒR[ƒh•ÏŠ· */ + /* 漢字コード変換 */ if(Pkt->KanjiCode != KANJI_NOCNV) { cInfo.Str = Buf; @@ -2025,29 +2970,45 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) cInfo.BufSize = BUFSIZE+3; do { - // ‚±‚±‚Å‘S‚ÄUTF-8‚Ö•ÏŠ·‚·‚é - // TODO: SJISˆÈŠO‚à’¼ÚUTF-8‚Ö•ÏŠ· + // ここで全てUTF-8へ変換する + // TODO: SJIS以外も直接UTF-8へ変換 // if(Pkt->KanjiCode == KANJI_JIS) // Continue = ConvSJIStoJIS(&cInfo); // else // Continue = ConvSJIStoEUC(&cInfo); - char Buf3[(BUFSIZE + 3) * 4]; - CODECONVINFO cInfo2; switch(Pkt->KanjiCodeDesired) { case KANJI_SJIS: switch(Pkt->KanjiCode) { case KANJI_SJIS: - memcpy(Buf3, cInfo.Str, cInfo.StrLen); - cInfo2.OutLen = cInfo.StrLen; - Continue = NO; +// memcpy(Buf3, cInfo.Str, cInfo.StrLen); +// cInfo2.OutLen = cInfo.StrLen; +// Continue = NO; + // カナ変換のため + Continue = ConvSJIStoJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvJIStoSJIS(&cInfo2); break; case KANJI_JIS: + Continue = ConvSJIStoJIS(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; break; case KANJI_EUC: + Continue = ConvSJIStoEUC(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; break; case KANJI_UTF8N: + Continue = ConvSJIStoUTF8N(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { memcpy(Buf3, "\xEF\xBB\xBF", 3); @@ -2057,7 +3018,7 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) break; } Continue = ConvSJIStoUTF8N(&cInfo); - memcpy(Buf3, cInfo.Str, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; } @@ -2067,17 +3028,38 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) { case KANJI_SJIS: Continue = ConvJIStoSJIS(&cInfo); - memcpy(Buf3, Buf2, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; case KANJI_JIS: - memcpy(Buf3, cInfo.Str, cInfo.StrLen); - cInfo2.OutLen = cInfo.StrLen; - Continue = NO; +// memcpy(Buf3, cInfo.Str, cInfo.StrLen); +// cInfo2.OutLen = cInfo.StrLen; +// Continue = NO; + // カナ変換のため + Continue = ConvJIStoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); break; case KANJI_EUC: + Continue = ConvJIStoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); break; case KANJI_UTF8N: + Continue = ConvJIStoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { memcpy(Buf3, "\xEF\xBB\xBF", 3); @@ -2087,8 +3069,6 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) break; } Continue = ConvJIStoSJIS(&cInfo); - InitCodeConvInfo(&cInfo2); - cInfo2.KanaCnv = NO; cInfo2.Str = cInfo.Buf; cInfo2.StrLen = cInfo.OutLen; cInfo2.Buf = Buf3; @@ -2102,17 +3082,38 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) { case KANJI_SJIS: Continue = ConvEUCtoSJIS(&cInfo); - memcpy(Buf3, Buf2, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; case KANJI_JIS: + Continue = ConvEUCtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); break; case KANJI_EUC: - memcpy(Buf3, cInfo.Str, cInfo.StrLen); - cInfo2.OutLen = cInfo.StrLen; - Continue = NO; +// memcpy(Buf3, cInfo.Str, cInfo.StrLen); +// cInfo2.OutLen = cInfo.StrLen; +// Continue = NO; + // カナ変換のため + Continue = ConvEUCtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); break; case KANJI_UTF8N: + Continue = ConvEUCtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { memcpy(Buf3, "\xEF\xBB\xBF", 3); @@ -2122,8 +3123,6 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) break; } Continue = ConvEUCtoSJIS(&cInfo); - InitCodeConvInfo(&cInfo2); - cInfo2.KanaCnv = NO; cInfo2.Str = cInfo.Buf; cInfo2.StrLen = cInfo.OutLen; cInfo2.Buf = Buf3; @@ -2133,6 +3132,50 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) } break; case KANJI_UTF8N: + switch(Pkt->KanjiCode) + { + case KANJI_SJIS: + Continue = ConvUTF8NtoSJIS(&cInfo); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Str, cInfo.StrLen); + cInfo2.OutLen = cInfo.StrLen; + Continue = NO; + break; + case KANJI_UTF8BOM: + if(ProcessedBOM == NO) + { + memcpy(Buf3, "\xEF\xBB\xBF", 3); + cInfo2.OutLen = 3; + Continue = YES; + ProcessedBOM = YES; + break; + } + memcpy(Buf3, cInfo.Str, cInfo.StrLen); + cInfo2.OutLen = cInfo.StrLen; + Continue = NO; + break; + } + break; + case KANJI_UTF8BOM: if(ProcessedBOM == NO) { if(memcmp(Buf, "\xEF\xBB\xBF", 3) == 0) @@ -2143,7 +3186,7 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) cInfo2.OutLen = 0; switch(Pkt->KanjiCode) { - case KANJI_UTF8N: + case KANJI_UTF8BOM: memcpy(Buf3, "\xEF\xBB\xBF", 3); cInfo2.OutLen = 3; break; @@ -2156,24 +3199,41 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) { case KANJI_SJIS: Continue = ConvUTF8NtoSJIS(&cInfo); - memcpy(Buf3, Buf2, cInfo.OutLen); + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); cInfo2.OutLen = cInfo.OutLen; break; case KANJI_JIS: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); break; case KANJI_EUC: + Continue = ConvUTF8NtoSJIS(&cInfo); + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); break; case KANJI_UTF8N: memcpy(Buf3, cInfo.Str, cInfo.StrLen); cInfo2.OutLen = cInfo.StrLen; Continue = NO; break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Str, cInfo.StrLen); + cInfo2.OutLen = cInfo.StrLen; + Continue = NO; + break; } break; } -// if(TermCodeConvAndSend(&tInfo, dSkt, Buf2, cInfo.OutLen, Pkt->Type) == FAIL) - if(TermCodeConvAndSend(&tInfo, dSkt, Buf3, cInfo2.OutLen, Pkt->Type) == FAIL) +// if(TermCodeConvAndSend(&tInfo, dSkt, Buf2, cInfo.OutLen, Pkt->Type) == FFFTP_FAIL) + if(TermCodeConvAndSend(&tInfo, dSkt, Buf3, cInfo2.OutLen, Pkt->Type, &Canceled[Pkt->ThreadCount]) == FFFTP_FAIL) { Pkt->Abort = ABORT_ERROR; break; @@ -2183,13 +3243,17 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) } else { - if(TermCodeConvAndSend(&tInfo, dSkt, Buf, iNumBytes, Pkt->Type) == FAIL) + // 同時接続対応 +// if(TermCodeConvAndSend(&tInfo, dSkt, Buf, iNumBytes, Pkt->Type) == FFFTP_FAIL) + if(TermCodeConvAndSend(&tInfo, dSkt, Buf, iNumBytes, Pkt->Type, &Canceled[Pkt->ThreadCount]) == FFFTP_FAIL) Pkt->Abort = ABORT_ERROR; } Pkt->ExistSize += iNumBytes; if(Pkt->hWndTrans != NULL) - AllTransSizeNow += iNumBytes; + // 同時接続対応 +// AllTransSizeNow += iNumBytes; + AllTransSizeNow[Pkt->ThreadCount] += iNumBytes; if(BackgrndMessageProc() == YES) ForceAbort = YES; @@ -2200,30 +3264,210 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) if((ForceAbort == NO) && (Pkt->Abort == ABORT_NONE)) { - /* ‘—‚èŽc‚µ‚½ƒf[ƒ^‚𑗐M */ + /* 送り残したデータを送信 */ if(Pkt->KanjiCode != KANJI_NOCNV) { cInfo.Buf = Buf2; cInfo.BufSize = BUFSIZE+3; FlushRestData(&cInfo); + switch(Pkt->KanjiCodeDesired) + { + case KANJI_SJIS: + switch(Pkt->KanjiCode) + { + case KANJI_SJIS: + // カナ変換のため + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvJIStoSJIS(&cInfo2); + break; + case KANJI_JIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_EUC: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + } + break; + case KANJI_JIS: + switch(Pkt->KanjiCode) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + // カナ変換のため + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + } + break; + case KANJI_EUC: + switch(Pkt->KanjiCode) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + // カナ変換のため + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + case KANJI_UTF8BOM: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoUTF8N(&cInfo2); + break; + } + break; + case KANJI_UTF8N: + switch(Pkt->KanjiCode) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + } + break; + case KANJI_UTF8BOM: + switch(Pkt->KanjiCode) + { + case KANJI_SJIS: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_JIS: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoJIS(&cInfo2); + break; + case KANJI_EUC: + cInfo2.Str = cInfo.Buf; + cInfo2.StrLen = cInfo.OutLen; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + ConvSJIStoEUC(&cInfo2); + break; + case KANJI_UTF8N: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + case KANJI_UTF8BOM: + memcpy(Buf3, cInfo.Buf, cInfo.OutLen); + cInfo2.OutLen = cInfo.OutLen; + break; + } + break; + } - if(TermCodeConvAndSend(&tInfo, dSkt, Buf2, cInfo.OutLen, Pkt->Type) == FAIL) +// if(TermCodeConvAndSend(&tInfo, dSkt, Buf2, cInfo.OutLen, Pkt->Type) == FFFTP_FAIL) + if(TermCodeConvAndSend(&tInfo, dSkt, Buf3, cInfo2.OutLen, Pkt->Type, &Canceled[Pkt->ThreadCount]) == FFFTP_FAIL) + Pkt->Abort = ABORT_ERROR; + cInfo2.Buf = Buf3; + cInfo2.BufSize = (BUFSIZE + 3) * 4; + FlushRestData(&cInfo2); + if(TermCodeConvAndSend(&tInfo, dSkt, Buf3, cInfo2.OutLen, Pkt->Type, &Canceled[Pkt->ThreadCount]) == FFFTP_FAIL) Pkt->Abort = ABORT_ERROR; } tInfo.Buf = Buf2; tInfo.BufSize = BUFSIZE+3; FlushRestTermCodeConvData(&tInfo); - if(SendData(dSkt, Buf2, tInfo.OutLen, 0, &Canceled) == FAIL) + // 同時接続対応 +// if(SendData(dSkt, Buf2, tInfo.OutLen, 0, &Canceled) == FFFTP_FAIL) + if(SendData(dSkt, Buf2, tInfo.OutLen, 0, &Canceled[Pkt->ThreadCount]) == FFFTP_FAIL) Pkt->Abort = ABORT_ERROR; } - /* ƒOƒ‰ƒt•\Ž¦‚ðXV */ + /* グラフ表示を更新 */ if(Pkt->hWndTrans != NULL) { KillTimer(Pkt->hWndTrans, TIMER_DISPLAY); DispTransferStatus(Pkt->hWndTrans, YES, Pkt); - TimeStart = time(NULL) - TimeStart + 1; + // 同時接続対応 +// TimeStart = time(NULL) - TimeStart + 1; + TimeStart[Pkt->ThreadCount] = time(NULL) - TimeStart[Pkt->ThreadCount] + 1; } CloseHandle(iFileHandle); } @@ -2243,7 +3487,9 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) ; #endif - iRetCode = ReadReplyMessage(Pkt->ctrl_skt, Buf, 1024, &Canceled, TmpBuf); + // 同時接続対応 +// iRetCode = ReadReplyMessage(Pkt->ctrl_skt, Buf, 1024, &Canceled, TmpBuf); + iRetCode = ReadReplyMessage(Pkt->ctrl_skt, Buf, 1024, &Canceled[Pkt->ThreadCount], TmpBuf); //#pragma aaa //DoPrintf("##UP REPLY : %s", Buf); @@ -2258,28 +3504,30 @@ static int UpLoadFile(TRANSPACKET *Pkt, SOCKET dSkt) } -/*----- ƒoƒbƒtƒ@‚Ì“à—e‚ð‰üsƒR[ƒh•ÏŠ·‚µ‚Ä‘—M -------------------------------- +/*----- バッファの内容を改行コード変換して送信 -------------------------------- * * Parameter -* TERMCODECONVINFO *tInfo : ‰üsƒR[ƒh•ÏŠ·ƒpƒPƒbƒg -* SOCKET Skt : ƒ\ƒPƒbƒg -* char *Data : ƒf[ƒ^ -* int Size : ƒf[ƒ^‚̃TƒCƒY -* int Ascii : ƒ‚[ƒh@@(TYPE_xx) +* TERMCODECONVINFO *tInfo : 改行コード変換パケット +* SOCKET Skt : ソケット +* char *Data : データ +* int Size : データのサイズ +* int Ascii : モード  (TYPE_xx) * * Return Value -* int ‰ž“šƒR[ƒh +* int 応答コード *----------------------------------------------------------------------------*/ -static int TermCodeConvAndSend(TERMCODECONVINFO *tInfo, SOCKET Skt, char *Data, int Size, int Ascii) +// 同時接続対応 +//static int TermCodeConvAndSend(TERMCODECONVINFO *tInfo, SOCKET Skt, char *Data, int Size, int Ascii) +static int TermCodeConvAndSend(TERMCODECONVINFO *tInfo, SOCKET Skt, char *Data, int Size, int Ascii, int *CancelCheckWork) { char Buf3[BUFSIZE*2]; int Continue; int Ret; - Ret = SUCCESS; + Ret = FFFTP_SUCCESS; -// CR-LFˆÈŠO‚̉üsƒR[ƒh‚ð•ÏŠ·‚µ‚È‚¢ƒ‚[ƒh‚Í‚±‚±‚֒ljÁ +// CR-LF以外の改行コードを変換しないモードはここへ追加 if(Ascii == TYPE_A) { tInfo->Str = Data; @@ -2289,26 +3537,30 @@ static int TermCodeConvAndSend(TERMCODECONVINFO *tInfo, SOCKET Skt, char *Data, do { Continue = ConvTermCodeToCRLF(tInfo); - if((Ret = SendData(Skt, Buf3, tInfo->OutLen, 0, &Canceled)) == FAIL) + // 同時接続対応 +// if((Ret = SendData(Skt, Buf3, tInfo->OutLen, 0, &Canceled)) == FFFTP_FAIL) + if((Ret = SendData(Skt, Buf3, tInfo->OutLen, 0, CancelCheckWork)) == FFFTP_FAIL) break; } while(Continue == YES); } else - Ret = SendData(Skt, Data, Size, 0, &Canceled); + // 同時接続対応 +// Ret = SendData(Skt, Data, Size, 0, &Canceled); + Ret = SendData(Skt, Data, Size, 0, CancelCheckWork); return(Ret); } -/*----- ƒAƒbƒvƒ[ƒhI—¹^’†Ž~Žž‚̃ƒbƒZ[ƒW‚ð•\Ž¦ ---------------------------- +/*----- アップロード終了/中止時のメッセージを表示 ---------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* int iRetCode : ‰ž“šƒR[ƒh +* TRANSPACKET *Pkt : 転送ファイル情報 +* int iRetCode : 応答コード * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ static void DispUploadFinishMsg(TRANSPACKET *Pkt, int iRetCode) @@ -2317,21 +3569,46 @@ static void DispUploadFinishMsg(TRANSPACKET *Pkt, int iRetCode) { if((iRetCode/100) >= FTP_CONTINUE) { - if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) - SetTaskMsg(MSGJPN113, TimeStart, Pkt->ExistSize/TimeStart); + // 同時接続対応 +// if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) +// SetTaskMsg(MSGJPN113, TimeStart, Pkt->ExistSize/TimeStart); + if((Pkt->hWndTrans != NULL) && (TimeStart[Pkt->ThreadCount] != 0)) + SetTaskMsg(MSGJPN113, TimeStart[Pkt->ThreadCount], Pkt->ExistSize/TimeStart[Pkt->ThreadCount]); else SetTaskMsg(MSGJPN114); if(Pkt->Abort != ABORT_USER) { - if(DispUpDownErrDialog(uperr_dlg, Pkt->hWndTrans, Pkt->LocalFile) == NO) - ClearAll = YES; + // 全て中止を選択後にダイアログが表示されるバグ対策 +// if(DispUpDownErrDialog(uperr_dlg, Pkt->hWndTrans, Pkt->LocalFile) == NO) + // 再転送対応 +// if(Canceled[Pkt->ThreadCount] == NO && ClearAll == NO && DispUpDownErrDialog(uperr_dlg, Pkt->hWndTrans, Pkt->LocalFile) == NO) +// ClearAll = YES; + if(Canceled[Pkt->ThreadCount] == NO && ClearAll == NO) + { + if(strncmp(Pkt->Cmd, "RETR", 4) == 0 || strncmp(Pkt->Cmd, "STOR", 4) == 0) + { + if(TransferErrorNotify == YES && DispUpDownErrDialog(uperr_dlg, Pkt->hWndTrans, Pkt) == NO) + ClearAll = YES; + else + { + Pkt->Mode = TransferErrorMode; + AddTransFileList(Pkt); + } + } + } } } else { - if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) - SetTaskMsg(MSGJPN115, TimeStart, Pkt->ExistSize/TimeStart); + // 同時接続対応 +// if((Pkt->hWndTrans != NULL) && (TimeStart != 0)) +// SetTaskMsg(MSGJPN115, TimeStart, Pkt->ExistSize/TimeStart); + if((Pkt->hWndTrans != NULL) && (TimeStart[Pkt->ThreadCount] != 0)) + // "0 B/S"と表示されるバグを修正 + // 原因は%dにあたる部分に64ビット値が渡されているため +// SetTaskMsg(MSGJPN115, TimeStart[Pkt->ThreadCount], Pkt->ExistSize/TimeStart[Pkt->ThreadCount]); + SetTaskMsg(MSGJPN115, (LONG)TimeStart[Pkt->ThreadCount], (LONG)(Pkt->ExistSize/TimeStart[Pkt->ThreadCount])); else SetTaskMsg(MSGJPN116); } @@ -2340,19 +3617,19 @@ static void DispUploadFinishMsg(TRANSPACKET *Pkt, int iRetCode) } -/*----- ƒAƒbƒvƒ[ƒh‚̃ŠƒWƒ…[ƒ€‚̏€”õ‚ðs‚¤ ---------------------------------- +/*----- アップロードのリジュームの準備を行う ---------------------------------- * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* iont ProcMode : ˆ—ƒ‚[ƒh(EXIST_xxx) -* LONGLONG Size : ƒzƒXƒg‚É‚ ‚éƒtƒ@ƒCƒ‹‚̃TƒCƒY -* int *Mode : ƒŠƒWƒ…[ƒ€‚ðs‚¤‚©‚Ç‚¤‚© (YES/NO) +* TRANSPACKET *Pkt : 転送ファイル情報 +* iont ProcMode : 処理モード(EXIST_xxx) +* LONGLONG Size : ホストにあるファイルのサイズ +* int *Mode : リジュームを行うかどうか (YES/NO) * * Return Value -* int ƒXƒe[ƒ^ƒX = YES +* int ステータス = YES * * Note -* Pkt->ExistSize‚̃Zƒbƒg‚ðs‚È‚¤ +* Pkt->ExistSizeのセットを行なう *----------------------------------------------------------------------------*/ static int SetUploadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int *Mode) @@ -2371,13 +3648,13 @@ static int SetUploadResume(TRANSPACKET *Pkt, int ProcMode, LONGLONG Size, int *M } -/*----- “]‘—’†ƒ_ƒCƒAƒƒOƒ{ƒbƒNƒX‚̃R[ƒ‹ƒoƒbƒN -------------------------------- +/*----- 転送中ダイアログボックスのコールバック -------------------------------- * * Parameter -* HWND hDlg : ƒEƒCƒ“ƒhƒEƒnƒ“ƒhƒ‹ -* UINT message : ƒƒbƒZ[ƒW”ԍ† -* WPARAM wParam : ƒƒbƒZ[ƒW‚Ì WPARAM ˆø” -* LPARAM lParam : ƒƒbƒZ[ƒW‚Ì LPARAM ˆø” +* HWND hDlg : ウインドウハンドル +* UINT message : メッセージ番号 +* WPARAM wParam : メッセージの WPARAM 引数 +* LPARAM lParam : メッセージの LPARAM 引数 * * Return Value * BOOL TRUE/FALSE @@ -2388,7 +3665,10 @@ static LRESULT CALLBACK TransDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM RECT RectDlg; RECT RectPar; HMENU hMenu; - static TRANSPACKET *Pkt; + // 同時接続対応 +// static TRANSPACKET *Pkt; + TRANSPACKET *Pkt; + int i; switch(Msg) { @@ -2417,11 +3697,18 @@ static LRESULT CALLBACK TransDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM case TRANS_STOP_ALL : ClearAll = YES; - /* ‚±‚±‚É break ‚Í‚È‚¢ */ + for(i = 0; i < MAX_DATA_CONNECTION; i++) + Canceled[i] = YES; + /* ここに break はない */ case IDCANCEL : + // 64ビット対応 +// if(!(Pkt = (TRANSPACKET*)GetWindowLong(hDlg, GWL_USERDATA))) + if(!(Pkt = (TRANSPACKET*)GetWindowLongPtr(hDlg, GWLP_USERDATA))) + break; Pkt->Abort = ABORT_USER; - Canceled = YES; +// Canceled = YES; + Canceled[Pkt->ThreadCount] = YES; break; } break; @@ -2433,27 +3720,36 @@ static LRESULT CALLBACK TransDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM SetForegroundWindow(hDlg); MoveToForeground = NO; KillTimer(hDlg, TIMER_DISPLAY); + // 64ビット対応 +// if(!(Pkt = (TRANSPACKET*)GetWindowLong(hDlg, GWL_USERDATA))) + if(!(Pkt = (TRANSPACKET*)GetWindowLongPtr(hDlg, GWLP_USERDATA))) + break; + if(Canceled[Pkt->ThreadCount] == YES) + Pkt->Abort = ABORT_USER; DispTransferStatus(hDlg, NO, Pkt); SetTimer(hDlg, TIMER_DISPLAY, DISPLAY_TIMING, NULL); } break; case WM_SET_PACKET : - Pkt = (TRANSPACKET *)lParam; +// Pkt = (TRANSPACKET *)lParam; + // 64ビット対応 +// SetWindowLong(hDlg, GWL_USERDATA, (LONG)lParam); + SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam); break; } return(FALSE); } -/*----- “]‘—ƒXƒe[ƒ^ƒX‚ð•\Ž¦ -------------------------------------------------- +/*----- 転送ステータスを表示 -------------------------------------------------- * * Parameter -* HWND hWnd : ƒEƒCƒ“ƒhƒEƒnƒ“ƒhƒ‹ -* int End : “]‘—‚ªŠ®—¹‚µ‚½‚©‚Ç‚¤‚© (YES/NO) +* HWND hWnd : ウインドウハンドル +* int End : 転送が完了したかどうか (YES/NO) * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ static void DispTransferStatus(HWND hWnd, int End, TRANSPACKET *Pkt) @@ -2482,11 +3778,15 @@ static void DispTransferStatus(HWND hWnd, int End, TRANSPACKET *Pkt) { if(End == NO) { - TotalLap = time(NULL) - TimeStart + 1; + // 同時接続対応 +// TotalLap = time(NULL) - TimeStart + 1; + TotalLap = time(NULL) - TimeStart[Pkt->ThreadCount] + 1; Bps = 0; if(TotalLap != 0) - Bps = AllTransSizeNow / TotalLap; + // 同時接続対応 +// Bps = AllTransSizeNow / TotalLap; + Bps = AllTransSizeNow[Pkt->ThreadCount] / TotalLap; Transed = Pkt->Size - Pkt->ExistSize; if(Pkt->Size <= 0) @@ -2533,16 +3833,16 @@ static void DispTransferStatus(HWND hWnd, int End, TRANSPACKET *Pkt) } -/*----- “]‘—‚·‚éƒtƒ@ƒCƒ‹‚̏î•ñ‚ð•\Ž¦ ------------------------------------------ +/*----- 転送するファイルの情報を表示 ------------------------------------------ * * Parameter -* TRANSPACKET *Pkt : “]‘—ƒtƒ@ƒCƒ‹î•ñ -* char *Title : ƒEƒCƒ“ƒhƒE‚̃^ƒCƒgƒ‹ -* int SkipButton : u‚±‚̃tƒ@ƒCƒ‹‚𒆎~vƒ{ƒ^ƒ“‚Ì—L–³ (TRUE/FALSE) -* int Info : ƒtƒ@ƒCƒ‹î•ñ‚ð•\Ž¦‚·‚é‚©‚Ç‚¤‚© (YES/NO) +* TRANSPACKET *Pkt : 転送ファイル情報 +* char *Title : ウインドウのタイトル +* int SkipButton : 「このファイルを中止」ボタンの有無 (TRUE/FALSE) +* int Info : ファイル情報を表示するかどうか (YES/NO) * * Return Value -* ‚È‚µ +* なし *----------------------------------------------------------------------------*/ static void DispTransFileInfo(TRANSPACKET *Pkt, char *Title, int SkipButton, int Info) @@ -2571,12 +3871,19 @@ static void DispTransFileInfo(TRANSPACKET *Pkt, char *Title, int SkipButton, int else if(Pkt->Type == TYPE_A) SendDlgItemMessage(Pkt->hWndTrans, TRANS_MODE, WM_SETTEXT, 0, (LPARAM)MSGJPN120); + // UTF-8対応 if(Pkt->KanjiCode == KANJI_NOCNV) SendDlgItemMessage(Pkt->hWndTrans, TRANS_KANJI, WM_SETTEXT, 0, (LPARAM)MSGJPN121); + else if(Pkt->KanjiCode == KANJI_SJIS) + SendDlgItemMessage(Pkt->hWndTrans, TRANS_KANJI, WM_SETTEXT, 0, (LPARAM)MSGJPN305); else if(Pkt->KanjiCode == KANJI_JIS) SendDlgItemMessage(Pkt->hWndTrans, TRANS_KANJI, WM_SETTEXT, 0, (LPARAM)MSGJPN122); else if(Pkt->KanjiCode == KANJI_EUC) SendDlgItemMessage(Pkt->hWndTrans, TRANS_KANJI, WM_SETTEXT, 0, (LPARAM)MSGJPN123); + else if(Pkt->KanjiCode == KANJI_UTF8N) + SendDlgItemMessage(Pkt->hWndTrans, TRANS_KANJI, WM_SETTEXT, 0, (LPARAM)MSGJPN306); + else if(Pkt->KanjiCode == KANJI_UTF8BOM) + SendDlgItemMessage(Pkt->hWndTrans, TRANS_KANJI, WM_SETTEXT, 0, (LPARAM)MSGJPN329); } else { @@ -2590,44 +3897,83 @@ static void DispTransFileInfo(TRANSPACKET *Pkt, char *Title, int SkipButton, int } -/*----- PASVƒRƒ}ƒ“ƒh‚Ì–ß‚è’l‚©‚çƒAƒhƒŒƒX‚ƃ|[ƒg”ԍ†‚𒊏o -------------------- +/*----- PASVコマンドの戻り値からアドレスとポート番号を抽出 -------------------- * * Parameter -* char *Str : PASVƒRƒ}ƒ“ƒh‚̃Šƒvƒ‰ƒC -* char *Adrs : ƒAƒhƒŒƒX‚̃Rƒs[æ ("www.xxx.yyy.zzz") -* int *Port : ƒ|[ƒg”ԍ†‚ðƒZƒbƒg‚·‚郏[ƒN -* int Max : ƒAƒhƒŒƒX•¶Žš—ñ‚̍ő咷 +* char *Str : PASVコマンドのリプライ +* char *Adrs : アドレスのコピー先 ("www.xxx.yyy.zzz") +* int *Port : ポート番号をセットするワーク +* int Max : アドレス文字列の最大長 * * Return Value -* int ƒXƒe[ƒ^ƒX -* SUCCESS/FAIL +* int ステータス +* FFFTP_SUCCESS/FFFTP_FAIL *----------------------------------------------------------------------------*/ -static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max) +static int GetAdrsAndPort(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max) +{ + int Result; + Result = FFFTP_FAIL; + switch(AskCurNetType()) + { + case NTYPE_IPV4: + Result = GetAdrsAndPortIPv4(Skt, Str, Adrs, Port, Max); + break; + case NTYPE_IPV6: + Result = GetAdrsAndPortIPv6(Skt, Str, Adrs, Port, Max); + break; + } + return Result; +} + + +// IPv6対応 +//static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max) +static int GetAdrsAndPortIPv4(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max) { char *Pos; char *Btm; + // コンマではなくドットを返すホストがあるため + char *OldBtm; int Sts; - Sts = FAIL; + Sts = FFFTP_FAIL; Pos = strchr(Str, '('); if(Pos != NULL) { Pos++; Btm = strchr(Pos, ','); + // コンマではなくドットを返すホストがあるため + if(Btm == NULL) + Btm = strchr(Pos, '.'); if(Btm != NULL) { Btm++; - Btm = strchr(Btm, ','); + // コンマではなくドットを返すホストがあるため +// Btm = strchr(Btm, ','); + OldBtm = Btm; + Btm = strchr(OldBtm, ','); + if(Btm == NULL) + Btm = strchr(OldBtm, '.'); if(Btm != NULL) { Btm++; - Btm = strchr(Btm, ','); + // コンマではなくドットを返すホストがあるため +// Btm = strchr(Btm, ','); + OldBtm = Btm; + Btm = strchr(OldBtm, ','); + if(Btm == NULL) + Btm = strchr(OldBtm, '.'); if(Btm != NULL) { Btm++; - Btm = strchr(Btm, ','); + // コンマではなくドットを返すホストがあるため +// Btm = strchr(Btm, ','); + OldBtm = Btm; + Btm = strchr(OldBtm, ','); + if(Btm == NULL) + Btm = strchr(OldBtm, '.'); if(Btm != NULL) { if((Btm - Pos) <= Max) @@ -2638,11 +3984,14 @@ static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max) Pos = Btm + 1; Btm = strchr(Pos, ','); + // コンマではなくドットを返すホストがあるため + if(Btm == NULL) + Btm = strchr(Pos, '.'); if(Btm != NULL) { Btm++; *Port = (atoi(Pos) * 0x100) + atoi(Btm); - Sts = SUCCESS; + Sts = FFFTP_SUCCESS; } } } @@ -2654,13 +4003,72 @@ static int GetAdrsAndPort(char *Str, char *Adrs, int *Port, int Max) } -/*----- Windows‚̃XƒyƒVƒƒƒ‹ƒfƒoƒCƒX‚©‚Ç‚¤‚©‚ð•Ô‚· ----------------------------- +// IPv6対応 +static int GetAdrsAndPortIPv6(SOCKET Skt, char *Str, char *Adrs, int *Port, int Max) +{ + char *Pos; + char *Btm; + int Sts; + int i; + struct sockaddr_in6 SockAddr; + + Sts = FFFTP_FAIL; + + Btm = strchr(Str, '('); + if(Btm != NULL) + { + Btm++; + Btm = strchr(Btm, '|'); + if(Btm != NULL) + { + Pos = Btm + 1; + Btm = strchr(Pos, '|'); + if(Btm != NULL) + { + Pos = Btm + 1; + Btm = strchr(Pos, '|'); + if(Btm != NULL) + { + if((Btm - Pos) <= Max) + { + if((Btm - Pos) > 0) + { + strncpy(Adrs, Pos, Btm - Pos); + *(Adrs + (Btm - Pos)) = NUL; + } + else + { + i = sizeof(SockAddr); + if(getpeername(Skt, (struct sockaddr*)&SockAddr, &i) != SOCKET_ERROR) + AddressToStringIPv6(Adrs, &SockAddr.sin6_addr); + } + + Pos = Btm + 1; + Btm = strchr(Pos, '|'); + if(Btm != NULL) + { + Btm++; + *Port = atoi(Pos); + Btm = strchr(Btm, ')'); + if(Btm != NULL) + Sts = FFFTP_SUCCESS; + } + } + } + } + } + } + return(Sts); +} + + +/*----- Windowsのスペシャルデバイスかどうかを返す ----------------------------- * * Parameter -* char *Fname : ƒtƒ@ƒCƒ‹–¼ +* char *Fname : ファイル名 * * Return Value -* int ƒXƒe[ƒ^ƒX (YES/NO) +* int ステータス (YES/NO) *----------------------------------------------------------------------------*/ static int IsSpecialDevice(char *Fname) @@ -2668,20 +4076,34 @@ static int IsSpecialDevice(char *Fname) int Sts; Sts = NO; - if((_stricmp(Fname, "CON") == 0) || - (_stricmp(Fname, "PRN") == 0) || - (_stricmp(Fname, "AUX") == 0) || - (_strnicmp(Fname, "CON.", 4) == 0) || - (_strnicmp(Fname, "PRN.", 4) == 0) || - (_strnicmp(Fname, "AUX.", 4) == 0)) + // 比較が不完全なバグ修正 +// if((_stricmp(Fname, "CON") == 0) || +// (_stricmp(Fname, "PRN") == 0) || +// (_stricmp(Fname, "AUX") == 0) || +// (_strnicmp(Fname, "CON.", 4) == 0) || +// (_strnicmp(Fname, "PRN.", 4) == 0) || +// (_strnicmp(Fname, "AUX.", 4) == 0)) +// { +// Sts = YES; +// } + if(_strnicmp(Fname, "AUX", 3) == 0|| _strnicmp(Fname, "CON", 3) == 0 || _strnicmp(Fname, "NUL", 3) == 0 || _strnicmp(Fname, "PRN", 3) == 0) { - Sts = YES; + if(*(Fname + 3) == '\0' || *(Fname + 3) == '.') + Sts = YES; + } + else if(_strnicmp(Fname, "COM", 3) == 0 || _strnicmp(Fname, "LPT", 3) == 0) + { + if(isdigit(*(Fname + 3)) != 0) + { + if(*(Fname + 4) == '\0' || *(Fname + 4) == '.') + Sts = YES; + } } return(Sts); } -/*----- ƒ~ƒ‰[ƒŠƒ“ƒO‚ł̃tƒ@ƒCƒ‹íœŠm”F -------------------------------------- +/*----- ミラーリングでのファイル削除確認 -------------------------------------- * * Parameter * int Cur @@ -2716,19 +4138,21 @@ static int MirrorDelNotify(int Cur, int Notify, TRANSPACKET *Pkt) } -/*----- ƒ~ƒ‰[ƒŠƒ“ƒO‚ł̃tƒ@ƒCƒ‹íœƒ_ƒCƒAƒƒO‚̃R[ƒ‹ƒoƒbƒN ------------------ +/*----- ミラーリングでのファイル削除ダイアログのコールバック ------------------ * * Parameter -* HWND hDlg : ƒEƒCƒ“ƒhƒEƒnƒ“ƒhƒ‹ -* UINT message : ƒƒbƒZ[ƒW”ԍ† -* WPARAM wParam : ƒƒbƒZ[ƒW‚Ì WPARAM ˆø” -* LPARAM lParam : ƒƒbƒZ[ƒW‚Ì LPARAM ˆø” +* HWND hDlg : ウインドウハンドル +* UINT message : メッセージ番号 +* WPARAM wParam : メッセージの WPARAM 引数 +* LPARAM lParam : メッセージの LPARAM 引数 * * Return Value * BOOL TRUE/FALSE *----------------------------------------------------------------------------*/ -static BOOL CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) +// 64ビット対応 +//static BOOL CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) +static INT_PTR CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) { static MIRRORDELETEINFO *DelInfo; switch (iMessage) @@ -2781,10 +4205,14 @@ static void SetErrorMsg(char *fmt, ...) { va_list Args; - if(strlen(ErrMsg) == 0) + // 同時接続対応 +// if(strlen(ErrMsg) == 0) + if(strlen(GetErrMsg()) == 0) { va_start(Args, fmt); - wvsprintf(ErrMsg, fmt, Args); + // 同時接続対応 +// wvsprintf(ErrMsg, fmt, Args); + wvsprintf(GetErrMsg(), fmt, Args); va_end(Args); } return; @@ -2795,13 +4223,13 @@ static void SetErrorMsg(char *fmt, ...) -/*----- ƒ_ƒEƒ“ƒ[ƒhŽž‚Ì•s³‚ȃpƒX‚ðƒ`ƒFƒbƒN ---------------------------------- +/*----- ダウンロード時の不正なパスをチェック ---------------------------------- * * Parameter -* TRANSPACKET *packet : ƒ_ƒEƒ“ƒ[ƒhî•ñ +* TRANSPACKET *packet : ダウンロード情報 * * Return Value -* int YES=•s³‚ȃpƒX/NO=–â‘è‚È‚¢ƒpƒX +* int YES=不正なパス/NO=問題ないパス *----------------------------------------------------------------------------*/ int CheckPathViolation(TRANSPACKET *packet) { @@ -2826,3 +4254,39 @@ int CheckPathViolation(TRANSPACKET *packet) } +// 同時接続対応 +static char* GetErrMsg() +{ + char* r; + DWORD ThreadId; + int i; + r = NULL; + WaitForSingleObject(hErrMsgMutex, INFINITE); + ThreadId = GetCurrentThreadId(); + i = 0; + while(i < MAX_DATA_CONNECTION + 1) + { + if(ErrMsgThreadId[i] == ThreadId) + { + r = ErrMsg[i]; + break; + } + i++; + } + if(!r) + { + i = 0; + while(i < MAX_DATA_CONNECTION + 1) + { + if(ErrMsgThreadId[i] == 0) + { + ErrMsgThreadId[i] = ThreadId; + r = ErrMsg[i]; + break; + } + i++; + } + } + ReleaseMutex(hErrMsgMutex); + return r; +}