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->cbSolid           = XRCCTRL(* this, "cbSolid",      wxCheckBox);\r
80         this->cbMMOptimize      = XRCCTRL(* this, "cbMMOptimize", wxCheckBox);\r
81         this->cbCompressHeader  = XRCCTRL(* this, "cbCompressHeader", wxCheckBox);\r
82         this->cbMakeSFX         = XRCCTRL(* this, "cbMakeSFX",    wxCheckBox);\r
83         // "Comment"タブ\r
84         this->tcComment         = XRCCTRL(* this, "tcComment",    wxTextCtrl);\r
85         // "Encryption"タブ\r
86         this->tcPassword        = XRCCTRL(* this, "tcPassword",   wxTextCtrl);\r
87         this->tcKeyfile         = XRCCTRL(* this, "tcKeyfile",    wxTextCtrl);\r
88         this->cbSplitSize       = XRCCTRL(* this, "cbSplitSize",  wxComboBox);\r
89         this->cbUnmask          = XRCCTRL(* this, "cbUnmask",     wxCheckBox);\r
90         this->cbEncryptHeader   = XRCCTRL(* this, "cbEncryptHeader", wxCheckBox);\r
91         this->chEncryptMethod   = XRCCTRL(* this, "chEncryptMethod", wxChoice);\r
92         // "Files"タブ\r
93         this->lcFiles           = XRCCTRL(* this, "lcFiles",      myListCtrl2);\r
94 \r
95         // 2回目以降は無視。\r
96         if (! this->cbDir->GetValue().IsEmpty())\r
97         {\r
98                 return;\r
99         }\r
100 \r
101         // ListCtrlに列を追加。\r
102         // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。\r
103         this->lcFiles->SetSingleStyle(wxLC_VIRTUAL);\r
104         this->lcFiles->InsertColumn(0, _("Input"),  wxLIST_FORMAT_LEFT,  150);\r
105         this->lcFiles->InsertColumn(1, _("Output"), wxLIST_FORMAT_LEFT,  290);\r
106         this->lcFiles->asInput = & this->files;\r
107         this->lcFiles->atDangerItem.SetTextColour(* wxRED);\r
108 \r
109         ::wxXmlResource::Get()->Unload(L_DIR_S_XRC wxT("dlg_make.xrc"));\r
110 \r
111         // 事前準備。\r
112         MainFrame * frm_main = (MainFrame *) this->GetParent();\r
113         wxString szArcPath = frm_main->fnArchive.GetPath(), szArcName = frm_main->fnArchive.GetName();\r
114 \r
115         // パス履歴読み込み。\r
116         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_PATH); i++)\r
117         {\r
118                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_PATH, i);\r
119                 if (sz.IsEmpty())\r
120                 {\r
121                         continue;\r
122                 }\r
123 \r
124                 this->cbDir->Append(sz);\r
125         }\r
126         // 書庫名履歴読み込み。\r
127         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_NAME); i++)\r
128         {\r
129                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_NAME, i);\r
130                 if (sz.IsEmpty())\r
131                 {\r
132                         continue;\r
133                 }\r
134 \r
135                 this->cbFileName->Append(sz);\r
136         }\r
137 \r
138         // パスを設定。\r
139         this->cbDir->SetValue(szArcPath);\r
140 \r
141         // コマンド別の処理。\r
142         switch (this->uCommand)\r
143         {\r
144         case TPI_COMMAND_EXTRACT:\r
145                 // 初期値を設定。\r
146                 this->SetTitle(_("Extract"));\r
147                 this->tcComment->SetValue(frm_main->aiArchive.szComment);\r
148 \r
149                 // コントロールを無効化。\r
150                 this->scLevel->Disable();\r
151                 this->scRR->Disable();\r
152                 this->cbSolid->Disable();\r
153                 this->cbMMOptimize->Disable();\r
154                 this->tcComment->SetEditable(false);\r
155                 this->cbEncryptHeader->Disable();\r
156                 this->chEncryptMethod->Disable();\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->cbCompressHeader->Disable();\r
164                 this->cbMakeSFX->Disable();\r
165 \r
166                 // 書庫名を設定。\r
167                 this->cbFileName->SetValue(szArcName);\r
168 \r
169                 // 書庫形式欄を設定。\r
170                 this->afInfo.Add(frm_main->aiArchive.fiInfo);\r
171                 this->chType->Append(frm_main->aiArchive.fiInfo.szTypeName);\r
172                 this->chType->SetSelection(0);\r
173                 {\r
174                         wxCommandEvent e;\r
175                         e.SetInt(0);\r
176                         this->OnChoice(e);\r
177                 }\r
178 \r
179                 if (this->uCommand != TPI_COMMAND_ADD)\r
180                 {\r
181                         break;\r
182                 }\r
183                 this->SetTitle(_("Add"));\r
184 \r
185                 // コントロールを無効化(追加時のみ)。\r
186                 this->cbDir->Disable();\r
187                 this->chDirMake->Disable();\r
188                 XRCCTRL(* this, "btnDefault", wxButton)->Disable();\r
189                 XRCCTRL(* this, "btnDesktop", wxButton)->Disable();\r
190                 XRCCTRL(* this, "btnCurrent", wxButton)->Disable();\r
191                 XRCCTRL(* this, "btnBrowse",  wxButton)->Disable();\r
192                 break;\r
193         case TPI_COMMAND_CREATE:\r
194                 this->SetTitle(_("Create"));\r
195 \r
196                 // 書庫名を設定。初期化の都合上.を付加しておく。\r
197                 this->cbFileName->SetValue(szArcName + wxT('.'));\r
198 \r
199                 // ライブラリを検索。\r
200                 TPIHandle tpi;\r
201                 wxDir fs(L_DIR_B_LIB);\r
202                 wxString szTPIName;\r
203                 if (fs.GetFirst(& szTPIName,wxT("*" TPI_EXT)))\r
204                 {\r
205                         do\r
206                         {\r
207                                 // ロード。\r
208                                 wxString szLibName = L_DIR_B_LIB + szTPIName;\r
209                                 if (tpi.InitLibrary(szLibName, wxEmptyString, 0))\r
210                                 {\r
211                                         // 対応する形式名を取得。\r
212                                         TPI_FORMATINFO fiInfo;\r
213                                         if (tpi.GetFormatInformation(& fiInfo, true))\r
214                                         {\r
215                                                 do\r
216                                                 {\r
217                                                         if (fiInfo.eSupportedCommand & TPI_COMMAND_CREATE && (this->lcFiles->asInput->GetCount() == 1 || fiInfo.fArchive))\r
218                                                         {\r
219                                                                 fiInfo.szTPIName = szLibName;\r
220                                                                 this->afInfo.Add(fiInfo);\r
221                                                                 this->chType->Append(fiInfo.szTypeName);\r
222                                                         }\r
223                                                 }\r
224                                                 while (tpi.GetFormatInformation(& fiInfo, false));\r
225                                         }\r
226                                         tpi.FreeLibrary();\r
227                                 }\r
228                         }\r
229                         while (fs.GetNext(& szTPIName));\r
230                 }\r
231 \r
232                 if (this->chType->GetCount() == 0)\r
233                 {\r
234                         // 形式の候補が一つもない場合。\r
235                         XRCCTRL(* this, "btnOK", wxButton)->Disable();\r
236                         break;\r
237                 }\r
238 \r
239                 // とりあえず最初の形式にしておく。\r
240                 this->chType->SetSelection(0);\r
241                 wxCommandEvent e;\r
242                 e.SetInt(0);\r
243                 this->OnChoice(e);\r
244                 break;\r
245         }\r
246 \r
247         // 展開/格納先を予測。ただしDTVスキャンに時間がかかる場合はスキップ可能。\r
248         if (this->lcFiles->asInput->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
249         {\r
250                 wxNotebookEvent e;\r
251                 e.SetSelection(3);\r
252                 this->OnTabChanged(e);\r
253         }\r
254 }\r
255 \r
256 void MakeDialog::OnBtnDefault(wxCommandEvent&)\r
257 {\r
258         this->cbDir->SetValue(((MainFrame *) this->GetParent())->conf.ReadId(CONF_DEFAULT_PATH, (wxString) wxEmptyString));\r
259 }\r
260 \r
261 void MakeDialog::OnBtnDesktop(wxCommandEvent&)\r
262 {\r
263         wxFileName fn(wxFileName::GetHomeDir(), wxT("Desktop"));\r
264         this->cbDir->SetValue(fn.GetFullPath());\r
265 }\r
266 \r
267 void MakeDialog::OnBtnCurrent(wxCommandEvent&)\r
268 {\r
269         this->cbDir->SetValue(((MainFrame *) this->GetParent())->fnArchive.GetPath());\r
270 }\r
271 \r
272 void MakeDialog::OnBtnBrowse(wxCommandEvent&)\r
273 {\r
274         wxDirDialog dd(this);\r
275         dd.SetPath(this->cbDir->GetValue());\r
276         if (dd.ShowModal() == wxID_OK)\r
277         {\r
278                 this->cbDir->SetValue(dd.GetPath());\r
279         }\r
280 }\r
281 \r
282 void MakeDialog::OnBtnBrowseKF(wxCommandEvent&)\r
283 {\r
284         wxFileDialog fd(this);\r
285         fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
286         if (fd.ShowModal() == wxID_OK)\r
287         {\r
288                 this->tcKeyfile->SetValue(fd.GetPath());\r
289         }\r
290 }\r
291 \r
292 void MakeDialog::OnBtnOK(wxCommandEvent&)\r
293 {\r
294         // 履歴書き込み。\r
295         if (this->uCommand != TPI_COMMAND_ADD)\r
296         {\r
297                 MainFrame * frm_main = (MainFrame *) this->GetParent();\r
298                 wxFileName fnCurrent(this->cbDir->GetValue(), this->uCommand == TPI_COMMAND_CREATE ? this->cbFileName->GetValue() : (wxString) wxEmptyString);\r
299                 frm_main->conf.WriteHistory(CONF_HISTORY_FULL, fnCurrent.GetFullPath());\r
300                 frm_main->conf.WriteHistory(CONF_HISTORY_PATH, fnCurrent.GetPath());\r
301                 frm_main->conf.WriteHistory(CONF_HISTORY_NAME, fnCurrent.GetFullName());\r
302         }\r
303         this->EndModal(wxID_OK);\r
304 }\r
305 \r
306 void MakeDialog::OnBtnCancel(wxCommandEvent&)\r
307 {\r
308         this->EndModal(wxID_CANCEL);\r
309 }\r
310 \r
311 void MakeDialog::OnChoice(wxCommandEvent& e)\r
312 {\r
313         TPI_FORMATINFO * fiInfo = & this->afInfo[e.GetInt()];\r
314         // 形式が各種設定に対応しているか。\r
315         // 作成時/追加時/展開時設定。\r
316         this->tcPassword->Enable(fiInfo->fEncryptPassword);\r
317         this->tcKeyfile->Enable(fiInfo->fEncryptKeyFile);\r
318         this->cbUnmask->Enable(fiInfo->fEncryptPassword);\r
319         this->chEncryptMethod->Enable(fiInfo->fEncryptPassword || fiInfo->fEncryptKeyFile);\r
320         XRCCTRL(* this, "btnBrowseKF", wxButton)->Enable(fiInfo->fEncryptKeyFile);\r
321         if (this->uCommand == TPI_COMMAND_EXTRACT)\r
322         {\r
323                 return;\r
324         }\r
325 \r
326         // 作成時/追加時設定。\r
327         this->scLevel->SetRange(fiInfo->nCompressLevelMin, fiInfo->nCompressLevelMax);\r
328         this->scLevel->SetValue(fiInfo->nCompressLevelMax);\r
329         this->scLevel->Enable(fiInfo->nCompressLevelMin != fiInfo->nCompressLevelMax);\r
330         this->scRR->SetRange(fiInfo->nRecoveryRecordMin, fiInfo->nRecoveryRecordMax);\r
331         this->scRR->SetValue(fiInfo->nRecoveryRecordMin);\r
332         this->scRR->Enable(fiInfo->nRecoveryRecordMin != fiInfo->nRecoveryRecordMax);\r
333         this->cbEncryptHeader->Enable(fiInfo->fEncryptHeader);\r
334         this->cbCompressHeader->Enable(fiInfo->fCompressHeader);\r
335         this->cbSolid->Enable(fiInfo->fSolid);\r
336         this->cbMMOptimize->Enable(fiInfo->fMMOptimize);\r
337         this->tcComment->Enable(fiInfo->fComment);\r
338         if (this->uCommand == TPI_COMMAND_ADD)\r
339         {\r
340                 return;\r
341         }\r
342 \r
343         // 作成時設定。\r
344         this->cbSplitSize->Enable(fiInfo->fMultiVolume);\r
345         this->cbMakeSFX->Enable(fiInfo->fSFX);\r
346 \r
347         wxFileName fn(this->cbFileName->GetValue());\r
348         fn.SetExt(this->cbMakeSFX->IsEnabled() && this->cbMakeSFX->IsChecked() ? EXE_EXT : fiInfo->szSuffix.BeforeFirst(wxT(';')));\r
349         this->cbFileName->SetValue(fn.GetFullName());\r
350 }\r
351 \r
352 void MakeDialog::OnCbUnmask(wxCommandEvent&)\r
353 {\r
354         this->tcPassword->SetWindowStyle(this->tcPassword->GetWindowStyle() & (this->cbUnmask->IsChecked() ? ~ wxTE_PASSWORD : wxTE_PASSWORD));\r
355         this->tcPassword->Refresh();\r
356 }\r
357 \r
358 void MakeDialog::OnCbMakeSFX(wxCommandEvent&)\r
359 {\r
360         wxFileName fn(this->cbFileName->GetValue());\r
361         fn.SetExt(this->cbMakeSFX->IsChecked() ? EXE_EXT : this->afInfo[this->chType->GetSelection()].szSuffix.BeforeFirst(wxT(';')));\r
362         this->cbFileName->SetValue(fn.GetFullName());\r
363 }\r
364 \r
365 void MakeDialog::OnTabChanged(wxNotebookEvent& e)\r
366 {\r
367         // "Files"タブのときは処理。\r
368         if (e.GetSelection() != 4)\r
369         {\r
370                 return;\r
371         }\r
372         this->lcFiles->DeleteAllItems();\r
373         this->lcFiles->asOutput.Clear();\r
374         this->lcFiles->apItem.Clear();\r
375 \r
376         switch (this->uCommand)\r
377         {\r
378         case TPI_COMMAND_EXTRACT:\r
379         {\r
380                 // ファイルの出力先を推測。\r
381                 wxString szOutputRootDir = WillMakeDirByArcName((MainFrame *) this->GetParent(), this) ? MakeDirPath(wxFileName::DirName(this->cbDir->GetValue()), wxFileName(this->cbFileName->GetValue()).GetName(), false).GetPath() : this->cbDir->GetValue();\r
382 \r
383                 // 各ファイルにパスを付加。\r
384                 bool fDTVWarning = false;\r
385                 for (size_t i = 0; i < this->lcFiles->asInput->GetCount(); i++)\r
386                 {\r
387                         wxString szOutputFile = szOutputRootDir + wxFileName::GetPathSeparator();\r
388                         wxFileName fnStored(this->lcFiles->asInput->Item(i));\r
389                         if (! this->cbIgnorePath->IsChecked())\r
390                         {\r
391                                 szOutputFile += fnStored.GetPathWithSep();\r
392                         }\r
393                         wxFileName fnOutput(szOutputFile + fnStored.GetFullName());\r
394                         if (! fnOutput.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG) || ! fnOutput.GetFullPath().StartsWith(szOutputRootDir))\r
395                         {\r
396                                 fDTVWarning = true;\r
397                                 this->lcFiles->apItem.Add(& this->lcFiles->atDangerItem);\r
398                         }\r
399                         else\r
400                         {\r
401                                 this->lcFiles->apItem.Add(NULL);\r
402                         }\r
403                         this->lcFiles->asOutput.Add(fnOutput.GetFullPath());\r
404                 }\r
405 \r
406                 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
407                 {\r
408                         this->cbIgnorePath->SetValue(true);\r
409                         this->OnTabChanged(e);\r
410                 }\r
411                 break;\r
412         }\r
413         case TPI_COMMAND_ADD:\r
414         case TPI_COMMAND_CREATE:\r
415                 // TODO : 格納パスを推測。\r
416                 this->lcFiles->asOutput = * this->lcFiles->asInput;\r
417                 this->lcFiles->apItem.SetCount(this->lcFiles->asInput->GetCount(), NULL);\r
418                 break;\r
419         }\r
420 \r
421         // リストビューに表示。\r
422         this->lcFiles->SetItemCount(this->lcFiles->asInput->GetCount());\r
423 }\r
424 \r
425 //******************************************************************************\r
426 // myListCtrl2\r
427 //******************************************************************************\r
428 \r
429 IMPLEMENT_DYNAMIC_CLASS(myListCtrl2, wxListView)\r
430 \r
431 //******************************************************************************\r
432 // Event handler.\r
433 //******************************************************************************\r
434 wxString myListCtrl2::OnGetItemText(long i, long column) const\r
435 {\r
436         // リストビューに項目を追加。\r
437         switch (column)\r
438         {\r
439         case 0:\r
440                 return this->asInput->Item(i);\r
441         case 1:\r
442                 return this->asOutput[i];\r
443         default:\r
444                 return wxEmptyString;\r
445         }\r
446 }\r
447 \r
448 wxListItemAttr * myListCtrl2::OnGetItemAttr(long i) const\r
449 {\r
450         return (wxListItemAttr *) this->apItem[i];\r
451 }\r