Line data Source code
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 "sc.hrc"
21 : #include "retypepassdlg.hxx"
22 : #include "scresid.hxx"
23 : #include "document.hxx"
24 : #include "tabprotection.hxx"
25 :
26 : #include <vcl/msgbox.hxx>
27 :
28 0 : ScRetypePassDlg::ScRetypePassDlg(vcl::Window* pParent) :
29 : ModalDialog(pParent, "RetypePass", "modules/scalc/ui/retypepassdialog.ui"),
30 :
31 : maTextNotProtected(ScResId(STR_NOT_PROTECTED)),
32 : maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED)),
33 : maTextHashBad(ScResId(STR_HASH_BAD)),
34 : maTextHashGood(ScResId(STR_HASH_GOOD)),
35 : maTextHashRegen(ScResId(STR_HASH_REGENERATED)),
36 :
37 : mpDocItem(static_cast<ScDocProtection*>(NULL)),
38 : mnCurScrollPos(0),
39 0 : meDesiredHash(PASSHASH_SHA1)
40 : {
41 0 : get(mpBtnOk ,"ok");
42 0 : get(mpTextDocStatus, "docStatusLabel");
43 0 : get(mpBtnRetypeDoc, "retypeDocButton");
44 0 : vcl::Window *pScrolledWindow = get<vcl::Window>("scrolledwindow");
45 0 : Size aSize(LogicToPixel(Size(190, 90), MAP_APPFONT));
46 0 : pScrolledWindow->set_width_request(aSize.Width());
47 0 : pScrolledWindow->set_height_request(aSize.Height());
48 0 : get(mpSheetsBox, "sheetsBox");
49 :
50 0 : Init();
51 0 : }
52 :
53 0 : ScRetypePassDlg::~ScRetypePassDlg()
54 : {
55 0 : disposeOnce();
56 0 : }
57 :
58 0 : void ScRetypePassDlg::dispose()
59 : {
60 0 : DeleteSheets();
61 0 : mpBtnOk.clear();
62 0 : mpTextDocStatus.clear();
63 0 : mpBtnRetypeDoc.clear();
64 0 : mpSheetsBox.clear();
65 0 : ModalDialog::dispose();
66 0 : }
67 :
68 0 : void ScRetypePassDlg::DeleteSheets()
69 : {
70 0 : for(auto it = maSheets.begin(); it != maSheets.end(); ++it)
71 : {
72 0 : VclPtr<vcl::Window> pWindow = (*it);
73 0 : vcl::Window *pChild = pWindow->GetWindow(GetWindowType::FirstChild);
74 0 : while (pChild)
75 : {
76 0 : VclPtr<vcl::Window> pOldChild = pChild;
77 0 : pChild = pChild->GetWindow(GetWindowType::Next);
78 0 : pOldChild.disposeAndClear();
79 0 : }
80 0 : pWindow.disposeAndClear();
81 0 : }
82 0 : }
83 :
84 0 : short ScRetypePassDlg::Execute()
85 : {
86 0 : PopulateDialog();
87 0 : CheckHashStatus();
88 0 : return ModalDialog::Execute();
89 : }
90 :
91 0 : void ScRetypePassDlg::SetDataFromDocument(const ScDocument& rDoc)
92 : {
93 0 : DeleteSheets();
94 0 : const ScDocProtection* pDocProtect = rDoc.GetDocProtection();
95 0 : if (pDocProtect && pDocProtect->isProtected())
96 0 : mpDocItem.reset(new ScDocProtection(*pDocProtect));
97 :
98 0 : SCTAB nTabCount = rDoc.GetTableCount();
99 0 : maTableItems.reserve(nTabCount);
100 0 : maSheets.reserve(nTabCount);
101 0 : for (SCTAB i = 0; i < nTabCount; ++i)
102 : {
103 0 : TableItem aTabItem;
104 0 : rDoc.GetName(i, aTabItem.maName);
105 :
106 0 : const ScTableProtection* pTabProtect = rDoc.GetTabProtection(i);
107 0 : if (pTabProtect && pTabProtect->isProtected())
108 0 : aTabItem.mpProtect.reset(new ScTableProtection(*pTabProtect));
109 :
110 0 : maTableItems.push_back(aTabItem);
111 0 : VclPtr<VclHBox> pSheet = VclPtr<VclHBox>::Create(mpSheetsBox, false, 12);
112 0 : pSheet->Show(true);
113 :
114 0 : VclPtr<FixedText> pFtSheetName = VclPtr<FixedText>::Create(pSheet);
115 0 : pFtSheetName->Show(true);
116 0 : pFtSheetName->SetStyle(WB_VCENTER);
117 0 : FixedText* pFtSheetStatus = VclPtr<FixedText>::Create(pSheet);
118 0 : pFtSheetStatus->Show(true);
119 0 : pFtSheetStatus->SetStyle(WB_VCENTER);
120 :
121 0 : VclPtr<PushButton> pBtnSheet = VclPtr<PushButton>::Create(static_cast<vcl::Window*>(pSheet));
122 0 : pBtnSheet->SetText(ScResId(STR_RETYPE));
123 0 : pBtnSheet->SetClickHdl(LINK(this, ScRetypePassDlg, RetypeBtnHdl));
124 0 : pBtnSheet->Disable();
125 0 : pBtnSheet->Show(true);
126 :
127 0 : maSheets.push_back(pSheet);
128 0 : }
129 0 : }
130 :
131 0 : void ScRetypePassDlg::SetDesiredHash(ScPasswordHash eHash)
132 : {
133 0 : meDesiredHash = eHash;
134 0 : }
135 :
136 0 : void ScRetypePassDlg::WriteNewDataToDocument(ScDocument& rDoc) const
137 : {
138 0 : if (mpDocItem.get())
139 0 : rDoc.SetDocProtection(mpDocItem.get());
140 :
141 0 : size_t nTabCount = static_cast<size_t>(rDoc.GetTableCount());
142 0 : size_t n = maTableItems.size();
143 0 : for (size_t i = 0; i < n; ++i)
144 : {
145 0 : if (i >= nTabCount)
146 0 : break;
147 :
148 0 : ScTableProtection* pTabProtect = maTableItems[i].mpProtect.get();
149 0 : if (pTabProtect)
150 0 : rDoc.SetTabProtection(static_cast<SCTAB>(i), pTabProtect);
151 : }
152 0 : }
153 :
154 0 : void ScRetypePassDlg::Init()
155 : {
156 0 : Link<> aLink = LINK( this, ScRetypePassDlg, OKHdl );
157 0 : mpBtnOk->SetClickHdl(aLink);
158 :
159 0 : aLink = LINK( this, ScRetypePassDlg, RetypeBtnHdl );
160 0 : mpBtnRetypeDoc->SetClickHdl(aLink);
161 :
162 0 : mpTextDocStatus->SetText(maTextNotProtected);
163 0 : mpBtnRetypeDoc->Disable();
164 0 : }
165 :
166 0 : void ScRetypePassDlg::PopulateDialog()
167 : {
168 : // Document protection first.
169 0 : SetDocData();
170 :
171 : // Sheet protection next.
172 0 : for (size_t i = 0; i < maTableItems.size(); ++i)
173 0 : SetTableData(i, static_cast< SCTAB >( i ));
174 0 : }
175 :
176 0 : void ScRetypePassDlg::SetDocData()
177 : {
178 0 : bool bBtnEnabled = false;
179 0 : if (mpDocItem.get() && mpDocItem->isProtected())
180 : {
181 0 : if (mpDocItem->isPasswordEmpty())
182 0 : mpTextDocStatus->SetText(maTextNotPassProtected);
183 0 : else if (mpDocItem->hasPasswordHash(meDesiredHash))
184 0 : mpTextDocStatus->SetText(maTextHashGood);
185 : else
186 : {
187 : // incompatible hash
188 0 : mpTextDocStatus->SetText(maTextHashBad);
189 0 : bBtnEnabled = true;
190 : }
191 : }
192 0 : mpBtnRetypeDoc->Enable(bBtnEnabled);
193 0 : }
194 :
195 0 : void ScRetypePassDlg::SetTableData(size_t nRowPos, SCTAB nTab)
196 : {
197 0 : if(nRowPos < maSheets.size())
198 : {
199 0 : FixedText* pName = static_cast<FixedText*>(maSheets[nRowPos]->GetChild(0));
200 0 : FixedText* pStatus = static_cast<FixedText*>(maSheets[nRowPos]->GetChild(1));
201 0 : PushButton* pBtn = static_cast<PushButton*>(maSheets[nRowPos]->GetChild(2));
202 :
203 0 : bool bBtnEnabled = false;
204 0 : pName->SetText(maTableItems[nTab].maName);
205 0 : const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get();
206 0 : if (pTabProtect && pTabProtect->isProtected())
207 : {
208 0 : if (pTabProtect->isPasswordEmpty())
209 0 : pStatus->SetText(maTextNotPassProtected);
210 0 : else if (pTabProtect->hasPasswordHash(meDesiredHash))
211 0 : pStatus->SetText(maTextHashGood);
212 : else
213 : {
214 : // incompatible hash
215 0 : pStatus->SetText(maTextHashBad);
216 0 : bBtnEnabled = true;
217 : }
218 : }
219 : else
220 0 : pStatus->SetText(maTextNotProtected);
221 :
222 0 : pBtn->Enable(bBtnEnabled);
223 : }
224 0 : }
225 :
226 0 : static bool lcl_IsInGoodStatus(ScPassHashProtectable* pProtected, ScPasswordHash eDesiredHash)
227 : {
228 0 : if (!pProtected || !pProtected->isProtected())
229 : // Not protected.
230 0 : return true;
231 :
232 0 : if (pProtected->isPasswordEmpty())
233 0 : return true;
234 :
235 0 : if (pProtected->hasPasswordHash(eDesiredHash))
236 0 : return true;
237 :
238 0 : return false;
239 : }
240 :
241 0 : void ScRetypePassDlg::CheckHashStatus()
242 : {
243 : do
244 : {
245 0 : if (!lcl_IsInGoodStatus(mpDocItem.get(), meDesiredHash))
246 0 : break;
247 :
248 0 : bool bStatusGood = true;
249 0 : size_t nTabCount = maTableItems.size();
250 0 : for (size_t i = 0; i < nTabCount && bStatusGood; ++i)
251 : {
252 0 : if (!lcl_IsInGoodStatus(maTableItems[i].mpProtect.get(), meDesiredHash))
253 0 : bStatusGood = false;
254 : }
255 0 : if (!bStatusGood)
256 0 : break;
257 :
258 0 : mpBtnOk->Enable();
259 0 : return;
260 : }
261 : while (false);
262 :
263 0 : mpBtnOk->Disable();
264 : }
265 :
266 0 : IMPL_LINK_NOARG(ScRetypePassDlg, OKHdl)
267 : {
268 0 : EndDialog(RET_OK);
269 0 : return 0;
270 : }
271 :
272 0 : IMPL_LINK( ScRetypePassDlg, RetypeBtnHdl, PushButton*, pBtn )
273 : {
274 0 : ScPassHashProtectable* pProtected = NULL;
275 0 : if (pBtn == mpBtnRetypeDoc)
276 : {
277 : // document protection.
278 0 : pProtected = mpDocItem.get();
279 : }
280 : else
281 : {
282 : // sheet protection.
283 0 : size_t aPos = 0;
284 0 : while(aPos < maSheets.size() && pBtn != maSheets[aPos]->GetChild(2))
285 0 : ++aPos;
286 :
287 0 : pProtected = aPos < maSheets.size() ? maTableItems[aPos].mpProtect.get() : 0;
288 : }
289 :
290 0 : if (!pProtected)
291 : // What the ... !?
292 0 : return 0;
293 :
294 0 : ScopedVclPtrInstance< ScRetypePassInputDlg > aDlg(this, pProtected);
295 0 : if (aDlg->Execute() == RET_OK)
296 : {
297 : // OK is pressed. Update the protected item.
298 0 : if (aDlg->IsRemovePassword())
299 : {
300 : // Remove password from this item.
301 0 : pProtected->setPassword(OUString());
302 : }
303 : else
304 : {
305 : // Set a new password.
306 0 : OUString aNewPass = aDlg->GetNewPassword();
307 0 : pProtected->setPassword(aNewPass);
308 : }
309 :
310 0 : SetDocData();
311 0 : CheckHashStatus();
312 : }
313 0 : return 0;
314 : }
315 :
316 0 : ScRetypePassInputDlg::ScRetypePassInputDlg(vcl::Window* pParent, ScPassHashProtectable* pProtected)
317 : : ModalDialog(pParent, "RetypePasswordDialog",
318 : "modules/scalc/ui/retypepassworddialog.ui")
319 0 : , mpProtected(pProtected)
320 : {
321 0 : get(m_pBtnOk, "ok");
322 0 : get(m_pBtnRetypePassword, "retypepassword");
323 0 : get(m_pBtnRemovePassword, "removepassword");
324 0 : get(m_pPasswordGrid, "passwordgrid");
325 0 : get(m_pPassword1Edit, "newpassEntry");
326 0 : get(m_pPassword2Edit, "confirmpassEntry");
327 0 : get(m_pBtnMatchOldPass, "mustmatch");
328 :
329 0 : Init();
330 0 : }
331 :
332 0 : ScRetypePassInputDlg::~ScRetypePassInputDlg()
333 : {
334 0 : disposeOnce();
335 0 : }
336 :
337 0 : void ScRetypePassInputDlg::dispose()
338 : {
339 0 : m_pBtnOk.clear();
340 0 : m_pBtnRetypePassword.clear();
341 0 : m_pPasswordGrid.clear();
342 0 : m_pPassword1Edit.clear();
343 0 : m_pPassword2Edit.clear();
344 0 : m_pBtnMatchOldPass.clear();
345 0 : m_pBtnRemovePassword.clear();
346 0 : ModalDialog::dispose();
347 0 : }
348 :
349 0 : short ScRetypePassInputDlg::Execute()
350 : {
351 0 : return ModalDialog::Execute();
352 : }
353 :
354 0 : bool ScRetypePassInputDlg::IsRemovePassword() const
355 : {
356 0 : return m_pBtnRemovePassword->IsChecked();
357 : }
358 :
359 0 : OUString ScRetypePassInputDlg::GetNewPassword() const
360 : {
361 0 : return m_pPassword1Edit->GetText();
362 : }
363 :
364 0 : void ScRetypePassInputDlg::Init()
365 : {
366 0 : Link<> aLink = LINK( this, ScRetypePassInputDlg, OKHdl );
367 0 : m_pBtnOk->SetClickHdl(aLink);
368 0 : aLink = LINK( this, ScRetypePassInputDlg, RadioBtnHdl );
369 0 : m_pBtnRetypePassword->SetClickHdl(aLink);
370 0 : m_pBtnRemovePassword->SetClickHdl(aLink);
371 0 : aLink = LINK( this, ScRetypePassInputDlg, CheckBoxHdl );
372 0 : m_pBtnMatchOldPass->SetClickHdl(aLink);
373 0 : aLink = LINK( this, ScRetypePassInputDlg, PasswordModifyHdl );
374 0 : m_pPassword1Edit->SetModifyHdl(aLink);
375 0 : m_pPassword2Edit->SetModifyHdl(aLink);
376 :
377 0 : m_pBtnOk->Disable();
378 0 : m_pBtnRetypePassword->Check(true);
379 0 : m_pBtnMatchOldPass->Check(true);
380 0 : m_pPassword1Edit->GrabFocus();
381 0 : }
382 :
383 0 : void ScRetypePassInputDlg::CheckPasswordInput()
384 : {
385 0 : OUString aPass1 = m_pPassword1Edit->GetText();
386 0 : OUString aPass2 = m_pPassword2Edit->GetText();
387 :
388 0 : if (aPass1.isEmpty() || aPass2.isEmpty())
389 : {
390 : // Empty password is not allowed.
391 0 : m_pBtnOk->Disable();
392 0 : return;
393 : }
394 :
395 0 : if (aPass1 != aPass2)
396 : {
397 : // The two passwords differ.
398 0 : m_pBtnOk->Disable();
399 0 : return;
400 : }
401 :
402 0 : if (!m_pBtnMatchOldPass->IsChecked())
403 : {
404 0 : m_pBtnOk->Enable();
405 0 : return;
406 : }
407 :
408 0 : if (!mpProtected)
409 : {
410 : // This should never happen!
411 0 : m_pBtnOk->Disable();
412 0 : return;
413 : }
414 :
415 0 : bool bPassGood = mpProtected->verifyPassword(aPass1);
416 0 : m_pBtnOk->Enable(bPassGood);
417 : }
418 :
419 0 : IMPL_LINK_NOARG(ScRetypePassInputDlg, OKHdl)
420 : {
421 0 : EndDialog(RET_OK);
422 0 : return 0;
423 : }
424 :
425 0 : IMPL_LINK( ScRetypePassInputDlg, RadioBtnHdl, RadioButton*, pBtn )
426 : {
427 0 : if (pBtn == m_pBtnRetypePassword)
428 : {
429 0 : m_pBtnRemovePassword->Check(false);
430 0 : m_pPasswordGrid->Enable();
431 0 : CheckPasswordInput();
432 : }
433 0 : else if (pBtn == m_pBtnRemovePassword)
434 : {
435 0 : m_pBtnRetypePassword->Check(false);
436 0 : m_pPasswordGrid->Disable();
437 0 : m_pBtnOk->Enable();
438 : }
439 :
440 0 : return 0;
441 : }
442 :
443 0 : IMPL_LINK_NOARG(ScRetypePassInputDlg, CheckBoxHdl)
444 : {
445 0 : CheckPasswordInput();
446 0 : return 0;
447 : }
448 :
449 0 : IMPL_LINK_NOARG(ScRetypePassInputDlg, PasswordModifyHdl)
450 : {
451 0 : CheckPasswordInput();
452 0 : return 0;
453 156 : }
454 :
455 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|