source: filezilla/trunk/fuentes/src/interface/chmoddialog.cpp @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

File size: 8.9 KB
Line 
1#include <filezilla.h>
2#include "chmoddialog.h"
3
4BEGIN_EVENT_TABLE(CChmodDialog, wxDialogEx)
5EVT_BUTTON(XRCID("wxID_OK"), CChmodDialog::OnOK)
6EVT_BUTTON(XRCID("wxID_CANCEL"), CChmodDialog::OnCancel)
7EVT_TEXT(XRCID("ID_NUMERIC"), CChmodDialog::OnNumericChanged)
8EVT_CHECKBOX(XRCID("ID_RECURSE"), CChmodDialog::OnRecurseChanged)
9END_EVENT_TABLE()
10
11CChmodDialog::CChmodDialog()
12{
13        for (int i = 0; i < 9; ++i) {
14                m_checkBoxes[i] = 0;
15                m_permissions[i] = 0;
16        }
17}
18
19bool CChmodDialog::Create(wxWindow* parent, int fileCount, int dirCount,
20                                                  const wxString& name, const char permissions[9])
21{
22        m_noUserTextChange = false;
23        lastChangedNumeric = false;
24
25        memcpy(m_permissions, permissions, 9);
26
27        SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
28        SetParent(parent);
29
30        wxString title;
31        if (!dirCount) {
32                if (fileCount == 1) {
33                        title = wxString::Format(_("Please select the new attributes for the file \"%s\"."), name);
34                }
35                else
36                        title = _("Please select the new attributes for the selected files.");
37        }
38        else {
39                if (!fileCount) {
40                        if (dirCount == 1) {
41                                title = wxString::Format(_("Please select the new attributes for the directory \"%s\"."), name);
42                        }
43                        else
44                                title = _("Please select the new attributes for the selected directories.");
45                }
46                else
47                        title = _("Please select the new attributes for the selected files and directories.");
48        }
49
50        if (!Load(parent, _T("ID_CHMODDIALOG"))) {
51                return false;
52        }
53
54        if (!SetChildLabel(XRCID("ID_DESC"), title, 300)) {
55                wxFAIL_MSG(_T("Could not set ID_DESC"));
56        }
57
58        if (!XRCCTRL(*this, "wxID_OK", wxButton))
59                return false;
60
61        if (!XRCCTRL(*this, "wxID_CANCEL", wxButton))
62                return false;
63
64        if (!XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl))
65                return false;
66
67        if (!WrapText(this, XRCID("ID_NUMERICTEXT"), 300)) {
68                wxFAIL_MSG(_T("Wrapping of ID_NUMERICTEXT failed"));
69        }
70
71        wxCheckBox* pRecurse = XRCCTRL(*this, "ID_RECURSE", wxCheckBox);
72        wxRadioButton* pApplyAll = XRCCTRL(*this, "ID_APPLYALL", wxRadioButton);
73        wxRadioButton* pApplyFiles = XRCCTRL(*this, "ID_APPLYFILES", wxRadioButton);
74        wxRadioButton* pApplyDirs = XRCCTRL(*this, "ID_APPLYDIRS", wxRadioButton);
75        if (!pRecurse || !pApplyAll || !pApplyFiles || !pApplyDirs)
76                return false;
77
78        if (!dirCount) {
79                pRecurse->Hide();
80                pApplyAll->Hide();
81                pApplyFiles->Hide();
82                pApplyDirs->Hide();
83        }
84
85        pApplyAll->Enable(false);
86        pApplyFiles->Enable(false);
87        pApplyDirs->Enable(false);
88
89        const wxChar* IDs[9] = { _T("ID_OWNERREAD"), _T("ID_OWNERWRITE"), _T("ID_OWNEREXECUTE"),
90                                                   _T("ID_GROUPREAD"), _T("ID_GROUPWRITE"), _T("ID_GROUPEXECUTE"),
91                                                   _T("ID_PUBLICREAD"), _T("ID_PUBLICWRITE"), _T("ID_PUBLICEXECUTE")
92                                                 };
93
94        for (int i = 0; i < 9; ++i) {
95                int id = wxXmlResource::GetXRCID(IDs[i]);
96                m_checkBoxes[i] = wxDynamicCast(FindWindow(id), wxCheckBox);
97
98                if (!m_checkBoxes[i])
99                        return false;
100
101                Connect(id, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(CChmodDialog::OnCheckboxClick));
102
103                switch (permissions[i])
104                {
105                default:
106                case 0:
107                        m_checkBoxes[i]->Set3StateValue(wxCHK_UNDETERMINED);
108                        break;
109                case 1:
110                        m_checkBoxes[i]->Set3StateValue(wxCHK_UNCHECKED);
111                        break;
112                case 2:
113                        m_checkBoxes[i]->Set3StateValue(wxCHK_CHECKED);
114                        break;
115                }
116        }
117
118        GetSizer()->Fit(this);
119        GetSizer()->SetSizeHints(this);
120
121        wxCommandEvent evt;
122        OnCheckboxClick(evt);
123
124        return true;
125}
126
127void CChmodDialog::OnOK(wxCommandEvent&)
128{
129        wxCheckBox* pRecurse = XRCCTRL(*this, "ID_RECURSE", wxCheckBox);
130        m_recursive = pRecurse->GetValue();
131        wxRadioButton* pApplyFiles = XRCCTRL(*this, "ID_APPLYFILES", wxRadioButton);
132        wxRadioButton* pApplyDirs = XRCCTRL(*this, "ID_APPLYDIRS", wxRadioButton);
133        if (pApplyFiles->GetValue())
134                m_applyType = 1;
135        else if (pApplyDirs->GetValue())
136                m_applyType = 2;
137        else
138                m_applyType = 0;
139        EndModal(wxID_OK);
140}
141
142void CChmodDialog::OnCancel(wxCommandEvent&)
143{
144        EndModal(wxID_CANCEL);
145}
146
147void CChmodDialog::OnCheckboxClick(wxCommandEvent&)
148{
149        lastChangedNumeric = false;
150        for (int i = 0; i < 9; ++i) {
151                wxCheckBoxState state = m_checkBoxes[i]->Get3StateValue();
152                switch (state)
153                {
154                default:
155                case wxCHK_UNDETERMINED:
156                        m_permissions[i] = 0;
157                        break;
158                case wxCHK_UNCHECKED:
159                        m_permissions[i] = 1;
160                        break;
161                case wxCHK_CHECKED:
162                        m_permissions[i] = 2;
163                        break;
164                }
165        }
166
167        wxString numericValue;
168        for (int i = 0; i < 3; ++i) {
169                if (!m_permissions[i * 3] || !m_permissions[i * 3 + 1] || !m_permissions[i * 3 + 2]) {
170                        numericValue += 'x';
171                        continue;
172                }
173
174                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);
175        }
176
177        wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl);
178        wxString oldValue = pTextCtrl->GetValue();
179
180        m_noUserTextChange = true;
181        pTextCtrl->SetValue(oldValue.Left(oldValue.Length() - 3) + numericValue);
182        m_noUserTextChange = false;
183        oldNumeric = numericValue;
184}
185
186void CChmodDialog::OnNumericChanged(wxCommandEvent&)
187{
188        if (m_noUserTextChange)
189                return;
190
191        lastChangedNumeric = true;
192
193        wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl);
194        wxString numeric = pTextCtrl->GetValue();
195        if (numeric.Length() < 3)
196                return;
197
198        numeric = numeric.Right(3);
199        for (int i = 0; i < 3; ++i) {
200                if ((numeric[i] < '0' || numeric[i] > '9') && numeric[i] != 'x')
201                        return;
202        }
203        for (int i = 0; i < 3; ++i) {
204                if (!oldNumeric.empty() && numeric[i] == oldNumeric[i])
205                        continue;
206                if (numeric[i] == 'x') {
207                        m_permissions[i * 3] = 0;
208                        m_permissions[i * 3 + 1] = 0;
209                        m_permissions[i * 3 + 2] = 0;
210                }
211                else {
212                        int value = numeric[i] - '0';
213                        m_permissions[i * 3] = (value & 4) ? 2 : 1;
214                        m_permissions[i * 3 + 1] = (value & 2) ? 2 : 1;
215                        m_permissions[i * 3 + 2] = (value & 1) ? 2 : 1;
216                }
217        }
218
219        oldNumeric = numeric;
220
221        for (int i = 0; i < 9; ++i) {
222                switch (m_permissions[i])
223                {
224                default:
225                case 0:
226                        m_checkBoxes[i]->Set3StateValue(wxCHK_UNDETERMINED);
227                        break;
228                case 1:
229                        m_checkBoxes[i]->Set3StateValue(wxCHK_UNCHECKED);
230                        break;
231                case 2:
232                        m_checkBoxes[i]->Set3StateValue(wxCHK_CHECKED);
233                        break;
234                }
235        }
236}
237
238wxString CChmodDialog::GetPermissions(const char* previousPermissions, bool dir)
239{
240        // Construct a new permission string
241
242        wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_NUMERIC", wxTextCtrl);
243        wxString numeric = pTextCtrl->GetValue();
244        if (numeric.Length() < 3)
245                return numeric;
246
247        for (unsigned int i = numeric.Length() - 3; i < numeric.Length(); ++i) {
248                if ((numeric[i] < '0' || numeric[i] > '9') && numeric[i] != 'x')
249                        return numeric;
250        }
251        if (!previousPermissions) {
252                // Use default of  (0...0)755 for dirs and
253                // 644 for files
254                if (numeric[numeric.Length() - 1] == 'x')
255                        numeric[numeric.Length() - 1] = dir ? '5' : '4';
256                if (numeric[numeric.Length() - 2] == 'x')
257                        numeric[numeric.Length() - 2] = dir ? '5' : '4';
258                if (numeric[numeric.Length() - 3] == 'x')
259                        numeric[numeric.Length() - 3] = dir ? '7' : '6';
260                numeric.Replace(_T("x"), _T("0"));
261                return numeric;
262        }
263
264        // 2 set, 1 unset, 0 keep
265
266        const char defaultPerms[9] = { 2, 2, 2, 2, 1, 2, 2, 1, 2 };
267        char perms[9];
268        memcpy(perms, m_permissions, 9);
269
270        wxString permission = numeric.Left(numeric.Length() - 3);
271        unsigned int k = 0;
272        for (unsigned int i = numeric.Length() - 3; i < numeric.Length(); ++i, ++k) {
273                for (unsigned int j = k * 3; j < k * 3 + 3; ++j) {
274                        if (!perms[j]) {
275                                if (previousPermissions[j])
276                                        perms[j] = previousPermissions[j];
277                                else
278                                        perms[j] = defaultPerms[j];
279                        }
280                }
281                permission += wxString::Format(_T("%d"), (int)(perms[k * 3] - 1) * 4 + (perms[k * 3 + 1] - 1) * 2 + (perms[k * 3 + 2] - 1) * 1);
282        }
283
284        return permission;
285}
286
287bool CChmodDialog::Recursive() const
288{
289        return m_recursive;
290}
291
292void CChmodDialog::OnRecurseChanged(wxCommandEvent&)
293{
294        wxCheckBox* pRecurse = XRCCTRL(*this, "ID_RECURSE", wxCheckBox);
295        wxRadioButton* pApplyAll = XRCCTRL(*this, "ID_APPLYALL", wxRadioButton);
296        wxRadioButton* pApplyFiles = XRCCTRL(*this, "ID_APPLYFILES", wxRadioButton);
297        wxRadioButton* pApplyDirs = XRCCTRL(*this, "ID_APPLYDIRS", wxRadioButton);
298        pApplyAll->Enable(pRecurse->GetValue());
299        pApplyFiles->Enable(pRecurse->GetValue());
300        pApplyDirs->Enable(pRecurse->GetValue());
301}
302
303bool CChmodDialog::ConvertPermissions(wxString rwx, char* permissions)
304{
305        if (!permissions)
306                return false;
307
308        int pos = rwx.Find('(');
309        if (pos != -1 && rwx.Last() == ')') {
310                // MLSD permissions:
311                //   foo (0644)
312                rwx.RemoveLast();
313                rwx = rwx.Mid(pos + 1);
314        }
315
316        if (rwx.Len() < 3)
317                return false;
318        size_t i;
319        for (i = 0; i < rwx.Len(); i++)
320                if (rwx[i] < '0' || rwx[i] > '9')
321                        break;
322        if (i == rwx.Len()) {
323                // Mode, e.g. 0723
324                for (i = 0; i < 3; ++i) {
325                        int m = rwx[rwx.Len() - 3 + i] - '0';
326
327                        for (int j = 0; j < 3; ++j) {
328                                if (m & (4 >> j))
329                                        permissions[i * 3 + j] = 2;
330                                else
331                                        permissions[i * 3 + j] = 1;
332                        }
333                }
334
335                return true;
336        }
337
338        const unsigned char permchars[3] = {'r', 'w', 'x'};
339
340        if (rwx.Length() != 10)
341                return false;
342
343        for (int j = 0; j < 9; ++j) {
344                bool set = rwx[j + 1] == permchars[j % 3];
345                permissions[j] = set ? 2 : 1;
346        }
347        if (rwx[3] == 's')
348                permissions[2] = 2;
349        if (rwx[6] == 's')
350                permissions[5] = 2;
351        if (rwx[9] == 't')
352                permissions[8] = 2;
353
354        return true;
355}
Note: See TracBrowser for help on using the repository browser.