LibreOffice Module sc (master)  1
retypepassdlg.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/svapp.hxx>
21 #include <strings.hrc>
22 #include <retypepassdlg.hxx>
23 #include <scresid.hxx>
24 #include <document.hxx>
25 #include <tabprotection.hxx>
26 
28  : GenericDialogController(pParent, "modules/scalc/ui/retypepassdialog.ui", "RetypePass")
29  , maTextNotProtected(ScResId(STR_NOT_PROTECTED))
30  , maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED))
31  , maTextHashBad(ScResId(STR_HASH_BAD))
32  , maTextHashGood(ScResId(STR_HASH_GOOD))
33  , meDesiredHash(PASSHASH_SHA1)
34  , mxBtnOk(m_xBuilder->weld_button("ok"))
35  , mxTextDocStatus(m_xBuilder->weld_label("docStatusLabel"))
36  , mxBtnRetypeDoc(m_xBuilder->weld_button("retypeDocButton"))
37  , mxScrolledWindow(m_xBuilder->weld_scrolled_window("scrolledwindow"))
38  , mxSheetsBox(m_xBuilder->weld_container("sheetsBox"))
39 {
40  mxScrolledWindow->set_size_request(mxScrolledWindow->get_approximate_digit_width() * 46,
41  mxScrolledWindow->get_text_height() * 10);
42  Init();
43 }
44 
46 
48 
50 {
53  return GenericDialogController::run();
54 }
55 
57  : m_xBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/passfragment.ui"))
58  , m_xSheetsBox(m_xBuilder->weld_container("PassEntry"))
59  , m_xName(m_xBuilder->weld_label("name"))
60  , m_xStatus(m_xBuilder->weld_label("status"))
61  , m_xButton(m_xBuilder->weld_button("button"))
62 {
63  m_xButton->set_label(ScResId(STR_RETYPE));
64 }
65 
67 {
68  DeleteSheets();
69  const ScDocProtection* pDocProtect = rDoc.GetDocProtection();
70  if (pDocProtect && pDocProtect->isProtected())
71  mpDocItem = std::make_shared<ScDocProtection>(*pDocProtect);
72 
73  SCTAB nTabCount = rDoc.GetTableCount();
74  maTableItems.reserve(nTabCount);
75  maSheets.reserve(nTabCount);
76  for (SCTAB i = 0; i < nTabCount; ++i)
77  {
78  TableItem aTabItem;
79  rDoc.GetName(i, aTabItem.maName);
80 
81  const ScTableProtection* pTabProtect = rDoc.GetTabProtection(i);
82  if (pTabProtect && pTabProtect->isProtected())
83  aTabItem.mpProtect = std::make_shared<ScTableProtection>(*pTabProtect);
84 
85  maTableItems.push_back(aTabItem);
86  maSheets.emplace_back(new PassFragment(mxSheetsBox.get()));
87  maSheets.back()->m_xButton->connect_clicked(LINK(this, ScRetypePassDlg, RetypeBtnHdl));
88  }
89 }
90 
92 
94 {
95  if (mpDocItem)
96  rDoc.SetDocProtection(mpDocItem.get());
97 
98  size_t nTabCount = static_cast<size_t>(rDoc.GetTableCount());
99  size_t n = maTableItems.size();
100  for (size_t i = 0; i < n; ++i)
101  {
102  if (i >= nTabCount)
103  break;
104 
105  ScTableProtection* pTabProtect = maTableItems[i].mpProtect.get();
106  if (pTabProtect)
107  rDoc.SetTabProtection(static_cast<SCTAB>(i), pTabProtect);
108  }
109 }
110 
112 {
113  Link<weld::Button&, void> aLink = LINK(this, ScRetypePassDlg, OKHdl);
114  mxBtnOk->connect_clicked(aLink);
115 
116  aLink = LINK(this, ScRetypePassDlg, RetypeBtnHdl);
117  mxBtnRetypeDoc->connect_clicked(aLink);
118 
120  mxBtnRetypeDoc->set_sensitive(false);
121 }
122 
124 {
125  // Document protection first.
126  SetDocData();
127 
128  // Sheet protection next.
129  for (size_t i = 0; i < maTableItems.size(); ++i)
130  SetTableData(i, static_cast<SCTAB>(i));
131 }
132 
134 {
135  bool bBtnEnabled = false;
136  if (mpDocItem && mpDocItem->isProtected())
137  {
138  if (mpDocItem->isPasswordEmpty())
140  else if (mpDocItem->hasPasswordHash(meDesiredHash))
141  mxTextDocStatus->set_label(maTextHashGood);
142  else
143  {
144  // incompatible hash
145  mxTextDocStatus->set_label(maTextHashBad);
146  bBtnEnabled = true;
147  }
148  }
149  mxBtnRetypeDoc->set_sensitive(bBtnEnabled);
150 }
151 
152 void ScRetypePassDlg::SetTableData(size_t nRowPos, SCTAB nTab)
153 {
154  if (nRowPos >= maSheets.size())
155  return;
156 
157  weld::Label& rName = *maSheets[nRowPos]->m_xName;
158  weld::Label& rStatus = *maSheets[nRowPos]->m_xStatus;
159  weld::Button& rBtn = *maSheets[nRowPos]->m_xButton;
160 
161  bool bBtnEnabled = false;
162  rName.set_label(maTableItems[nTab].maName);
163  const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get();
164  if (pTabProtect && pTabProtect->isProtected())
165  {
166  if (pTabProtect->isPasswordEmpty())
168  else if (pTabProtect->hasPasswordHash(meDesiredHash))
169  rStatus.set_label(maTextHashGood);
170  else
171  {
172  // incompatible hash
173  rStatus.set_label(maTextHashBad);
174  bBtnEnabled = true;
175  }
176  }
177  else
178  rStatus.set_label(maTextNotProtected);
179 
180  rBtn.set_sensitive(bBtnEnabled);
181 }
182 
183 static bool lcl_IsInGoodStatus(const ScPassHashProtectable* pProtected, ScPasswordHash eDesiredHash)
184 {
185  if (!pProtected || !pProtected->isProtected())
186  // Not protected.
187  return true;
188 
189  if (pProtected->isPasswordEmpty())
190  return true;
191 
192  if (pProtected->hasPasswordHash(eDesiredHash))
193  return true;
194 
195  return false;
196 }
197 
199 {
200  do
201  {
203  break;
204 
205  bool bStatusGood = true;
206  size_t nTabCount = maTableItems.size();
207  for (size_t i = 0; i < nTabCount && bStatusGood; ++i)
208  {
209  if (!lcl_IsInGoodStatus(maTableItems[i].mpProtect.get(), meDesiredHash))
210  bStatusGood = false;
211  }
212  if (!bStatusGood)
213  break;
214 
215  mxBtnOk->set_sensitive(true);
216  return;
217  } while (false);
218 
219  mxBtnOk->set_sensitive(false);
220 }
221 
223 
224 IMPL_LINK(ScRetypePassDlg, RetypeBtnHdl, weld::Button&, rBtn, void)
225 {
226  ScPassHashProtectable* pProtected = nullptr;
227  if (&rBtn == mxBtnRetypeDoc.get())
228  {
229  // document protection.
230  pProtected = mpDocItem.get();
231  }
232  else
233  {
234  // sheet protection.
235  size_t aPos = 0;
236  while (aPos < maSheets.size() && &rBtn != maSheets[aPos]->m_xButton.get())
237  ++aPos;
238 
239  pProtected = aPos < maSheets.size() ? maTableItems[aPos].mpProtect.get() : nullptr;
240  }
241 
242  if (!pProtected)
243  // What the ... !?
244  return;
245 
246  ScRetypePassInputDlg aDlg(m_xDialog.get(), pProtected);
247  if (aDlg.run() != RET_OK)
248  return;
249 
250  // OK is pressed. Update the protected item.
251  if (aDlg.IsRemovePassword())
252  {
253  // Remove password from this item.
254  pProtected->setPassword(OUString());
255  }
256  else
257  {
258  // Set a new password.
259  OUString aNewPass = aDlg.GetNewPassword();
260  pProtected->setPassword(aNewPass);
261  }
262 
263  SetDocData();
264  CheckHashStatus();
265 }
266 
268  : GenericDialogController(pParent, "modules/scalc/ui/retypepassworddialog.ui",
269  "RetypePasswordDialog")
270  , m_pProtected(pProtected)
271  , m_xBtnOk(m_xBuilder->weld_button("ok"))
272  , m_xBtnRetypePassword(m_xBuilder->weld_radio_button("retypepassword"))
273  , m_xPasswordGrid(m_xBuilder->weld_widget("passwordgrid"))
274  , m_xPassword1Edit(m_xBuilder->weld_entry("newpassEntry"))
275  , m_xPassword2Edit(m_xBuilder->weld_entry("confirmpassEntry"))
276  , m_xBtnMatchOldPass(m_xBuilder->weld_check_button("mustmatch"))
277  , m_xBtnRemovePassword(m_xBuilder->weld_radio_button("removepassword"))
278 {
279  Init();
280 }
281 
283 
284 bool ScRetypePassInputDlg::IsRemovePassword() const { return m_xBtnRemovePassword->get_active(); }
285 
286 OUString ScRetypePassInputDlg::GetNewPassword() const { return m_xPassword1Edit->get_text(); }
287 
289 {
290  m_xBtnOk->connect_clicked(LINK(this, ScRetypePassInputDlg, OKHdl));
291  m_xBtnRetypePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl));
292  m_xBtnRemovePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl));
293  m_xBtnMatchOldPass->connect_toggled(LINK(this, ScRetypePassInputDlg, CheckBoxHdl));
294  Link<weld::Entry&, void> aLink2 = LINK(this, ScRetypePassInputDlg, PasswordModifyHdl);
295  m_xPassword1Edit->connect_changed(aLink2);
296  m_xPassword2Edit->connect_changed(aLink2);
297 
298  m_xBtnOk->set_sensitive(false);
299  m_xBtnRetypePassword->set_active(true);
300  m_xBtnMatchOldPass->set_active(true);
301  m_xPassword1Edit->grab_focus();
302 }
303 
305 {
306  OUString aPass1 = m_xPassword1Edit->get_text();
307  OUString aPass2 = m_xPassword2Edit->get_text();
308 
309  if (aPass1.isEmpty() || aPass2.isEmpty())
310  {
311  // Empty password is not allowed.
312  m_xBtnOk->set_sensitive(false);
313  return;
314  }
315 
316  if (aPass1 != aPass2)
317  {
318  // The two passwords differ.
319  m_xBtnOk->set_sensitive(false);
320  return;
321  }
322 
323  if (!m_xBtnMatchOldPass->get_active())
324  {
325  m_xBtnOk->set_sensitive(true);
326  return;
327  }
328 
329  if (!m_pProtected)
330  {
331  // This should never happen!
332  m_xBtnOk->set_sensitive(false);
333  return;
334  }
335 
336  bool bPassGood = m_pProtected->verifyPassword(aPass1);
337  m_xBtnOk->set_sensitive(bPassGood);
338 }
339 
341 
343 {
344  if (m_xBtnRetypePassword->get_active())
345  {
346  m_xPasswordGrid->set_sensitive(true);
347  CheckPasswordInput();
348  }
349  else
350  {
351  m_xPasswordGrid->set_sensitive(false);
352  m_xBtnOk->set_sensitive(true);
353  }
354 }
355 
357 {
358  CheckPasswordInput();
359 }
360 
362 {
363  CheckPasswordInput();
364 }
365 
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PassFragment(weld::Widget *pParent)
virtual bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2=PASSHASH_UNSPECIFIED) const override
virtual bool isPasswordEmpty() const =0
SC_DLLPUBLIC void SetTabProtection(SCTAB nTab, const ScTableProtection *pProtect)
Definition: documen3.cxx:1906
std::vector< std::unique_ptr< PassFragment > > maSheets
virtual bool isProtected() const =0
std::unique_ptr< weld::Container > mxSheetsBox
sheet protection state container
virtual ~ScRetypePassInputDlg() override
std::unique_ptr< weld::ScrolledWindow > mxScrolledWindow
sal_Int64 n
virtual bool isProtected() const override
std::unique_ptr< weld::Button > m_xButton
bool IsRemovePassword() const
std::unique_ptr< weld::Button > m_xBtnOk
ScRetypePassInputDlg()=delete
std::unique_ptr< weld::Entry > m_xPassword2Edit
virtual bool isPasswordEmpty() const override
IMPL_LINK(ScRetypePassDlg, RetypeBtnHdl, weld::Button &, rBtn, void)
std::unique_ptr< weld::Button > mxBtnRetypeDoc
static bool lcl_IsInGoodStatus(const ScPassHashProtectable *pProtected, ScPasswordHash eDesiredHash)
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:312
std::unique_ptr< weld::Button > mxBtnOk
virtual ~ScRetypePassDlg() override
void SetDataFromDocument(const ScDocument &rDoc)
virtual short run() override
std::shared_ptr< ScDocProtection > mpDocItem
void SetDesiredHash(ScPasswordHash eHash)
std::unique_ptr< weld::RadioButton > m_xBtnRetypePassword
ScPasswordHash
OUString GetNewPassword() const
OUString maTextHashGood
void WriteNewDataToDocument(ScDocument &rDoc) const
Write the new set of password data to the document instance to overwrite the current ones...
SC_DLLPUBLIC ScDocProtection * GetDocProtection() const
Definition: documen3.cxx:1865
::std::vector< TableItem > maTableItems
int i
virtual bool verifyPassword(const OUString &aPassText) const =0
ScPasswordHash meDesiredHash
OUString maTextHashBad
ScPassHashProtectable * m_pProtected
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
OUString maTextNotPassProtected
ScRetypePassDlg(weld::Window *pParent)
virtual bool isProtected() const override
void CheckHashStatus()
Check the status of all hash values to see if it's okay to enable the OK button.
std::unique_ptr< weld::CheckButton > m_xBtnMatchOldPass
virtual void set_label(const OUString &rText)=0
IMPL_LINK_NOARG(ScRetypePassDlg, OKHdl, weld::Button &, void)
std::shared_ptr< ScTableProtection > mpProtect
void SetTableData(size_t nRowPos, SCTAB nTab)
virtual bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2=PASSHASH_UNSPECIFIED) const =0
OUString maName
std::unique_ptr< weld::RadioButton > m_xBtnRemovePassword
RET_OK
virtual void setPassword(const OUString &aPassText)=0
OUString maTextNotProtected
Reference< XExecutableDialog > m_xDialog
SC_DLLPUBLIC void SetDocProtection(const ScDocProtection *pProtect)
Definition: documen3.cxx:1870
std::unique_ptr< weld::Entry > m_xPassword1Edit
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:211
virtual void set_sensitive(bool sensitive)=0
sal_Int16 SCTAB
Definition: types.hxx:23
std::unique_ptr< weld::Label > mxTextDocStatus
SC_DLLPUBLIC const ScTableProtection * GetTabProtection(SCTAB nTab) const
Definition: documen3.cxx:1898