OSDN Git Service

最近作成した書庫や展開先の履歴を記録する機能と、その保存件数を指定するLastUsed-Countを設定に追加。
[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->bIsMake = true;\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_NOTEBOOK_PAGE_CHANGED(XRCID("nbTabs"), MakeDialog::OnTabChanged)\r
58 END_EVENT_TABLE()\r
59 \r
60 //******************************************************************************\r
61 // Event handler.\r
62 //******************************************************************************\r
63 \r
64 void MakeDialog::OnInit(wxInitDialogEvent&)\r
65 {\r
66         // XRCと結びつけ。\r
67         // "General"タブ\r
68         this->cbDir             = XRCCTRL(* this, "cbDir",        wxComboBox);\r
69         this->cbFileName        = XRCCTRL(* this, "cbFileName",   wxComboBox);\r
70         this->cbOpenAfter       = XRCCTRL(* this, "cbOpenAfter",  wxCheckBox);\r
71         this->cbIgnorePath      = XRCCTRL(* this, "cbIgnorePath", wxCheckBox);\r
72         this->cbExitAfter       = XRCCTRL(* this, "cbExitAfter",  wxCheckBox);\r
73         this->chType            = XRCCTRL(* this, "chType",       wxChoice);\r
74         this->chDirMake         = XRCCTRL(* this, "chDirMake",    wxChoice);\r
75         // "Config"タブ\r
76         this->scLevel           = XRCCTRL(* this, "scLevel",      wxSpinCtrl);\r
77         this->scRR              = XRCCTRL(* this, "scRR",         wxSpinCtrl);\r
78         this->tcPassword        = XRCCTRL(* this, "tcPassword",   wxTextCtrl);\r
79         this->tcKeyfile         = XRCCTRL(* this, "tcKeyfile",    wxTextCtrl);\r
80         this->cbSplitSize       = XRCCTRL(* this, "cbSplitSize",  wxComboBox);\r
81         this->cbUnmask          = XRCCTRL(* this, "cbUnmask",     wxCheckBox);\r
82         this->cbEncryptHeader   = XRCCTRL(* this, "cbEncryptHeader", wxCheckBox);\r
83         this->cbSolid           = XRCCTRL(* this, "cbSolid",      wxCheckBox);\r
84         this->cbMMOptimize      = XRCCTRL(* this, "cbMMOptimize", wxCheckBox);\r
85         this->cbMakeSFX         = XRCCTRL(* this, "cbMakeSFX",    wxCheckBox);\r
86         // "Comment"タブ\r
87         this->tcComment         = XRCCTRL(* this, "tcComment",    wxTextCtrl);\r
88         // "Files"タブ\r
89         this->lcFiles           = XRCCTRL(* this, "lcFiles",      wxListCtrl);\r
90 \r
91         // 2回目以降は無視。\r
92         if (! this->cbDir->GetValue().IsEmpty())\r
93         {\r
94                 return;\r
95         }\r
96 \r
97         // ListCtrlに列を追加。\r
98         this->lcFiles->InsertColumn(0, _("Input"),  wxLIST_FORMAT_LEFT,  150);\r
99         this->lcFiles->InsertColumn(1, _("Output"), wxLIST_FORMAT_LEFT,  300);\r
100 \r
101         ::wxXmlResource::Get()->Unload(L_DIR_S_XRC wxT("dlg_make.xrc"));\r
102 \r
103         // 事前準備。\r
104         MainFrame * frm_main = (MainFrame *) this->GetParent();\r
105         wxString szArcPath = frm_main->fnArchive.GetPath(), szArcName = frm_main->fnArchive.GetName();\r
106 \r
107         // 展開時は各種コントロールの状態を変更する。\r
108         if (! this->bIsMake)\r
109         {\r
110                 this->cbFileName->Disable();\r
111                 this->chType->Disable();\r
112                 this->chDirMake->Enable();\r
113                 this->scLevel->Disable();\r
114                 this->scRR->Disable();\r
115                 this->cbSplitSize->Disable();\r
116                 this->cbEncryptHeader->Disable();\r
117                 this->cbSolid->Disable();\r
118                 this->cbMMOptimize->Disable();\r
119                 this->cbMakeSFX->Disable();\r
120                 this->tcComment->SetEditable(false);\r
121 \r
122                 // 初期値を設定。\r
123                 this->tcComment->SetValue(frm_main->szComment);\r
124 \r
125                 // 展開先を予測。ただしDTVスキャンに時間がかかる場合はスキップ可能。\r
126                 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
127                 {\r
128                         wxNotebookEvent e;\r
129                         e.SetSelection(-3);\r
130                         this->OnTabChanged(e);\r
131                 }\r
132         }\r
133 \r
134         // 履歴読み込み。\r
135         wxArrayString asPath, asName;\r
136         asPath.Add(szArcPath);\r
137         asName.Add(szArcName);\r
138         for (int i = 0; i < frm_main->conf.Read(wxT("LastUsed-Count"), 7); i++)\r
139         {\r
140                 wxFileName fnLastOpen(frm_main->conf.Read(wxString::Format(wxT("LastUsed%d"), i), wxEmptyString));\r
141                 if (! fnLastOpen.IsOk())\r
142                 {\r
143                         continue;\r
144                 }\r
145 \r
146                 wxString szPath = fnLastOpen.GetPath(), szName = fnLastOpen.GetName();\r
147                 if (! szPath.IsEmpty() && asPath.Index(szPath) == wxNOT_FOUND)\r
148                 {\r
149                         asPath.Add(szPath);\r
150                         this->cbDir->Append(szPath);\r
151                 }\r
152                 if (! szName.IsEmpty() && asName.Index(szName) == wxNOT_FOUND)\r
153                 {\r
154                         asName.Add(szName);\r
155                         this->cbFileName->Append(szName);\r
156                 }\r
157         }\r
158 \r
159         // 書庫名を設定。\r
160         this->cbDir->SetValue(szArcPath);\r
161         this->cbFileName->SetValue(szArcName);\r
162 \r
163         if (! this->bIsMake)\r
164         {\r
165                 // 展開時の処理はここまで。\r
166                 return;\r
167         }\r
168 \r
169         // ライブラリを検索。\r
170         TPIHandle tpi;\r
171         wxFileSystem fs;\r
172         fs.ChangePathTo(L_DIR_B_LIB, true);\r
173         wxString szTPIName = fs.FindFirst(wxT("*" TPI_EXT), wxFILE);\r
174         while (! szTPIName.IsEmpty())\r
175         {\r
176                 // ロード。\r
177                 if (tpi.InitLibrary(szTPIName, wxEmptyString, 0))\r
178                 {\r
179                         // 対応する形式名を取得。\r
180                         TPI_FORMATINFO fiInfo;\r
181                         if (tpi.GetFormatInformation(& fiInfo, true))\r
182                         {\r
183                                 do\r
184                                 {\r
185                                         if (fiInfo.llSupportedCommand & TPI_COMMAND_ADD && (this->files.GetCount() == 1 || fiInfo.fArchive))\r
186                                         {\r
187                                                 fiInfo.szTPIName = szTPIName;\r
188                                                 this->afInfo.Add(fiInfo);\r
189                                                 this->chType->Append(fiInfo.szTypeName);\r
190                                         }\r
191                                 }\r
192                                 while (tpi.GetFormatInformation(& fiInfo, false));\r
193                         }\r
194                         tpi.FreeLibrary();\r
195                 }\r
196                 szTPIName = fs.FindNext();\r
197         }\r
198 \r
199         // とりあえず最初の形式にしておく。\r
200         this->chType->SetSelection(0);\r
201         wxCommandEvent e;\r
202         e.SetInt(0);\r
203         this->OnChoice(e);\r
204 }\r
205 \r
206 void MakeDialog::OnBtnDefault(wxCommandEvent&)\r
207 {\r
208         this->cbDir->SetValue(((MainFrame *) this->GetParent())->conf.Read(wxT("DefaultPath"), wxEmptyString));\r
209 }\r
210 \r
211 void MakeDialog::OnBtnDesktop(wxCommandEvent&)\r
212 {\r
213         wxFileName fn(wxFileName::GetHomeDir(), wxT("Desktop"));\r
214         this->cbDir->SetValue(fn.GetFullPath());\r
215 }\r
216 \r
217 void MakeDialog::OnBtnCurrent(wxCommandEvent&)\r
218 {\r
219         this->cbDir->SetValue(((MainFrame *) this->GetParent())->fnArchive.GetPath());\r
220 }\r
221 \r
222 void MakeDialog::OnBtnBrowse(wxCommandEvent&)\r
223 {\r
224         wxDirDialog dd(this);\r
225         dd.SetPath(this->cbDir->GetValue());\r
226         if (dd.ShowModal() == wxID_OK)\r
227         {\r
228                 this->cbDir->SetValue(dd.GetPath());\r
229         }\r
230 }\r
231 \r
232 void MakeDialog::OnBtnBrowseKF(wxCommandEvent&)\r
233 {\r
234         wxFileDialog fd(this);\r
235         fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
236         if (fd.ShowModal() == wxID_OK)\r
237         {\r
238                 this->tcKeyfile->SetValue(fd.GetPath());\r
239         }\r
240 }\r
241 \r
242 void MakeDialog::OnBtnOK(wxCommandEvent&)\r
243 {\r
244         // 履歴書き込み。\r
245         MainFrame * frm_main = (MainFrame *) this->GetParent();\r
246         wxFileName fnCurrent(this->cbDir->GetValue(), this->bIsMake ? this->cbFileName->GetValue() : (wxString) wxEmptyString);\r
247         wxArrayString asLastUsed;\r
248         asLastUsed.Add(fnCurrent.GetFullPath());\r
249         for (int i = 0; i < frm_main->conf.Read(wxT("LastUsed-Count"), 7); i++)\r
250         {\r
251                 wxString szPath = frm_main->conf.Read(wxString::Format(wxT("LastUsed%d"), i), wxEmptyString);\r
252                 if (! szPath.IsEmpty() && asLastUsed.Index(szPath) == wxNOT_FOUND)\r
253                 {\r
254                         asLastUsed.Add(szPath);\r
255                 }\r
256         }\r
257         for (size_t i = 0; i < asLastUsed.GetCount(); i++)\r
258         {\r
259                 frm_main->conf.Write(wxString::Format(wxT("LastUsed%d"), i), asLastUsed[i]);\r
260         }\r
261 \r
262         this->EndModal(wxID_OK);\r
263 }\r
264 \r
265 void MakeDialog::OnBtnCancel(wxCommandEvent&)\r
266 {\r
267         this->EndModal(wxID_CANCEL);\r
268 }\r
269 \r
270 void MakeDialog::OnChoice(wxCommandEvent& e)\r
271 {\r
272         TPI_FORMATINFO * fiInfo = & this->afInfo[e.GetInt()];\r
273         // 形式が各種設定に対応しているか。\r
274         this->scLevel->SetRange(fiInfo->sCompressLevelMin, fiInfo->sCompressLevelMax);\r
275         this->scLevel->SetValue(fiInfo->sCompressLevelMax);\r
276         this->scLevel->Enable(fiInfo->sCompressLevelMin != fiInfo->sCompressLevelMax);\r
277         this->scRR->SetRange(fiInfo->sRecoveryRecordMin, fiInfo->sRecoveryRecordMax);\r
278         this->scRR->SetValue(fiInfo->sRecoveryRecordMin);\r
279         this->scRR->Enable(fiInfo->sRecoveryRecordMin != fiInfo->sRecoveryRecordMax);\r
280         this->cbSplitSize->Enable(fiInfo->fMultiVolume);\r
281         this->tcPassword->Enable(fiInfo->fEncryptPassword);\r
282         this->cbUnmask->Enable(fiInfo->fEncryptPassword);\r
283         this->tcKeyfile->Enable(fiInfo->fEncryptKeyFile);\r
284         this->cbEncryptHeader->Enable(fiInfo->fEncryptHeader);\r
285         this->cbMakeSFX->Enable(fiInfo->fSFX);\r
286         this->cbSolid->Enable(fiInfo->fSolid);\r
287         this->cbMMOptimize->Enable(fiInfo->fMMOptimize);\r
288         this->tcComment->Enable(fiInfo->fComment);\r
289 }\r
290 \r
291 void MakeDialog::OnCbUnmask(wxCommandEvent&)\r
292 {\r
293         this->tcPassword->SetWindowStyle(this->tcPassword->GetWindowStyle() & (this->cbUnmask->IsChecked() ? ~ wxTE_PASSWORD : wxTE_PASSWORD));\r
294         this->tcPassword->Refresh();\r
295 }\r
296 \r
297 void MakeDialog::OnTabChanged(wxNotebookEvent& e)\r
298 {\r
299         // "Files"タブのときは処理。\r
300         bool bReallyShow = e.GetSelection() == 3;\r
301         if (abs(e.GetSelection()) != 3)\r
302         {\r
303                 return;\r
304         }\r
305 \r
306         // "Files"タブを表示する初回かどうか。\r
307         if (bReallyShow && this->lcFiles->GetItemCount() == 0)\r
308         {\r
309                 // ファイルリストを追加。\r
310                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
311                 {\r
312                         this->lcFiles->InsertItem(i, this->files[i]);\r
313                 }\r
314         }\r
315 \r
316         if (bIsMake)\r
317         {\r
318                 // 格納パスを推測。\r
319                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
320                 {\r
321                         if (bReallyShow)\r
322                         {\r
323                                 this->lcFiles->SetItem(i, 1, this->files[i]);\r
324                         }\r
325                 }\r
326         }\r
327         else\r
328         {\r
329                 // ファイルの出力先を推測。\r
330                 wxString szOutputRootDir = WillMakeDirByArcName((MainFrame *) this->GetParent(), this) ? MakeDirPath(wxFileName::DirName(this->cbDir->GetValue()), wxFileName(this->cbFileName->GetValue()).GetName(), false).GetPath() : this->cbDir->GetValue();\r
331 \r
332                 // 各ファイルにパスを付加。\r
333                 bool fDTVWarning = false;\r
334                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
335                 {\r
336                         wxString szOutputFile = szOutputRootDir + wxFileName::GetPathSeparator();\r
337                         wxFileName fnStored(this->files[i]);\r
338                         if (! this->cbIgnorePath->IsChecked())\r
339                         {\r
340                                 szOutputFile += fnStored.GetPathWithSep();\r
341                         }\r
342                         szOutputFile += fnStored.GetFullName();\r
343                         wxFileName fnOutput(szOutputFile);\r
344                         if (! fnOutput.Normalize() || ! fnOutput.GetFullPath().StartsWith(szOutputRootDir))\r
345                         {\r
346                                 fDTVWarning = true;\r
347                                 if (bReallyShow)\r
348                                 {\r
349                                         this->lcFiles->SetItemTextColour(i, * wxRED);\r
350                                 }\r
351                         }\r
352                         if (bReallyShow)\r
353                         {\r
354                                 this->lcFiles->SetItem(i, 1, fnOutput.GetFullPath());\r
355                         }\r
356                 }\r
357 \r
358                 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
359                 {\r
360                         this->cbIgnorePath->SetValue(true);\r
361                         if (bReallyShow)\r
362                         {\r
363                                 this->OnTabChanged(e);\r
364                         }\r
365                 }\r
366         }\r
367 }\r