X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=filelist.c;h=97da4302057e0bc6dea008f46ffb22b46b5612ee;hb=27179b11319a3068cbf7b1c0d0adae30eba505a0;hp=f2a67afc7a9c9049133ab2e2c79ed8b04f3ba183;hpb=2c07fce2c369fa3199b3e7a3c95e6ff439f66fab;p=ffftp%2Fffftp.git diff --git a/filelist.c b/filelist.c old mode 100644 new mode 100755 index f2a67af..97da430 --- a/filelist.c +++ b/filelist.c @@ -83,24 +83,34 @@ static LRESULT FileListCommonWndProc(HWND hWnd, UINT message, WPARAM wParam, LPA static void AddDispFileList(FLISTANCHOR *Anchor, char *Name, FILETIME *Time, LONGLONG Size, int Attr, int Type, int Link, char *Owner, int InfoExist, int Win); static void EraseDispFileList(FLISTANCHOR *Anchor); static void DispFileList2View(HWND hWnd, FLISTANCHOR *Anchor); -static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, FILETIME *Time, int Attr, char *Owner, int Link, int InfoExist); +// ファイルアイコン表示対応 +//static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, FILETIME *Time, int Attr, char *Owner, int Link, int InfoExist); +static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, FILETIME *Time, int Attr, char *Owner, int Link, int InfoExist, int ImageId); // 64ビット対応 //static BOOL CALLBACK SelectDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK SelectDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); +static int GetImageIndex(int Win, int Pos); static void DispListList(FILELIST *Pos, char *Title); -static void MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork); -static void MakeRemoteTree2(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork); +// ファイル一覧バグ修正 +//static void MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork); +//static void MakeRemoteTree2(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork); +static int MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork); +static int MakeRemoteTree2(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork); static void CopyTmpListToFileList(FILELIST **Base, FILELIST *List); static int GetListOneLine(char *Buf, int Max, FILE *Fd); static int MakeDirPath(char *Str, int ListType, char *Path, char *Dir); -static void MakeLocalTree(char *Path, FILELIST **Base); +// ファイル一覧バグ修正 +//static void MakeLocalTree(char *Path, FILELIST **Base); +static int MakeLocalTree(char *Path, FILELIST **Base); static void AddFileList(FILELIST *Pkt, FILELIST **Base); -static int AnalizeFileInfo(char *Str); +static int AnalyzeFileInfo(char *Str); static int CheckUnixType(char *Str, char *Tmp, int Add1, int Add2, int Day); static int CheckHHMMformat(char *Str); static int CheckYYMMDDformat(char *Str, char Sym, int Dig3); static int CheckYYYYMMDDformat(char *Str, char Sym); -static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, FILETIME *Time, int *Attr, char *Owner, int *Link, int *InfoExist); +// Windows Server 2008 R2 +static int CheckMMDDYYYYformat(char *Str, char Sym); +static int ResolveFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, FILETIME *Time, int *Attr, char *Owner, int *Link, int *InfoExist); static int FindField(char *Str, char *Buf, int Num, int ToLast); // MLSD対応 static int FindField2(char *Str, char *Buf, char Separator, int Num, int ToLast); @@ -122,6 +132,10 @@ extern int RemoteWidth; extern int ListHeight; extern char FilterStr[FILTER_EXT_LEN+1]; extern HWND hHelpWin; +// 外部アプリケーションへドロップ後にローカル側のファイル一覧に作業フォルダが表示されるバグ対策 +extern int SuppressRefresh; +// ローカル側自動更新 +extern HANDLE ChangeNotification; /* 設定値 */ extern int LocalWidth; @@ -135,6 +149,12 @@ extern int DotFile; extern int DispIgnoreHide; extern int DispDrives; extern int MoveMode; +// ファイルアイコン表示対応 +extern int DispFileIcon; +// タイムスタンプのバグ修正 +extern int DispTimeSeconds; +// ファイルの属性を数字で表示 +extern int DispPermissionsNumber; /*===== ローカルなワーク =====*/ @@ -145,6 +165,8 @@ static WNDPROC LocalProcPtr; static WNDPROC RemoteProcPtr; static HIMAGELIST ListImg = NULL; +// ファイルアイコン表示対応 +static HIMAGELIST ListImgFileIcon = NULL; static char FindStr[40+1] = { "*" }; /* 検索文字列 */ static int IgnoreNew = NO; @@ -179,12 +201,21 @@ int MakeListWin(HWND hWnd, HINSTANCE hInst) LV_COLUMN LvCol; long Tmp; + // 変数が未初期化のバグ修正 + memset(&LvCol, 0, sizeof(LV_COLUMN)); + /*===== ローカル側のリストビュー =====*/ + // 高DPI対応 +// hWndListLocal = CreateWindowEx(/*WS_EX_STATICEDGE*/WS_EX_CLIENTEDGE, +// WC_LISTVIEWA, NULL, +// WS_CHILD | /*WS_BORDER | */LVS_REPORT | LVS_SHOWSELALWAYS, +// 0, TOOLWIN_HEIGHT*2, LocalWidth, ListHeight, +// GetMainHwnd(), (HMENU)1500, hInst, NULL); hWndListLocal = CreateWindowEx(/*WS_EX_STATICEDGE*/WS_EX_CLIENTEDGE, WC_LISTVIEWA, NULL, WS_CHILD | /*WS_BORDER | */LVS_REPORT | LVS_SHOWSELALWAYS, - 0, TOOLWIN_HEIGHT*2, LocalWidth, ListHeight, + 0, AskToolWinHeight()*2, LocalWidth, ListHeight, GetMainHwnd(), (HMENU)1500, hInst, NULL); if(hWndListLocal != NULL) @@ -232,10 +263,16 @@ int MakeListWin(HWND hWnd, HINSTANCE hInst) /*===== ホスト側のリストビュー =====*/ + // 高DPI対応 +// hWndListRemote = CreateWindowEx(/*WS_EX_STATICEDGE*/WS_EX_CLIENTEDGE, +// WC_LISTVIEWA, NULL, +// WS_CHILD | /*WS_BORDER | */LVS_REPORT | LVS_SHOWSELALWAYS, +// LocalWidth + SepaWidth, TOOLWIN_HEIGHT*2, RemoteWidth, ListHeight, +// GetMainHwnd(), (HMENU)1500, hInst, NULL); hWndListRemote = CreateWindowEx(/*WS_EX_STATICEDGE*/WS_EX_CLIENTEDGE, WC_LISTVIEWA, NULL, WS_CHILD | /*WS_BORDER | */LVS_REPORT | LVS_SHOWSELALWAYS, - LocalWidth + SepaWidth, TOOLWIN_HEIGHT*2, RemoteWidth, ListHeight, + LocalWidth + SepaWidth, AskToolWinHeight()*2, RemoteWidth, ListHeight, GetMainHwnd(), (HMENU)1500, hInst, NULL); if(hWndListRemote != NULL) @@ -491,6 +528,11 @@ static void doTransferRemoteFile(void) remove(fn); } + // 同時接続対応 + DisableUserOpe(); + // 外部アプリケーションへドロップ後にローカル側のファイル一覧に作業フォルダが表示されるバグ対策 + SuppressRefresh = 1; + // ダウンロード先をテンポラリに設定 SetLocalDirHist(TmpDir); @@ -522,6 +564,12 @@ static void doTransferRemoteFile(void) SetLocalDirHist(LocDir); SetCurrentDirAsDirHist(); + // 外部アプリケーションへドロップ後にローカル側のファイル一覧に作業フォルダが表示されるバグ対策 + SuppressRefresh = 0; + GetLocalDirForWnd(); + // 同時接続対応 + EnableUserOpe(); + remoteFileListBase = FileListBase; // あとでフリーすること remoteFileListBaseNoExpand = FileListBaseNoExpand; // あとでフリーすること strncpy_s(remoteFileDir, sizeof(remoteFileDir), TmpDir, _TRUNCATE); @@ -784,6 +832,9 @@ static LRESULT FileListCommonWndProc(HWND hWnd, UINT message, WPARAM wParam, LPA return(CallWindowProc(ProcPtr, hWnd, message, wParam, lParam)); case WM_DROPFILES : + // 同時接続対応 + if(AskUserOpeDisabled() == YES) + break; // ドラッグ中は処理しない。ドラッグ後にWM_LBUTTONDOWNが飛んでくるため、そこで処理する。 if (Dragging == YES) return (FALSE); @@ -791,7 +842,7 @@ static LRESULT FileListCommonWndProc(HWND hWnd, UINT message, WPARAM wParam, LPA if(hWnd == hWndListRemote) { if(AskConnecting() == YES) - UpLoadDragProc(wParam); + UploadDragProc(wParam); } else if(hWnd == hWndListLocal) { @@ -816,6 +867,9 @@ static LRESULT FileListCommonWndProc(HWND hWnd, UINT message, WPARAM wParam, LPA hCsrDrg = LoadCursor(NULL, IDC_ARROW); SetCursor(hCsrDrg); + // 同時接続対応 + if(AskUserOpeDisabled() == YES) + break; Point.x = (long)(short)LOWORD(lParam); Point.y = (long)(short)HIWORD(lParam); ClientToScreen(hWnd, &Point); @@ -896,6 +950,11 @@ static LRESULT FileListCommonWndProc(HWND hWnd, UINT message, WPARAM wParam, LPA } +#if defined(HAVE_TANDEM) + if(FileListBaseNoExpand == NULL) + pf = FileListBase; + else +#endif pf = FileListBaseNoExpand; for (filenum = 0; pf ; filenum++) { pf = pf->Next; @@ -1110,6 +1169,9 @@ void GetListTabWidth(void) LV_COLUMN LvCol; int i; + // 変数が未初期化のバグ修正 + memset(&LvCol, 0, sizeof(LV_COLUMN)); + for(i = 0; i <= 3; i++) { LvCol.mask = LVCF_WIDTH; @@ -1258,9 +1320,9 @@ void GetRemoteDirForWnd(int Mode, int *CancelCheckWork) while(GetListOneLine(Str, FMAX_PATH, fd) == FFFTP_SUCCESS) { - if((ListType = AnalizeFileInfo(Str)) != LIST_UNKNOWN) + if((ListType = AnalyzeFileInfo(Str)) != LIST_UNKNOWN) { - if((Type = ResolvFileInfo(Str, ListType, Buf, &Size, &Time, &Attr, Owner, &Link, &InfoExist)) != NODE_NONE) + if((Type = ResolveFileInfo(Str, ListType, Buf, &Size, &Time, &Attr, Owner, &Link, &InfoExist)) != NODE_NONE) { if(AskFilterStr(Buf, Type) == YES) { @@ -1318,6 +1380,64 @@ void GetRemoteDirForWnd(int Mode, int *CancelCheckWork) * なし *----------------------------------------------------------------------------*/ +// ファイルアイコン表示対応 +void RefreshIconImageList(FLISTANCHOR *Anchor) +{ + HBITMAP hBitmap; + int ImageId; + FILELIST *Pos; + int i; + char Cur[FMAX_PATH+1]; + SHFILEINFO FileInfo; + if(DispFileIcon == YES) + { + SendMessage(hWndListLocal, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)NULL); + ShowWindow(hWndListLocal, SW_SHOW); + SendMessage(hWndListRemote, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)NULL); + ShowWindow(hWndListRemote, SW_SHOW); + ImageList_Destroy(ListImgFileIcon); + ListImgFileIcon = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 0, 1); + hBitmap = LoadBitmap(GetFtpInst(), MAKEINTRESOURCE(dirattr16_bmp)); + ImageList_AddMasked(ListImgFileIcon, hBitmap, RGB(255, 0, 0)); + DeleteObject(hBitmap); + ImageId = 0; + Pos = Anchor->Top; + for(i = 0; i < Anchor->Files; i++) + { + Pos->ImageId = -1; + if(Pos->Node == NODE_DRIVE) + strcpy(Cur, Pos->File); + else + { + AskLocalCurDir(Cur, FMAX_PATH); + SetYenTail(Cur); + strcat(Cur, Pos->File); + } + if(SHGetFileInfo(Cur, 0, &FileInfo, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON) != 0) + { + if(ImageList_AddIcon(ListImgFileIcon, FileInfo.hIcon) >= 0) + { + Pos->ImageId = ImageId; + ImageId++; + } + DestroyIcon(FileInfo.hIcon); + } + Pos = Pos->Next; + } + SendMessage(hWndListLocal, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ListImgFileIcon); + ShowWindow(hWndListLocal, SW_SHOW); + SendMessage(hWndListRemote, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ListImgFileIcon); + ShowWindow(hWndListRemote, SW_SHOW); + } + else + { + SendMessage(hWndListLocal, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ListImg); + ShowWindow(hWndListLocal, SW_SHOW); + SendMessage(hWndListRemote, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ListImg); + ShowWindow(hWndListRemote, SW_SHOW); + } +} + void GetLocalDirForWnd(void) { HANDLE fHnd; @@ -1337,6 +1457,11 @@ void GetLocalDirForWnd(void) SetLocalDirHist(Scan); DispLocalFreeSpace(Scan); + // ローカル側自動更新 + if(ChangeNotification != INVALID_HANDLE_VALUE) + FindCloseChangeNotification(ChangeNotification); + ChangeNotification = FindFirstChangeNotification(Scan, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE); + /* ディレクトリ/ファイル */ SetYenTail(Scan); @@ -1370,7 +1495,7 @@ void GetLocalDirForWnd(void) if(DispDrives) { GetLogicalDriveStrings(FMAX_PATH, Scan); - NoDrives = LoadHideDriveListRegistory(); + NoDrives = LoadHideDriveListRegistry(); Pos = Scan; while(*Pos != NUL) @@ -1386,6 +1511,8 @@ void GetLocalDirForWnd(void) } } + // ファイルアイコン表示対応 + RefreshIconImageList(&Anchor); DispFileList2View(GetLocalHwnd(), &Anchor); EraseDispFileList(&Anchor); @@ -1450,15 +1577,36 @@ static void AddDispFileList(FLISTANCHOR *Anchor, char *Name, FILETIME *Time, LON if((Sort & SORT_GET_ORD) == SORT_ASCENT) { - if((((Sort & SORT_MASK_ORD) == SORT_EXT) && - ((Cmp = _mbsicmp(GetFileExt(Name), GetFileExt(Pos->File))) < 0)) || - (((Sort & SORT_MASK_ORD) == SORT_SIZE) && - ((Cmp = Size - Pos->Size) < 0)) || - (((Sort & SORT_MASK_ORD) == SORT_DATE) && - ((Cmp = CompareFileTime(Time, &Pos->Time)) < 0))) - { + // 読みにくいのでリファクタリング +// if((((Sort & SORT_MASK_ORD) == SORT_EXT) && +// ((Cmp = _mbsicmp(GetFileExt(Name), GetFileExt(Pos->File))) < 0)) || +//#if defined(HAVE_TANDEM) +// ((AskHostType() == HTYPE_TANDEM) && +// ((Sort & SORT_MASK_ORD) == SORT_EXT) && +// ((Cmp = Attr - Pos->Attr) < 0)) || +//#endif +// (((Sort & SORT_MASK_ORD) == SORT_SIZE) && +// ((Cmp = Size - Pos->Size) < 0)) || +// (((Sort & SORT_MASK_ORD) == SORT_DATE) && +// ((Cmp = CompareFileTime(Time, &Pos->Time)) < 0))) +// { +// break; +// } + if(((Sort & SORT_MASK_ORD) == SORT_EXT) && + ((Cmp = _mbsicmp(GetFileExt(Name), GetFileExt(Pos->File))) < 0)) + break; +#if defined(HAVE_TANDEM) + if((AskHostType() == HTYPE_TANDEM) && + ((Sort & SORT_MASK_ORD) == SORT_EXT) && + ((Cmp = Attr - Pos->Attr) < 0)) + break; +#endif + if(((Sort & SORT_MASK_ORD) == SORT_SIZE) && + ((Cmp = Size - Pos->Size) < 0)) + break; + if(((Sort & SORT_MASK_ORD) == SORT_DATE) && + ((Cmp = CompareFileTime(Time, &Pos->Time)) < 0)) break; - } if(((Sort & SORT_MASK_ORD) == SORT_NAME) || (Cmp == 0)) { @@ -1468,15 +1616,36 @@ static void AddDispFileList(FLISTANCHOR *Anchor, char *Name, FILETIME *Time, LON } else { + // 読みにくいのでリファクタリング +// if((((Sort & SORT_MASK_ORD) == SORT_EXT) && +// ((Cmp = _mbsicmp(GetFileExt(Name), GetFileExt(Pos->File))) > 0)) || +//#if defined(HAVE_TANDEM) +// ((AskHostType() == HTYPE_TANDEM) && +// ((Sort & SORT_MASK_ORD) == SORT_EXT) && +// ((Cmp = Attr - Pos->Attr) > 0)) || +//#endif +// (((Sort & SORT_MASK_ORD) == SORT_SIZE) && +// ((Cmp = Size - Pos->Size) > 0)) || +// (((Sort & SORT_MASK_ORD) == SORT_DATE) && +// ((Cmp = CompareFileTime(Time, &Pos->Time)) > 0))) +// { +// break; +// } if((((Sort & SORT_MASK_ORD) == SORT_EXT) && - ((Cmp = _mbsicmp(GetFileExt(Name), GetFileExt(Pos->File))) > 0)) || - (((Sort & SORT_MASK_ORD) == SORT_SIZE) && - ((Cmp = Size - Pos->Size) > 0)) || - (((Sort & SORT_MASK_ORD) == SORT_DATE) && - ((Cmp = CompareFileTime(Time, &Pos->Time)) > 0))) - { + ((Cmp = _mbsicmp(GetFileExt(Name), GetFileExt(Pos->File))) > 0))) + break; +#if defined(HAVE_TANDEM) + if(((AskHostType() == HTYPE_TANDEM) && + ((Sort & SORT_MASK_ORD) == SORT_EXT) && + ((Cmp = Attr - Pos->Attr) > 0))) + break; +#endif + if(((Sort & SORT_MASK_ORD) == SORT_SIZE) && + ((Cmp = Size - Pos->Size) > 0)) + break; + if(((Sort & SORT_MASK_ORD) == SORT_DATE) && + ((Cmp = CompareFileTime(Time, &Pos->Time)) > 0)) break; - } if(((Sort & SORT_MASK_ORD) == SORT_NAME) || (Cmp == 0)) { @@ -1565,7 +1734,9 @@ static void DispFileList2View(HWND hWnd, FLISTANCHOR *Anchor) Pos = Anchor->Top; for(i = 0; i < Anchor->Files; i++) { - AddListView(hWnd, -1, Pos->File, Pos->Node, Pos->Size, &Pos->Time, Pos->Attr, Pos->Owner, Pos->Link, Pos->InfoExist); + // ファイルアイコン表示対応 +// AddListView(hWnd, -1, Pos->File, Pos->Node, Pos->Size, &Pos->Time, Pos->Attr, Pos->Owner, Pos->Link, Pos->InfoExist); + AddListView(hWnd, -1, Pos->File, Pos->Node, Pos->Size, &Pos->Time, Pos->Attr, Pos->Owner, Pos->Link, Pos->InfoExist, Pos->ImageId); Pos = Pos->Next; } @@ -1595,7 +1766,9 @@ static void DispFileList2View(HWND hWnd, FLISTANCHOR *Anchor) * なし *----------------------------------------------------------------------------*/ -static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, FILETIME *Time, int Attr, char *Owner, int Link, int InfoExist) +// ファイルアイコン表示対応 +//static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, FILETIME *Time, int Attr, char *Owner, int Link, int InfoExist) +static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, FILETIME *Time, int Attr, char *Owner, int Link, int InfoExist, int ImageId) { LV_ITEM LvItem; char Tmp[20]; @@ -1603,6 +1776,8 @@ static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, if(Pos == -1) Pos = SendMessage(hWnd, LVM_GETITEMCOUNT, 0, 0); + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); /* アイコン/ファイル名 */ LvItem.mask = LVIF_TEXT | LVIF_IMAGE; LvItem.iItem = Pos; @@ -1614,10 +1789,15 @@ static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, LvItem.iImage = Type; else LvItem.iImage = 4; + // ファイルアイコン表示対応 + if(DispFileIcon == YES && hWnd == GetLocalHwnd()) + LvItem.iImage = ImageId + 5; LvItem.iItem = SendMessage(hWnd, LVM_INSERTITEM, 0, (LPARAM)&LvItem); /* 日付/時刻 */ - FileTime2TimeString(Time, Tmp, DISPFORM_LEGACY, InfoExist); + // タイムスタンプのバグ修正 +// FileTime2TimeString(Time, Tmp, DISPFORM_LEGACY, InfoExist); + FileTime2TimeString(Time, Tmp, DISPFORM_LEGACY, InfoExist, DispTimeSeconds); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 1; @@ -1643,6 +1823,12 @@ static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 3; +#if defined(HAVE_TANDEM) + if (AskHostType() == HTYPE_TANDEM) { + _itoa_s(Attr, Tmp, sizeof(Tmp), 10); + LvItem.pszText = Tmp; + } else +#endif LvItem.pszText = GetFileExt(Name); LvItem.iItem = SendMessage(hWnd, LVM_SETITEM, 0, (LPARAM)&LvItem); @@ -1650,8 +1836,14 @@ static void AddListView(HWND hWnd, int Pos, char *Name, int Type, LONGLONG Size, { /* 属性 */ strcpy(Tmp, ""); +#if defined(HAVE_TANDEM) + if((InfoExist & FINFO_ATTR) && (AskHostType() != HTYPE_TANDEM)) +#else if(InfoExist & FINFO_ATTR) - AttrValue2String(Attr, Tmp); +#endif + // ファイルの属性を数字で表示 +// AttrValue2String(Attr, Tmp); + AttrValue2String(Attr, Tmp, DispPermissionsNumber); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 4; @@ -1698,7 +1890,9 @@ void ReSortDispList(int Win, int *CancelCheckWork) * なし *----------------------------------------------------------------------------*/ -void SelectFileInList(HWND hWnd, int Type) +// ローカル側自動更新 +//void SelectFileInList(HWND hWnd, int Type) +void SelectFileInList(HWND hWnd, int Type, FILELIST *Base) { int Win; int WinDst; @@ -1712,6 +1906,8 @@ void SelectFileInList(HWND hWnd, int Type) FILETIME Time2; int Find; + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); Win = WIN_LOCAL; WinDst = WIN_REMOTE; if(hWnd == GetRemoteHwnd()) @@ -1814,6 +2010,22 @@ void SelectFileInList(HWND hWnd, int Type) } } break; + + // ローカル側自動更新 + case SELECT_LIST : + for(i = 0; i < Num; i++) + { + LvItem.state = 0; + GetNodeName(Win, i, Name, FMAX_PATH); + if(SearchFileList(Name, Base, COMP_STRICT) != NULL) + LvItem.state = LVIS_SELECTED; + LvItem.mask = LVIF_STATE; + LvItem.iItem = i; + LvItem.stateMask = LVIS_SELECTED; + LvItem.iSubItem = 0; + SendMessage(hWnd, LVM_SETITEMSTATE, i, (LPARAM)&LvItem); + } + break; } return; } @@ -1892,6 +2104,8 @@ void FindFileInList(HWND hWnd, int Type) LV_ITEM LvItem; char *Title; + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); Win = WIN_LOCAL; Title = MSGJPN050; if(hWnd == GetRemoteHwnd()) @@ -2153,6 +2367,58 @@ int GetNextSelected(int Win, int Pos, int All) } +// ローカル側自動更新 +int GetHotSelected(int Win, char *Fname) +{ + HWND hWnd; + int Pos; + + hWnd = GetLocalHwnd(); + if(Win == WIN_REMOTE) + hWnd = GetRemoteHwnd(); + + Pos = SendMessage(hWnd, LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)MAKELPARAM(LVNI_FOCUSED, 0)); + if(Pos != -1) + GetNodeName(Win, Pos, Fname, FMAX_PATH); + + return Pos; +} + +int SetHotSelected(int Win, char *Fname) +{ + HWND hWnd; + int i; + int Num; + char Name[FMAX_PATH+1]; + LV_ITEM LvItem; + int Pos; + + hWnd = GetLocalHwnd(); + if(Win == WIN_REMOTE) + hWnd = GetRemoteHwnd(); + + Num = GetItemCount(Win); + memset(&LvItem, 0, sizeof(LV_ITEM)); + Pos = -1; + for(i = 0; i < Num; i++) + { + LvItem.state = 0; + GetNodeName(Win, i, Name, FMAX_PATH); + if(_mbscmp(Fname, Name) == 0) + { + Pos = i; + LvItem.state = LVIS_FOCUSED; + } + LvItem.mask = LVIF_STATE; + LvItem.iItem = i; + LvItem.stateMask = LVIS_FOCUSED; + LvItem.iSubItem = 0; + SendMessage(hWnd, LVM_SETITEMSTATE, i, (LPARAM)&LvItem); + } + + return Pos; +} + /*----- 指定された名前のアイテムを探す ---------------------------------------- * * Parameter @@ -2173,6 +2439,8 @@ int FindNameNode(int Win, char *Name) if(Win == WIN_REMOTE) hWnd = GetRemoteHwnd(); + // 変数が未初期化のバグ修正 + memset(&FindInfo, 0, sizeof(LV_FINDINFO)); FindInfo.flags = LVFI_STRING; FindInfo.psz = Name; return(SendMessage(hWnd, LVM_FINDITEM, -1, (LPARAM)&FindInfo)); @@ -2200,6 +2468,8 @@ void GetNodeName(int Win, int Pos, char *Buf, int Max) if(Win == WIN_REMOTE) hWnd = GetRemoteHwnd(); + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 0; @@ -2233,6 +2503,8 @@ int GetNodeTime(int Win, int Pos, FILETIME *Buf) if(Win == WIN_REMOTE) hWnd = GetRemoteHwnd(); + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 1; @@ -2267,6 +2539,8 @@ int GetNodeSize(int Win, int Pos, LONGLONG *Buf) if(Win == WIN_REMOTE) hWnd = GetRemoteHwnd(); + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 2; @@ -2275,6 +2549,13 @@ int GetNodeSize(int Win, int Pos, LONGLONG *Buf) SendMessage(hWnd, LVM_GETITEM, 0, (LPARAM)&LvItem); *Buf = -1; Ret = NO; +#if defined(HAVE_TANDEM) + if(AskHostType() == HTYPE_TANDEM) { + RemoveComma(Tmp); + *Buf = _atoi64(Tmp); + Ret = YES; + } else +#endif if(strlen(Tmp) > 0) { RemoveComma(Tmp); @@ -2307,14 +2588,26 @@ int GetNodeAttr(int Win, int Pos, int *Buf) Ret = NO; if(Win == WIN_REMOTE) { + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; +#if defined(HAVE_TANDEM) + if(AskHostType() == HTYPE_TANDEM) + LvItem.iSubItem = 3; + else +#endif LvItem.iSubItem = 4; LvItem.pszText = Tmp; LvItem.cchTextMax = 20; SendMessage(GetRemoteHwnd(), LVM_GETITEM, 0, (LPARAM)&LvItem); if(strlen(Tmp) > 0) { +#if defined(HAVE_TANDEM) + if(AskHostType() == HTYPE_TANDEM) + *Buf = atoi(Tmp); + else +#endif *Buf = AttrString2Value(Tmp); Ret = YES; } @@ -2344,6 +2637,8 @@ int GetNodeType(int Win, int Pos) if(Win == WIN_REMOTE) hWnd = GetRemoteHwnd(); + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 2; @@ -2362,6 +2657,35 @@ int GetNodeType(int Win, int Pos) } +/*----- 指定位置のアイテムのイメージ番号を返す ---------------------------------------- +* +* Parameter +* int Win : ウインドウ番号 (WIN_xxx) +* int Pos : 位置 +* +* Return Value +* int イメージ番号 +* 4 Symlink +*----------------------------------------------------------------------------*/ +static int GetImageIndex(int Win, int Pos) +{ + HWND hWnd; + LV_ITEM LvItem; + + hWnd = GetLocalHwnd(); + if(Win == WIN_REMOTE) + hWnd = GetRemoteHwnd(); + + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); + LvItem.mask = LVIF_IMAGE; + LvItem.iItem = Pos; + LvItem.iSubItem = 0; + SendMessage(hWnd, LVM_GETITEM, 0, (LPARAM)&LvItem); + return LvItem.iImage; +} + + /*----- 指定位置のアイテムのオーナ名を返す ------------------------------------ * * Parameter @@ -2381,6 +2705,8 @@ void GetNodeOwner(int Win, int Pos, char *Buf, int Max) strcpy(Buf, ""); if(Win == WIN_REMOTE) { + // 変数が未初期化のバグ修正 + memset(&LvItem, 0, sizeof(LV_ITEM)); LvItem.mask = LVIF_TEXT; LvItem.iItem = Pos; LvItem.iSubItem = 5; @@ -2459,8 +2785,12 @@ double GetSelectedTotalSize(int Win) * なし *----------------------------------------------------------------------------*/ -void MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *CancelCheckWork) +// ファイル一覧バグ修正 +//void MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *CancelCheckWork) +int MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *CancelCheckWork) { + // ファイル一覧バグ修正 + int Sts; int Pos; char Name[FMAX_PATH+1]; char Cur[FMAX_PATH+1]; @@ -2469,6 +2799,8 @@ void MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *Ca DWORD Attr; int Ignore; + // ファイル一覧バグ修正 + Sts = FFFTP_SUCCESS; if((All == YES) || (GetSelectedCount(Win) > 0)) { /*===== カレントディレクトリのファイル =====*/ @@ -2480,6 +2812,9 @@ void MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *Ca if((Node == NODE_FILE) || ((Expand == NO) && (Node == NODE_DIR))) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + Pkt.InfoExist = 0; GetNodeName(Win, Pos, Pkt.File, FMAX_PATH); if(GetNodeSize(Win, Pos, &Pkt.Size) == YES) @@ -2516,6 +2851,9 @@ void MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *Ca { if(GetNodeType(Win, Pos) == NODE_DIR) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + GetNodeName(Win, Pos, Name, FMAX_PATH); strcpy(Pkt.File, Name); ReplaceAll(Pkt.File, '\\', '/'); @@ -2535,26 +2873,59 @@ void MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *Ca if(Ignore == NO) { - Pkt.Node = NODE_DIR; +// Pkt.Node = NODE_DIR; + if(GetImageIndex(Win, Pos) == 4) // symlink + Pkt.Node = NODE_FILE; + else + Pkt.Node = NODE_DIR; Pkt.Attr = 0; Pkt.Size = 0; memset(&Pkt.Time, 0, sizeof(FILETIME)); AddFileList(&Pkt, Base); - if(Win == WIN_LOCAL) - MakeLocalTree(Name, Base); - else - { - AskRemoteCurDir(Cur, FMAX_PATH); - - if((AskListCmdMode() == NO) && - (AskUseNLST_R() == YES)) - MakeRemoteTree1(Name, Cur, Base, CancelCheckWork); +// if(Win == WIN_LOCAL) +// MakeLocalTree(Name, Base); +// else +// { +// AskRemoteCurDir(Cur, FMAX_PATH); +// +// if((AskListCmdMode() == NO) && +// (AskUseNLST_R() == YES)) +// MakeRemoteTree1(Name, Cur, Base, CancelCheckWork); +// else +// MakeRemoteTree2(Name, Cur, Base, CancelCheckWork); +// } + if(GetImageIndex(Win, Pos) != 4) { // symlink + if(Win == WIN_LOCAL) + // ファイル一覧バグ修正 +// MakeLocalTree(Name, Base); + { + if(MakeLocalTree(Name, Base) == FFFTP_FAIL) + Sts = FFFTP_FAIL; + } else - MakeRemoteTree2(Name, Cur, Base, CancelCheckWork); + { + AskRemoteCurDir(Cur, FMAX_PATH); + + if((AskListCmdMode() == NO) && + (AskUseNLST_R() == YES)) + // ファイル一覧バグ修正 +// MakeRemoteTree1(Name, Cur, Base, CancelCheckWork); + { + if(MakeRemoteTree1(Name, Cur, Base, CancelCheckWork) == FFFTP_FAIL) + Sts = FFFTP_FAIL; + } + else + // ファイル一覧バグ修正 +// MakeRemoteTree2(Name, Cur, Base, CancelCheckWork); + { + if(MakeRemoteTree2(Name, Cur, Base, CancelCheckWork) == FFFTP_FAIL) + Sts = FFFTP_FAIL; + } //DispListList(*Base, "LIST"); + } } } } @@ -2562,7 +2933,9 @@ void MakeSelectedFileList(int Win, int Expand, int All, FILELIST **Base, int *Ca } } } - return; + // ファイル一覧バグ修正 +// return; + return(Sts); } @@ -2613,14 +2986,26 @@ void MakeDroppedFileList(WPARAM wParam, char *Cur, FILELIST **Base) if((GetFileAttributes(Name) & FILE_ATTRIBUTE_DIRECTORY) == 0) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + Pkt.Node = NODE_FILE; strcpy(Pkt.File, GetFileName(Name)); memset(&Pkt.Time, 0, sizeof(FILETIME)); +#if defined(HAVE_TANDEM) + /* Guardian スペースへのアップロードのためにサイズが必要 */ + Pkt.Size = 0; + Pkt.InfoExist = 0; +#endif if((fHnd = FindFirstFile(Name, &Find)) != INVALID_HANDLE_VALUE) { FindClose(fHnd); Pkt.Time = Find.ftLastWriteTime; +#if defined(HAVE_TANDEM) + Pkt.Size = MakeLongLong(Find.nFileSizeHigh, Find.nFileSizeLow); + Pkt.InfoExist |= (FINFO_TIME | FINFO_DATE | FINFO_SIZE); +#endif } AddFileList(&Pkt, Base); } @@ -2634,6 +3019,9 @@ void MakeDroppedFileList(WPARAM wParam, char *Cur, FILELIST **Base) if(GetFileAttributes(Name) & FILE_ATTRIBUTE_DIRECTORY) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + Pkt.Node = NODE_DIR; strcpy(Pkt.File, GetFileName(Name)); AddFileList(&Pkt, Base); @@ -2686,10 +3074,16 @@ void MakeDroppedDir(WPARAM wParam, char *Cur) * NLST -alLR を使う *----------------------------------------------------------------------------*/ -static void MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork) +// ファイル一覧バグ修正 +//static void MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork) +static int MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork) { + // ファイル一覧バグ修正 + int Ret; int Sts; + // ファイル一覧バグ修正 + Ret = FFFTP_FAIL; if(DoCWD(Path, NO, NO, NO) == FTP_COMPLETE) { /* サブフォルダも含めたリストを取得 */ @@ -2697,9 +3091,16 @@ static void MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelC DoCWD(Cur, NO, NO, NO); if(Sts == FTP_COMPLETE) + // ファイル一覧バグ修正 +// AddRemoteTreeToFileList(999, Path, RDIR_NLST, Base); + { AddRemoteTreeToFileList(999, Path, RDIR_NLST, Base); + Ret = FFFTP_SUCCESS; + } } - return; + // ファイル一覧バグ修正 +// return; + return(Ret); } @@ -2717,13 +3118,19 @@ static void MakeRemoteTree1(char *Path, char *Cur, FILELIST **Base, int *CancelC * 各フォルダに移動してリストを取得 *----------------------------------------------------------------------------*/ -static void MakeRemoteTree2(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork) +// ファイル一覧バグ修正 +//static void MakeRemoteTree2(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork) +static int MakeRemoteTree2(char *Path, char *Cur, FILELIST **Base, int *CancelCheckWork) { + // ファイル一覧バグ修正 + int Ret; int Sts; FILELIST *CurList; FILELIST *Pos; FILELIST Pkt; + // ファイル一覧バグ修正 + Ret = FFFTP_FAIL; /* VAX VMS は CWD xxx/yyy という指定ができないので */ /* CWD xxx, Cwd yyy と複数に分ける */ if(AskHostType() != HTYPE_VMS) @@ -2748,28 +3155,48 @@ static void MakeRemoteTree2(char *Path, char *Cur, FILELIST **Base, int *CancelC AddRemoteTreeToFileList(999, Path, RDIR_CWD, &CurList); CopyTmpListToFileList(Base, CurList); + // ファイル一覧バグ修正 + Ret = FFFTP_SUCCESS; + Pos = CurList; while(Pos != NULL) { if(Pos->Node == NODE_DIR) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + /* まずディレクトリ名をセット */ strcpy(Pkt.File, Pos->File); - Pkt.Node = NODE_DIR; +// Pkt.Node = NODE_DIR; + Pkt.Link = Pos->Link; + if(Pkt.Link == YES) + Pkt.Node = NODE_FILE; + else + Pkt.Node = NODE_DIR; Pkt.Size = 0; Pkt.Attr = 0; memset(&Pkt.Time, 0, sizeof(FILETIME)); AddFileList(&Pkt, Base); /* そのディレクトリの中を検索 */ - MakeRemoteTree2(Pos->File, Cur, Base, CancelCheckWork); +// MakeRemoteTree2(Pos->File, Cur, Base, CancelCheckWork); + if(Pkt.Link == NO) + // ファイル一覧バグ修正 +// MakeRemoteTree2(Pos->File, Cur, Base, CancelCheckWork); + { + if(MakeRemoteTree2(Pos->File, Cur, Base, CancelCheckWork) == FFFTP_FAIL) + Ret = FFFTP_FAIL; + } } Pos = Pos->Next; } DeleteFileList(&CurList); } } - return; + // ファイル一覧バグ修正 +// return; + return(Ret); } @@ -2837,12 +3264,15 @@ void AddRemoteTreeToFileList(int Num, char *Path, int IncDir, FILELIST **Base) while(GetListOneLine(Str, FMAX_PATH, fd) == FFFTP_SUCCESS) { - if((ListType = AnalizeFileInfo(Str)) == LIST_UNKNOWN) + if((ListType = AnalyzeFileInfo(Str)) == LIST_UNKNOWN) { if(MakeDirPath(Str, ListType, Path, Dir) == FFFTP_SUCCESS) { if(IncDir == RDIR_NLST) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + strcpy(Pkt.File, Dir); Pkt.Node = NODE_DIR; Pkt.Size = 0; @@ -2854,13 +3284,16 @@ void AddRemoteTreeToFileList(int Num, char *Path, int IncDir, FILELIST **Base) } else { - Node = ResolvFileInfo(Str, ListType, Name, &Size, &Time, &Attr, Owner, &Link, &InfoExist); + Node = ResolveFileInfo(Str, ListType, Name, &Size, &Time, &Attr, Owner, &Link, &InfoExist); if(AskFilterStr(Name, Node) == YES) { if((Node == NODE_FILE) || ((IncDir == RDIR_CWD) && (Node == NODE_DIR))) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + strcpy(Pkt.File, Dir); if(strlen(Pkt.File) > 0) SetSlashTail(Pkt.File); @@ -3007,14 +3440,21 @@ static int MakeDirPath(char *Str, int ListType, char *Path, char *Dir) * なし *----------------------------------------------------------------------------*/ -static void MakeLocalTree(char *Path, FILELIST **Base) +// ファイル一覧バグ修正 +//static void MakeLocalTree(char *Path, FILELIST **Base) +static int MakeLocalTree(char *Path, FILELIST **Base) { + // ファイル一覧バグ修正 + int Sts; char Src[FMAX_PATH+1]; HANDLE fHnd; WIN32_FIND_DATA FindBuf; FILELIST Pkt; SYSTEMTIME TmpStime; + // ファイル一覧バグ修正 + Sts = FFFTP_FAIL; + strcpy(Src, Path); SetYenTail(Src); strcat(Src, "*"); @@ -3028,6 +3468,9 @@ static void MakeLocalTree(char *Path, FILELIST **Base) { if(AskFilterStr(FindBuf.cFileName, NODE_FILE) == YES) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + strcpy(Pkt.File, Path); SetSlashTail(Pkt.File); strcat(Pkt.File, FindBuf.cFileName); @@ -3037,7 +3480,10 @@ static void MakeLocalTree(char *Path, FILELIST **Base) Pkt.Attr = 0; Pkt.Time = FindBuf.ftLastWriteTime; FileTimeToSystemTime(&Pkt.Time, &TmpStime); - TmpStime.wSecond = 0; + // タイムスタンプのバグ修正 +// TmpStime.wSecond = 0; + if(DispTimeSeconds == NO) + TmpStime.wSecond = 0; TmpStime.wMilliseconds = 0; SystemTimeToFileTime(&TmpStime, &Pkt.Time); AddFileList(&Pkt, Base); @@ -3050,12 +3496,17 @@ static void MakeLocalTree(char *Path, FILELIST **Base) if((fHnd = FindFirstFileAttr(Src, &FindBuf, DispIgnoreHide)) != INVALID_HANDLE_VALUE) { + // ファイル一覧バグ修正 + Sts = FFFTP_SUCCESS; do { if((FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (strcmp(FindBuf.cFileName, ".") != 0) && (strcmp(FindBuf.cFileName, "..") != 0)) { + // 変数が未初期化のバグ修正 + memset(&Pkt, 0, sizeof(FILELIST)); + strcpy(Src, Path); SetYenTail(Src); strcat(Src, FindBuf.cFileName); @@ -3067,13 +3518,18 @@ static void MakeLocalTree(char *Path, FILELIST **Base) memset(&Pkt.Time, 0, sizeof(FILETIME)); AddFileList(&Pkt, Base); - MakeLocalTree(Src, Base); + // ファイル一覧バグ修正 +// MakeLocalTree(Src, Base); + if(MakeLocalTree(Src, Base) == FFFTP_FAIL) + Sts = FFFTP_FAIL; } } while(FindNextFileAttr(fHnd, &FindBuf, DispIgnoreHide) == TRUE); FindClose(fHnd); } - return; + // ファイル一覧バグ修正 +// return; + return(Sts); } @@ -3203,7 +3659,7 @@ FILELIST *SearchFileList(char *Fname, FILELIST *Base, int Caps) * int リストタイプ (LIST_xxx) *----------------------------------------------------------------------------*/ -static int AnalizeFileInfo(char *Str) +static int AnalyzeFileInfo(char *Str) { int Ret; char Tmp[FMAX_PATH+1]; @@ -3233,11 +3689,26 @@ static int AnalizeFileInfo(char *Str) Ret = LIST_SHIBASOKU; else { + // MLSD対応 + if(FindField(Str, Tmp, 0, NO) == FFFTP_SUCCESS) + { + _strlwr(Tmp); + if(strstr(Tmp, "type=") != NULL) + { + if(FindField2(Str, Tmp, ';', 1, NO) == FFFTP_SUCCESS && FindField2(Str, Tmp, '=', 1, NO) == FFFTP_SUCCESS) + { + Ret = LIST_MLSD; + } + } + } + /* 以下のフォーマットをチェック */ /* LIST_UNIX_10, LIST_UNIX_20, LIST_UNIX_12, LIST_UNIX_22, LIST_UNIX_50, LIST_UNIX_60 */ /* MELCOM80 */ - if(FindField(Str, Tmp, 0, NO) == FFFTP_SUCCESS) + // MLSD対応 +// if(FindField(Str, Tmp, 0, NO) == FFFTP_SUCCESS) + if(Ret == LIST_UNKNOWN && FindField(Str, Tmp, 0, NO) == FFFTP_SUCCESS) { /* MELCOM80は "d rwxrwxrwx" のようにスペースが空いている */ Flag1 = NO; @@ -3350,6 +3821,13 @@ static int AnalizeFileInfo(char *Str) if((Ret != LIST_UNKNOWN) && (Flag1 == YES)) Ret |= LIST_MELCOM; + + // uClinux + if((Ret == LIST_UNKNOWN) && + (FindField(Str, Tmp, 5+Add1, NO) == FFFTP_SUCCESS)) + { + Ret = LIST_UNIX_17; + } } } @@ -3496,6 +3974,27 @@ static int AnalizeFileInfo(char *Str) } } + // Windows Server 2008 R2 + if(Ret == LIST_UNKNOWN) + { + if((FindField(Str, Tmp, 1, NO) == FFFTP_SUCCESS) && + (CheckHHMMformat(Tmp) == YES)) + { + if((FindField(Str, Tmp, 2, NO) == FFFTP_SUCCESS) && + ((Tmp[0] == '<') || (IsDigit(Tmp[0]) != 0))) + { + if(FindField(Str, Tmp, 3, NO) == FFFTP_SUCCESS) + { + if((FindField(Str, Tmp, 0, NO) == FFFTP_SUCCESS) && + (CheckMMDDYYYYformat(Tmp, NUL) != 0)) + { + Ret = LIST_DOS_5; + } + } + } + } + } + /* 以下のフォーマットをチェック */ /* LIST_CHAMELEON */ @@ -3651,15 +4150,21 @@ static int AnalizeFileInfo(char *Str) } } } +#if defined(HAVE_TANDEM) + /* 以下のフォーマットをチェック */ + /* LIST_TANDEM */ - // MLSD対応 - if(Ret == LIST_UNKNOWN) - { - if(FindField2(Str, Tmp, ';', 1, NO) == FFFTP_SUCCESS && FindField2(Str, Tmp, '=', 1, NO) == FFFTP_SUCCESS) - { - Ret = LIST_MLSD; + /* OSS の場合は自動判別可能のため Ret == LIST_UNKNOWN のチェックは後 */ + if(AskRealHostType() == HTYPE_TANDEM) { + if(Ret == LIST_UNKNOWN) { + SetOSS(NO); + Ret = LIST_TANDEM; + } else { + SetOSS(YES); } } +#endif + } DoPrintf("ListType=%d", Ret); @@ -3944,6 +4449,26 @@ static int CheckYYYYMMDDformat(char *Str, char Sym) } +// Windows Server 2008 R2 +static int CheckMMDDYYYYformat(char *Str, char Sym) +{ + int Ret; + + Ret = NO; + if((strlen(Str) == 10) && + (IsDigitSym(Str[0], Sym) != 0) && (IsDigitSym(Str[1], Sym) != 0) && + (IsDigit(Str[2]) == 0) && + (IsDigitSym(Str[3], Sym) != 0) && (IsDigitSym(Str[4], Sym) != 0) && + (IsDigit(Str[5]) == 0) && + (IsDigitSym(Str[6], Sym) != 0) && (IsDigitSym(Str[7], Sym) != 0) && + (IsDigitSym(Str[8], Sym) != 0) && (IsDigitSym(Str[9], Sym) != 0)) + { + Ret = YES; + } + return(Ret); +} + + /*----- ファイル情報からファイル名、サイズなどを取り出す ---------------------- * * Parameter @@ -3961,7 +4486,7 @@ static int CheckYYYYMMDDformat(char *Str, char Sym) * int 種類 (NODE_xxxx) *----------------------------------------------------------------------------*/ -static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, FILETIME *Time, int *Attr, char *Owner, int *Link, int *InfoExist) +static int ResolveFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, FILETIME *Time, int *Attr, char *Owner, int *Link, int *InfoExist) { SYSTEMTIME sTime; SYSTEMTIME sTimeNow; @@ -3982,6 +4507,8 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, /* まずクリアしておく */ Ret = NODE_NONE; + // バグ対策 + memset(Fname, NUL, FMAX_PATH+1); *Size = -1; *Attr = 0; *Link = NO; @@ -4090,6 +4617,48 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, } break; + // Windows Server 2008 R2 + case LIST_DOS_5 : + *InfoExist |= (FINFO_TIME | FINFO_DATE | FINFO_SIZE); + + /* 日付 */ + FindField(Str, Buf, 0, NO); + sTime.wMonth = atoi(Buf); + sTime.wDay = atoi(Buf+3); + sTime.wYear = atoi(Buf+6); + + /* 時刻 */ + FindField(Str, Buf, 1, NO); + sTime.wHour = atoi(Buf); + sTime.wMinute = atoi(Buf+3); + sTime.wSecond = 0; + sTime.wMilliseconds = 0; + if(_strnicmp(Buf+5, "AM", 2) == 0) + { + if(sTime.wHour == 12) + sTime.wHour = 0; + } + else if(_strnicmp(Buf+5, "PM", 2) == 0) + { + if(sTime.wHour != 12) + sTime.wHour += 12; + } + SystemTimeToFileTime(&sTime, Time); + SpecificLocalFileTime2FileTime(Time, AskHostTimeZone()); + + /* サイズ */ + FindField(Str, Buf, 2, NO); + *Size = _atoi64(Buf); + + /* 名前 */ + if(FindField(Str, Fname, 3, YES) == FFFTP_SUCCESS) + { + Ret = NODE_FILE; + if(Buf[0] == '<') + Ret = NODE_DIR; + } + break; + case LIST_OS2 : *InfoExist |= (FINFO_DATE | FINFO_SIZE); @@ -4657,6 +5226,152 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, } break; +#if defined(HAVE_TANDEM) + case LIST_TANDEM : + *InfoExist |= (FINFO_TIME | FINFO_DATE | FINFO_SIZE | FINFO_ATTR); + /* Open 中だったらずらす */ + if(FindField(Str, Buf, 1, NO) != FFFTP_SUCCESS) + break; + if (!strncmp(Buf, "O", 1)) { + offs = 1; + } + /* 日付 */ + if(FindField(Str, Buf, 3 + offs, NO) != FFFTP_SUCCESS) + break; + if (Buf[1] == '-') { /* 日付が 1桁 */ + sTime.wYear = Assume1900or2000(atoi(Buf + 6)); + Buf[5] = 0; + GetMonth(Buf+2, &sTime.wMonth, &sTime.wDay); /* wDayは常に0 */ + sTime.wDay = atoi(Buf); + sTime.wDayOfWeek = 0; + } else { + sTime.wYear = Assume1900or2000(atoi(Buf + 7)); + Buf[6] = 0; + GetMonth(Buf+3, &sTime.wMonth, &sTime.wDay); /* wDayは常に0 */ + sTime.wDay = atoi(Buf); + sTime.wDayOfWeek = 0; + } + /* 時刻 */ + FindField(Str, Buf, 4 + offs, NO); + sTime.wHour = atoi(Buf); + sTime.wMinute = atoi(Buf+3); + sTime.wSecond = atoi(Buf+6); + sTime.wMilliseconds = 0; + SystemTimeToFileTime(&sTime, Time); + SpecificLocalFileTime2FileTime(Time, AskHostTimeZone()); + + /* 属性 セキュリティではなく FileCode を保存する */ + FindField(Str, Buf, 1 + offs, NO); + *Attr = atoi(Buf); + /* サイズ */ + FindField(Str, Buf, 2 + offs, NO); + *Size = _atoi64(Buf); + /* オーナ名 */ + if(FindField(Str, Buf, 5 + offs, NO) == FFFTP_SUCCESS) { + if(strncmp(Buf, "Owner", sizeof("Owner"))) { + memset(Owner, NUL, OWNER_NAME_LEN+1); + strncpy(Owner, Buf, OWNER_NAME_LEN); + /* 通常は 255,255 だが、20, 33 などにも対応する */ + /* 最後の文字が , だったら後ろとつなげる */ + if (Buf[strlen(Buf)-1] == ',') { + FindField(Str, Buf, 6 + offs, NO); + strncat(Owner, Buf, OWNER_NAME_LEN - strlen(Buf)); + } + /* ファイル名 */ + if(FindField(Str, Fname, 0, NO) == FFFTP_SUCCESS) { + Ret = NODE_FILE; + } + } + } + break; +#endif + + // MLSD対応 + // 以下の形式に対応 + // fact1=value1;fact2=value2;fact3=value3; filename\r\n + // 不完全な実装のホストが存在するため以下の形式も許容 + // fact1=value1;fact2=value2;fact3=value3 filename\r\n + // fact1=value1;fact2=value2;fact3=value3;filename\r\n + // SymlinkはRFC3659の7.7.4. A More Complex Exampleに + // よるとtype=OS.unix=slink:(target)だが + // ProFTPDはtype=OS.unix=symlink:(target)となる + case LIST_MLSD: + { + int i = 0; + char StrBuf[(FMAX_PATH * 2) + 1]; + char Fact[FMAX_PATH + 1]; + char Name[FMAX_PATH + 1]; + char Value[FMAX_PATH + 1]; + char Value2[FMAX_PATH + 1]; + char* pFileName; + strncpy(StrBuf, Str, FMAX_PATH * 2); + StrBuf[FMAX_PATH * 2] = '\0'; + if((pFileName = strstr(StrBuf, "; ")) != NULL) + { + *pFileName = '\0'; + pFileName += 2; + } + else if((pFileName = strchr(StrBuf, ' ')) != NULL) + { + *pFileName = '\0'; + pFileName++; + } + else if((pFileName = strrchr(StrBuf, ';')) != NULL) + { + *pFileName = '\0'; + pFileName++; + } + if(pFileName != NULL) + strcpy(Fname, pFileName); + while(FindField2(StrBuf, Fact, ';', i, NO) == FFFTP_SUCCESS) + { + if(FindField2(Fact, Name, '=', 0, NO) == FFFTP_SUCCESS && FindField2(Fact, Value, '=', 1, NO) == FFFTP_SUCCESS) + { + if(_stricmp(Name, "type") == 0) + { + if(_stricmp(Value, "dir") == 0) + Ret = NODE_DIR; + else if(_stricmp(Value, "file") == 0) + Ret = NODE_FILE; + else if(_stricmp(Value, "OS.unix") == 0) + if(FindField2(Fact, Value2, '=', 2, NO) == FFFTP_SUCCESS) + if(_stricmp(Value2, "symlink") == 0 || _stricmp(Value2, "slink") == 0) { // ProFTPD is symlink. A example of RFC3659 is slink. + Ret = NODE_DIR; + *Link = YES; + } + } + else if(_stricmp(Name, "size") == 0) + { + *Size = _atoi64(Value); + *InfoExist |= FINFO_SIZE; + } + else if(_stricmp(Name, "modify") == 0) + { + sTime.wYear = atoi_n(Value, 4); + sTime.wMonth = atoi_n(Value + 4, 2); + sTime.wDay = atoi_n(Value + 6, 2); + sTime.wHour = atoi_n(Value + 8, 2); + sTime.wMinute = atoi_n(Value + 10, 2); + sTime.wSecond = atoi_n(Value + 12, 2); + sTime.wMilliseconds = 0; + SystemTimeToFileTime(&sTime, Time); + // 時刻はGMT +// SpecificLocalFileTime2FileTime(Time, AskHostTimeZone()); + *InfoExist |= FINFO_DATE | FINFO_TIME; + } + else if(_stricmp(Name, "UNIX.mode") == 0) + { + *Attr = strtol(Value, NULL, 16); + *InfoExist |= FINFO_ATTR; + } + else if(_stricmp(Name, "UNIX.owner") == 0) + strcpy(Owner, Value); + } + i++; + } + } + break; + case LIST_UNIX_10 : case LIST_UNIX_11 : case LIST_UNIX_12 : @@ -4688,6 +5403,8 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, // case LIST_MELCOM : // linux-ftpd case LIST_UNIX_16 : + // uClinux + case LIST_UNIX_17 : default: /* offsはサイズの位置, offs=0はカラム4 */ offs = 0; @@ -4743,6 +5460,9 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, (ListType == LIST_UNIX_73) || (ListType == LIST_UNIX_16)) offs2 = -1; + // uClinux + if(ListType == LIST_UNIX_17) + offs2 = -3; /* offs3はオーナ名の位置 */ offs3 = 0; @@ -4773,6 +5493,9 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, (ListType == LIST_UNIX_74) || (ListType == LIST_UNIX_75)) Flag2 = 1; + // uClinux + if(ListType == LIST_UNIX_17) + Flag2 = -1; *InfoExist |= (FINFO_DATE | FINFO_SIZE | FINFO_ATTR); @@ -4870,6 +5593,11 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, } } } + // uClinux + else if(Flag2 == -1) + { + *InfoExist &= ~(FINFO_DATE | FINFO_TIME); + } else { /* LIST_UNIX_?4, LIST_UNIX_?5 の時 */ @@ -4922,57 +5650,6 @@ static int ResolvFileInfo(char *Str, int ListType, char *Fname, LONGLONG *Size, Ret = NODE_NONE; } break; - - // MLSD対応 - case LIST_MLSD: - { - int i = 0; - char Tmp[FMAX_PATH + 1]; - char Name[FMAX_PATH + 1]; - char Value[FMAX_PATH + 1]; - while(FindField2(Str, Tmp, ';', i, NO) == FFFTP_SUCCESS) - { - if(i >= 1 && strncmp(Tmp, " ", 1) == 0) - strcpy(Fname, strstr(Str, "; ") + 2); - else if(FindField2(Tmp, Name, '=', 0, NO) == FFFTP_SUCCESS && FindField2(Tmp, Value, '=', 1, NO) == FFFTP_SUCCESS) - { - if(_stricmp(Name, "type") == 0) - { - if(_stricmp(Value, "dir") == 0) - Ret = NODE_DIR; - else if(_stricmp(Value, "file") == 0) - Ret = NODE_FILE; - } - else if(_stricmp(Name, "size") == 0) - { - *Size = _atoi64(Value); - *InfoExist |= FINFO_SIZE; - } - else if(_stricmp(Name, "modify") == 0) - { - sTime.wYear = atoi_n(Value, 4); - sTime.wMonth = atoi_n(Value + 4, 2); - sTime.wDay = atoi_n(Value + 6, 2); - sTime.wHour = atoi_n(Value + 8, 2); - sTime.wMinute = atoi_n(Value + 10, 2); - sTime.wSecond = atoi_n(Value + 12, 2); - sTime.wMilliseconds = 0; - SystemTimeToFileTime(&sTime, Time); -// SpecificLocalFileTime2FileTime(Time, AskHostTimeZone()); - *InfoExist |= FINFO_DATE | FINFO_TIME; - } - else if(_stricmp(Name, "UNIX.mode") == 0) - { - *Attr = strtol(Value, NULL, 16); - *InfoExist |= FINFO_ATTR; - } - else if(_stricmp(Name, "UNIX.owner") == 0) - strcpy(Owner, Value); - } - i++; - } - } - break; } // UTF-8対応 @@ -5550,7 +6227,7 @@ static int atoi_n(const char *Str, int Len) // UTF-8対応 // ファイル一覧から漢字コードを推測 -// 優先度はUTF-8、Shift_JIS、EUC、JISの順 +// 優先度はUTF-8、Shift_JIS、EUC、JIS、UTF-8 HFS+の順 int AnalyzeNameKanjiCode(int Num) { char Str[FMAX_PATH+1]; @@ -5570,7 +6247,11 @@ int AnalyzeNameKanjiCode(int Num) int PointJIS; int PointEUC; int PointUTF8N; + int PointUTF8HFSX; char* p; + CODECONVINFO cInfo1; + CODECONVINFO cInfo2; + char Buf[FMAX_PATH+1]; NameKanjiCode = KANJI_AUTO; Point = 0; @@ -5578,15 +6259,16 @@ int AnalyzeNameKanjiCode(int Num) PointJIS = 0; PointEUC = 0; PointUTF8N = 0; + PointUTF8HFSX = 0; MakeCacheFileName(Num, Str); if((fd = fopen(Str, "rb")) != NULL) { while(GetListOneLine(Str, FMAX_PATH, fd) == FFFTP_SUCCESS) { - if((ListType = AnalizeFileInfo(Str)) != LIST_UNKNOWN) + if((ListType = AnalyzeFileInfo(Str)) != LIST_UNKNOWN) { strcpy(Name, ""); - Node = ResolvFileInfo(Str, ListType | LIST_RAW_NAME, Name, &Size, &Time, &Attr, Owner, &Link, &InfoExist); + Node = ResolveFileInfo(Str, ListType | LIST_RAW_NAME, Name, &Size, &Time, &Attr, Owner, &Link, &InfoExist); p = Name; while(*p != '\0') { @@ -5599,28 +6281,56 @@ int AnalyzeNameKanjiCode(int Num) } if(!p) { + // ASCII文字の範囲外 if(!CheckStringM(Name)) - PointUTF8N++; - else { - switch(CheckKanjiCode(Name, strlen(Name), KANJI_SJIS)) - { - case KANJI_SJIS: - PointSJIS++; - break; - case KANJI_JIS: - PointJIS++; - break; - case KANJI_EUC: - PointEUC++; - break; - } + InitCodeConvInfo(&cInfo1); + cInfo1.KanaCnv = NO; + cInfo1.Str = Name; + cInfo1.StrLen = strlen(Name); + cInfo1.Buf = Buf; + cInfo1.BufSize = FMAX_PATH; + cInfo2 = cInfo1; + ConvUTF8NtoUTF8HFSX(&cInfo1); + ConvUTF8HFSXtoUTF8N(&cInfo2); + if(cInfo1.OutLen > (int)strlen(Name)) + PointUTF8N++; + else + PointUTF8HFSX++; + if(cInfo2.OutLen < (int)strlen(Name)) + PointUTF8HFSX++; + else + PointUTF8N++; + } + switch(CheckKanjiCode(Name, strlen(Name), KANJI_SJIS)) + { + case KANJI_SJIS: + PointSJIS++; + break; + case KANJI_EUC: + PointEUC++; + break; + } + } + else + { + // ASCII文字の範囲内 + switch(CheckKanjiCode(Name, strlen(Name), KANJI_SJIS)) + { + case KANJI_JIS: + PointJIS++; + break; } } } } fclose(fd); } + if(PointUTF8HFSX >= Point) + { + NameKanjiCode = KANJI_UTF8HFSX; + Point = PointUTF8HFSX; + } if(PointJIS >= Point) { NameKanjiCode = KANJI_JIS;