OSDN Git Service

書庫を作成する際のコマンドコードとしてTPI_COMMAND_CREATEを追加。
[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_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         if (! this->bIsMake)\r
110         {\r
111                 this->cbFileName->Disable();\r
112                 this->chType->Disable();\r
113                 this->chDirMake->Enable();\r
114                 this->scLevel->Disable();\r
115                 this->scRR->Disable();\r
116                 this->cbSplitSize->Disable();\r
117                 this->cbEncryptHeader->Disable();\r
118                 this->cbSolid->Disable();\r
119                 this->cbMMOptimize->Disable();\r
120                 this->cbMakeSFX->Disable();\r
121                 this->tcComment->SetEditable(false);\r
122 \r
123                 // 初期値を設定。\r
124                 this->tcComment->SetValue(frm_main->szComment);\r
125 \r
126                 // 展開先を予測。ただしDTVスキャンに時間がかかる場合はスキップ可能。\r
127                 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
128                 {\r
129                         wxNotebookEvent e;\r
130                         e.SetSelection(-3);\r
131                         this->OnTabChanged(e);\r
132                 }\r
133         }\r
134 \r
135         // パス履歴読み込み。\r
136         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_PATH); i++)\r
137         {\r
138                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_PATH, i);\r
139                 if (sz.IsEmpty())\r
140                 {\r
141                         continue;\r
142                 }\r
143 \r
144                 this->cbDir->Append(sz);\r
145         }\r
146 \r
147         // 書庫名履歴読み込み。\r
148         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_NAME); i++)\r
149         {\r
150                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_NAME, i);\r
151                 if (sz.IsEmpty())\r
152                 {\r
153                         continue;\r
154                 }\r
155 \r
156                 this->cbFileName->Append(sz);\r
157         }\r
158 \r
159         // パスを設定。\r
160         this->cbDir->SetValue(szArcPath);\r
161 \r
162         if (! this->bIsMake)\r
163         {\r
164                 // 書庫名を設定。\r
165                 this->cbFileName->SetValue(szArcName);\r
166 \r
167                 // 展開時の処理はここまで。\r
168                 return;\r
169         }\r
170 \r
171         // 書庫名を設定。初期化の都合上.を付加しておく。\r
172         this->cbFileName->SetValue(szArcName + wxT('.'));\r
173 \r
174         // ライブラリを検索。\r
175         TPIHandle tpi;\r
176         wxFileSystem fs;\r
177         fs.ChangePathTo(L_DIR_B_LIB, true);\r
178         wxString szTPIName = fs.FindFirst(wxT("*" TPI_EXT), wxFILE);\r
179         while (! szTPIName.IsEmpty())\r
180         {\r
181                 // ロード。\r
182                 if (tpi.InitLibrary(szTPIName, wxEmptyString, 0))\r
183                 {\r
184                         // 対応する形式名を取得。\r
185                         TPI_FORMATINFO fiInfo;\r
186                         if (tpi.GetFormatInformation(& fiInfo, true))\r
187                         {\r
188                                 do\r
189                                 {\r
190                                         if (fiInfo.llSupportedCommand & TPI_COMMAND_CREATE && (this->files.GetCount() == 1 || fiInfo.fArchive))\r
191                                         {\r
192                                                 fiInfo.szTPIName = szTPIName;\r
193                                                 this->afInfo.Add(fiInfo);\r
194                                                 this->chType->Append(fiInfo.szTypeName);\r
195                                         }\r
196                                 }\r
197                                 while (tpi.GetFormatInformation(& fiInfo, false));\r
198                         }\r
199                         tpi.FreeLibrary();\r
200                 }\r
201                 szTPIName = fs.FindNext();\r
202         }\r
203 \r
204         // とりあえず最初の形式にしておく。\r
205         this->chType->SetSelection(0);\r
206         wxCommandEvent e;\r
207         e.SetInt(0);\r
208         this->OnChoice(e);\r
209 }\r
210 \r
211 void MakeDialog::OnBtnDefault(wxCommandEvent&)\r
212 {\r
213         this->cbDir->SetValue(((MainFrame *) this->GetParent())->conf.ReadId(CONF_DEFAULT_PATH, (wxString) wxEmptyString));\r
214 }\r
215 \r
216 void MakeDialog::OnBtnDesktop(wxCommandEvent&)\r
217 {\r
218         wxFileName fn(wxFileName::GetHomeDir(), wxT("Desktop"));\r
219         this->cbDir->SetValue(fn.GetFullPath());\r
220 }\r
221 \r
222 void MakeDialog::OnBtnCurrent(wxCommandEvent&)\r
223 {\r
224         this->cbDir->SetValue(((MainFrame *) this->GetParent())->fnArchive.GetPath());\r
225 }\r
226 \r
227 void MakeDialog::OnBtnBrowse(wxCommandEvent&)\r
228 {\r
229         wxDirDialog dd(this);\r
230         dd.SetPath(this->cbDir->GetValue());\r
231         if (dd.ShowModal() == wxID_OK)\r
232         {\r
233                 this->cbDir->SetValue(dd.GetPath());\r
234         }\r
235 }\r
236 \r
237 void MakeDialog::OnBtnBrowseKF(wxCommandEvent&)\r
238 {\r
239         wxFileDialog fd(this);\r
240         fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
241         if (fd.ShowModal() == wxID_OK)\r
242         {\r
243                 this->tcKeyfile->SetValue(fd.GetPath());\r
244         }\r
245 }\r
246 \r
247 void MakeDialog::OnBtnOK(wxCommandEvent&)\r
248 {\r
249         // 履歴書き込み。\r
250         MainFrame * frm_main = (MainFrame *) this->GetParent();\r
251         wxFileName fnCurrent(this->cbDir->GetValue(), this->bIsMake ? this->cbFileName->GetValue() : (wxString) wxEmptyString);\r
252         frm_main->conf.WriteHistory(CONF_HISTORY_FULL, fnCurrent.GetFullPath());\r
253         frm_main->conf.WriteHistory(CONF_HISTORY_PATH, fnCurrent.GetPath());\r
254         frm_main->conf.WriteHistory(CONF_HISTORY_NAME, fnCurrent.GetFullName());\r
255 \r
256         this->EndModal(wxID_OK);\r
257 }\r
258 \r
259 void MakeDialog::OnBtnCancel(wxCommandEvent&)\r
260 {\r
261         this->EndModal(wxID_CANCEL);\r
262 }\r
263 \r
264 void MakeDialog::OnChoice(wxCommandEvent& e)\r
265 {\r
266         TPI_FORMATINFO * fiInfo = & this->afInfo[e.GetInt()];\r
267         // 形式が各種設定に対応しているか。\r
268         this->scLevel->SetRange(fiInfo->sCompressLevelMin, fiInfo->sCompressLevelMax);\r
269         this->scLevel->SetValue(fiInfo->sCompressLevelMax);\r
270         this->scLevel->Enable(fiInfo->sCompressLevelMin != fiInfo->sCompressLevelMax);\r
271         this->scRR->SetRange(fiInfo->sRecoveryRecordMin, fiInfo->sRecoveryRecordMax);\r
272         this->scRR->SetValue(fiInfo->sRecoveryRecordMin);\r
273         this->scRR->Enable(fiInfo->sRecoveryRecordMin != fiInfo->sRecoveryRecordMax);\r
274         this->cbSplitSize->Enable(fiInfo->fMultiVolume);\r
275         this->tcPassword->Enable(fiInfo->fEncryptPassword);\r
276         this->cbUnmask->Enable(fiInfo->fEncryptPassword);\r
277         this->tcKeyfile->Enable(fiInfo->fEncryptKeyFile);\r
278         this->cbEncryptHeader->Enable(fiInfo->fEncryptHeader);\r
279         this->cbMakeSFX->Enable(fiInfo->fSFX);\r
280         this->cbSolid->Enable(fiInfo->fSolid);\r
281         this->cbMMOptimize->Enable(fiInfo->fMMOptimize);\r
282         this->tcComment->Enable(fiInfo->fComment);\r
283 \r
284         wxFileName fn(this->cbFileName->GetValue());\r
285         fn.SetExt(this->cbMakeSFX->IsEnabled() && this->cbMakeSFX->IsChecked() ? EXE_EXT : fiInfo->szSuffix.BeforeFirst(wxT(';')));\r
286         this->cbFileName->SetValue(fn.GetFullName());\r
287 }\r
288 \r
289 void MakeDialog::OnCbUnmask(wxCommandEvent&)\r
290 {\r
291         this->tcPassword->SetWindowStyle(this->tcPassword->GetWindowStyle() & (this->cbUnmask->IsChecked() ? ~ wxTE_PASSWORD : wxTE_PASSWORD));\r
292         this->tcPassword->Refresh();\r
293 }\r
294 \r
295 void MakeDialog::OnCbMakeSFX(wxCommandEvent&)\r
296 {\r
297         wxFileName fn(this->cbFileName->GetValue());\r
298         fn.SetExt(this->cbMakeSFX->IsChecked() ? EXE_EXT : this->afInfo[this->chType->GetSelection()].szSuffix.BeforeFirst(wxT(';')));\r
299         this->cbFileName->SetValue(fn.GetFullName());\r
300 }\r
301 \r
302 void MakeDialog::OnTabChanged(wxNotebookEvent& e)\r
303 {\r
304         // "Files"タブのときは処理。\r
305         bool bReallyShow = e.GetSelection() == 3;\r
306         if (abs(e.GetSelection()) != 3)\r
307         {\r
308                 return;\r
309         }\r
310 \r
311         // "Files"タブを表示する初回かどうか。\r
312         if (bReallyShow && this->lcFiles->GetItemCount() == 0)\r
313         {\r
314                 // ファイルリストを追加。\r
315                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
316                 {\r
317                         this->lcFiles->InsertItem(i, this->files[i]);\r
318                 }\r
319         }\r
320 \r
321         if (bIsMake)\r
322         {\r
323                 // 格納パスを推測。\r
324                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
325                 {\r
326                         if (bReallyShow)\r
327                         {\r
328                                 this->lcFiles->SetItem(i, 1, this->files[i]);\r
329                         }\r
330                 }\r
331         }\r
332         else\r
333         {\r
334                 // ファイルの出力先を推測。\r
335                 wxString szOutputRootDir = WillMakeDirByArcName((MainFrame *) this->GetParent(), this) ? MakeDirPath(wxFileName::DirName(this->cbDir->GetValue()), wxFileName(this->cbFileName->GetValue()).GetName(), false).GetPath() : this->cbDir->GetValue();\r
336 \r
337                 // 各ファイルにパスを付加。\r
338                 bool fDTVWarning = false;\r
339                 for (size_t i = 0; i < this->files.GetCount(); i++)\r
340                 {\r
341                         wxString szOutputFile = szOutputRootDir + wxFileName::GetPathSeparator();\r
342                         wxFileName fnStored(this->files[i]);\r
343                         if (! this->cbIgnorePath->IsChecked())\r
344                         {\r
345                                 szOutputFile += fnStored.GetPathWithSep();\r
346                         }\r
347                         szOutputFile += fnStored.GetFullName();\r
348                         wxFileName fnOutput(szOutputFile);\r
349                         if (! fnOutput.Normalize() || ! fnOutput.GetFullPath().StartsWith(szOutputRootDir))\r
350                         {\r
351                                 fDTVWarning = true;\r
352                                 if (bReallyShow)\r
353                                 {\r
354                                         this->lcFiles->SetItemTextColour(i, * wxRED);\r
355                                 }\r
356                         }\r
357                         if (bReallyShow)\r
358                         {\r
359                                 this->lcFiles->SetItem(i, 1, fnOutput.GetFullPath());\r
360                         }\r
361                 }\r
362 \r
363                 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
364                 {\r
365                         this->cbIgnorePath->SetValue(true);\r
366                         if (bReallyShow)\r
367                         {\r
368                                 this->OnTabChanged(e);\r
369                         }\r
370                 }\r
371         }\r
372 }\r