OSDN Git Service

改行文字やタブ文字を名前に含むファイルを含む書庫を開こうとした場合に警告する機能を追加。
[tpi/lychee.git] / src / lychee / frm_main.cpp
index f175f73..3a02ef6 100644 (file)
@@ -1,4 +1,4 @@
-/*******************************************************************************\r
+/*******************************************************************************\r
   TPI - flexible but useless plug-in framework.\r
   Copyright (C) 2002-2009 Silky\r
 \r
@@ -103,6 +103,7 @@ BEGIN_EVENT_TABLE(MainFrame, wxFrame)
        EVT_MENU(XRCID("Arc_Create"),  MainFrame::OnArcCreate)\r
        EVT_MENU(XRCID("Arc_Open"),    MainFrame::OnArcOpen)\r
        EVT_MENU(XRCID("Arc_Close"),   MainFrame::OnArcClose)\r
+       EVT_MENU(XRCID("Arc_Clone"),   MainFrame::OnArcClone)\r
        EVT_MENU(XRCID("Arc_Add"),     MainFrame::OnArcAdd)\r
        EVT_MENU(XRCID("Arc_SFX"),     MainFrame::OnArcConvert)\r
        EVT_MENU(XRCID("Arc_UnSFX"),   MainFrame::OnArcConvert)\r
@@ -121,9 +122,13 @@ BEGIN_EVENT_TABLE(MainFrame, wxFrame)
        // TreeView\r
        EVT_TREE_SEL_CHANGED(XRCID("TreeView"), MainFrame::OnTreeChanged)\r
        EVT_TREE_BEGIN_DRAG( XRCID("TreeView"), MainFrame::OnTreeBeginDrag)\r
+       EVT_COMMAND_CONTEXT_MENU(XRCID("TreeView"), MainFrame::OnContextMenu)\r
        // ListView\r
-       EVT_LIST_ITEM_ACTIVATED(XRCID("ListView"), MainFrame::OnListItemDClick)\r
-       EVT_LIST_BEGIN_DRAG(    XRCID("ListView"), MainFrame::OnListBeginDrag)\r
+       EVT_LIST_ITEM_SELECTED(  XRCID("ListView"), MainFrame::OnListItemSelect)\r
+       EVT_LIST_ITEM_DESELECTED(XRCID("ListView"), MainFrame::OnListItemSelect)\r
+       EVT_LIST_ITEM_ACTIVATED( XRCID("ListView"), MainFrame::OnListItemDClick)\r
+       EVT_LIST_BEGIN_DRAG(     XRCID("ListView"), MainFrame::OnListBeginDrag)\r
+       EVT_COMMAND_CONTEXT_MENU(XRCID("ListView"), MainFrame::OnContextMenu)\r
        // Filter\r
        EVT_TEXT(XRCID("tcFilter"), MainFrame::OnFilter)\r
 END_EVENT_TABLE()\r
@@ -212,8 +217,7 @@ void MainFrame::OnArcCreate(wxCommandEvent& e)
        if (e.GetClientData() == NULL)\r
        {\r
                // 処理対象のファイルを選択。\r
-               wxFileDialog fd(this, _("Choose files to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));\r
-               fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
+               wxFileDialog fd(this, _("Choose files to compress"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
                if (fd.ShowModal() == wxID_CANCEL)\r
                {\r
                        return;\r
@@ -312,12 +316,13 @@ void MainFrame::OnArcCreate(wxCommandEvent& e)
 \r
 void MainFrame::OnArcOpen(wxCommandEvent& e)\r
 {\r
+       // モード取得。通常は0, それ以外で開く場合は1, ファイルDnDなら2。\r
+       int nMode = e.GetInt() == 2 ? 2 : e.GetId() == XRCID("Arc_Open") ? 0 : 1;\r
+\r
        // 書庫を選択。\r
-       if (e.GetId() == XRCID("Arc_Open"))\r
+       if (nMode == 0)\r
        {\r
-               wxFileDialog fd(this);\r
-               fd.SetDirectory(this->conf.ReadHistory(CONF_HISTORY_PATH, 0));\r
-               fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
+               wxFileDialog fd(this, _("Choose an archive"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
                if (fd.ShowModal() == wxID_CANCEL)\r
                {\r
                        return;\r
@@ -333,7 +338,7 @@ void MainFrame::OnArcOpen(wxCommandEvent& e)
        // DnD以外で書庫を開く場合、TPIを読み込み。\r
        TPI_PROCESSINFO piInfo;\r
        piInfo.fiInfo.nUnpackedSize = e.GetExtraLong();\r
-       if (e.GetInt() != 1 && ! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))\r
+       if (nMode != 2 && ! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))\r
        {\r
                procDlg.Show(false);\r
                tpi.FreeLibrary();\r
@@ -394,6 +399,18 @@ void MainFrame::OnArcOpen(wxCommandEvent& e)
                                return;\r
                        }\r
 \r
+                       // 拡張子のみ設定されている場合。\r
+                       if (piInfo.fiInfo.szStoredName.IsEmpty())\r
+                       {\r
+                               piInfo.fiInfo.szStoredName = this->fnArchive.GetName();\r
+                               if (piInfo.fiInfo.fnFileName.HasExt())\r
+                               {\r
+                                       piInfo.fiInfo.szStoredName += wxT('.') + piInfo.fiInfo.fnFileName.GetExt();\r
+                               }\r
+                               piInfo.fiInfo.fnFileName = wxFileName(piInfo.fiInfo.szStoredName);\r
+                       }\r
+\r
+                       // セキュリティチェック。\r
                        // ルート記号を削除。\r
                        wxString szPath = piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX);\r
                        if (szPath.StartsWith(wxT("/")))\r
@@ -401,11 +418,20 @@ void MainFrame::OnArcOpen(wxCommandEvent& e)
                                piInfo.fiInfo.fnFileName = wxFileName(szPath.AfterFirst(wxT('/')), piInfo.fiInfo.fnFileName.GetFullName(), wxPATH_DOS);\r
                        }\r
 \r
-                       // ツリービューに反映。\r
-                       bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? true : false;\r
-                       TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);\r
+                       // 改行文字/タブ文字などを削除。\r
+                       if (piInfo.fiInfo.szStoredName.Find(wxT('\r')) != wxNOT_FOUND\r
+                       ||  piInfo.fiInfo.szStoredName.Find(wxT('\n')) != wxNOT_FOUND\r
+                       ||  piInfo.fiInfo.szStoredName.Find(wxT('\t')) != wxNOT_FOUND)\r
+                       {\r
+                               wxString sz = piInfo.fiInfo.fnFileName.GetFullPath();\r
+                               sz.Replace(wxT("\r"), wxT(" "));\r
+                               sz.Replace(wxT("\n"), wxT(" "));\r
+                               sz.Replace(wxT("\t"), wxT(" "));\r
+                               piInfo.fiInfo.eDanger = TRUE;\r
+                               piInfo.fiInfo.fnFileName = wxFileName(sz);\r
+                               wxLogWarning(_("This archive may contain files whose name contains some special characters like CR(\\r), LF(\\n), Tab(\\t) and some problem would be happen if you extract these files. Don\'t extract these files carelessly.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());\r
+                       }\r
 \r
-                       // セキュリティチェック。\r
                        // DTV検査。\r
                        if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)\r
                        {\r
@@ -433,6 +459,10 @@ void MainFrame::OnArcOpen(wxCommandEvent& e)
                                }\r
                        }\r
 \r
+                       // ツリービューに反映。\r
+                       bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? true : false;\r
+                       TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);\r
+\r
                        // ディレクトリ属性を含むものについては情報を保存しない。\r
                        if (fDir)\r
                        {\r
@@ -471,15 +501,15 @@ void MainFrame::OnArcOpen(wxCommandEvent& e)
        this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);\r
        this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);\r
 \r
-       // ツールバー・メニューバー設定。\r
+       // ツールバー・メニューバー設定。ファイル選択時しか動作しない削除などは別に設定。\r
        SetMenuToolState("Arc_Close",   true);\r
        SetMenuToolState("Arc_Add",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD)   == TPI_COMMAND_ADD   && this->aiArchive.fiInfo.fArchive);\r
        SetMenuToolState("Arc_SFX",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX)    == TPI_COMMAND_SFX   && ! this->aiArchive.fSFX);\r
        SetMenuToolState("Arc_UnSFX",   (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX)  == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);\r
        SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);\r
-       SetMenuToolState("Arc_Delete",  (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);\r
        SetMenuToolState("Arc_Test",    (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST)   == TPI_COMMAND_TEST);\r
        SetMenuToolState("Arc_Repair",  (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);\r
+       this->menubar->Enable(XRCID("Arc_Clone"), true);\r
 \r
        procDlg.Show(false);\r
        this->Raise();\r
@@ -501,6 +531,7 @@ void MainFrame::OnArcClose(wxCommandEvent& e)
        SetMenuToolState("Arc_Delete",  false);\r
        SetMenuToolState("Arc_Test",    false);\r
        SetMenuToolState("Arc_Repair",  false);\r
+       this->menubar->Enable(XRCID("Arc_Clone"), false);\r
 \r
        for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)\r
        {\r
@@ -525,6 +556,24 @@ void MainFrame::OnArcClose(wxCommandEvent& e)
        }\r
 }\r
 \r
+void MainFrame::OnArcClone(wxCommandEvent&)\r
+{\r
+       // 保存先を尋ねる。\r
+       wxFileDialog fd(this, _("Clone archive"), this->fnArchive.GetPath(), this->fnArchive.GetFullName(), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
+       if (fd.ShowModal() == wxID_CANCEL)\r
+       {\r
+               return;\r
+       }\r
+       this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
+\r
+       // コピー。\r
+       ::wxCopyFile(this->fnArchive.GetFullPath(), fd.GetPath());\r
+       wxFileName fn(fd.GetPath());\r
+       wxDateTime dtAccess, dtModify, dtCreate;\r
+       this->fnArchive.GetTimes(& dtAccess, & dtModify, & dtCreate);\r
+       fn.SetTimes(& dtAccess, & dtModify, & dtCreate);\r
+}\r
+\r
 void MainFrame::OnArcAdd(wxCommandEvent& e)\r
 {\r
        // 作成ダイアログを設定。\r
@@ -534,8 +583,7 @@ void MainFrame::OnArcAdd(wxCommandEvent& e)
        mkDlg.uCommand = TPI_COMMAND_ADD;\r
 \r
        // 処理対象のファイルを選択。\r
-       wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0));\r
-       fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
+       wxFileDialog fd(this, _("Choose files to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);\r
        if (fd.ShowModal() == wxID_CANCEL)\r
        {\r
                return;\r
@@ -604,8 +652,7 @@ void MainFrame::OnArcConvert(wxCommandEvent& e)
        swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");\r
 \r
        // 保存先を尋ねる。\r
-       wxFileDialog fd(this, swInfo.fMakeSFX ? _("Save as SFX") : _("Save as normal archive"), this->fnArchive.GetPath(), this->fnArchive.GetName() + (swInfo.fMakeSFX ? EXE_EXT : (wxString) wxEmptyString));\r
-       fd.SetWindowStyleFlag(wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
+       wxFileDialog fd(this, swInfo.fMakeSFX ? _("Save as SFX") : _("Save as normal archive"), this->fnArchive.GetPath(), this->fnArchive.GetName() + (swInfo.fMakeSFX ? EXE_EXT : (wxString) wxEmptyString), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
        if (fd.ShowModal() == wxID_CANCEL)\r
        {\r
                return;\r
@@ -628,8 +675,12 @@ void MainFrame::OnArcExtract(wxCommandEvent& e)
        TPI_SWITCHES swInfo;\r
        swInfo.pCustomSwitches = NULL;\r
 \r
-       // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3、クリップボードなら4。\r
+       // ã\83¢ã\83¼ã\83\89å\8f\96å¾\97ã\80\82é\80\9a常ã\81¯0, å®\9fè¡\8cã\81ªã\82\891, ã\83\95ã\82¡ã\82¤ã\83«DnDã\81ªã\82\89\80\81ã\83\87ã\82£ã\83¬ã\82¯ã\83\88ã\83ªDnDã\81ªã\82\89\80\81ã\82¯ã\83ªã\83\83ã\83\97ã\83\9cã\83¼ã\83\89ã\81ªã\82\89\80\81ã\82³ã\83³ã\83\86ã\82­ã\82¹ã\83\88ã\83¡ã\83\8bã\83¥ã\83¼ã\81\8bã\82\89ã\81ªã\82\89\80\82\r
        int nMode = e.GetInt();\r
+       if (e.GetInt() == 8)\r
+       {\r
+               nMode = 0;\r
+       }\r
        // 実行時のみ使用。\r
        wxFileType * ftFile = NULL;\r
 \r
@@ -642,22 +693,6 @@ void MainFrame::OnArcExtract(wxCommandEvent& e)
 \r
        if (nMode != 0)\r
        {\r
-               if (nMode == 1)\r
-               {\r
-                       // コマンドを取得。\r
-                       ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());\r
-                       if (! ftFile)\r
-                       {\r
-                               // 種類が取得できないときは設定を読み込む。初期設定ではテキストとみなす。\r
-                               ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));\r
-                               if (! ftFile)\r
-                               {\r
-                                       wxLogError(_("Unable to get the file type!"));\r
-                                       return;\r
-                               }\r
-                       }\r
-               }\r
-\r
                // 作業ディレクトリ作成。\r
                swInfo.fStoreDirectoryPathes = false;\r
                wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");\r
@@ -735,20 +770,31 @@ void MainFrame::OnArcExtract(wxCommandEvent& e)
        {\r
                if (nMode == 1)\r
                {\r
+                       // コマンドを取得。\r
+                       ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());\r
+                       if (! ftFile || ftFile->GetOpenCommand(wxEmptyString).IsEmpty())\r
+                       {\r
+                               // 種類が取得できないときはテキストとみなす。\r
+                               ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));\r
+                       }\r
+\r
                        // コマンドを実行。\r
                        wxString szTempFile = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName();\r
-                       if (tpi.nErrorCode == TPI_ERROR_SUCCESS)\r
+                       bool fSuccess = tpi.nErrorCode == TPI_ERROR_SUCCESS && ftFile != NULL;\r
+                       myProcess * pCallback = new myProcess(szTempFile, swInfo.fnDestinationDirectory.GetPath());\r
+                       if (fSuccess)\r
                        {\r
 #ifdef __LINUX__\r
                                // Linuxでは引用符で囲む必要がある。\r
-                               ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_SYNC);\r
+                               fSuccess = ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_ASYNC, pCallback) > 0;\r
 #else\r
-                               ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_SYNC);\r
+                               fSuccess = ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_ASYNC, pCallback) > 0;\r
 #endif\r
                        }\r
-\r
-                       ::wxRemoveFile(szTempFile);\r
-                       ::wxRmdir(swInfo.fnDestinationDirectory.GetPath());\r
+                       if (! fSuccess)\r
+                       {\r
+                               pCallback->OnTerminate(0, 0);\r
+                       }\r
                }\r
                else\r
                {\r
@@ -800,6 +846,7 @@ void MainFrame::OnArcExtract(wxCommandEvent& e)
                                {\r
                                        for (size_t i = 0; i < asFiles.GetCount(); i++)\r
                                        {\r
+                                               chmod(asFiles[i].ToUTF8(), 0600);\r
                                                ::wxRemoveFile(asFiles[i]);\r
                                        }\r
                                }\r
@@ -815,6 +862,8 @@ void MainFrame::OnArcDelete(wxCommandEvent& e)
        // 全ファイル削除は危険ではないかと。\r
        if (this->list_ctrl->GetSelectedItemCount() == 0)\r
        {\r
+               // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
+               SetMenuToolState("Arc_Delete", false);\r
                return;\r
        }\r
 \r
@@ -901,6 +950,8 @@ void MainFrame::OnExeCopy(wxCommandEvent & e)
 {\r
        if (this->list_ctrl->GetSelectedItemCount() == 0)\r
        {\r
+               // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
+               this->menubar->Enable(XRCID("Exe_Copy"), false);\r
                return;\r
        }\r
 \r
@@ -1002,8 +1053,22 @@ void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)
        this->OnArcExtract(e1);\r
 }\r
 \r
+void MainFrame::OnContextMenu(wxContextMenuEvent& e)\r
+{\r
+       wxPoint p = e.GetPosition();\r
+       this->list_ctrl->PopupMenu(this->menubar->GetMenu(1), p == wxDefaultPosition ? this->list_ctrl->GetPosition() : this->list_ctrl->ScreenToClient(p));\r
+}\r
+\r
 // ListView\r
 \r
+void MainFrame::OnListItemSelect(wxListEvent&)\r
+{\r
+       // ファイルに対する動作の設定。但し、選択解除時はwxのバグで呼び出されない。\r
+       bool fEnable = this->list_ctrl->GetSelectedItemCount() > 0;\r
+       SetMenuToolState("Arc_Delete", fEnable && (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);\r
+       this->menubar->Enable(XRCID("Exe_Copy"), fEnable);\r
+}\r
+\r
 void MainFrame::OnListItemDClick(wxListEvent&)\r
 {\r
        wxCommandEvent e;\r