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 {
47 }
48 
50 {
51  maSheets.clear();
52 }
53 
55 {
58  return GenericDialogController::run();
59 }
60 
62  : m_xBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/passfragment.ui"))
63  , m_xSheetsBox(m_xBuilder->weld_container("PassEntry"))
64  , m_xName(m_xBuilder->weld_label("name"))
65  , m_xStatus(m_xBuilder->weld_label("status"))
66  , m_xButton(m_xBuilder->weld_button("button"))
67 {
68  m_xButton->set_label(ScResId(STR_RETYPE));
69 }
70 
72 {
73  DeleteSheets();
74  const ScDocProtection* pDocProtect = rDoc.GetDocProtection();
75  if (pDocProtect && pDocProtect->isProtected())
76  mpDocItem = std::make_shared<ScDocProtection>(*pDocProtect);
77 
78  SCTAB nTabCount = rDoc.GetTableCount();
79  maTableItems.reserve(nTabCount);
80  maSheets.reserve(nTabCount);
81  for (SCTAB i = 0; i < nTabCount; ++i)
82  {
83  TableItem aTabItem;
84  rDoc.GetName(i, aTabItem.maName);
85 
86  const ScTableProtection* pTabProtect = rDoc.GetTabProtection(i);
87  if (pTabProtect && pTabProtect->isProtected())
88  aTabItem.mpProtect = std::make_shared<ScTableProtection>(*pTabProtect);
89 
90  maTableItems.push_back(aTabItem);
91  maSheets.emplace_back(new PassFragment(mxSheetsBox.get()));
92  maSheets.back()->m_xButton->connect_clicked(LINK(this, ScRetypePassDlg, RetypeBtnHdl));
93  }
94 }
95 
97 {
98  meDesiredHash = eHash;
99 }
100 
102 {
103  if (mpDocItem)
104  rDoc.SetDocProtection(mpDocItem.get());
105 
106  size_t nTabCount = static_cast<size_t>(rDoc.GetTableCount());
107  size_t n = maTableItems.size();
108  for (size_t i = 0; i < n; ++i)
109  {
110  if (i >= nTabCount)
111  break;
112 
113  ScTableProtection* pTabProtect = maTableItems[i].mpProtect.get();
114  if (pTabProtect)
115  rDoc.SetTabProtection(static_cast<SCTAB>(i), pTabProtect);
116  }
117 }
118 
120 {
121  Link<weld::Button&,void> aLink = LINK( this, ScRetypePassDlg, OKHdl );
122  mxBtnOk->connect_clicked(aLink);
123 
124  aLink = LINK( this, ScRetypePassDlg, RetypeBtnHdl );
125  mxBtnRetypeDoc->connect_clicked(aLink);
126 
128  mxBtnRetypeDoc->set_sensitive(false);
129 }
130 
132 {
133  // Document protection first.
134  SetDocData();
135 
136  // Sheet protection next.
137  for (size_t i = 0; i < maTableItems.size(); ++i)
138  SetTableData(i, static_cast< SCTAB >( i ));
139 }
140 
142 {
143  bool bBtnEnabled = false;
144  if (mpDocItem && mpDocItem->isProtected())
145  {
146  if (mpDocItem->isPasswordEmpty())
148  else if (mpDocItem->hasPasswordHash(meDesiredHash))
149  mxTextDocStatus->set_label(maTextHashGood);
150  else
151  {
152  // incompatible hash
153  mxTextDocStatus->set_label(maTextHashBad);
154  bBtnEnabled = true;
155  }
156  }
157  mxBtnRetypeDoc->set_sensitive(bBtnEnabled);
158 }
159 
160 void ScRetypePassDlg::SetTableData(size_t nRowPos, SCTAB nTab)
161 {
162  if (nRowPos < maSheets.size())
163  {
164  weld::Label& rName = *maSheets[nRowPos]->m_xName;
165  weld::Label& rStatus = *maSheets[nRowPos]->m_xStatus;
166  weld::Button& rBtn = *maSheets[nRowPos]->m_xButton;
167 
168  bool bBtnEnabled = false;
169  rName.set_label(maTableItems[nTab].maName);
170  const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get();
171  if (pTabProtect && pTabProtect->isProtected())
172  {
173  if (pTabProtect->isPasswordEmpty())
175  else if (pTabProtect->hasPasswordHash(meDesiredHash))
176  rStatus.set_label(maTextHashGood);
177  else
178  {
179  // incompatible hash
180  rStatus.set_label(maTextHashBad);
181  bBtnEnabled = true;
182  }
183  }
184  else
185  rStatus.set_label(maTextNotProtected);
186 
187  rBtn.set_sensitive(bBtnEnabled);
188  }
189 }
190 
191 static bool lcl_IsInGoodStatus(const ScPassHashProtectable* pProtected, ScPasswordHash eDesiredHash)
192 {
193  if (!pProtected || !pProtected->isProtected())
194  // Not protected.
195  return true;
196 
197  if (pProtected->isPasswordEmpty())
198  return true;
199 
200  if (pProtected->hasPasswordHash(eDesiredHash))
201  return true;
202 
203  return false;
204 }
205 
207 {
208  do
209  {
211  break;
212 
213  bool bStatusGood = true;
214  size_t nTabCount = maTableItems.size();
215  for (size_t i = 0; i < nTabCount && bStatusGood; ++i)
216  {
217  if (!lcl_IsInGoodStatus(maTableItems[i].mpProtect.get(), meDesiredHash))
218  bStatusGood = false;
219  }
220  if (!bStatusGood)
221  break;
222 
223  mxBtnOk->set_sensitive(true);
224  return;
225  }
226  while (false);
227 
228  mxBtnOk->set_sensitive(false);
229 }
230 
232 {
233  m_xDialog->response(RET_OK);
234 }
235 
236 IMPL_LINK(ScRetypePassDlg, RetypeBtnHdl, weld::Button&, rBtn, void)
237 {
238  ScPassHashProtectable* pProtected = nullptr;
239  if (&rBtn == mxBtnRetypeDoc.get())
240  {
241  // document protection.
242  pProtected = mpDocItem.get();
243  }
244  else
245  {
246  // sheet protection.
247  size_t aPos = 0;
248  while (aPos < maSheets.size() && &rBtn != maSheets[aPos]->m_xButton.get())
249  ++aPos;
250 
251  pProtected = aPos < maSheets.size() ? maTableItems[aPos].mpProtect.get() : nullptr;
252  }
253 
254  if (!pProtected)
255  // What the ... !?
256  return;
257 
258  ScRetypePassInputDlg aDlg(m_xDialog.get(), pProtected);
259  if (aDlg.run() == RET_OK)
260  {
261  // OK is pressed. Update the protected item.
262  if (aDlg.IsRemovePassword())
263  {
264  // Remove password from this item.
265  pProtected->setPassword(OUString());
266  }
267  else
268  {
269  // Set a new password.
270  OUString aNewPass = aDlg.GetNewPassword();
271  pProtected->setPassword(aNewPass);
272  }
273 
274  SetDocData();
275  CheckHashStatus();
276  }
277 }
278 
280  : GenericDialogController(pParent, "modules/scalc/ui/retypepassworddialog.ui", "RetypePasswordDialog")
281  , m_pProtected(pProtected)
282  , m_xBtnOk(m_xBuilder->weld_button("ok"))
283  , m_xBtnRetypePassword(m_xBuilder->weld_radio_button("retypepassword"))
284  , m_xPasswordGrid(m_xBuilder->weld_widget("passwordgrid"))
285  , m_xPassword1Edit(m_xBuilder->weld_entry("newpassEntry"))
286  , m_xPassword2Edit(m_xBuilder->weld_entry("confirmpassEntry"))
287  , m_xBtnMatchOldPass(m_xBuilder->weld_check_button("mustmatch"))
288  , m_xBtnRemovePassword(m_xBuilder->weld_radio_button("removepassword"))
289 {
290  Init();
291 }
292 
294 {
295 }
296 
298 {
299  return m_xBtnRemovePassword->get_active();
300 }
301 
303 {
304  return m_xPassword1Edit->get_text();
305 }
306 
308 {
309  m_xBtnOk->connect_clicked(LINK(this, ScRetypePassInputDlg, OKHdl));
310  m_xBtnRetypePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl));
311  m_xBtnRemovePassword->connect_toggled(LINK(this, ScRetypePassInputDlg, RadioBtnHdl));
312  m_xBtnMatchOldPass->connect_toggled(LINK(this, ScRetypePassInputDlg, CheckBoxHdl));
313  Link<weld::Entry&,void> aLink2 = LINK( this, ScRetypePassInputDlg, PasswordModifyHdl );
314  m_xPassword1Edit->connect_changed(aLink2);
315  m_xPassword2Edit->connect_changed(aLink2);
316 
317  m_xBtnOk->set_sensitive(false);
318  m_xBtnRetypePassword->set_active(true);
319  m_xBtnMatchOldPass->set_active(true);
320  m_xPassword1Edit->grab_focus();
321 }
322 
324 {
325  OUString aPass1 = m_xPassword1Edit->get_text();
326  OUString aPass2 = m_xPassword2Edit->get_text();
327 
328  if (aPass1.isEmpty() || aPass2.isEmpty())
329  {
330  // Empty password is not allowed.
331  m_xBtnOk->set_sensitive(false);
332  return;
333  }
334 
335  if (aPass1 != aPass2)
336  {
337  // The two passwords differ.
338  m_xBtnOk->set_sensitive(false);
339  return;
340  }
341 
342  if (!m_xBtnMatchOldPass->get_active())
343  {
344  m_xBtnOk->set_sensitive(true);
345  return;
346  }
347 
348  if (!m_pProtected)
349  {
350  // This should never happen!
351  m_xBtnOk->set_sensitive(false);
352  return;
353  }
354 
355  bool bPassGood = m_pProtected->verifyPassword(aPass1);
356  m_xBtnOk->set_sensitive(bPassGood);
357 }
358 
360 {
361  m_xDialog->response(RET_OK);
362 }
363 
365 {
366  if (m_xBtnRetypePassword->get_active())
367  {
368  m_xPasswordGrid->set_sensitive(true);
369  CheckPasswordInput();
370  }
371  else
372  {
373  m_xPasswordGrid->set_sensitive(false);
374  m_xBtnOk->set_sensitive(false);
375  }
376 }
377 
379 {
380  CheckPasswordInput();
381 }
382 
384 {
385  CheckPasswordInput();
386 }
387 
388 /* 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:1888
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:314
std::unique_ptr< weld::Button > mxBtnOk
virtual ~ScRetypePassDlg() override
void SetDataFromDocument(const ScDocument &rDoc)
virtual short run() override
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:1847
::std::vector< TableItem > maTableItems
int i
virtual bool verifyPassword(const OUString &aPassText) const =0
ScPasswordHash meDesiredHash
OUString maTextHashBad
ScPassHashProtectable * m_pProtected
TabProtectionPtr mpProtect
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
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)
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 ScTableProtection * GetTabProtection(SCTAB nTab) const
Definition: documen3.cxx:1880
SC_DLLPUBLIC void SetDocProtection(const ScDocProtection *pProtect)
Definition: documen3.cxx:1852
std::unique_ptr< weld::Entry > m_xPassword1Edit
DocProtectionPtr mpDocItem
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:213
virtual void set_sensitive(bool sensitive)=0
sal_Int16 SCTAB
Definition: types.hxx:23
std::unique_ptr< weld::Label > mxTextDocStatus