#include #include "chmoddialog.h" BEGIN_EVENT_TABLE(CChmodDialog, wxDialogEx) EVT_BUTTON(XRCID("wxID_OK"), CChmodDialog::OnOK) EVT_BUTTON(XRCID("wxID_CANCEL"), CChmodDialog::OnCancel) EVT_TEXT(XRCID("ID_NUMERIC"), CChmodDialog::OnNumericChanged) EVT_CHECKBOX(XRCID("ID_RECURSE"), CChmodDialog::OnRecurseChanged) END_EVENT_TABLE() CChmodDialog::CChmodDialog() { for (int i = 0; i < 9; ++i) { m_checkBoxes[i] = 0; m_permissions[i] = 0; } } bool CChmodDialog::Create(wxWindow* parent, int fileCount, int dirCount, const wxString& name, const char permissions[9]) { m_noUserTextChange = false; lastChangedNumeric = false; memcpy(m_permissions, permissions, 9); SetExtraStyle(wxWS_EX_BLOCK_EVENTS); SetParent(parent); wxString title; if (!dirCount) { if (fileCount == 1) { title = wxString::Format(_("Please select the new attributes for the file \"%s\"."), name); } else title = _("Please select the new attributes for the selected files."); } else { if (!fileCount) { if (dirCount == 1) { title = wxString::Format(_("Please select the new attributes for the directory \"%s\"."), name); } else title = _("Please select the new attributes for the selected directories."); } else title = _("Please select the new attributes for the selected files and directories."); } if (!Load(parent, _T("ID_CHMODDIALOG"))) { return false; } if (!SetChildLabel(XRCID("ID_DESC"), title, 300)) { wxFAIL_MSG(_T("Could not set ID_DESC")); } if (!XRCCTRL(*this, "wxID_OK", wxButton)) return false; if (!XRCCTRL(*this, "wxID_CANCEL", wxButton)) return false; if (!XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl)) return false; if (!WrapText(this, XRCID("ID_NUMERICTEXT"), 300)) { wxFAIL_MSG(_T("Wrapping of ID_NUMERICTEXT failed")); } wxCheckBox* pRecurse = XRCCTRL(*this, "ID_RECURSE", wxCheckBox); wxRadioButton* pApplyAll = XRCCTRL(*this, "ID_APPLYALL", wxRadioButton); wxRadioButton* pApplyFiles = XRCCTRL(*this, "ID_APPLYFILES", wxRadioButton); wxRadioButton* pApplyDirs = XRCCTRL(*this, "ID_APPLYDIRS", wxRadioButton); if (!pRecurse || !pApplyAll || !pApplyFiles || !pApplyDirs) return false; if (!dirCount) { pRecurse->Hide(); pApplyAll->Hide(); pApplyFiles->Hide(); pApplyDirs->Hide(); } pApplyAll->Enable(false); pApplyFiles->Enable(false); pApplyDirs->Enable(false); const wxChar* IDs[9] = { _T("ID_OWNERREAD"), _T("ID_OWNERWRITE"), _T("ID_OWNEREXECUTE"), _T("ID_GROUPREAD"), _T("ID_GROUPWRITE"), _T("ID_GROUPEXECUTE"), _T("ID_PUBLICREAD"), _T("ID_PUBLICWRITE"), _T("ID_PUBLICEXECUTE") }; for (int i = 0; i < 9; ++i) { int id = wxXmlResource::GetXRCID(IDs[i]); m_checkBoxes[i] = wxDynamicCast(FindWindow(id), wxCheckBox); if (!m_checkBoxes[i]) return false; Connect(id, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(CChmodDialog::OnCheckboxClick)); switch (permissions[i]) { default: case 0: m_checkBoxes[i]->Set3StateValue(wxCHK_UNDETERMINED); break; case 1: m_checkBoxes[i]->Set3StateValue(wxCHK_UNCHECKED); break; case 2: m_checkBoxes[i]->Set3StateValue(wxCHK_CHECKED); break; } } GetSizer()->Fit(this); GetSizer()->SetSizeHints(this); wxCommandEvent evt; OnCheckboxClick(evt); return true; } void CChmodDialog::OnOK(wxCommandEvent&) { wxCheckBox* pRecurse = XRCCTRL(*this, "ID_RECURSE", wxCheckBox); m_recursive = pRecurse->GetValue(); wxRadioButton* pApplyFiles = XRCCTRL(*this, "ID_APPLYFILES", wxRadioButton); wxRadioButton* pApplyDirs = XRCCTRL(*this, "ID_APPLYDIRS", wxRadioButton); if (pApplyFiles->GetValue()) m_applyType = 1; else if (pApplyDirs->GetValue()) m_applyType = 2; else m_applyType = 0; EndModal(wxID_OK); } void CChmodDialog::OnCancel(wxCommandEvent&) { EndModal(wxID_CANCEL); } void CChmodDialog::OnCheckboxClick(wxCommandEvent&) { lastChangedNumeric = false; for (int i = 0; i < 9; ++i) { wxCheckBoxState state = m_checkBoxes[i]->Get3StateValue(); switch (state) { default: case wxCHK_UNDETERMINED: m_permissions[i] = 0; break; case wxCHK_UNCHECKED: m_permissions[i] = 1; break; case wxCHK_CHECKED: m_permissions[i] = 2; break; } } wxString numericValue; for (int i = 0; i < 3; ++i) { if (!m_permissions[i * 3] || !m_permissions[i * 3 + 1] || !m_permissions[i * 3 + 2]) { numericValue += 'x'; continue; } numericValue += wxString::Format(_T("%d"), (m_permissions[i * 3] - 1) * 4 + (m_permissions[i * 3 + 1] - 1) * 2 + (m_permissions[i * 3 + 2] - 1) * 1); } wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl); wxString oldValue = pTextCtrl->GetValue(); m_noUserTextChange = true; pTextCtrl->SetValue(oldValue.Left(oldValue.Length() - 3) + numericValue); m_noUserTextChange = false; oldNumeric = numericValue; } void CChmodDialog::OnNumericChanged(wxCommandEvent&) { if (m_noUserTextChange) return; lastChangedNumeric = true; wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl); wxString numeric = pTextCtrl->GetValue(); if (numeric.Length() < 3) return; numeric = numeric.Right(3); for (int i = 0; i < 3; ++i) { if ((numeric[i] < '0' || numeric[i] > '9') && numeric[i] != 'x') return; } for (int i = 0; i < 3; ++i) { if (!oldNumeric.empty() && numeric[i] == oldNumeric[i]) continue; if (numeric[i] == 'x') { m_permissions[i * 3] = 0; m_permissions[i * 3 + 1] = 0; m_permissions[i * 3 + 2] = 0; } else { int value = numeric[i] - '0'; m_permissions[i * 3] = (value & 4) ? 2 : 1; m_permissions[i * 3 + 1] = (value & 2) ? 2 : 1; m_permissions[i * 3 + 2] = (value & 1) ? 2 : 1; } } oldNumeric = numeric; for (int i = 0; i < 9; ++i) { switch (m_permissions[i]) { default: case 0: m_checkBoxes[i]->Set3StateValue(wxCHK_UNDETERMINED); break; case 1: m_checkBoxes[i]->Set3StateValue(wxCHK_UNCHECKED); break; case 2: m_checkBoxes[i]->Set3StateValue(wxCHK_CHECKED); break; } } } wxString CChmodDialog::GetPermissions(const char* previousPermissions, bool dir) { // Construct a new permission string wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl); wxString numeric = pTextCtrl->GetValue(); if (numeric.Length() < 3) return numeric; for (unsigned int i = numeric.Length() - 3; i < numeric.Length(); ++i) { if ((numeric[i] < '0' || numeric[i] > '9') && numeric[i] != 'x') return numeric; } if (!previousPermissions) { // Use default of (0...0)755 for dirs and // 644 for files if (numeric[numeric.Length() - 1] == 'x') numeric[numeric.Length() - 1] = dir ? '5' : '4'; if (numeric[numeric.Length() - 2] == 'x') numeric[numeric.Length() - 2] = dir ? '5' : '4'; if (numeric[numeric.Length() - 3] == 'x') numeric[numeric.Length() - 3] = dir ? '7' : '6'; numeric.Replace(_T("x"), _T("0")); return numeric; } // 2 set, 1 unset, 0 keep const char defaultPerms[9] = { 2, 2, 2, 2, 1, 2, 2, 1, 2 }; char perms[9]; memcpy(perms, m_permissions, 9); wxString permission = numeric.Left(numeric.Length() - 3); unsigned int k = 0; for (unsigned int i = numeric.Length() - 3; i < numeric.Length(); ++i, ++k) { for (unsigned int j = k * 3; j < k * 3 + 3; ++j) { if (!perms[j]) { if (previousPermissions[j]) perms[j] = previousPermissions[j]; else perms[j] = defaultPerms[j]; } } permission += wxString::Format(_T("%d"), (int)(perms[k * 3] - 1) * 4 + (perms[k * 3 + 1] - 1) * 2 + (perms[k * 3 + 2] - 1) * 1); } return permission; } bool CChmodDialog::Recursive() const { return m_recursive; } void CChmodDialog::OnRecurseChanged(wxCommandEvent&) { wxCheckBox* pRecurse = XRCCTRL(*this, "ID_RECURSE", wxCheckBox); wxRadioButton* pApplyAll = XRCCTRL(*this, "ID_APPLYALL", wxRadioButton); wxRadioButton* pApplyFiles = XRCCTRL(*this, "ID_APPLYFILES", wxRadioButton); wxRadioButton* pApplyDirs = XRCCTRL(*this, "ID_APPLYDIRS", wxRadioButton); pApplyAll->Enable(pRecurse->GetValue()); pApplyFiles->Enable(pRecurse->GetValue()); pApplyDirs->Enable(pRecurse->GetValue()); } bool CChmodDialog::ConvertPermissions(wxString rwx, char* permissions) { if (!permissions) return false; int pos = rwx.Find('('); if (pos != -1 && rwx.Last() == ')') { // MLSD permissions: // foo (0644) rwx.RemoveLast(); rwx = rwx.Mid(pos + 1); } if (rwx.Len() < 3) return false; size_t i; for (i = 0; i < rwx.Len(); i++) if (rwx[i] < '0' || rwx[i] > '9') break; if (i == rwx.Len()) { // Mode, e.g. 0723 for (i = 0; i < 3; ++i) { int m = rwx[rwx.Len() - 3 + i] - '0'; for (int j = 0; j < 3; ++j) { if (m & (4 >> j)) permissions[i * 3 + j] = 2; else permissions[i * 3 + j] = 1; } } return true; } const unsigned char permchars[3] = {'r', 'w', 'x'}; if (rwx.Length() != 10) return false; for (int j = 0; j < 9; ++j) { bool set = rwx[j + 1] == permchars[j % 3]; permissions[j] = set ? 2 : 1; } if (rwx[3] == 's') permissions[2] = 2; if (rwx[6] == 's') permissions[5] = 2; if (rwx[9] == 't') permissions[8] = 2; return true; }