OSDN Git Service

終了時の処理を改善。
[tpi/lychee.git] / src / lychee / frm_main.cpp
1 /*******************************************************************************\r
2   TPI - flexible but useless plug-in framework.\r
3   Copyright (C) 2002-2009 Silky\r
4 \r
5   This library is free software; you can redistribute it and/or modify it under\r
6   the terms of the GNU Lesser General Public License as published by the Free\r
7   Software Foundation; either version 2.1 of the License, or (at your option)\r
8   any later version.\r
9 \r
10   This library is distributed in the hope that it will be useful, but WITHOUT\r
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or \r
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r
13   for more details.\r
14 \r
15   You should have received a copy of the GNU Lesser General Public License along\r
16   with this library; if not, write to the Free Software Foundation, Inc.,\r
17   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
18 \r
19   $Id$\r
20 *******************************************************************************/\r
21 \r
22 #include "lychee.h"\r
23 \r
24 #include "frm_main.h"\r
25 #include "cls_filedroptarget.h"\r
26 #include "dlg_make.h"\r
27 #include "dlg_process.h"\r
28 #include "functions.h"\r
29 \r
30 #include <wx/arrimpl.cpp>\r
31 \r
32 WX_DEFINE_OBJARRAY(ArrayTPI_FILEINFO);\r
33 \r
34 #define SetMenuToolState(id, state) this->toolbar->EnableTool(XRCID(id), state); this->menubar->Enable(XRCID(id), state)\r
35 \r
36 //******************************************************************************\r
37 //    グローバル変数\r
38 //******************************************************************************\r
39 \r
40 wxImageList g_hIconT(16, 16), g_hIconLL(32, 32), g_hIconLS(16, 16);\r
41 int g_nSortColumn;\r
42 bool g_fSortAscend;\r
43 \r
44 //******************************************************************************\r
45 // MainFrame\r
46 //******************************************************************************\r
47 \r
48 MainFrame::MainFrame(): wxFrame()\r
49 {\r
50 }\r
51 \r
52 MainFrame::~MainFrame()\r
53 {\r
54         // 設定を記録。\r
55         if (! this->IsIconized() && ! this->IsMaximized())\r
56         {\r
57                 int a, b;\r
58                 this->GetSize(& a, & b);\r
59                 this->conf.WriteId(CONF_WINDOW_WIDTH,  a);\r
60                 this->conf.WriteId(CONF_WINDOW_HEIGHT, b);\r
61                 this->GetPosition(& a, & b);\r
62                 this->conf.WriteId(CONF_WINDOW_X, a);\r
63                 this->conf.WriteId(CONF_WINDOW_Y, b);\r
64         }\r
65         this->conf.WriteId(CONF_WINDOW_SPLITTER_POS, this->window_splitter->GetSashPosition());\r
66 \r
67         // ツールバー/ステータスバー関連。\r
68         this->conf.WriteId(CONF_WINDOW_STATUSBAR, this->statusbar->IsShown());\r
69         this->conf.WriteId(CONF_WINDOW_TOOLBAR,   this->toolbar->IsShown());\r
70 \r
71         // ListView関連。\r
72         this->conf.WriteId(CONF_LISTVIEW_SHOWMODE, this->menubar->IsChecked(XRCID("Exe_View_Icons")) ? 1 : this->menubar->IsChecked(XRCID("Exe_View_List")) ? 2 : 0);\r
73         if (this->menubar->IsChecked(XRCID("Exe_View_Details")))\r
74         {\r
75                 this->conf.WriteId(CONF_LISTVIEW_C_FILENAME, this->list_ctrl->GetColumnWidth(0));\r
76                 this->conf.WriteId(CONF_LISTVIEW_C_UNPACKED, this->list_ctrl->GetColumnWidth(1));\r
77                 this->conf.WriteId(CONF_LISTVIEW_C_PACKED,   this->list_ctrl->GetColumnWidth(2));\r
78                 this->conf.WriteId(CONF_LISTVIEW_C_RATIO,    this->list_ctrl->GetColumnWidth(3));\r
79                 this->conf.WriteId(CONF_LISTVIEW_C_METHOD,   this->list_ctrl->GetColumnWidth(4));\r
80                 this->conf.WriteId(CONF_LISTVIEW_C_ATTR,         this->list_ctrl->GetColumnWidth(5));\r
81                 this->conf.WriteId(CONF_LISTVIEW_C_LASTMOD,  this->list_ctrl->GetColumnWidth(6));\r
82                 this->conf.WriteId(CONF_LISTVIEW_C_PATH,     this->list_ctrl->GetColumnWidth(7));\r
83                 this->conf.WriteId(CONF_LISTVIEW_C_TYPE,     this->list_ctrl->GetColumnWidth(8));\r
84                 this->conf.WriteId(CONF_LISTVIEW_C_NO,       this->list_ctrl->GetColumnWidth(9));\r
85                 this->conf.WriteId(CONF_LISTVIEW_C_COMMENT,  this->list_ctrl->GetColumnWidth(10));\r
86                 this->conf.WriteId(CONF_LISTVIEW_S_COLUMN,   g_nSortColumn);\r
87                 this->conf.WriteId(CONF_LISTVIEW_S_ASCEND,   g_fSortAscend);\r
88         }\r
89 \r
90         wxCommandEvent e;\r
91         this->Show(false);\r
92         this->OnArcClose(e);\r
93 }\r
94 \r
95 //******************************************************************************\r
96 // Event Table.\r
97 //******************************************************************************\r
98 \r
99 BEGIN_EVENT_TABLE(MainFrame, wxFrame)\r
100         EVT_INIT_DIALOG(      MainFrame::OnInit)\r
101         // Menu\r
102         EVT_MENU(XRCID("Arc_Create"),  MainFrame::OnArcCreate)\r
103         EVT_MENU(XRCID("Arc_Open"),    MainFrame::OnArcOpen)\r
104         EVT_MENU(XRCID("Arc_Close"),   MainFrame::OnArcClose)\r
105         EVT_MENU(XRCID("Arc_Clone"),   MainFrame::OnArcClone)\r
106         EVT_MENU(XRCID("Arc_Add"),     MainFrame::OnArcAdd)\r
107         EVT_MENU(XRCID("Arc_SFX"),     MainFrame::OnArcConvert)\r
108         EVT_MENU(XRCID("Arc_UnSFX"),   MainFrame::OnArcConvert)\r
109         EVT_MENU(XRCID("Exe_Exit"),    MainFrame::OnExit)\r
110         EVT_MENU(XRCID("Arc_Extract"), MainFrame::OnArcExtract)\r
111         EVT_MENU(XRCID("Arc_Delete"),  MainFrame::OnArcDelete)\r
112         EVT_MENU(XRCID("Arc_Test"),    MainFrame::OnArcTest)\r
113         EVT_MENU(XRCID("Arc_Repair"),  MainFrame::OnArcRepair)\r
114         EVT_MENU(XRCID("Exe_Copy"),    MainFrame::OnExeCopy)\r
115         EVT_MENU(XRCID("Exe_View_Icons"),  MainFrame::OnViewMode)\r
116         EVT_MENU(XRCID("Exe_View_Details"),MainFrame::OnViewMode)\r
117         EVT_MENU(XRCID("Exe_View_List"),   MainFrame::OnViewMode)\r
118         EVT_MENU(XRCID("Exe_View_ToolBar"),MainFrame::OnShowToolBar)\r
119         EVT_MENU(XRCID("Exe_View_StatusBar"),MainFrame::OnShowStatusBar)\r
120         EVT_MENU(XRCID("Exe_View_SelectAll"),MainFrame::OnSelectAll)\r
121         // TreeView\r
122         EVT_TREE_SEL_CHANGED(XRCID("TreeView"), MainFrame::OnTreeChanged)\r
123         EVT_TREE_BEGIN_DRAG( XRCID("TreeView"), MainFrame::OnTreeBeginDrag)\r
124         EVT_COMMAND_CONTEXT_MENU(XRCID("TreeView"), MainFrame::OnContextMenu)\r
125         // ListView\r
126         EVT_LIST_ITEM_SELECTED(  XRCID("ListView"), MainFrame::OnListItemSelect)\r
127         EVT_LIST_ITEM_DESELECTED(XRCID("ListView"), MainFrame::OnListItemSelect)\r
128         EVT_LIST_ITEM_ACTIVATED( XRCID("ListView"), MainFrame::OnListItemDClick)\r
129         EVT_LIST_BEGIN_DRAG(     XRCID("ListView"), MainFrame::OnListBeginDrag)\r
130         EVT_COMMAND_CONTEXT_MENU(XRCID("ListView"), MainFrame::OnContextMenu)\r
131         // Filter\r
132         EVT_TEXT(XRCID("tcFilter"), MainFrame::OnFilter)\r
133 END_EVENT_TABLE()\r
134 \r
135 //******************************************************************************\r
136 // Event handler.\r
137 //******************************************************************************\r
138 \r
139 void MainFrame::OnInit(wxInitDialogEvent&)\r
140 {\r
141         // XRCと結びつけ。\r
142         this->menubar    = this->GetMenuBar();\r
143         this->toolbar    = this->GetToolBar();\r
144         this->statusbar = XRCCTRL(* this, "statusbar", wxStatusBar);\r
145         this->tree_ctrl = XRCCTRL(* this, "TreeView", wxTreeCtrl);\r
146         this->list_ctrl = XRCCTRL(* this, "ListView", myListCtrl);\r
147         this->window_splitter = XRCCTRL(* this, "window_splitter", wxSplitterWindow);\r
148         this->tcFilter  = XRCCTRL(* this->toolbar, "tcFilter", wxTextCtrl);\r
149 \r
150         // 設定を読み込み。\r
151         this->SetSize(this->conf.ReadId(CONF_WINDOW_X, 0l), this->conf.ReadId(CONF_WINDOW_Y, 0l), this->conf.ReadId(CONF_WINDOW_WIDTH, 800l), this->conf.ReadId(CONF_WINDOW_HEIGHT, 400l), wxSIZE_ALLOW_MINUS_ONE);\r
152         wxTheMimeTypesManager->Initialize(wxMAILCAP_ALL);\r
153 \r
154         // 初期値設定。\r
155         {\r
156                 wxIcon icon;\r
157                 icon.CopyFromBitmap(wxBitmap(L_DIR_S_ICO wxT("app.png"), wxBITMAP_TYPE_ANY));\r
158                 this->SetIcon(icon);\r
159         }\r
160         wxCommandEvent e;\r
161         this->OnArcClose(e);\r
162         this->SetDropTarget(new myFileDropTarget(this));\r
163 \r
164         // スプリッター設定。\r
165         this->window_splitter->SetSashPosition(this->conf.ReadId(CONF_WINDOW_SPLITTER_POS, 200l));\r
166 \r
167         // リストビュー設定。\r
168         int nIconMode = this->conf.ReadId(CONF_LISTVIEW_SHOWMODE, 0l);\r
169         e.SetId(nIconMode == 1 ? XRCID("Exe_View_Icons") : (nIconMode == 2 ? XRCID("Exe_View_List") : XRCID("Exe_View_Details")));\r
170         this->OnViewMode(e);\r
171         // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。\r
172         this->list_ctrl->SetSingleStyle(wxLC_VIRTUAL);\r
173         this->list_ctrl->InsertColumn(0, _("Filename"),      wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_FILENAME, 140l));\r
174         this->list_ctrl->InsertColumn(1, _("Unpacked"),      wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_UNPACKED,  80l));\r
175         this->list_ctrl->InsertColumn(2, _("Packed"),        wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_PACKED,    80l));\r
176         this->list_ctrl->InsertColumn(3, _("Ratio"),         wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_RATIO,     50l));\r
177         this->list_ctrl->InsertColumn(4, _("Method"),        wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_METHOD,    60l));\r
178         this->list_ctrl->InsertColumn(5, _("Attr"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_ATTR,      50l));\r
179         this->list_ctrl->InsertColumn(6, _("Last modified"), wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_LASTMOD,  150l));\r
180         this->list_ctrl->InsertColumn(7, _("Path"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_PATH,     100l));\r
181         this->list_ctrl->InsertColumn(8, _("Type"),          wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_TYPE,     100l));\r
182         this->list_ctrl->InsertColumn(9, _("No."),           wxLIST_FORMAT_RIGHT,  this->conf.ReadId(CONF_LISTVIEW_C_NO,        35l));\r
183         this->list_ctrl->InsertColumn(10,_("Comment"),       wxLIST_FORMAT_LEFT,   this->conf.ReadId(CONF_LISTVIEW_C_COMMENT,   35l));\r
184         g_nSortColumn = this->conf.ReadId(CONF_LISTVIEW_S_COLUMN, 9l);\r
185         g_fSortAscend = this->conf.ReadId(CONF_LISTVIEW_S_ASCEND, true);\r
186 \r
187         // ツールバー/ステータスバー設定。\r
188         int nStatusBarParts[] = {70, 70, 180, 50, -1};\r
189         this->statusbar->SetFieldsCount(5, nStatusBarParts);\r
190         this->SetStatusBarPane(-1);\r
191         bool fShow = this->conf.ReadId(CONF_WINDOW_STATUSBAR, true);\r
192         this->menubar->Check(XRCID("Exe_View_StatusBar"), fShow);\r
193         this->statusbar->Show(fShow);\r
194         fShow = this->conf.ReadId(CONF_WINDOW_TOOLBAR, true);\r
195         this->menubar->Check(XRCID("Exe_View_ToolBar"), fShow);\r
196         this->toolbar->Show(fShow);\r
197 }\r
198 \r
199 // MenuBar\r
200 \r
201 void MainFrame::OnExit(wxCommandEvent&)\r
202 {\r
203         this->Close(true);\r
204 }\r
205 \r
206 void MainFrame::OnArcCreate(wxCommandEvent& e)\r
207 {\r
208         TPI_SWITCHES swInfo;\r
209         swInfo.pCustomSwitches = NULL;\r
210 \r
211         // 作成ダイアログを設定。\r
212         MakeDialog mkDlg(this, TPI_COMMAND_CREATE);\r
213         if (e.GetClientData() == NULL)\r
214         {\r
215                 // 処理対象のファイルを選択。\r
216                 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
217                 if (fd.ShowModal() == wxID_CANCEL)\r
218                 {\r
219                         return;\r
220                 }\r
221                 swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
222                 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
223                 fd.GetFilenames(mkDlg.files);\r
224         }\r
225         else\r
226         {\r
227                 mkDlg.files = * (wxArrayString *) e.GetClientData();\r
228                 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());\r
229                 // 相対パスに変換。\r
230                 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)\r
231                 {\r
232                         wxFileName fn(mkDlg.files[n]);\r
233                         fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());\r
234                         mkDlg.files[n] = fn.GetFullPath();\r
235                 }\r
236         }\r
237 \r
238         this->OnArcClose(e);\r
239         // 書庫名はファイル名の拡張子より前、もしくはディレクトリ名。\r
240         this->fnArchive = wxFileName(mkDlg.files[0]);\r
241         this->fnArchive.SetName(mkDlg.files.GetCount() == 1 ? (this->fnArchive.GetName().IsEmpty() ? this->fnArchive.GetDirs().Last() : this->fnArchive.GetName()) : swInfo.fnDestinationDirectory.GetDirs().Last());\r
242         this->fnArchive.SetEmptyExt();\r
243         this->fnArchive.SetPath(swInfo.fnDestinationDirectory.GetPath());\r
244 \r
245         // ダイアログを表示。\r
246         if (mkDlg.ShowModal() == wxID_CANCEL)\r
247         {\r
248                 return;\r
249         }\r
250 \r
251         // 各種設定。\r
252         int nSelected = mkDlg.chType->GetSelection();\r
253         swInfo.nArchiveType         = mkDlg.afInfo[nSelected].nTypeId;\r
254         swInfo.fStoreDirectoryPathes= ! mkDlg.cbIgnorePath->IsChecked();\r
255         swInfo.fMakeSFX                     = mkDlg.cbMakeSFX->IsChecked();\r
256         swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
257         swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
258         swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
259         swInfo.fCompressHeader      = mkDlg.cbCompressHeader->IsChecked();\r
260         swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
261         swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
262         swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
263         swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
264         swInfo.szComment            = mkDlg.tcComment->GetValue();\r
265         mkDlg.cbSplitSize->GetValue().ToULongLong(& swInfo.nSplitSize);\r
266 \r
267         // TPIを読み込み。\r
268         this->fnArchive = wxFileName(mkDlg.cbDir->GetValue(), mkDlg.cbFileName->GetValue());\r
269         if (! tpi.InitLibrary(mkDlg.afInfo[nSelected].szTPIName, this->fnArchive.GetFullPath(), TPICallbackProc, mkDlg.afInfo[nSelected].nTypeId))\r
270         {\r
271                 this->ErrorCheck(tpi.nErrorCode, wxT("InitLibrary"));\r
272                 return;\r
273         }\r
274 \r
275         // 処理を行う。\r
276         {\r
277                 ProcessDialog procDlg(this, mkDlg.files.GetCount());\r
278                 procDlg.Show(true);\r
279 \r
280                 tpi.Command(TPI_COMMAND_CREATE, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
281                 this->ErrorCheck(tpi.nErrorCode);\r
282                 procDlg.Show(false);\r
283         }\r
284         tpi.FreeLibrary();\r
285 \r
286         if (mkDlg.cbOpenAfter->IsChecked())\r
287         {\r
288                 // 作成先を開く。\r
289                 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
290         }\r
291 \r
292         if (mkDlg.cbExitAfter->IsChecked())\r
293         {\r
294                 // 終了。\r
295                 this->Close(true);\r
296         }\r
297 \r
298         // 終了しない場合は書庫を開く。\r
299         this->OnArcOpen(e);\r
300 }\r
301 \r
302 void MainFrame::OnArcOpen(wxCommandEvent& e)\r
303 {\r
304         // モード取得。通常は0, それ以外で開く場合は1, ファイルDnDなら2。\r
305         int nMode = e.GetInt() == 2 ? 2 : e.GetId() == XRCID("Arc_Open") ? 0 : 1;\r
306 \r
307         // 書庫を選択。\r
308         if (nMode == 0)\r
309         {\r
310                 wxFileDialog fd(this, _("Choose an archive"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
311                 if (fd.ShowModal() == wxID_CANCEL)\r
312                 {\r
313                         return;\r
314                 }\r
315                 this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
316                 this->fnArchive = wxFileName(fd.GetPath());\r
317         }\r
318 \r
319         // 進捗ダイアログ表示。\r
320         ProcessDialog procDlg(this);\r
321         procDlg.Show(true);\r
322 \r
323         // DnD以外で書庫を開く場合、TPIを読み込み。\r
324         TPI_PROCESSINFO piInfo;\r
325         piInfo.fiInfo.nUnpackedSize = 0;\r
326         if (! this->LoadTPI(this->fnArchive.GetFullPath(), & piInfo.fiInfo.nUnpackedSize))\r
327         {\r
328                 procDlg.Show(false);\r
329                 if (nMode == 2)\r
330                 {\r
331                         // DnDの場合は書庫を作成する。\r
332                         this->OnArcCreate(e);\r
333                 }\r
334                 else if (this->IsShown())\r
335                 {\r
336                         wxBell();\r
337                         this->statusbar->SetStatusText(_("No plug-in supporting this archive was found!"), 4);\r
338                 }\r
339                 else\r
340                 {\r
341                         wxLogError(_("No plug-in supporting this archive was found!"));\r
342                         this->Close(true);\r
343                 }\r
344                 return;\r
345         }\r
346 \r
347         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
348         piInfo.eStatus = 0x1001;\r
349         if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
350         {\r
351                 procDlg.Show(false);\r
352                 tpi.CloseArchive();\r
353                 wxCommandEvent e;\r
354                 this->OnArcClose(e);\r
355                 return;\r
356         }\r
357 \r
358         // 配列のサイズを確保。\r
359         this->fileinfo.Alloc(piInfo.fiInfo.nUnpackedSize);\r
360 \r
361         // 履歴に追加。\r
362         this->conf.WriteHistory(CONF_HISTORY_PATH, this->fnArchive.GetPath());\r
363         this->conf.WriteHistory(CONF_HISTORY_NAME, this->fnArchive.GetFullName());\r
364         this->conf.WriteHistory(CONF_HISTORY_FULL, this->fnArchive.GetFullPath());\r
365 \r
366         // 書庫のアイコンを取得し、書庫ルートを作成。\r
367         g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_closed.png"), wxBITMAP_TYPE_ANY));\r
368         g_hIconT.Add(wxBitmap(L_DIR_S_ICO wxT("folder_open.png"), wxBITMAP_TYPE_ANY));\r
369         this->tree_ctrl->SetImageList(& g_hIconT);\r
370         wxTreeItemId\r
371                 idRoot = this->tree_ctrl->AddRoot(wxEmptyString),\r
372 #ifdef __WINDOWS__\r
373                 idArchive = this->tree_ctrl->AppendItem(idRoot, this->fnArchive.GetFullName(), g_hIconT.Add(GetFileTypeIcon(this->fnArchive))),\r
374 #else\r
375                 idArchive = this->tree_ctrl->AppendItem(idRoot, this->fnArchive.GetFullName(), g_hIconT.Add(GetFileTypeIcon(this->fnArchive).ConvertToImage().Rescale(16, 16))),\r
376 #endif\r
377                 idArcRoot = this->tree_ctrl->AppendItem(idRoot, wxT("-----"), 0, 1);\r
378 \r
379         // 巨大書庫のときにファイル名検査を省略するか。\r
380         bool bDTVCheck = piInfo.fiInfo.nUnpackedSize < 10000 || ::AskDlg(_("This archive contains so many files that it takes long to check Directory Traversal Vulnerability(DTV) problem. If you are sure this archive is safe, you can skip this scanning process. Do you want to scan for DTV problem?"), this) == wxNO;\r
381 \r
382         // ファイル情報をロード。\r
383         if (tpi.GetFileInformation(& piInfo.fiInfo, true))\r
384         {\r
385                 piInfo.eStatus = 0x1002;\r
386                 piInfo.nProcessedSize = 0;\r
387                 do\r
388                 {\r
389                         piInfo.nProcessedSize++;\r
390                         if (this->ErrorCheck(procDlg.CallbackProc(TPI_NOTIFY_COMMON, & piInfo), wxT("Callback")) == TPI_CALLBACK_CANCEL)\r
391                         {\r
392                                 procDlg.Show(false);\r
393                                 tpi.CloseArchive();\r
394                                 wxCommandEvent e;\r
395                                 this->OnArcClose(e);\r
396                                 return;\r
397                         }\r
398 \r
399                         // 拡張子のみ設定されている場合。\r
400                         if (piInfo.fiInfo.szStoredName.IsEmpty())\r
401                         {\r
402                                 piInfo.fiInfo.szStoredName = this->fnArchive.GetName();\r
403                                 if (piInfo.fiInfo.fnFileName.HasExt())\r
404                                 {\r
405                                         piInfo.fiInfo.szStoredName += wxT('.') + piInfo.fiInfo.fnFileName.GetExt();\r
406                                 }\r
407                                 piInfo.fiInfo.fnFileName = wxFileName(piInfo.fiInfo.szStoredName);\r
408                         }\r
409 \r
410                         // セキュリティチェック。\r
411                         // ルート記号を削除。\r
412                         wxString szPath = piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX);\r
413                         if (szPath.StartsWith(wxT("/")) || szPath.StartsWith(wxT("./")))\r
414                         {\r
415                                 piInfo.fiInfo.fnFileName = wxFileName(szPath.AfterFirst(wxT('/')), piInfo.fiInfo.fnFileName.GetFullName(), wxPATH_DOS);\r
416                         }\r
417                         // ルートメンバの情報は無視する。\r
418                         if (piInfo.fiInfo.fnFileName.GetFullPath().IsEmpty() || piInfo.fiInfo.fnFileName.GetFullPath() == wxT("."))\r
419                         {\r
420                                 continue;\r
421                         }\r
422 \r
423                         // 改行文字/タブ文字などを削除。\r
424                         if (piInfo.fiInfo.szStoredName.Find(wxT('\r')) != wxNOT_FOUND\r
425                         ||  piInfo.fiInfo.szStoredName.Find(wxT('\n')) != wxNOT_FOUND\r
426                         ||  piInfo.fiInfo.szStoredName.Find(wxT('\t')) != wxNOT_FOUND)\r
427                         {\r
428                                 wxString sz = piInfo.fiInfo.fnFileName.GetFullPath();\r
429                                 sz.Replace(wxT("\r"), wxT(" "));\r
430                                 sz.Replace(wxT("\n"), wxT(" "));\r
431                                 sz.Replace(wxT("\t"), wxT(" "));\r
432                                 piInfo.fiInfo.eDanger = TRUE;\r
433                                 piInfo.fiInfo.fnFileName = wxFileName(sz);\r
434                                 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
435                         }\r
436 \r
437                         if (bDTVCheck)\r
438                         {\r
439                                 // DTV検査。\r
440                                 if (piInfo.fiInfo.fnFileName.GetPathWithSep(wxPATH_UNIX).Find(wxT("../")) != wxNOT_FOUND)\r
441                                 {\r
442                                         piInfo.fiInfo.eDanger = TRUE;\r
443                                         wxLogWarning(_("This archive may have Directory Traversal Vulnerability(DTV) problem, and some danger files may be extracted to the unexpected system directory! You should use the \"Ignore file pathes\" option when extracting this archive.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());\r
444                                 }\r
445                                 // 空白の連続による拡張子偽装を検査。\r
446                                 if (piInfo.fiInfo.fnFileName.GetFullName().Find(wxT("        ")) != wxNOT_FOUND)\r
447                                 {\r
448                                         piInfo.fiInfo.eDanger = TRUE;\r
449                                         wxLogWarning(_("This archive may contain extension-disguised files whose real extension is hidden by using many blank charactor and you may mistake that it is a \"safe\" file. Don\'t execute these files carelessly.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());\r
450                                 }\r
451                                 // Unicode制御文字を検査。\r
452                                 for (wxChar c = 0x200c; c <= 0x206f; c++)\r
453                                 {\r
454                                         if (piInfo.fiInfo.fnFileName.GetFullName().Find(c) != wxNOT_FOUND)\r
455                                         {\r
456                                                 piInfo.fiInfo.eDanger = TRUE;\r
457                                                 wxLogWarning(_("This archive may contain extension-disguised files whose real extension is hidden by using Unicode control character and you may mistake that it is a \"safe\" file. Don\'t execute these files carelessly.\nDanger file is:\n%s"), piInfo.fiInfo.fnFileName.GetFullPath().c_str());\r
458                                         }\r
459                                         switch (c)\r
460                                         {\r
461                                         case 0x200f: c = 0x2027; break;\r
462                                         case 0x202e: c = 0x2060; break;\r
463                                         }\r
464                                 }\r
465                         }\r
466 \r
467                         // ツリービューに反映。\r
468                         bool fDir = piInfo.fiInfo.dwAttribute & TPI_ATTRIBUTE_DIRECTORY ? true : false;\r
469                         TreeView_CheckNewerItem(this->tree_ctrl, idArcRoot, fDir ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetPath(), true);\r
470 \r
471                         // ディレクトリ属性を含むものについては情報を保存しない。\r
472                         if (fDir)\r
473                         {\r
474                                 continue;\r
475                         }\r
476 \r
477                         // 情報を保存してカウントアップ。\r
478                         this->fileinfo.Add(piInfo.fiInfo);\r
479                 }\r
480                 while (tpi.GetFileInformation(& piInfo.fiInfo));\r
481         }\r
482 \r
483         // GetFileInformationがエラー終了した場合。\r
484         this->ErrorCheck(tpi.nErrorCode, wxT("GetFileInformation"));\r
485 \r
486         // 書庫の情報を取得。\r
487         tpi.GetArchiveInformation(& this->aiArchive);\r
488         this->ErrorCheck(tpi.nErrorCode, wxT("GetArchiveInformation"));\r
489         this->szPassword = procDlg.szPassword;\r
490 \r
491         // 書庫を閉じる。\r
492         tpi.CloseArchive();\r
493         this->ErrorCheck(tpi.nErrorCode, wxT("CloseArchive"));\r
494 \r
495         // 以下、UI処理。\r
496         this->fileinfo.Shrink();\r
497         this->tree_ctrl->Freeze();\r
498         if (this->fileinfo.Count() < 10000)\r
499         {\r
500                 this->tree_ctrl->ExpandAll();\r
501                 this->tree_ctrl->SelectItem(idArchive);\r
502         }\r
503         else\r
504         {\r
505                 // ファイル数が多いとソートに時間がかかるので、書庫のルートを表示させる。\r
506                 this->tree_ctrl->Expand(idArcRoot);\r
507                 this->tree_ctrl->SelectItem(idArcRoot);\r
508         }\r
509         // ツリービューの位置合わせ。\r
510         this->tree_ctrl->ScrollTo(idArchive);\r
511         this->tree_ctrl->SetScrollPos(wxHORIZONTAL, 0);\r
512         this->tree_ctrl->Thaw();\r
513         this->list_ctrl->atDangerItem.SetTextColour(* wxRED);\r
514         this->list_ctrl->atEncryptedItem.SetTextColour(wxColour(wxT("forest green")));\r
515 \r
516         // ステータスバー設定。\r
517         this->statusbar->SetStatusText(this->aiArchive.fiInfo.szTypeName, 0);\r
518         this->statusbar->SetStatusText(wxString::Format(_("%u file(s)"), this->fileinfo.GetCount()), 1);\r
519         this->statusbar->SetStatusText(wxString::Format(wxString("%" wxLongLongFmtSpec "uB -> %" wxLongLongFmtSpec "uB"), this->aiArchive.nUnpackedSize, this->aiArchive.nPackedSize), 2);\r
520         this->statusbar->SetStatusText(wxString::Format(wxT("%3.1f%%"), this->aiArchive.wCompressRatio / 10.0), 3);\r
521         this->statusbar->SetStatusText(this->fnArchive.GetFullPath(), 4);\r
522         this->statusbar->SetToolTip(\r
523                 wxString::Format(\r
524                         _("%s(%s)\nTPI: %s(%s)\nAccess: %s\nModify: %s\nCreate: %s\nComment:\n%s"),\r
525                         this->fnArchive.GetFullName().c_str(), this->aiArchive.fiInfo.szTypeName.c_str(),\r
526                         this->aiArchive.fiInfo.szTPIName.c_str(), this->aiArchive.fiInfo.szEngineName.c_str(),\r
527                         this->aiArchive.tmAccess.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
528                         this->aiArchive.tmModify.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
529                         this->aiArchive.tmCreate.Format(_("%Y/%m/%d %H:%M:%S")).c_str(),\r
530                         this->aiArchive.szComment.c_str()\r
531                 )\r
532         );\r
533 \r
534         // ツールバー・メニューバー設定。ファイル選択時しか動作しない削除などは別に設定。\r
535         SetMenuToolState("Arc_Close",   true);\r
536         SetMenuToolState("Arc_Add",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_ADD)   == TPI_COMMAND_ADD   && this->aiArchive.fiInfo.fArchive);\r
537         SetMenuToolState("Arc_SFX",     (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_SFX)    == TPI_COMMAND_SFX   && ! this->aiArchive.fSFX);\r
538         SetMenuToolState("Arc_UnSFX",   (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_UNSFX)  == TPI_COMMAND_UNSFX && this->aiArchive.fSFX);\r
539         SetMenuToolState("Arc_Extract", (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_EXTRACT)== TPI_COMMAND_EXTRACT);\r
540         SetMenuToolState("Arc_Test",    (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_TEST)   == TPI_COMMAND_TEST);\r
541         SetMenuToolState("Arc_Repair",  (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_REPAIR) == TPI_COMMAND_REPAIR);\r
542         this->menubar->Enable(XRCID("Arc_Clone"), true);\r
543 \r
544         procDlg.Show(false);\r
545         this->Raise();\r
546 }\r
547 \r
548 void MainFrame::OnArcClose(wxCommandEvent& e)\r
549 {\r
550         // ツリービュー・リストビュー設定。\r
551         this->tree_ctrl->DeleteAllItems();\r
552         this->list_ctrl->DeleteAllItems();\r
553         this->list_ctrl->apShowFile.Clear();\r
554 \r
555         // ツールバー・メニューバー設定。\r
556         SetMenuToolState("Arc_Close",   false);\r
557         SetMenuToolState("Arc_Add",     false);\r
558         SetMenuToolState("Arc_SFX",     false);\r
559         SetMenuToolState("Arc_UnSFX",   false);\r
560         SetMenuToolState("Arc_Extract", false);\r
561         SetMenuToolState("Arc_Delete",  false);\r
562         SetMenuToolState("Arc_Test",    false);\r
563         SetMenuToolState("Arc_Repair",  false);\r
564         this->menubar->Enable(XRCID("Arc_Clone"), false);\r
565 \r
566         for (int i = 0; i < this->statusbar->GetFieldsCount(); i++)\r
567         {\r
568                 this->statusbar->SetStatusText(wxEmptyString, i);\r
569         }\r
570         this->statusbar->SetToolTip(wxEmptyString);\r
571         this->fileinfo.Clear();\r
572         this->szPassword.Empty();\r
573         this->aiArchive.szComment.Empty();\r
574         this->aiArchive.fnArchive.Clear();\r
575         this->aiArchive.fiInfo.szTypeName.Empty();\r
576         this->aiArchive.fiInfo.szSuffix.Empty();\r
577         this->aiArchive.fiInfo.szEngineName.Empty();\r
578         this->aiArchive.fiInfo.szTPIName.Empty();\r
579 \r
580         g_hIconT.RemoveAll();\r
581         g_hIconLL.RemoveAll();\r
582         g_hIconLS.RemoveAll();\r
583 \r
584         // DnDで書庫を開くときは既に読み込まれているTPIを用いるので、解放してはいけない。\r
585         if (e.GetExtraLong() == 0)\r
586         {\r
587                 tpi.FreeLibrary();\r
588         }\r
589 }\r
590 \r
591 void MainFrame::OnArcClone(wxCommandEvent&)\r
592 {\r
593         // 保存先を尋ねる。\r
594         wxFileDialog fd(this, _("Clone archive"), this->fnArchive.GetPath(), this->fnArchive.GetFullName(), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
595         if (fd.ShowModal() == wxID_CANCEL)\r
596         {\r
597                 return;\r
598         }\r
599         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
600 \r
601         // コピー。\r
602         ::wxCopyFile(this->fnArchive.GetFullPath(), fd.GetPath());\r
603         wxFileName fn(fd.GetPath());\r
604         wxDateTime dtAccess, dtModify, dtCreate;\r
605         this->fnArchive.GetTimes(& dtAccess, & dtModify, & dtCreate);\r
606         fn.SetTimes(& dtAccess, & dtModify, & dtCreate);\r
607 }\r
608 \r
609 void MainFrame::OnArcAdd(wxCommandEvent& e)\r
610 {\r
611         // 作成ダイアログを設定。\r
612         MakeDialog mkDlg(this, TPI_COMMAND_ADD);\r
613 \r
614         TPI_SWITCHES swInfo;\r
615         swInfo.pCustomSwitches       = NULL;\r
616 \r
617         if (e.GetClientData() == NULL)\r
618         {\r
619                 if (::wxGetKeyState(WXK_SHIFT))\r
620                 {\r
621                         // 処理対象のフォルダを選択。\r
622                         wxDirDialog dd(this, _("Choose dir to add"), this->conf.ReadHistory(CONF_HISTORY_PATH, 0), wxDD_DIR_MUST_EXIST);\r
623                         if (dd.ShowModal() == wxID_CANCEL)\r
624                         {\r
625                                 return;\r
626                         }\r
627                         swInfo.fnDestinationDirectory = wxFileName(dd.GetPath());\r
628                         this->conf.WriteHistory(CONF_HISTORY_PATH, swInfo.fnDestinationDirectory.GetPath());\r
629                         mkDlg.files.Add(swInfo.fnDestinationDirectory.GetFullName());\r
630                 }\r
631                 else\r
632                 {\r
633                         // 処理対象のファイルを選択。\r
634                         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
635                         if (fd.ShowModal() == wxID_CANCEL)\r
636                         {\r
637                                 return;\r
638                         }\r
639                         fd.GetFilenames(mkDlg.files);\r
640                         swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
641                         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
642                 }\r
643         }\r
644         else\r
645         {\r
646                 mkDlg.files = * (wxArrayString *) e.GetClientData();\r
647                 swInfo.fnDestinationDirectory = wxFileName::DirName(wxFileName(mkDlg.files[0]).GetPath());\r
648                 // 相対パスに変換。\r
649                 for (size_t n = 0; n < mkDlg.files.GetCount(); n++)\r
650                 {\r
651                         wxFileName fn(mkDlg.files[n]);\r
652                         fn.MakeRelativeTo(swInfo.fnDestinationDirectory.GetPath());\r
653                         mkDlg.files[n] = fn.GetFullPath();\r
654                 }\r
655         }\r
656 \r
657         // ダイアログを表示。\r
658         if (mkDlg.ShowModal() == wxID_CANCEL)\r
659         {\r
660                 return;\r
661         }\r
662 \r
663         // 各種設定。\r
664         swInfo.fMakeSFX              = false;\r
665         swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();\r
666         swInfo.fSolid               = mkDlg.cbSolid->IsChecked();\r
667         swInfo.fMMOptimize          = mkDlg.cbMMOptimize->IsChecked();\r
668         swInfo.fEncryptHeader       = mkDlg.cbEncryptHeader->IsChecked();\r
669         swInfo.nCompressLevel       = mkDlg.scLevel->GetValue();\r
670         swInfo.nRecoveryRecord      = mkDlg.scRR->GetValue();\r
671         swInfo.szPassword           = mkDlg.tcPassword->GetValue();\r
672         swInfo.szKeyFile            = mkDlg.tcKeyfile->GetValue();\r
673         swInfo.szComment            = mkDlg.tcComment->GetValue();\r
674 \r
675         // 処理を行う。\r
676         {\r
677                 ProcessDialog procDlg(this, mkDlg.files.GetCount(), this->szPassword);\r
678                 procDlg.Show(true);\r
679 \r
680                 tpi.Command(TPI_COMMAND_ADD, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
681                 this->ErrorCheck(tpi.nErrorCode);\r
682                 procDlg.Show(false);\r
683         }\r
684 \r
685         if (mkDlg.cbOpenAfter->IsChecked())\r
686         {\r
687                 // 作成先を開く。\r
688                 ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
689         }\r
690 \r
691         if (mkDlg.cbExitAfter->IsChecked())\r
692         {\r
693                 // 終了。\r
694                 this->Close(true);\r
695         }\r
696 \r
697         // 終了しない場合は書庫を再読み込み。\r
698         this->OnArcOpen(e);\r
699 }\r
700 \r
701 void MainFrame::OnArcConvert(wxCommandEvent& e)\r
702 {\r
703         TPI_SWITCHES swInfo;\r
704         swInfo.fMakeSFX = e.GetId() == XRCID("Arc_SFX");\r
705 \r
706         // 保存先を尋ねる。\r
707         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
708         if (fd.ShowModal() == wxID_CANCEL)\r
709         {\r
710                 return;\r
711         }\r
712         swInfo.fnDestinationDirectory = wxFileName::DirName(fd.GetDirectory());\r
713         this->conf.WriteHistory(CONF_HISTORY_PATH, fd.GetDirectory());\r
714 \r
715         wxArrayString files;\r
716         files.Add(fd.GetPath());\r
717 \r
718         ProcessDialog procDlg(this);\r
719         procDlg.Show(true);\r
720         tpi.Command(swInfo.fMakeSFX ? TPI_COMMAND_SFX : TPI_COMMAND_UNSFX, & swInfo, this->fnArchive.GetFullPath(), files);\r
721         this->ErrorCheck(tpi.nErrorCode);\r
722         procDlg.Show(false);\r
723 }\r
724 \r
725 void MainFrame::OnArcExtract(wxCommandEvent& e)\r
726 {\r
727         TPI_SWITCHES swInfo;\r
728         swInfo.pCustomSwitches = NULL;\r
729         swInfo.szPassword = this->szPassword;\r
730 \r
731         // モード取得。通常は0, 実行なら1, ファイルDnDなら2、ディレクトリDnDなら3、クリップボードなら4、コンテキストメニューからなら8。\r
732         int nMode = e.GetInt();\r
733         if (e.GetInt() == 8)\r
734         {\r
735                 nMode = 0;\r
736         }\r
737         // 実行時のみ使用。\r
738         wxFileType * ftFile = NULL;\r
739 \r
740         // 展開ダイアログを作成。DnDまたは実行時は表示しない。\r
741         MakeDialog mkDlg(this, TPI_COMMAND_EXTRACT);\r
742         mkDlg.files    = MakeTargetFileList(this, nMode == 1, nMode == 0);\r
743 \r
744         bool bMakeDir = false;\r
745         if (nMode != 0)\r
746         {\r
747                 // 作業ディレクトリ作成。\r
748                 swInfo.fStoreDirectoryPathes = false;\r
749                 wxString szDestDirBase = nMode == 3 ? this->tree_ctrl->GetItemText(this->tree_ctrl->GetSelection()) : wxT("tpi_tmp");\r
750                 if (szDestDirBase == wxT("-----"))\r
751                 {\r
752                         // 書庫ルートのときは書庫名にしておく。\r
753                         szDestDirBase = this->fnArchive.GetName();\r
754                 }\r
755                 swInfo.fnDestinationDirectory = MakeDirPath(wxFileName::DirName(wxStandardPaths::Get().GetTempDir()), szDestDirBase, true);\r
756                 if (! swInfo.fnDestinationDirectory.IsOk())\r
757                 {\r
758                         wxLogError(_("Unable to make the temporary directory!"));\r
759                         return;\r
760                 }\r
761         }\r
762         else\r
763         {\r
764                 if (mkDlg.ShowModal() == wxID_CANCEL)\r
765                 {\r
766                         return;\r
767                 }\r
768 \r
769                 // 各種設定。\r
770                 swInfo.fStoreDirectoryPathes = ! mkDlg.cbIgnorePath->IsChecked();\r
771                 swInfo.fnDestinationDirectory = wxFileName::DirName(mkDlg.cbDir->GetValue());\r
772                 swInfo.szPassword = mkDlg.tcPassword->GetValue();\r
773                 swInfo.szKeyFile  = mkDlg.tcKeyfile->GetValue();\r
774 \r
775                 // 必要なら書庫名でディレクトリを作成する。\r
776                 bMakeDir = WillMakeDirByArcName(this, & mkDlg);\r
777                 if (bMakeDir)\r
778                 {\r
779                         swInfo.fnDestinationDirectory = MakeDirPath(swInfo.fnDestinationDirectory, this->fnArchive.GetName(), true);\r
780                         if (! swInfo.fnDestinationDirectory.IsOk())\r
781                         {\r
782                                 wxLogError(_("Unable to make the destination directory!"));\r
783                                 return;\r
784                         }\r
785                 }\r
786         }\r
787 \r
788         // 処理を行う。\r
789         {\r
790                 ProcessDialog procDlg(this, mkDlg.files.GetCount(), this->szPassword);\r
791                 procDlg.Show(true);\r
792 \r
793                 tpi.Command(TPI_COMMAND_EXTRACT, & swInfo, this->fnArchive.GetFullPath(), mkDlg.files);\r
794                 this->ErrorCheck(tpi.nErrorCode);\r
795                 procDlg.Show(false);\r
796         }\r
797 \r
798         if (nMode == 0)\r
799         {\r
800                 if (mkDlg.cbOpenAfter->IsChecked())\r
801                 {\r
802                         // 展開先を開く。\r
803                         if (mkDlg.chDirMake->GetSelection() == 2 && ! bMakeDir)\r
804                         {\r
805                                 wxTreeItemId tiArcSub = this->tree_ctrl->GetLastChild(this->tree_ctrl->GetLastChild(this->tree_ctrl->GetRootItem()));\r
806                                 if (tiArcSub.IsOk())\r
807                                 {\r
808                                         swInfo.fnDestinationDirectory.SetFullName(this->tree_ctrl->GetItemText(tiArcSub));\r
809                                 }\r
810                         }\r
811                         ::wxExecute(DIR_APP + QuoteString(swInfo.fnDestinationDirectory.GetFullPath()));\r
812                 }\r
813 \r
814                 if (mkDlg.cbExitAfter->IsChecked())\r
815                 {\r
816                         // 終了。\r
817                         this->Close(true);\r
818                 }\r
819         }\r
820         else\r
821         {\r
822                 if (nMode == 1)\r
823                 {\r
824                         // コマンドを取得。\r
825                         ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(wxFileName(mkDlg.files[0], wxPATH_DOS).GetExt());\r
826                         if (! ftFile || ftFile->GetOpenCommand(wxEmptyString).IsEmpty())\r
827                         {\r
828                                 // 種類が取得できないときはテキストとみなす。\r
829                                 ftFile = wxTheMimeTypesManager->GetFileTypeFromExtension(this->conf.ReadId(CONF_DEFAULT_EXT, (wxString) wxT("txt")));\r
830                         }\r
831 \r
832                         // コマンドを実行。\r
833                         wxString szTempFile = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[0], wxPATH_DOS).GetFullName();\r
834                         bool fSuccess = tpi.nErrorCode == TPI_ERROR_SUCCESS && ftFile != NULL;\r
835                         myProcess * pCallback = new myProcess(szTempFile, swInfo.fnDestinationDirectory.GetPath());\r
836                         if (fSuccess)\r
837                         {\r
838 #ifdef __LINUX__\r
839                                 // Linuxでは引用符で囲む必要がある。\r
840                                 fSuccess = ::wxExecute(ftFile->GetOpenCommand(QuoteString(szTempFile)), wxEXEC_ASYNC, pCallback) > 0;\r
841 #else\r
842                                 fSuccess = ::wxExecute(ftFile->GetOpenCommand(szTempFile), wxEXEC_ASYNC, pCallback) > 0;\r
843 #endif\r
844                         }\r
845                         if (! fSuccess)\r
846                         {\r
847                                 pCallback->OnTerminate(0, 0);\r
848                         }\r
849                 }\r
850                 else\r
851                 {\r
852                         // 展開対象を決定。\r
853                         wxArrayString asFiles;\r
854                         myFileDataObject * objFile = new myFileDataObject();\r
855                         objFile->szTempDir = nMode == 3 ? swInfo.fnDestinationDirectory.GetPath() : swInfo.fnDestinationDirectory.GetFullPath();\r
856                         for (size_t i = 0; i < mkDlg.files.GetCount(); i++)\r
857                         {\r
858                                 wxString szFileName = swInfo.fnDestinationDirectory.GetPathWithSep() + wxFileName(mkDlg.files[i], wxPATH_DOS).GetFullName();\r
859                                 if (nMode == 3)\r
860                                 {\r
861                                         asFiles.Add(szFileName);\r
862                                 }\r
863                                 else\r
864                                 {\r
865                                         // リストに追加。\r
866                                         objFile->AddFile(szFileName);\r
867                                 }\r
868                         }\r
869                         if (nMode == 3)\r
870                         {\r
871                                 objFile->AddFile(objFile->szTempDir);\r
872                         }\r
873 \r
874                         if (nMode == 4)\r
875                         {\r
876                                 wxTheClipboard->SetData(objFile);\r
877                         }\r
878                         else\r
879                         {\r
880                                 // 自身にドロップされると煩雑なので、一時的にドロップを受け付けないようにしておく。\r
881                                 this->SetDropTarget(NULL);\r
882 \r
883                                 // DnD開始。\r
884                                 wxDropSource dropSource(* objFile, this);\r
885                                 wxDragResult drResult = dropSource.DoDragDrop();\r
886                                 if (drResult != wxDragCancel && drResult != wxDragNone && drResult != wxDragMove)\r
887                                 {\r
888 #ifdef __LINUX__\r
889                                         // Linuxではまだ処理が終わっていない(コンテキストメニューが表示されている)ので、とりあえず3秒だけ待つ。\r
890                                         sleep(3);\r
891 #endif\r
892                                 }\r
893                                 this->SetDropTarget(new myFileDropTarget(this));\r
894 \r
895                                 // ディレクトリDnDのときは、先にディレクトリの中のファイルを消しておく。\r
896                                 if (nMode == 3)\r
897                                 {\r
898                                         for (size_t i = 0; i < asFiles.GetCount(); i++)\r
899                                         {\r
900                                                 chmod(asFiles[i].ToUTF8(), 0600);\r
901                                                 ::wxRemoveFile(asFiles[i]);\r
902                                         }\r
903                                 }\r
904 \r
905                                 delete objFile;\r
906                         }\r
907                 }\r
908         }\r
909 }\r
910 \r
911 void MainFrame::OnArcDelete(wxCommandEvent& e)\r
912 {\r
913         // 全ファイル削除は危険ではないかと。\r
914         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
915         {\r
916                 // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
917                 SetMenuToolState("Arc_Delete", false);\r
918                 return;\r
919         }\r
920 \r
921         if (::AskDlg(_("Are you sure to delete selected files?"), this) == wxNO)\r
922         {\r
923                 return;\r
924         }\r
925 \r
926         // 処理を行う。\r
927         {\r
928                 wxArrayString asFiles = MakeTargetFileList(this);\r
929                 ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
930                 procDlg.Show(true);\r
931 \r
932                 TPI_SWITCHES swInfo;\r
933                 swInfo.szPassword = this->szPassword;\r
934                 tpi.Command(TPI_COMMAND_DELETE, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
935                 this->ErrorCheck(tpi.nErrorCode);\r
936                 procDlg.Show(false);\r
937         }\r
938 \r
939         // 書庫を再読み込みする。\r
940         this->OnArcOpen(e);\r
941 }\r
942 \r
943 void MainFrame::OnArcTest(wxCommandEvent&)\r
944 {\r
945         // 処理を行う。\r
946         wxArrayString asFiles = MakeTargetFileList(this);\r
947         ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
948         procDlg.Show(true);\r
949 \r
950         TPI_SWITCHES swInfo;\r
951         swInfo.szPassword = this->szPassword;\r
952         tpi.Command(TPI_COMMAND_TEST, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
953         this->ErrorCheck(tpi.nErrorCode);\r
954         procDlg.Show(false);\r
955 }\r
956 \r
957 void MainFrame::OnArcRepair(wxCommandEvent&)\r
958 {\r
959         // 処理を行う。\r
960         wxArrayString asFiles = MakeTargetFileList(this);\r
961         ProcessDialog procDlg(this, asFiles.GetCount(), this->szPassword);\r
962         procDlg.Show(true);\r
963 \r
964         TPI_SWITCHES swInfo;\r
965         swInfo.szPassword = this->szPassword;\r
966         tpi.Command(TPI_COMMAND_REPAIR, & swInfo, this->fnArchive.GetFullPath(), asFiles);\r
967         this->ErrorCheck(tpi.nErrorCode);\r
968         procDlg.Show(false);    \r
969 }\r
970 \r
971 void MainFrame::OnExeCopy(wxCommandEvent & e)\r
972 {\r
973         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
974         {\r
975                 // wxのバグで自動では無効化できないので、実行しようとしたときに無効化する。\r
976                 this->menubar->Enable(XRCID("Exe_Copy"), false);\r
977                 return;\r
978         }\r
979 \r
980         if (! wxTheClipboard->Open())\r
981         {\r
982                 return;\r
983         }\r
984 \r
985         e.SetInt(4);\r
986         this->OnArcExtract(e);\r
987         wxTheClipboard->Close();\r
988 }\r
989 \r
990 void MainFrame::OnViewMode(wxCommandEvent & e)\r
991 {\r
992         int n = e.GetId();\r
993         this->menubar->Check(n, true);\r
994         this->list_ctrl->SetSingleStyle(wxLC_REPORT, n == XRCID("Exe_View_Details"));\r
995         this->list_ctrl->SetSingleStyle(wxLC_ICON,   n == XRCID("Exe_View_Icons"));\r
996         this->list_ctrl->SetSingleStyle(wxLC_LIST,   n == XRCID("Exe_View_List"));\r
997 }\r
998 \r
999 void MainFrame::OnShowToolBar(wxCommandEvent & e)\r
1000 {\r
1001         this->toolbar->Show(e.IsChecked());\r
1002 }\r
1003 \r
1004 void MainFrame::OnShowStatusBar(wxCommandEvent & e)\r
1005 {\r
1006         this->statusbar->Show(e.IsChecked());\r
1007 }\r
1008 \r
1009 void MainFrame::OnSelectAll(wxCommandEvent &)\r
1010 {\r
1011         for (int i = 0; i < this->list_ctrl->GetItemCount(); i++)\r
1012         {\r
1013                 this->list_ctrl->Select(i, true);\r
1014         }\r
1015 }\r
1016 \r
1017 // TreeView\r
1018 \r
1019 void MainFrame::OnTreeChanged(wxTreeEvent& e)\r
1020 {\r
1021         // ツリービューからパスを取得。\r
1022         wxString szNodePath = TreeView_GetItemPath(this->tree_ctrl, e.GetItem());\r
1023         // リストビューを初期化。\r
1024         this->list_ctrl->apShowFile.Clear();\r
1025         this->list_ctrl->DeleteAllItems();\r
1026         g_hIconLL.RemoveAll();\r
1027         g_hIconLS.RemoveAll();\r
1028 \r
1029         // 現在のアイテムの選択状態を無効にしておく。\r
1030         long nSelected = this->list_ctrl->GetFirstSelected();\r
1031         while (nSelected != -1)\r
1032         {\r
1033                 this->list_ctrl->Select(nSelected, false);\r
1034                 nSelected = this->list_ctrl->GetNextSelected(nSelected);\r
1035         }\r
1036 \r
1037         // アイコン設定。\r
1038         this->list_ctrl->SetImageList(& g_hIconLL, wxIMAGE_LIST_NORMAL);\r
1039         this->list_ctrl->SetImageList(& g_hIconLS, wxIMAGE_LIST_SMALL);\r
1040 \r
1041         // 配列と比較し、パスが一致しなければ消す。\r
1042         for (size_t i = 0; i < this->fileinfo.GetCount(); i++)\r
1043         {\r
1044                 // パスを比較。\r
1045                 if (szNodePath == wxT("*") || szNodePath == this->fileinfo[i].fnFileName.GetPath())\r
1046                 {\r
1047                         // 項目がフォルダであるなら無視。\r
1048                         if (this->fileinfo[i].fnFileName.IsDir() || ! TreeView_CheckNewerItem(this->tree_ctrl, this->tree_ctrl->GetLastChild(this->tree_ctrl->GetRootItem()), this->fileinfo[i].fnFileName.GetFullPath(), false))\r
1049                         {\r
1050                                 continue;\r
1051                         }\r
1052 \r
1053                         // フィルタにかからなければ無視。\r
1054                         if (this->fileinfo[i].fnFileName.GetFullName().MakeLower().Find(this->tcFilter->GetValue().MakeLower()) == wxNOT_FOUND)\r
1055                         {\r
1056                                 continue;\r
1057                         }\r
1058 \r
1059                         this->list_ctrl->apShowFile.Add(& this->fileinfo[i]);\r
1060                 }\r
1061         }\r
1062 \r
1063         // ソートして表示。\r
1064         this->list_ctrl->apShowFile.Sort(& ListCtrlCompareProc);\r
1065         this->list_ctrl->SetItemCount(this->list_ctrl->apShowFile.GetCount());\r
1066 }\r
1067 \r
1068 void MainFrame::OnTreeBeginDrag(wxTreeEvent& e)\r
1069 {\r
1070         // TODO : アイテムが子階層を持っていても展開できない。\r
1071         this->tree_ctrl->SelectItem(e.GetItem());\r
1072 \r
1073         wxCommandEvent e1;\r
1074         e1.SetInt(3);\r
1075         this->OnArcExtract(e1);\r
1076 }\r
1077 \r
1078 void MainFrame::OnContextMenu(wxContextMenuEvent& e)\r
1079 {\r
1080         wxPoint p = e.GetPosition();\r
1081         this->list_ctrl->PopupMenu(this->menubar->GetMenu(1), p == wxDefaultPosition ? this->list_ctrl->GetPosition() : this->list_ctrl->ScreenToClient(p));\r
1082 }\r
1083 \r
1084 // ListView\r
1085 \r
1086 void MainFrame::OnListItemSelect(wxListEvent&)\r
1087 {\r
1088         // ファイルに対する動作の設定。但し、選択解除時はwxのバグで呼び出されない。\r
1089         bool fEnable = this->list_ctrl->GetSelectedItemCount() > 0;\r
1090         SetMenuToolState("Arc_Delete", fEnable && (this->aiArchive.fiInfo.eSupportedCommand & TPI_COMMAND_DELETE) == TPI_COMMAND_DELETE && this->aiArchive.fiInfo.fArchive);\r
1091         this->menubar->Enable(XRCID("Exe_Copy"), fEnable);\r
1092 }\r
1093 \r
1094 void MainFrame::OnListItemDClick(wxListEvent&)\r
1095 {\r
1096         wxCommandEvent e;\r
1097         e.SetInt(1);\r
1098         this->OnArcExtract(e);\r
1099 }\r
1100 \r
1101 void MainFrame::OnListBeginDrag(wxListEvent&)\r
1102 {\r
1103         if (this->list_ctrl->GetSelectedItemCount() == 0)\r
1104         {\r
1105                 // アイテムを選択せずドラッグしようとした場合。\r
1106                 return;\r
1107         }\r
1108 \r
1109         wxCommandEvent e;\r
1110         e.SetInt(2);\r
1111         this->OnArcExtract(e);\r
1112 }\r
1113 \r
1114 // Filter\r
1115 \r
1116 void MainFrame::OnFilter(wxCommandEvent&)\r
1117 {\r
1118         wxTreeEvent e;\r
1119         e.SetItem(this->tree_ctrl->GetSelection());\r
1120         this->OnTreeChanged(e);\r
1121 }\r
1122 \r
1123 // イベントハンドラ以外。\r
1124 \r
1125 bool MainFrame::LoadTPI(const wxString & szFileName, wxULongLong_t * llFileCount)\r
1126 {\r
1127         // 書庫を開いていれば閉じておく。\r
1128         wxCommandEvent e;\r
1129         this->OnArcClose(e);\r
1130 \r
1131         // TPIを読み込み。\r
1132         wxDir fs(L_DIR_B_LIB);\r
1133         wxString szTPIName;\r
1134         if (fs.GetFirst(& szTPIName, wxT("*" TPI_EXT)))\r
1135         {\r
1136                 do\r
1137                 {\r
1138                         // 初期化。\r
1139                         if (! tpi.InitLibrary(L_DIR_B_LIB + szTPIName, szFileName, TPICallbackProc))\r
1140                         {\r
1141                                 tpi.FreeLibrary();\r
1142                                 continue;\r
1143                         }\r
1144 \r
1145                         // 対応確認。\r
1146                         if (! tpi.OpenArchive(szFileName, llFileCount))\r
1147                         {\r
1148                                 tpi.FreeLibrary();\r
1149                                 * llFileCount = 0;\r
1150                                 continue;\r
1151                         }\r
1152                         return true;\r
1153                 }\r
1154                 while (fs.GetNext(& szTPIName));\r
1155         }\r
1156         return false;\r
1157 }\r
1158 \r
1159 int MainFrame::ErrorCheck(int nErrorCode, const wxString & szAPIName)\r
1160 {\r
1161         switch (nErrorCode)\r
1162         {\r
1163         case TPI_ERROR_SUCCESS:\r
1164         case TPI_ERROR_S_ENDOFDATA:\r
1165         case TPI_CALLBACK_CONTINUE:\r
1166                 break;\r
1167         case TPI_ERROR_D_UNSUPPORTED:\r
1168                 wxLogError(_("Sorry, this function is not supported yet."));\r
1169                 break;\r
1170         case TPI_ERROR_D_SKIPPED:\r
1171         case TPI_CALLBACK_CANCEL:\r
1172                 break;\r
1173         default:\r
1174                 wxLogError(_("Error: %s()!\nError code: %d"), szAPIName.c_str(), nErrorCode);\r
1175         }\r
1176         return nErrorCode;\r
1177 }\r