Click here to Skip to main content
15,885,216 members
Articles / Desktop Programming / MFC

TCExplorer - Portable Software to Import, Export, Delete, Rename, View, Edit and Execute Files in TrueCrypt Containers

Rate me:
Please Sign up or sign in to vote.
4.71/5 (13 votes)
9 Oct 20079 min read 208.2K   2.5K   52  
A portable software to import, export, delete, rename, view, edit and execute files in TrueCrypt containers without requiring administrative privileges
/***************************************************************
 * 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);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Researcher
Singapore Singapore
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions