OSDN Git Service

wxFileSystemをwxDirに変更。wxChar,wxStringの曖昧さを解消。
[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                 wxDir fs(L_DIR_B_LIB);\r
199                 wxString szTPIName;\r
200                 if (fs.GetFirst(& szTPIName,wxT("*" TPI_EXT)))\r
201                 {\r
202                         do\r
203                         {\r
204                                 // ロード。\r
205                                 wxString szLibName = L_DIR_B_LIB + szTPIName;\r
206                                 if (tpi.InitLibrary(szLibName, wxEmptyString, 0))\r
207                                 {\r
208                                         // 対応する形式名を取得。\r
209                                         TPI_FORMATINFO fiInfo;\r
210                                         if (tpi.GetFormatInformation(& fiInfo, true))\r
211                                         {\r
212                                                 do\r
213                                                 {\r
214                                                         if (fiInfo.eSupportedCommand & TPI_COMMAND_CREATE && (this->files.GetCount() == 1 || fiInfo.fArchive))\r
215                                                         {\r
216                                                                 fiInfo.szTPIName = szLibName;\r
217                                                                 this->afInfo.Add(fiInfo);\r
218                                                                 this->chType->Append(fiInfo.szTypeName);\r
219                                                         }\r
220                                                 }\r
221                                                 while (tpi.GetFormatInformation(& fiInfo, false));\r
222                                         }\r
223                                         tpi.FreeLibrary();\r
224                                 }\r
225                         }\r
226                         while (fs.GetNext(& szTPIName));\r
227                 }\r
228 \r
229                 if (this->chType->GetCount() == 0)\r
230                 {\r
231                         // 形式の候補が一つもない場合。\r
232                         XRCCTRL(* this, "btnOK", wxButton)->Disable();\r
233                         break;\r
234                 }\r
235 \r
236                 // とりあえず最初の形式にしておく。\r
237                 this->chType->SetSelection(0);\r
238                 wxCommandEvent e;\r
239                 e.SetInt(0);\r
240                 this->OnChoice(e);\r
241                 break;\r
242         }\r
243 }\r
244 \r
245 void MakeDialog::OnBtnDefault(wxCommandEvent&)\r
246 {\r
247         this->cbDir->SetValue(((MainFrame *) this->GetParent())->conf.ReadId(CONF_DEFAULT_PATH, (wxString) wxEmptyString));\r
248 }\r
249 \r
250 void MakeDialog::OnBtnDesktop(wxCommandEvent&)\r
251 {\r
252         wxFileName fn(wxFileName::GetHomeDir(), wxT("Desktop"));\r
253         this->cbDir->SetValue(fn.GetFullPath());\r
254 }\r
255 \r
256 void MakeDialog::OnBtnCurrent(wxCommandEvent&)\r
257 {\r
258         this->cbDir->SetValue(((MainFrame *) this->GetParent())->fnArchive.GetPath());\r
259 }\r
260 \r
261 void MakeDialog::OnBtnBrowse(wxCommandEvent&)\r
262 {\r
263         wxDirDialog dd(this);\r
264         dd.SetPath(this->cbDir->GetValue());\r
265         if (dd.ShowModal() == wxID_OK)\r
266         {\r
267                 this->cbDir->SetValue(dd.GetPath());\r
268         }\r
269 }\r
270 \r
271 void MakeDialog::OnBtnBrowseKF(wxCommandEvent&)\r
272 {\r
273         wxFileDialog fd(this);\r
274         fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
275         if (fd.ShowModal() == wxID_OK)\r
276         {\r
277                 this->tcKeyfile->SetValue(fd.GetPath());\r
278         }\r
279 }\r
280 \r
281 void MakeDialog::OnBtnOK(wxCommandEvent&)\r
282 {\r
283         // 履歴書き込み。\r
284         if (this->uCommand != TPI_COMMAND_ADD)\r
285         {\r
286                 MainFrame * frm_main = (MainFrame *) this->GetParent();\r
287                 wxFileName fnCurrent(this->cbDir->GetValue(), this->uCommand == TPI_COMMAND_CREATE ? this->cbFileName->GetValue() : (wxString) wxEmptyString);\r
288                 frm_main->conf.WriteHistory(CONF_HISTORY_FULL, fnCurrent.GetFullPath());\r
289                 frm_main->conf.WriteHistory(CONF_HISTORY_PATH, fnCurrent.GetPath());\r
290                 frm_main->conf.WriteHistory(CONF_HISTORY_NAME, fnCurrent.GetFullName());\r
291         }\r
292         this->EndModal(wxID_OK);\r
293 }\r
294 \r
295 void MakeDialog::OnBtnCancel(wxCommandEvent&)\r
296 {\r
297         this->EndModal(wxID_CANCEL);\r
298 }\r
299 \r
300 void MakeDialog::OnChoice(wxCommandEvent& e)\r
301 {\r
302         TPI_FORMATINFO * fiInfo = & this->afInfo[e.GetInt()];\r
303         // 形式が各種設定に対応しているか。\r
304         // 作成時/追加時/展開時設定。\r
305         this->tcPassword->Enable(fiInfo->fEncryptPassword);\r
306         this->cbUnmask->Enable(fiInfo->fEncryptPassword);\r
307         this->tcKeyfile->Enable(fiInfo->fEncryptKeyFile);\r
308         if (this->uCommand == TPI_COMMAND_EXTRACT)\r
309         {\r
310                 return;\r
311         }\r
312 \r
313         // 作成時/追加時設定。\r
314         this->scLevel->SetRange(fiInfo->nCompressLevelMin, fiInfo->nCompressLevelMax);\r
315         this->scLevel->SetValue(fiInfo->nCompressLevelMax);\r
316         this->scLevel->Enable(fiInfo->nCompressLevelMin != fiInfo->nCompressLevelMax);\r
317         this->scRR->SetRange(fiInfo->nRecoveryRecordMin, fiInfo->nRecoveryRecordMax);\r
318         this->scRR->SetValue(fiInfo->nRecoveryRecordMin);\r
319         this->scRR->Enable(fiInfo->nRecoveryRecordMin != fiInfo->nRecoveryRecordMax);\r
320         this->cbEncryptHeader->Enable(fiInfo->fEncryptHeader);\r
321         this->cbSolid->Enable(fiInfo->fSolid);\r
322         this->cbMMOptimize->Enable(fiInfo->fMMOptimize);\r
323         this->tcComment->Enable(fiInfo->fComment);\r
324         if (this->uCommand == TPI_COMMAND_ADD)\r
325         {\r
326                 return;\r
327         }\r
328 \r
329         // 作成時設定。\r
330         this->cbSplitSize->Enable(fiInfo->fMultiVolume);\r
331         this->cbMakeSFX->Enable(fiInfo->fSFX);\r
332 \r
333         wxFileName fn(this->cbFileName->GetValue());\r
334         fn.SetExt(this->cbMakeSFX->IsEnabled() && this->cbMakeSFX->IsChecked() ? EXE_EXT : fiInfo->szSuffix.BeforeFirst(wxT(';')));\r
335         this->cbFileName->SetValue(fn.GetFullName());\r
336 }\r
337 \r
338 void MakeDialog::OnCbUnmask(wxCommandEvent&)\r
339 {\r
340         this->tcPassword->SetWindowStyle(this->tcPassword->GetWindowStyle() & (this->cbUnmask->IsChecked() ? ~ wxTE_PASSWORD : wxTE_PASSWORD));\r
341         this->tcPassword->Refresh();\r
342 }\r
343 \r
344 void MakeDialog::OnCbMakeSFX(wxCommandEvent&)\r
345 {\r
346         wxFileName fn(this->cbFileName->GetValue());\r
347         fn.SetExt(this->cbMakeSFX->IsChecked() ? EXE_EXT : this->afInfo[this->chType->GetSelection()].szSuffix.BeforeFirst(wxT(';')));\r
348         this->cbFileName->SetValue(fn.GetFullName());\r
349 }\r
350 \r
351 void MakeDialog::OnTabChanged(wxNotebookEvent& e)\r
352 {\r
353         // "Files"タブのときは処理。\r
354         bool bReallyShow = e.GetSelection() == 3;\r
355         if (abs(e.GetSelection()) != 3)\r
356         {\r
357                 return;\r
358         }\r
359 \r
360         // "Files"タブを表示する初回かどうか。\r
361         if (bReallyShow && this->lcFiles->GetItemCount() == 0)\r
362         {\r
363                 // ファイルリストを追加。\r
364                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
365                 {\r
366                         this->lcFiles->InsertItem(i, this->files[i]);\r
367                 }\r
368         }\r
369 \r
370         switch (this->uCommand)\r
371         {\r
372         case TPI_COMMAND_EXTRACT:\r
373         {\r
374                 // ファイルの出力先を推測。\r
375                 wxString szOutputRootDir = WillMakeDirByArcName((MainFrame *) this->GetParent(), this) ? MakeDirPath(wxFileName::DirName(this->cbDir->GetValue()), wxFileName(this->cbFileName->GetValue()).GetName(), false).GetPath() : this->cbDir->GetValue();\r
376 \r
377                 // 各ファイルにパスを付加。\r
378                 bool fDTVWarning = false;\r
379                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
380                 {\r
381                         wxString szOutputFile = szOutputRootDir + wxFileName::GetPathSeparator();\r
382                         wxFileName fnStored(this->files[i]);\r
383                         if (! this->cbIgnorePath->IsChecked())\r
384                         {\r
385                                 szOutputFile += fnStored.GetPathWithSep();\r
386                         }\r
387                         szOutputFile += fnStored.GetFullName();\r
388                         wxFileName fnOutput(szOutputFile);\r
389                         if (! fnOutput.Normalize() || ! fnOutput.GetFullPath().StartsWith(szOutputRootDir))\r
390                         {\r
391                                 fDTVWarning = true;\r
392                                 if (bReallyShow)\r
393                                 {\r
394                                         this->lcFiles->SetItemTextColour(i, * wxRED);\r
395                                 }\r
396                         }\r
397                         if (bReallyShow)\r
398                         {\r
399                                 this->lcFiles->SetItem(i, 1, fnOutput.GetFullPath());\r
400                         }\r
401                 }\r
402 \r
403                 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
404                 {\r
405                         this->cbIgnorePath->SetValue(true);\r
406                         if (bReallyShow)\r
407                         {\r
408                                 this->OnTabChanged(e);\r
409                         }\r
410                 }\r
411                 break;\r
412         }\r
413         case TPI_COMMAND_ADD:\r
414         case TPI_COMMAND_CREATE:\r
415                 // 格納パスを推測。\r
416                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
417                 {\r
418                         if (bReallyShow)\r
419                         {\r
420                                 this->lcFiles->SetItem(i, 1, this->files[i]);\r
421                         }\r
422                 }\r
423                 break;\r
424         }\r
425 }\r