1 /*******************************************************************************
\r
2 TPI - flexible but useless plug-in framework.
\r
3 Copyright (C) 2002-2009 Silky
\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
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
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
20 *******************************************************************************/
\r
24 #include "dlg_make.h"
\r
25 #include "frm_main.h"
\r
26 #include "functions.h"
\r
28 #include <wx/dirdlg.h>
\r
29 #include <wx/arrimpl.cpp>
\r
31 WX_DEFINE_OBJARRAY(ArrayTPI_FORMATINFO);
\r
33 //******************************************************************************
\r
35 //******************************************************************************
\r
37 MakeDialog::MakeDialog(): wxDialog()
\r
39 this->uCommand = TPI_COMMAND_CREATE;
\r
42 //******************************************************************************
\r
44 //******************************************************************************
\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
61 //******************************************************************************
\r
63 //******************************************************************************
\r
65 void MakeDialog::OnInit(wxInitDialogEvent&)
\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
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
88 this->tcComment = XRCCTRL(* this, "tcComment", wxTextCtrl);
\r
90 this->lcFiles = XRCCTRL(* this, "lcFiles", myListCtrl2);
\r
93 if (! this->cbDir->GetValue().IsEmpty())
\r
99 // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。
\r
100 this->lcFiles->SetSingleStyle(wxLC_VIRTUAL);
\r
101 this->lcFiles->InsertColumn(0, _("Input"), wxLIST_FORMAT_LEFT, 150);
\r
102 this->lcFiles->InsertColumn(1, _("Output"), wxLIST_FORMAT_LEFT, 290);
\r
103 this->lcFiles->asInput = this->files;
\r
104 this->lcFiles->atDangerItem.SetTextColour(* wxRED);
\r
106 ::wxXmlResource::Get()->Unload(L_DIR_S_XRC wxT("dlg_make.xrc"));
\r
109 MainFrame * frm_main = (MainFrame *) this->GetParent();
\r
110 wxString szArcPath = frm_main->fnArchive.GetPath(), szArcName = frm_main->fnArchive.GetName();
\r
113 for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_PATH); i++)
\r
115 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_PATH, i);
\r
121 this->cbDir->Append(sz);
\r
124 for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_NAME); i++)
\r
126 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_NAME, i);
\r
132 this->cbFileName->Append(sz);
\r
136 this->cbDir->SetValue(szArcPath);
\r
139 switch (this->uCommand)
\r
141 case TPI_COMMAND_EXTRACT:
\r
143 this->SetTitle(_("Extract"));
\r
144 this->tcComment->SetValue(frm_main->aiArchive.szComment);
\r
146 // 展開先を予測。ただしDTVスキャンに時間がかかる場合はスキップ可能。
\r
147 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
151 this->OnTabChanged(e);
\r
155 this->scLevel->Disable();
\r
156 this->scRR->Disable();
\r
157 this->cbEncryptHeader->Disable();
\r
158 this->cbSolid->Disable();
\r
159 this->cbMMOptimize->Disable();
\r
160 this->tcComment->SetEditable(false);
\r
161 case TPI_COMMAND_ADD:
\r
162 // コントロールを無効化(展開時も)。
\r
163 this->cbFileName->Disable();
\r
164 this->chType->Disable();
\r
165 this->chDirMake->Enable();
\r
166 this->cbSplitSize->Disable();
\r
167 this->cbMakeSFX->Disable();
\r
170 this->cbFileName->SetValue(szArcName);
\r
173 this->afInfo.Add(frm_main->aiArchive.fiInfo);
\r
174 this->chType->Append(frm_main->aiArchive.fiInfo.szTypeName);
\r
176 // とりあえず最初の形式にしておく。
\r
177 this->chType->SetSelection(0);
\r
184 if (this->uCommand != TPI_COMMAND_ADD)
\r
188 this->SetTitle(_("Add"));
\r
190 // コントロールを無効化(追加時のみ)。
\r
191 this->cbDir->Disable();
\r
192 this->chDirMake->Disable();
\r
194 case TPI_COMMAND_CREATE:
\r
195 this->SetTitle(_("Create"));
\r
197 // 書庫名を設定。初期化の都合上.を付加しておく。
\r
198 this->cbFileName->SetValue(szArcName + wxT('.'));
\r
202 wxDir fs(L_DIR_B_LIB);
\r
203 wxString szTPIName;
\r
204 if (fs.GetFirst(& szTPIName,wxT("*" TPI_EXT)))
\r
209 wxString szLibName = L_DIR_B_LIB + szTPIName;
\r
210 if (tpi.InitLibrary(szLibName, wxEmptyString, 0))
\r
213 TPI_FORMATINFO fiInfo;
\r
214 if (tpi.GetFormatInformation(& fiInfo, true))
\r
218 if (fiInfo.eSupportedCommand & TPI_COMMAND_CREATE && (this->lcFiles->asInput.GetCount() == 1 || fiInfo.fArchive))
\r
220 fiInfo.szTPIName = szLibName;
\r
221 this->afInfo.Add(fiInfo);
\r
222 this->chType->Append(fiInfo.szTypeName);
\r
225 while (tpi.GetFormatInformation(& fiInfo, false));
\r
230 while (fs.GetNext(& szTPIName));
\r
233 if (this->chType->GetCount() == 0)
\r
236 XRCCTRL(* this, "btnOK", wxButton)->Disable();
\r
240 // とりあえず最初の形式にしておく。
\r
241 this->chType->SetSelection(0);
\r
249 void MakeDialog::OnBtnDefault(wxCommandEvent&)
\r
251 this->cbDir->SetValue(((MainFrame *) this->GetParent())->conf.ReadId(CONF_DEFAULT_PATH, (wxString) wxEmptyString));
\r
254 void MakeDialog::OnBtnDesktop(wxCommandEvent&)
\r
256 wxFileName fn(wxFileName::GetHomeDir(), wxT("Desktop"));
\r
257 this->cbDir->SetValue(fn.GetFullPath());
\r
260 void MakeDialog::OnBtnCurrent(wxCommandEvent&)
\r
262 this->cbDir->SetValue(((MainFrame *) this->GetParent())->fnArchive.GetPath());
\r
265 void MakeDialog::OnBtnBrowse(wxCommandEvent&)
\r
267 wxDirDialog dd(this);
\r
268 dd.SetPath(this->cbDir->GetValue());
\r
269 if (dd.ShowModal() == wxID_OK)
\r
271 this->cbDir->SetValue(dd.GetPath());
\r
275 void MakeDialog::OnBtnBrowseKF(wxCommandEvent&)
\r
277 wxFileDialog fd(this);
\r
278 fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);
\r
279 if (fd.ShowModal() == wxID_OK)
\r
281 this->tcKeyfile->SetValue(fd.GetPath());
\r
285 void MakeDialog::OnBtnOK(wxCommandEvent&)
\r
288 if (this->uCommand != TPI_COMMAND_ADD)
\r
290 MainFrame * frm_main = (MainFrame *) this->GetParent();
\r
291 wxFileName fnCurrent(this->cbDir->GetValue(), this->uCommand == TPI_COMMAND_CREATE ? this->cbFileName->GetValue() : (wxString) wxEmptyString);
\r
292 frm_main->conf.WriteHistory(CONF_HISTORY_FULL, fnCurrent.GetFullPath());
\r
293 frm_main->conf.WriteHistory(CONF_HISTORY_PATH, fnCurrent.GetPath());
\r
294 frm_main->conf.WriteHistory(CONF_HISTORY_NAME, fnCurrent.GetFullName());
\r
296 this->EndModal(wxID_OK);
\r
299 void MakeDialog::OnBtnCancel(wxCommandEvent&)
\r
301 this->EndModal(wxID_CANCEL);
\r
304 void MakeDialog::OnChoice(wxCommandEvent& e)
\r
306 TPI_FORMATINFO * fiInfo = & this->afInfo[e.GetInt()];
\r
307 // 形式が各種設定に対応しているか。
\r
309 this->tcPassword->Enable(fiInfo->fEncryptPassword);
\r
310 this->cbUnmask->Enable(fiInfo->fEncryptPassword);
\r
311 this->tcKeyfile->Enable(fiInfo->fEncryptKeyFile);
\r
312 if (this->uCommand == TPI_COMMAND_EXTRACT)
\r
318 this->scLevel->SetRange(fiInfo->nCompressLevelMin, fiInfo->nCompressLevelMax);
\r
319 this->scLevel->SetValue(fiInfo->nCompressLevelMax);
\r
320 this->scLevel->Enable(fiInfo->nCompressLevelMin != fiInfo->nCompressLevelMax);
\r
321 this->scRR->SetRange(fiInfo->nRecoveryRecordMin, fiInfo->nRecoveryRecordMax);
\r
322 this->scRR->SetValue(fiInfo->nRecoveryRecordMin);
\r
323 this->scRR->Enable(fiInfo->nRecoveryRecordMin != fiInfo->nRecoveryRecordMax);
\r
324 this->cbEncryptHeader->Enable(fiInfo->fEncryptHeader);
\r
325 this->cbSolid->Enable(fiInfo->fSolid);
\r
326 this->cbMMOptimize->Enable(fiInfo->fMMOptimize);
\r
327 this->tcComment->Enable(fiInfo->fComment);
\r
328 if (this->uCommand == TPI_COMMAND_ADD)
\r
334 this->cbSplitSize->Enable(fiInfo->fMultiVolume);
\r
335 this->cbMakeSFX->Enable(fiInfo->fSFX);
\r
337 wxFileName fn(this->cbFileName->GetValue());
\r
338 fn.SetExt(this->cbMakeSFX->IsEnabled() && this->cbMakeSFX->IsChecked() ? EXE_EXT : fiInfo->szSuffix.BeforeFirst(wxT(';')));
\r
339 this->cbFileName->SetValue(fn.GetFullName());
\r
342 void MakeDialog::OnCbUnmask(wxCommandEvent&)
\r
344 this->tcPassword->SetWindowStyle(this->tcPassword->GetWindowStyle() & (this->cbUnmask->IsChecked() ? ~ wxTE_PASSWORD : wxTE_PASSWORD));
\r
345 this->tcPassword->Refresh();
\r
348 void MakeDialog::OnCbMakeSFX(wxCommandEvent&)
\r
350 wxFileName fn(this->cbFileName->GetValue());
\r
351 fn.SetExt(this->cbMakeSFX->IsChecked() ? EXE_EXT : this->afInfo[this->chType->GetSelection()].szSuffix.BeforeFirst(wxT(';')));
\r
352 this->cbFileName->SetValue(fn.GetFullName());
\r
355 void MakeDialog::OnTabChanged(wxNotebookEvent& e)
\r
357 // "Files"タブのときは処理。
\r
358 if (e.GetSelection() != 3)
\r
362 this->lcFiles->DeleteAllItems();
\r
363 this->lcFiles->asOutput.Clear();
\r
364 this->lcFiles->apItem.Clear();
\r
366 switch (this->uCommand)
\r
368 case TPI_COMMAND_EXTRACT:
\r
371 wxString szOutputRootDir = WillMakeDirByArcName((MainFrame *) this->GetParent(), this) ? MakeDirPath(wxFileName::DirName(this->cbDir->GetValue()), wxFileName(this->cbFileName->GetValue()).GetName(), false).GetPath() : this->cbDir->GetValue();
\r
374 bool fDTVWarning = false;
\r
375 for (size_t i = 0; i < this->lcFiles->asInput.GetCount(); i++)
\r
377 wxString szOutputFile = szOutputRootDir + wxFileName::GetPathSeparator();
\r
378 wxFileName fnStored(this->lcFiles->asInput[i]);
\r
379 if (! this->cbIgnorePath->IsChecked())
\r
381 szOutputFile += fnStored.GetPathWithSep();
\r
383 wxFileName fnOutput(szOutputFile + fnStored.GetFullName());
\r
384 if (! fnOutput.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG) || ! fnOutput.GetFullPath().StartsWith(szOutputRootDir))
\r
386 fDTVWarning = true;
\r
387 this->lcFiles->apItem.Add(& this->lcFiles->atDangerItem);
\r
391 this->lcFiles->apItem.Add(NULL);
\r
393 this->lcFiles->asOutput.Add(fnOutput.GetFullPath());
\r
396 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
398 this->cbIgnorePath->SetValue(true);
\r
399 this->OnTabChanged(e);
\r
403 case TPI_COMMAND_ADD:
\r
404 case TPI_COMMAND_CREATE:
\r
406 this->lcFiles->asOutput = this->lcFiles->asInput;
\r
407 this->lcFiles->apItem.SetCount(this->lcFiles->asInput.GetCount(), NULL);
\r
412 this->lcFiles->SetItemCount(this->lcFiles->asInput.GetCount());
\r
415 //******************************************************************************
\r
417 //******************************************************************************
\r
419 IMPLEMENT_DYNAMIC_CLASS(myListCtrl2, wxListView)
\r
421 //******************************************************************************
\r
423 //******************************************************************************
\r
424 wxString myListCtrl2::OnGetItemText(long i, long column) const
\r
430 return this->asInput[i];
\r
432 return this->asOutput[i];
\r
434 return wxEmptyString;
\r
438 wxListItemAttr * myListCtrl2::OnGetItemAttr(long i) const
\r
440 return (wxListItemAttr *) this->apItem[i];
\r