/***************************************************************
* Name: TCList.cpp
* Author: Yap Chun Wei
* Created: 2007-05-23
* License: Public domain
**************************************************************/
#ifdef WX_PRECOMP
#include "wx_pch.h"
#endif
#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__
#include "TCList.h"
#include "TCExplorerMain.h"
#include "wx/html/htmlwin.h"
#include "wx/statline.h"
TCList::TCList(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name)
: wxListCtrl(parent, id, pos, size, style, validator, name),
tcFile_(0),
progress_(0),
startDrag_(false),
canDrop_(true),
confirmFileReplace_(0),
confirm_(this, wxID_ANY, _("Confirm File Replace"), wxDefaultPosition, wxSize(480, -1), wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
{
// Set event handlers.
parent->Connect(idTCList, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(TCList::OnActivate), 0, this);
parent->Connect(idTCList, wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(TCList::OnExport), 0, this);
parent->Connect(idTCList, wxEVT_COMMAND_LIST_END_LABEL_EDIT, wxListEventHandler(TCList::OnRename), 0, this);
parent->Connect(idTCList, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(TCList::OnSelect), 0, this);
parent->Connect(idTCList, wxEVT_COMMAND_LIST_KEY_DOWN, wxListEventHandler(TCList::OnKeyPress), 0, this);
parent->Connect(idTCList, wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(TCList::OnContext), 0, this);
parent->Connect(idContextView, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TCList::OnContextView), 0, this);
Connect(idTCList, wxEVT_SET_FOCUS, wxFocusEventHandler(TCList::OnFocus), 0, this);
}
TCList::~TCList()
{
// Remove event handlers.
GetParent()->Disconnect(idTCList, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(TCList::OnActivate), 0, this);
GetParent()->Disconnect(idTCList, wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(TCList::OnExport), 0, this);
GetParent()->Disconnect(idTCList, wxEVT_COMMAND_LIST_END_LABEL_EDIT, wxListEventHandler(TCList::OnRename), 0, this);
GetParent()->Disconnect(idTCList, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(TCList::OnSelect), 0, this);
GetParent()->Disconnect(idTCList, wxEVT_COMMAND_LIST_KEY_DOWN, wxListEventHandler(TCList::OnKeyPress), 0, this);
GetParent()->Disconnect(idTCList, wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(TCList::OnContext), 0, this);
GetParent()->Disconnect(idContextView, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TCList::OnContextView), 0, this);
Disconnect(idTCList, wxEVT_SET_FOCUS, wxFocusEventHandler(TCList::OnFocus), 0, this);
}
bool TCList::Open(LPCTSTR tcfile)
{
// Get password of TrueCrypt container from user.
wxPasswordEntryDialog password(this, _("Password for TrueCrypt file"));
if (password.ShowModal() != wxID_OK) return false;
// Open TrueCrypt container.
if (tcFile_) delete tcFile_;
tcFile_ = new TCFile();
if (tcFile_->Open(tcfile, (const char*)password.GetValue().mb_str())>=0)
{
// Show contents of the root directory
ShowDirectory(_("/"));
// Show some details on the TrueCrypt container.
wxFrame *parent = (wxFrame*)GetParent();
parent->SetStatusText(tcfile, 0);
parent->SetStatusText(wxString::Format(_("Size: %0.2f MB"), tcFile_->GetTotalSize()), 1);
parent->SetStatusText(wxString::Format(_("Used: %0.2f MB"), tcFile_->GetUsedSize()), 2);
parent->SetStatusText(wxString::Format(_("Free: %0.2f MB"), tcFile_->GetFreeSize()), 3);
}
else
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
Close();
}
}
void TCList::Close()
{
// Close the TrueCrypt container.
if (tcFile_)
{
delete tcFile_;
tcFile_ = 0;
}
openedFiles_.clear();
DeleteTemporaryDirectory();
DeleteAllItems();
TCExplorerFrame *parent = (TCExplorerFrame*)GetParent();
parent->curDir_->SetValue(_(""));
}
void TCList::RefreshList()
{
// Refresh contents of the current active directory of TrueCrypt container.
ShowDirectory(GetCurrentActiveDirectory());
}
void TCList::RefreshTCDetails()
{
if (tcFile_)
{
// Refresh some details on the TrueCrypt container.
tcFile_->RefreshPartition();
wxFrame *parent = (wxFrame*)GetParent();
parent->SetStatusText(wxString::Format(_("Used: %0.2f MB"), tcFile_->GetUsedSize()), 2);
parent->SetStatusText(wxString::Format(_("Free: %0.2f MB"), tcFile_->GetFreeSize()), 3);
}
}
void TCList::ShowDirectory(const wxString& dir)
{
if (tcFile_)
{
// Update current active directory.
wxString cDir = dir;
if (cDir.IsEmpty()) cDir = _("/");
wxFileName curDir = cDir;
wxArrayString dirs = curDir.GetDirs();
int maxDirs = dirs.GetCount();
vector<wxString> oldDirPaths_ = dirPaths_;
dirPaths_.resize(maxDirs);
for (int i=0; i<maxDirs; ++i) dirPaths_[i] = dirs[i];
if (!curDir.GetFullName().IsEmpty()) dirPaths_.push_back(curDir.GetFullName());
// Show contents of current active directory.
TCExplorerFrame *parent = (TCExplorerFrame*)GetParent();
if (parent->viewFileSize_)
{
if (!tcFile_->DirectoryList((const char*)cDir.mb_str(), directories_, files_, true))
{
wxMessageDialog msg(this, _("Cannot find '") + cDir + _("'. Make sure the path is correct."), _("TCExplorer"), wxICON_ERROR);
msg.ShowModal();
dirPaths_ = oldDirPaths_;
return;
}
}
else
{
if (!tcFile_->DirectoryList((const char*)cDir.mb_str(), directories_, files_))
{
wxMessageDialog msg(this, _("Cannot find '") + cDir + _("'. Make sure the path is correct."), _("TCExplorer"), wxICON_ERROR);
msg.ShowModal();
dirPaths_ = oldDirPaths_;
return;
}
}
DeleteAllItems();
long itemIndex;
// Insert directories.
set<wxString>::iterator it = directories_.begin();
set<wxString>::iterator ite = directories_.end();
for (; it!=ite; ++it)
{
InsertItem(GetItemCount(), *it, wxFileIconsTable::folder);
}
// Insert files.
map<wxString,u32>::iterator fit = files_.begin();
map<wxString,u32>::iterator fite = files_.end();
size_t maxColours = parent->colours_.size();
for (; fit!=fite; ++fit)
{
itemIndex = InsertItem(GetItemCount(), fit->first, wxFileIconsTable::file);
wxString ext = wxFileName(fit->first).GetExt();
for (size_t i=0; i<maxColours; ++i)
{
if (ext == parent->colours_[i].first)
{
SetItemTextColour(itemIndex, parent->colours_[i].second);
break;
}
}
if (parent->viewFileSize_)
{
wxString fileSize = wxFileName::GetHumanReadableSize(wxULongLong(fit->second), _("0 B"));
SetItem(itemIndex, 1, fileSize);
}
}
parent->curDir_->SetValue(GetCurrentActiveDirectory());
}
}
void TCList::OnActivate(wxListEvent& event)
{
wxString curItem = event.GetLabel();
if (curItem == _(".."))
{
// Go up one directory level.
dirPaths_.pop_back();
RefreshList();
}
else if (curItem != _(".") && directories_.find(curItem)!=directories_.end())
{
// Go down one directory level.
dirPaths_.push_back(curItem);
RefreshList();
}
else
{
wxString sdir = GetCurrentActiveDirectory();
// Create temporary system directory to store exported directories and files.
TCExplorerFrame *parent = (TCExplorerFrame*)GetParent();
wxString ddir = parent->tempDir_;
HandleTemporaryDirectory();
if (!wxDirExists(ddir)) wxMkdir(ddir);
// Export files from TrueCrypt container and open them.
ddir += _("\\~TC") + wxString::Format(_("%d"), openedFiles_.size()) + _("TC~");
if (!wxDirExists(ddir)) wxMkdir(ddir);
long item = -1;
for ( ;; )
{
item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1) break;
wxString name = GetItemText(item);
wxString destination = ddir + wxFileName::GetPathSeparator() + name;
if (directories_.find(name)==directories_.end())
{
// File.
wxString source = sdir + name;
if (tcFile_->Export((const char*)source.mb_str(), (const char*)destination.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
else
{
/*
// Platform independent but may give DDE execute errors
wxString runCmd = (wxTheMimeTypesManager->GetFileTypeFromExtension(destination.AfterLast('.')))->GetOpenCommand(destination);
if (!runCmd.IsEmpty())
{
OpenedFile openedFile;
openedFile.pathInTC_ = source;
openedFile.pathInTemp_ = destination;
wxFileName file = destination;
openedFile.lastmodified_ = file.GetModificationTime();
openedFiles_.push_back(openedFile);
wxExecute(runCmd);
}
*/
// Only for Windows.
OpenedFile openedFile;
openedFile.pathInTC_ = source;
openedFile.pathInTemp_ = destination;
wxFileName file = destination;
openedFile.lastmodified_ = file.GetModificationTime();
openedFiles_.push_back(openedFile);
wxExecute(_("rundll32 SHELL32.DLL,ShellExec_RunDLL \"") + destination + _("\""));
}
}
}
}
}
void TCList::OnSelect(wxListEvent& event)
{
// Get full name of currently directory/file.
curSelected_ = GetCurrentActiveDirectory() + event.GetLabel();
}
void TCList::OnExport(wxListEvent& event)
{
// Prepare list of directories and files to be exported.
TCExplorerFrame *parent = (TCExplorerFrame*)GetParent();
wxString ddir = parent->tempDir_;
wxFileDataObject files;
long item = -1;
for ( ;; )
{
item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1) break;
wxString name = GetItemText(item);
wxString destination = ddir + wxFileName::GetPathSeparator() + name;
if (directories_.find(name)!=directories_.end())
{
// Directory.
files.AddFile(destination);
}
else
{
// File.
files.AddFile(destination);
}
}
// Pass control to Windows drag and drop.
startDrag_ = true;
TCDropSource dragSource(files, this);
dragSource.SetData(files);
wxDragResult result = dragSource.DoDragDrop(TRUE);
startDrag_ = false;
HandleTemporaryDirectory();
}
void TCList::OnKeyPress(wxListEvent& event)
{
switch (event.GetKeyCode())
{
case WXK_F5: // F5 is pressed.
RefreshList();
break;
case WXK_DELETE: // Delete key is pressed.
{
// Ask for delete confirmation.
wxMessageDialog msg(this, _("Are you sure you want to delete these files?"), _("Confirm delete"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
if (msg.ShowModal()==wxID_NO) break;
// Prepare progress dialog
wxString sdir = GetCurrentActiveDirectory();
int maxFilesInDir = 0;
long item = -1;
for ( ;; )
{
item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1 ) break;
wxString name = GetItemText(item);
if (directories_.find(name)!=directories_.end())
{
// Directory.
maxFilesInDir += CountTCFiles(sdir + name + _("/"));
}
else
{
// File.
++maxFilesInDir;
}
}
if (progress_) delete progress_;
progress_ = new wxProgressDialog(_("Delete"), wxString(_(" "),20), maxFilesInDir, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME);
progressIndex_ = 0;
// Delete directories and files from TrueCrypt container.
item = -1;
for ( ;; )
{
item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1 ) break;
wxString name = GetItemText(item);
if (directories_.find(name)!=directories_.end())
{
// Directory.
DeleteDirectory(sdir + name + _("/"));
}
else
{
// File.
wxString source = sdir + name;
progress_->Update(++progressIndex_, _("Deleting ") + source);
if (tcFile_->Delete((const char*)source.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
}
delete progress_;
progress_ = 0;
RefreshList();
RefreshTCDetails();
break;
}
}
}
void TCList::OnRename(wxListEvent& event)
{
// Rename a directory/file.
wxString destination = GetCurrentActiveDirectory() + event.GetLabel();
if (curSelected_!=destination && !event.GetLabel().IsEmpty())
{
if (tcFile_->Move((const char*)curSelected_.mb_str(), (const char*)destination.mb_str())>=0)
{
RefreshList();
}
else
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
}
void TCList::OnContext(wxContextMenuEvent& event)
{
wxPoint point = ScreenToClient(wxGetMousePosition());
wxMenu menu;
menu.Append(idContextView, _("View with Internal Viewer"));
long index = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (GetItemCount()==0 || index==-1)
{
menu.Enable(idContextView, false);
}
PopupMenu(&menu, point);
}
void TCList::OnContextView(wxCommandEvent& event)
{
// Export files from TrueCrypt container to memory and open them.
wxString sdir = GetCurrentActiveDirectory();
long item = -1;
for ( ;; )
{
item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1) break;
wxString name = GetItemText(item);
if (directories_.find(name)==directories_.end())
{
// File.
wxString source = sdir + name;
if (tcFile_->ExportToMemory((const char*)source.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
else
{
wxDialog dlg(this, wxID_ANY, name, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER);
wxHtmlWindow *html = new wxHtmlWindow(&dlg, -1, wxDefaultPosition, wxSize(640, 480), wxHW_SCROLLBAR_AUTO);
html->SetBorders(0);
html->LoadPage(_("memory:") + name);
html->SetSize(html->GetInternalRepresentation()->GetWidth(), html->GetInternalRepresentation()->GetHeight());
wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
topsizer->Add(html, 1, wxGROW|wxALL, 5);
topsizer->Add(new wxStaticLine(&dlg, -1), 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
topsizer->Add(new wxButton(&dlg, wxID_OK, _("Ok")), 0, wxALL | wxALIGN_RIGHT, 15);
dlg.SetSizer(topsizer);
topsizer->Fit(&dlg);
dlg.Centre();
dlg.ShowModal();
wxMemoryFSHandler::RemoveFile(name);
}
}
}
}
void TCList::OnFocus(wxFocusEvent& event)
{
size_t maxOpenedFiles = openedFiles_.size();
for (size_t i=0; i<maxOpenedFiles; ++i)
{
wxFileName file = openedFiles_[i].pathInTemp_;
wxDateTime lastmodified = file.GetModificationTime();
if (lastmodified > openedFiles_[i].lastmodified_)
{
openedFiles_[i].lastmodified_ = lastmodified;
wxMessageDialog msg(this, _("File ") + openedFiles_[i].pathInTemp_ + _(" has been changed since it was extracted.\n\nUpdate ") + openedFiles_[i].pathInTC_ + _(" in TrueCrypt container with this file?"), _("TCExplorer"), wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
if (msg.ShowModal() == wxID_YES)
{
wxString curActiveDir = GetCurrentActiveDirectory();
wxFileName tcfile = openedFiles_[i].pathInTC_;
SetCurrentActiveDirectory(tcfile.GetPath());
wxArrayString filenames;
filenames.Add(openedFiles_[i].pathInTemp_);
confirmFileReplace_ = 1;
Import(filenames);
ShowDirectory(curActiveDir);
}
}
}
}
void TCList::Import(const wxArrayString& filenames)
{
// Prepare progress dialog
int maxFilesInDir = 0;
int maxFiles = filenames.GetCount();
for (int i=0; i<maxFiles; ++i)
{
if (wxDirExists(filenames[i]))
{
// Directory.
maxFilesInDir += CountSystemFiles(filenames[i]);
}
else
{
// File.
++maxFilesInDir;
}
}
if (progress_) delete progress_;
progress_ = new wxProgressDialog(_("Import"), wxString(_(" "),20), maxFilesInDir, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME);
progressIndex_ = 0;
// Import directories and files into TrueCrypt container.
totalBytesAvailable_ = tcFile_->GetFreeSizeInBytes();
totalBytesImported_ = 0;
wxString dir = GetCurrentActiveDirectory();
set<wxString> directories;
map<wxString,u32> files;
tcFile_->DirectoryList((const char*)dir.mb_str(), directories, files, true);
for (int i=0; i<maxFiles; ++i)
{
if (wxDirExists(filenames[i]))
{
// Directory.
if (!ImportDirectory(filenames[i], dir)) break;
}
else
{
// File.
progress_->Update(++progressIndex_, _("Importing ") + filenames[i]);
wxFileName filename = filenames[i];
wxStructStat strucStat;
wxStat(filenames[i], &strucStat);
map<wxString,u32>::iterator findex;
if ((findex=files.find(filename.GetFullName()))==files.end()) totalBytesImported_ += (UINT64)strucStat.st_size;
else
{
if (confirmFileReplace_ == -1) continue;
else if (confirmFileReplace_ == 0)
{
confirm_.fileCtrl_->SetLabel(_("This folder '") + dir + _("' already contains a file name '") + filename.GetFullName() + _("'."));
confirm_.oriFileSizeCtrl_->SetLabel(wxFileName::GetHumanReadableSize(wxULongLong(findex->second), _("0 B")));
confirm_.newFileSizeCtrl_->SetLabel(wxFileName::GetHumanReadableSize(wxULongLong(strucStat.st_size), _("0 B")));
int retVal = confirm_.ShowModal();
if (retVal == wxID_YESTOALL) confirmFileReplace_ = 1;
else if (retVal == wxID_NO) continue;
else if (retVal == wxID_NOTOALL)
{
confirmFileReplace_ = -1;
continue;
}
else if (retVal == wxID_CANCEL) break;
}
totalBytesImported_ += (UINT64)strucStat.st_size>(UINT64)findex->second ? (UINT64)strucStat.st_size-(UINT64)findex->second : 0;
}
UINT64 tba = totalBytesAvailable_;
UINT64 tbi = totalBytesImported_;
if (totalBytesImported_ > totalBytesAvailable_)
{
wxMessageDialog msg(this,
wxString::Format(_("Cannot import %s: There is not enough free disk space.\n\nDelete one or more files to free disk space, and then try again."), filenames[i].c_str())
, _("Error Importing File or Folder"), wxICON_ERROR);
msg.ShowModal();
break;
}
wxString destination = dir + filename.GetFullName();
if (tcFile_->Import((const char*)filenames[i].mb_str(), (const char*)destination.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
}
delete progress_;
progress_ = 0;
confirmFileReplace_ = 0;
RefreshList();
RefreshTCDetails();
}
void TCList::Export()
{
wxString sdir = GetCurrentActiveDirectory();
// Create temporary system directory to store exported directories and files.
TCExplorerFrame *parent = (TCExplorerFrame*)GetParent();
wxString ddir = parent->tempDir_;
HandleTemporaryDirectory();
if (!wxDirExists(ddir)) wxMkdir(ddir);
// Prepare progress dialog
int maxFilesInDir = 0;
long item = -1;
for ( ;; )
{
item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1 ) break;
wxString name = GetItemText(item);
if (directories_.find(name)!=directories_.end())
{
// Directory.
maxFilesInDir += CountTCFiles(sdir + name + _("/"));
}
else
{
// File.
++maxFilesInDir;
}
}
if (progress_) delete progress_;
progress_ = new wxProgressDialog(_("Export"), wxString(_(" "),20), maxFilesInDir, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_SMOOTH | wxPD_ELAPSED_TIME);
progressIndex_ = 0;
// Export directories and files from TrueCrypt container.
item = -1;
for ( ;; )
{
item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1) break;
wxString name = GetItemText(item);
wxString destination = ddir + wxFileName::GetPathSeparator() + name;
if (directories_.find(name)!=directories_.end())
{
// Directory.
ExportDirectory(sdir + name + _("/"), destination + _("/"));
}
else
{
// File.
wxString source = sdir + name;
progress_->Update(++progressIndex_, _("Exporting ") + source);
if (tcFile_->Export((const char*)source.mb_str(), (const char*)destination.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
}
delete progress_;
progress_ = 0;
}
bool TCList::ImportDirectory(wxString fromDir, const wxString& toTCDir)
{
// Get contents of destination TrueCrypt directory.
set<wxString> directories;
map<wxString,u32> files;
tcFile_->DirectoryList((const char*)toTCDir.mb_str(), directories, files);
wxString TCDir = wxFileName(fromDir).GetFullName();
if (directories.find(TCDir)==directories.end())
{
// Create TrueCrypt directory.
TCDir = toTCDir + TCDir;
if (tcFile_->CreateFolder((const char*)TCDir.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
TCDir += _("/");
}
else TCDir = toTCDir + TCDir + _("/");
// Import directories and files into TrueCrypt container.
tcFile_->DirectoryList((const char*)TCDir.mb_str(), directories, files, true);
fromDir += _("\\");
wxDir dir(fromDir);
wxString name;
bool hasFile = dir.GetFirst(&name);
while (hasFile)
{
wxString source = fromDir + name;
if (wxDirExists(source))
{
// Directory.
if (!ImportDirectory(source, TCDir)) return false;
}
else
{
// File.
progress_->Update(++progressIndex_, _("Importing ") + source);
wxStructStat strucStat;
wxStat(source, &strucStat);
map<wxString,u32>::iterator findex;
if ((findex=files.find(name))==files.end()) totalBytesImported_ += (UINT64)strucStat.st_size;
else
{
if (confirmFileReplace_ == -1)
{
hasFile = dir.GetNext(&name);
continue;
}
else if (confirmFileReplace_ == 0)
{
confirm_.fileCtrl_->SetLabel(_("This folder '") + TCDir + _("' already contains a file name '") + name + _("'."));
confirm_.oriFileSizeCtrl_->SetLabel(wxFileName::GetHumanReadableSize(wxULongLong(findex->second), _("0 B")));
confirm_.newFileSizeCtrl_->SetLabel(wxFileName::GetHumanReadableSize(wxULongLong(strucStat.st_size), _("0 B")));
int retVal = confirm_.ShowModal();
if (retVal == wxID_YESTOALL) confirmFileReplace_ = 1;
else if (retVal == wxID_NO)
{
hasFile = dir.GetNext(&name);
continue;
}
else if (retVal == wxID_NOTOALL)
{
confirmFileReplace_ = -1;
hasFile = dir.GetNext(&name);
continue;
}
else if (retVal == wxID_CANCEL) return false;
}
totalBytesImported_ += (UINT64)strucStat.st_size>(UINT64)findex->second ? (UINT64)strucStat.st_size-(UINT64)findex->second : 0;
}
if (totalBytesImported_ > totalBytesAvailable_)
{
wxMessageDialog msg(this,
wxString::Format(_("Cannot import %s: There is not enough free disk space.\n\nDelete one or more files to free disk space, and then try again."), source.c_str())
, _("Error Importing File or Folder"), wxICON_ERROR);
msg.ShowModal();
return false;
}
wxString destination = TCDir + name;
if (tcFile_->Import((const char*)source.mb_str(), (const char*)destination.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
hasFile = dir.GetNext(&name);
}
return true;
}
void TCList::ExportDirectory(const wxString& fromTCDir, const wxString& toDir)
{
// Create temporary system directory to store exported directories and files.
::wxMkdir(toDir);
// Get contents of TrueCrypt directory.
set<wxString> directories;
map<wxString,u32> files;
tcFile_->DirectoryList((const char*)fromTCDir.mb_str(), directories, files);
// Export directories from TrueCrypt container.
set<wxString>::iterator it = directories.begin();
set<wxString>::iterator ite = directories.end();
for (; it!=ite; ++it)
{
if (*it == _(".") || *it == _("..")) continue;
wxString dir = toDir + *it + _("/");
ExportDirectory(fromTCDir + *it + _("/"), dir);
}
// Export files from TrueCrypt container.
map<wxString,u32>::iterator fit = files.begin();
map<wxString,u32>::iterator fite = files.end();
for (; fit!=fite; ++fit)
{
wxString source = fromTCDir + fit->first;
wxString destination = toDir + fit->first;
progress_->Update(++progressIndex_, _("Exporting ") + source);
if (tcFile_->Export((const char*)source.mb_str(), (const char*)destination.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
}
void TCList::DeleteDirectory(const wxString& TCDir)
{
// Get contents of TrueCrypt directory to be deleted.
set<wxString> directories;
map<wxString,u32> files;
tcFile_->DirectoryList((const char*)TCDir.mb_str(), directories, files);
// Delete directories from TrueCrypt container.
set<wxString>::iterator it = directories.begin();
set<wxString>::iterator ite = directories.end();
for (; it!=ite; ++it)
{
if (*it == _(".") || *it == _("..")) continue;
wxString dir = TCDir + *it + _("/");
DeleteDirectory(dir);
}
// Delete files from TrueCrypt container.
map<wxString,u32>::iterator fit = files.begin();
map<wxString,u32>::iterator fite = files.end();
for (; fit!=fite; ++fit)
{
wxString file = TCDir + fit->first;
progress_->Update(++progressIndex_, _("Deleting ") + file);
if (tcFile_->Delete((const char*)file.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
// Delete given directory from TrueCrypt container.
if (tcFile_->Delete((const char*)TCDir.mb_str())<0)
{
wxMessageDialog msg(this, tcFile_->errorMessage_, _("Error"), wxICON_ERROR);
msg.ShowModal();
}
}
wxString TCList::GetCurrentActiveDirectory()
{
///< Get current active TrueCrypt container directory (with terminating slash).
wxString dir = _("/");
int maxCurDir = dirPaths_.size();
for (int i=0; i<maxCurDir; ++i) dir += dirPaths_[i] + _("/");
return dir;
}
void TCList::SetCurrentActiveDirectory(const wxString& path)
{
wxString cDir = path;
if (cDir.IsEmpty()) cDir = _("/");
wxFileName curDir = cDir;
wxArrayString dirs = curDir.GetDirs();
int maxDirs = dirs.GetCount();
dirPaths_.resize(maxDirs);
for (int i=0; i<maxDirs; ++i) dirPaths_[i] = dirs[i];
if (!curDir.GetFullName().IsEmpty()) dirPaths_.push_back(curDir.GetFullName());
}
int TCList::CountSystemFiles(wxString sysDir)
{
int maxFiles = 0;
sysDir += _("\\");
wxDir dir(sysDir);
wxString name;
bool hasFile = dir.GetFirst(&name);
while (hasFile)
{
wxString source = sysDir + name;
if (wxDirExists(source))
{
// Count number of files in this subdirectory and its subdirectories.
maxFiles += CountSystemFiles(source);
}
else
{
// Count number of files in this subdirectory.
++maxFiles;
}
hasFile = dir.GetNext(&name);
}
return maxFiles;
}
int TCList::CountTCFiles(const wxString& TCDir)
{
int maxFiles = 0;
set<wxString> directories;
map<wxString,u32> files;
tcFile_->DirectoryList((const char*)TCDir.mb_str(), directories, files);
// Count number of files in all subdirectories.
set<wxString>::iterator it = directories.begin();
set<wxString>::iterator ite = directories.end();
for (; it!=ite; ++it)
{
if (*it == _(".") || *it == _("..")) continue;
wxString dir = TCDir + *it + _("/");
maxFiles += CountTCFiles(dir); // Count number of files in this subdirectory and its subdirectories.
}
// Count number of files in this subdirectory.
maxFiles += files.size();
return maxFiles;
}
void TCList::HandleTemporaryDirectory()
{
// Delete temporary directory only if there is no opened files.
if (openedFiles_.empty()) DeleteTemporaryDirectory();
}
void TCList::DeleteTemporaryDirectory()
{
openedFiles_.clear();
TCExplorerFrame *parent = (TCExplorerFrame*)GetParent();
switch (parent->tempOptions_.deleteTemp_)
{
case 1:
DeleteSystemDirectory(parent->tempDir_);
break;
case 2:
SecureDeleteSystemDirectory(parent->tempDir_);
break;
case 3:
EraserDeleteSystemDirectory(parent->tempDir_);
break;
}
}
void TCList::DeleteSystemDirectory(wxString sysDir)
{
if (wxDirExists(sysDir))
{
wxDir dir(sysDir);
wxString name;
bool hasFile = dir.GetFirst(&name);
while (hasFile)
{
wxString source = sysDir + wxFileName::GetPathSeparator() + name;
if (wxDirExists(source))
{
// Delete this subdirectory and its subdirectories.
DeleteSystemDirectory(source);
}
else
{
// Delete files in this subdirectory.
::wxRemoveFile(source);
}
hasFile = dir.GetNext(&name);
}
}
::wxRmdir(sysDir);
}
void TCList::SecureDeleteSystemDirectory(wxString sysDir)
{
wxString newName;
if (wxDirExists(sysDir))
{
wxDir dir(sysDir);
wxString name;
bool hasFile = dir.GetFirst(&name);
while (hasFile)
{
wxString source = sysDir + wxFileName::GetPathSeparator() + name;
if (wxDirExists(source))
{
// Delete this subdirectory and its subdirectories.
SecureDeleteSystemDirectory(source);
}
else
{
// Delete files in this subdirectory.
wxFFile f(source, _("rb+"));
if (f.IsOpened())
{
wxFileOffset maxLength = f.Length();
char null = '\0';
for (wxFileOffset i=0; i<maxLength; ++i)
{
f.Write(&null, 1);
}
f.Close();
}
newName = sysDir + _("\\~");
if (wxRenameFile(source, newName)) wxRemoveFile(newName);
else wxRemoveFile(source);
}
hasFile = dir.GetNext(&name);
}
}
wxLogNull nolog;
newName = sysDir.BeforeLast(wxT('\\')) + _("\\~");
if (wxRenameFile(sysDir, newName)) wxRmdir(newName);
else wxRmdir(sysDir);
}
void TCList::EraserDeleteSystemDirectory(wxString sysDir)
{
TCExplorerFrame *parent = (TCExplorerFrame*)GetParent();
wxFileName tempdir = parent->tempDir_;
wxProcess *process = new wxProcess(this);
process->Redirect();
wxExecute(parent->tempOptions_.eraserFile_ + _(" -folder \"") + tempdir.GetShortPath() + _("\" -subfolders ") + parent->tempOptions_.eraserArgs_, wxEXEC_ASYNC, process);
}