OSDN Git Service

追加時に作成時と同様のダイアログを表示し、詳細な設定を行える機能を追加。
[tpi/lychee.git] / src / lychee / dlg_make.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 "dlg_make.h"\r
25 #include "frm_main.h"\r
26 #include "functions.h"\r
27 \r
28 #include <wx/dirdlg.h>\r
29 #include <wx/arrimpl.cpp>\r
30 \r
31 WX_DEFINE_OBJARRAY(ArrayTPI_FORMATINFO);\r
32 \r
33 //******************************************************************************\r
34 // MakeDialog\r
35 //******************************************************************************\r
36 \r
37 MakeDialog::MakeDialog(): wxDialog()\r
38 {\r
39         this->uCommand = TPI_COMMAND_CREATE;\r
40 }\r
41 \r
42 //******************************************************************************\r
43 // Event Table.\r
44 //******************************************************************************\r
45 \r
46 BEGIN_EVENT_TABLE(MakeDialog, wxDialog)\r
47         EVT_INIT_DIALOG(                 MakeDialog::OnInit)\r
48         EVT_BUTTON(XRCID("btnDefault"),  MakeDialog::OnBtnDefault)\r
49         EVT_BUTTON(XRCID("btnDesktop"),  MakeDialog::OnBtnDesktop)\r
50         EVT_BUTTON(XRCID("btnCurrent"),  MakeDialog::OnBtnCurrent)\r
51         EVT_BUTTON(XRCID("btnBrowse"),   MakeDialog::OnBtnBrowse)\r
52         EVT_BUTTON(XRCID("btnBrowseKF"), MakeDialog::OnBtnBrowseKF)\r
53         EVT_BUTTON(XRCID("btnOK"),       MakeDialog::OnBtnOK)\r
54         EVT_BUTTON(XRCID("btnCancel"),   MakeDialog::OnBtnCancel)\r
55         EVT_CHOICE(XRCID("chType"),      MakeDialog::OnChoice)\r
56         EVT_CHECKBOX(XRCID("cbUnmask"),  MakeDialog::OnCbUnmask)\r
57         EVT_CHECKBOX(XRCID("cbMakeSFX"), MakeDialog::OnCbMakeSFX)\r
58         EVT_NOTEBOOK_PAGE_CHANGED(XRCID("nbTabs"), MakeDialog::OnTabChanged)\r
59 END_EVENT_TABLE()\r
60 \r
61 //******************************************************************************\r
62 // Event handler.\r
63 //******************************************************************************\r
64 \r
65 void MakeDialog::OnInit(wxInitDialogEvent&)\r
66 {\r
67         // XRCと結びつけ。\r
68         // "General"タブ\r
69         this->cbDir             = XRCCTRL(* this, "cbDir",        wxComboBox);\r
70         this->cbFileName        = XRCCTRL(* this, "cbFileName",   wxComboBox);\r
71         this->cbOpenAfter       = XRCCTRL(* this, "cbOpenAfter",  wxCheckBox);\r
72         this->cbIgnorePath      = XRCCTRL(* this, "cbIgnorePath", wxCheckBox);\r
73         this->cbExitAfter       = XRCCTRL(* this, "cbExitAfter",  wxCheckBox);\r
74         this->chType            = XRCCTRL(* this, "chType",       wxChoice);\r
75         this->chDirMake         = XRCCTRL(* this, "chDirMake",    wxChoice);\r
76         // "Config"タブ\r
77         this->scLevel           = XRCCTRL(* this, "scLevel",      wxSpinCtrl);\r
78         this->scRR              = XRCCTRL(* this, "scRR",         wxSpinCtrl);\r
79         this->tcPassword        = XRCCTRL(* this, "tcPassword",   wxTextCtrl);\r
80         this->tcKeyfile         = XRCCTRL(* this, "tcKeyfile",    wxTextCtrl);\r
81         this->cbSplitSize       = XRCCTRL(* this, "cbSplitSize",  wxComboBox);\r
82         this->cbUnmask          = XRCCTRL(* this, "cbUnmask",     wxCheckBox);\r
83         this->cbEncryptHeader   = XRCCTRL(* this, "cbEncryptHeader", wxCheckBox);\r
84         this->cbSolid           = XRCCTRL(* this, "cbSolid",      wxCheckBox);\r
85         this->cbMMOptimize      = XRCCTRL(* this, "cbMMOptimize", wxCheckBox);\r
86         this->cbMakeSFX         = XRCCTRL(* this, "cbMakeSFX",    wxCheckBox);\r
87         // "Comment"タブ\r
88         this->tcComment         = XRCCTRL(* this, "tcComment",    wxTextCtrl);\r
89         // "Files"タブ\r
90         this->lcFiles           = XRCCTRL(* this, "lcFiles",      wxListCtrl);\r
91 \r
92         // 2回目以降は無視。\r
93         if (! this->cbDir->GetValue().IsEmpty())\r
94         {\r
95                 return;\r
96         }\r
97 \r
98         // ListCtrlに列を追加。\r
99         this->lcFiles->InsertColumn(0, _("Input"),  wxLIST_FORMAT_LEFT,  150);\r
100         this->lcFiles->InsertColumn(1, _("Output"), wxLIST_FORMAT_LEFT,  300);\r
101 \r
102         ::wxXmlResource::Get()->Unload(L_DIR_S_XRC wxT("dlg_make.xrc"));\r
103 \r
104         // 事前準備。\r
105         MainFrame * frm_main = (MainFrame *) this->GetParent();\r
106         wxString szArcPath = frm_main->fnArchive.GetPath(), szArcName = frm_main->fnArchive.GetName();\r
107 \r
108         // パス履歴読み込み。\r
109         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_PATH); i++)\r
110         {\r
111                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_PATH, i);\r
112                 if (sz.IsEmpty())\r
113                 {\r
114                         continue;\r
115                 }\r
116 \r
117                 this->cbDir->Append(sz);\r
118         }\r
119         // 書庫名履歴読み込み。\r
120         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_NAME); i++)\r
121         {\r
122                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_NAME, i);\r
123                 if (sz.IsEmpty())\r
124                 {\r
125                         continue;\r
126                 }\r
127 \r
128                 this->cbFileName->Append(sz);\r
129         }\r
130 \r
131         // パスを設定。\r
132         this->cbDir->SetValue(szArcPath);\r
133 \r
134         // コマンド別の処理。\r
135         switch (this->uCommand)\r
136         {\r
137         case TPI_COMMAND_EXTRACT:\r
138                 // 初期値を設定。\r
139                 this->SetTitle(_("Extract"));\r
140                 this->tcComment->SetValue(frm_main->aiArchive.szComment);\r
141 \r
142                 // 展開先を予測。ただしDTVスキャンに時間がかかる場合はスキップ可能。\r
143                 if (this->files.GetCount() < 3000 || ::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) == wxYES)\r
144                 {\r
145                         wxNotebookEvent e;\r
146                         e.SetSelection(-3);\r
147                         this->OnTabChanged(e);\r
148                 }\r
149 \r
150                 // コントロールを無効化。\r
151                 this->scLevel->Disable();\r
152                 this->scRR->Disable();\r
153                 this->cbEncryptHeader->Disable();\r
154                 this->cbSolid->Disable();\r
155                 this->cbMMOptimize->Disable();\r
156                 this->tcComment->SetEditable(false);\r
157         case TPI_COMMAND_ADD:\r
158                 // コントロールを無効化(展開時も)。\r
159                 this->cbFileName->Disable();\r
160                 this->chType->Disable();\r
161                 this->chDirMake->Enable();\r
162                 this->cbSplitSize->Disable();\r
163                 this->cbMakeSFX->Disable();\r
164 \r
165                 // 書庫名を設定。\r
166                 this->cbFileName->SetValue(szArcName);\r
167 \r
168                 // 書庫形式欄を設定。\r
169                 this->afInfo.Add(frm_main->aiArchive.fiInfo);\r
170                 this->chType->Append(frm_main->aiArchive.fiInfo.szTypeName);\r
171 \r
172                 // とりあえず最初の形式にしておく。\r
173                 this->chType->SetSelection(0);\r
174                 {\r
175                         wxCommandEvent e;\r
176                         e.SetInt(0);\r
177                         this->OnChoice(e);\r
178                 }\r
179 \r
180                 if (this->uCommand != TPI_COMMAND_ADD)\r
181                 {\r
182                         break;\r
183                 }\r
184                 this->SetTitle(_("Add"));\r
185 \r
186                 // コントロールを無効化(追加時のみ)。\r
187                 this->cbDir->Disable();\r
188                 this->chDirMake->Disable();\r
189                 break;\r
190         case TPI_COMMAND_CREATE:\r
191                 this->SetTitle(_("Create"));\r
192 \r
193                 // 書庫名を設定。初期化の都合上.を付加しておく。\r
194                 this->cbFileName->SetValue(szArcName + wxT('.'));\r
195 \r
196                 // ライブラリを検索。\r
197                 TPIHandle tpi;\r
198                 wxFileSystem fs;\r
199                 fs.ChangePathTo(L_DIR_B_LIB, true);\r
200                 wxString szTPIName = fs.FindFirst(wxT("*" TPI_EXT), wxFILE);\r
201                 while (! szTPIName.IsEmpty())\r
202                 {\r
203                         // ロード。\r
204                         if (tpi.InitLibrary(szTPIName, wxEmptyString, 0))\r
205                         {\r
206                                 // 対応する形式名を取得。\r
207                                 TPI_FORMATINFO fiInfo;\r
208                                 if (tpi.GetFormatInformation(& fiInfo, true))\r
209                                 {\r
210                                         do\r
211                                         {\r
212                                                 if (fiInfo.llSupportedCommand & TPI_COMMAND_CREATE && (this->files.GetCount() == 1 || fiInfo.fArchive))\r
213                                                 {\r
214                                                         fiInfo.szTPIName = szTPIName;\r
215                                                         this->afInfo.Add(fiInfo);\r
216                                                         this->chType->Append(fiInfo.szTypeName);\r
217                                                 }\r
218                                         }\r
219                                         while (tpi.GetFormatInformation(& fiInfo, false));\r
220                                 }\r
221                                 tpi.FreeLibrary();\r
222                         }\r
223                         szTPIName = fs.FindNext();\r
224                 }\r
225 \r
226                 // とりあえず最初の形式にしておく。\r
227                 this->chType->SetSelection(0);\r
228                 {\r
229                         wxCommandEvent e;\r
230                         e.SetInt(0);\r
231                         this->OnChoice(e);\r
232                 }\r
233                 break;\r
234         }\r
235 }\r
236 \r
237 void MakeDialog::OnBtnDefault(wxCommandEvent&)\r
238 {\r
239         this->cbDir->SetValue(((MainFrame *) this->GetParent())->conf.ReadId(CONF_DEFAULT_PATH, (wxString) wxEmptyString));\r
240 }\r
241 \r
242 void MakeDialog::OnBtnDesktop(wxCommandEvent&)\r
243 {\r
244         wxFileName fn(wxFileName::GetHomeDir(), wxT("Desktop"));\r
245         this->cbDir->SetValue(fn.GetFullPath());\r
246 }\r
247 \r
248 void MakeDialog::OnBtnCurrent(wxCommandEvent&)\r
249 {\r
250         this->cbDir->SetValue(((MainFrame *) this->GetParent())->fnArchive.GetPath());\r
251 }\r
252 \r
253 void MakeDialog::OnBtnBrowse(wxCommandEvent&)\r
254 {\r
255         wxDirDialog dd(this);\r
256         dd.SetPath(this->cbDir->GetValue());\r
257         if (dd.ShowModal() == wxID_OK)\r
258         {\r
259                 this->cbDir->SetValue(dd.GetPath());\r
260         }\r
261 }\r
262 \r
263 void MakeDialog::OnBtnBrowseKF(wxCommandEvent&)\r
264 {\r
265         wxFileDialog fd(this);\r
266         fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
267         if (fd.ShowModal() == wxID_OK)\r
268         {\r
269                 this->tcKeyfile->SetValue(fd.GetPath());\r
270         }\r
271 }\r
272 \r
273 void MakeDialog::OnBtnOK(wxCommandEvent&)\r
274 {\r
275         // 履歴書き込み。\r
276         if (this->uCommand != TPI_COMMAND_ADD)\r
277         {\r
278                 MainFrame * frm_main = (MainFrame *) this->GetParent();\r
279                 wxFileName fnCurrent(this->cbDir->GetValue(), this->uCommand == TPI_COMMAND_CREATE ? this->cbFileName->GetValue() : (wxString) wxEmptyString);\r
280                 frm_main->conf.WriteHistory(CONF_HISTORY_FULL, fnCurrent.GetFullPath());\r
281                 frm_main->conf.WriteHistory(CONF_HISTORY_PATH, fnCurrent.GetPath());\r
282                 frm_main->conf.WriteHistory(CONF_HISTORY_NAME, fnCurrent.GetFullName());\r
283         }\r
284         this->EndModal(wxID_OK);\r
285 }\r
286 \r
287 void MakeDialog::OnBtnCancel(wxCommandEvent&)\r
288 {\r
289         this->EndModal(wxID_CANCEL);\r
290 }\r
291 \r
292 void MakeDialog::OnChoice(wxCommandEvent& e)\r
293 {\r
294         TPI_FORMATINFO * fiInfo = & this->afInfo[e.GetInt()];\r
295         // 形式が各種設定に対応しているか。\r
296         // 作成時/追加時/展開時設定。\r
297         this->tcPassword->Enable(fiInfo->fEncryptPassword);\r
298         this->cbUnmask->Enable(fiInfo->fEncryptPassword);\r
299         this->tcKeyfile->Enable(fiInfo->fEncryptKeyFile);\r
300         if (this->uCommand == TPI_COMMAND_EXTRACT)\r
301         {\r
302                 return;\r
303         }\r
304 \r
305         // 作成時/追加時設定。\r
306         this->scLevel->SetRange(fiInfo->sCompressLevelMin, fiInfo->sCompressLevelMax);\r
307         this->scLevel->SetValue(fiInfo->sCompressLevelMax);\r
308         this->scLevel->Enable(fiInfo->sCompressLevelMin != fiInfo->sCompressLevelMax);\r
309         this->scRR->SetRange(fiInfo->sRecoveryRecordMin, fiInfo->sRecoveryRecordMax);\r
310         this->scRR->SetValue(fiInfo->sRecoveryRecordMin);\r
311         this->scRR->Enable(fiInfo->sRecoveryRecordMin != fiInfo->sRecoveryRecordMax);\r
312         this->cbEncryptHeader->Enable(fiInfo->fEncryptHeader);\r
313         this->cbSolid->Enable(fiInfo->fSolid);\r
314         this->cbMMOptimize->Enable(fiInfo->fMMOptimize);\r
315         this->tcComment->Enable(fiInfo->fComment);\r
316         if (this->uCommand == TPI_COMMAND_ADD)\r
317         {\r
318                 return;\r
319         }\r
320 \r
321         // 作成時設定。\r
322         this->cbSplitSize->Enable(fiInfo->fMultiVolume);\r
323         this->cbMakeSFX->Enable(fiInfo->fSFX);\r
324 \r
325         wxFileName fn(this->cbFileName->GetValue());\r
326         fn.SetExt(this->cbMakeSFX->IsEnabled() && this->cbMakeSFX->IsChecked() ? EXE_EXT : fiInfo->szSuffix.BeforeFirst(wxT(';')));\r
327         this->cbFileName->SetValue(fn.GetFullName());\r
328 }\r
329 \r
330 void MakeDialog::OnCbUnmask(wxCommandEvent&)\r
331 {\r
332         this->tcPassword->SetWindowStyle(this->tcPassword->GetWindowStyle() & (this->cbUnmask->IsChecked() ? ~ wxTE_PASSWORD : wxTE_PASSWORD));\r
333         this->tcPassword->Refresh();\r
334 }\r
335 \r
336 void MakeDialog::OnCbMakeSFX(wxCommandEvent&)\r
337 {\r
338         wxFileName fn(this->cbFileName->GetValue());\r
339         fn.SetExt(this->cbMakeSFX->IsChecked() ? EXE_EXT : this->afInfo[this->chType->GetSelection()].szSuffix.BeforeFirst(wxT(';')));\r
340         this->cbFileName->SetValue(fn.GetFullName());\r
341 }\r
342 \r
343 void MakeDialog::OnTabChanged(wxNotebookEvent& e)\r
344 {\r
345         // "Files"タブのときは処理。\r
346         bool bReallyShow = e.GetSelection() == 3;\r
347         if (abs(e.GetSelection()) != 3)\r
348         {\r
349                 return;\r
350         }\r
351 \r
352         // "Files"タブを表示する初回かどうか。\r
353         if (bReallyShow && this->lcFiles->GetItemCount() == 0)\r
354         {\r
355                 // ファイルリストを追加。\r
356                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
357                 {\r
358                         this->lcFiles->InsertItem(i, this->files[i]);\r
359                 }\r
360         }\r
361 \r
362         switch (this->uCommand)\r
363         {\r
364         case TPI_COMMAND_EXTRACT:\r
365         {\r
366                 // ファイルの出力先を推測。\r
367                 wxString szOutputRootDir = WillMakeDirByArcName((MainFrame *) this->GetParent(), this) ? MakeDirPath(wxFileName::DirName(this->cbDir->GetValue()), wxFileName(this->cbFileName->GetValue()).GetName(), false).GetPath() : this->cbDir->GetValue();\r
368 \r
369                 // 各ファイルにパスを付加。\r
370                 bool fDTVWarning = false;\r
371                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
372                 {\r
373                         wxString szOutputFile = szOutputRootDir + wxFileName::GetPathSeparator();\r
374                         wxFileName fnStored(this->files[i]);\r
375                         if (! this->cbIgnorePath->IsChecked())\r
376                         {\r
377                                 szOutputFile += fnStored.GetPathWithSep();\r
378                         }\r
379                         szOutputFile += fnStored.GetFullName();\r
380                         wxFileName fnOutput(szOutputFile);\r
381                         if (! fnOutput.Normalize() || ! fnOutput.GetFullPath().StartsWith(szOutputRootDir))\r
382                         {\r
383                                 fDTVWarning = true;\r
384                                 if (bReallyShow)\r
385                                 {\r
386                                         this->lcFiles->SetItemTextColour(i, * wxRED);\r
387                                 }\r
388                         }\r
389                         if (bReallyShow)\r
390                         {\r
391                                 this->lcFiles->SetItem(i, 1, fnOutput.GetFullPath());\r
392                         }\r
393                 }\r
394 \r
395                 if (fDTVWarning && ::AskDlg(_("This archive may have Directory Traversal Vulnerability(DTV) problem, and some danger files may be extracted to the unexpected system directory! It is strongly recommended to ignore file path. Would you like to do so?"), this) == wxYES)\r
396                 {\r
397                         this->cbIgnorePath->SetValue(true);\r
398                         if (bReallyShow)\r
399                         {\r
400                                 this->OnTabChanged(e);\r
401                         }\r
402                 }\r
403                 break;\r
404         }\r
405         case TPI_COMMAND_ADD:\r
406         case TPI_COMMAND_CREATE:\r
407                 // 格納パスを推測。\r
408                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
409                 {\r
410                         if (bReallyShow)\r
411                         {\r
412                                 this->lcFiles->SetItem(i, 1, this->files[i]);\r
413                         }\r
414                 }\r
415                 break;\r
416         }\r
417 }\r