1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27 #include "retypepassdlg.hxx"
28 #include "retypepassdlg.hrc"
29 #include "scresid.hxx"
30 #include "document.hxx"
31 #include "tabprotection.hxx"
32
33 #include <stdio.h>
34
35 #include <vcl/msgbox.hxx>
36
ScRetypePassDlg(Window * pParent)37 ScRetypePassDlg::ScRetypePassDlg(Window* pParent) :
38 ModalDialog(pParent, ScResId(RID_SCDLG_RETYPEPASS)),
39
40 maBtnOk (this, ScResId(BTN_OK)),
41 maBtnCancel (this, ScResId(BTN_CANCEL)),
42 maBtnHelp (this, ScResId(BTN_HELP)),
43
44 maTextDescription(this, ScResId(FT_DESC)),
45 maLineDocument(this, ScResId(FL_DOCUMENT)),
46 maTextDocStatus(this, ScResId(FT_DOCSTATUS)),
47 maBtnRetypeDoc(this, ScResId(BTN_RETYPE_DOC)),
48
49 maLineSheet(this, ScResId(FL_SHEET)),
50 maTextSheetName1(this, ScResId(FT_SHEETNAME1)),
51 maTextSheetStatus1(this, ScResId(FT_SHEETSTATUS1)),
52 maBtnRetypeSheet1(this, ScResId(BTN_RETYPE_SHEET1)),
53
54 maTextSheetName2(this, ScResId(FT_SHEETNAME2)),
55 maTextSheetStatus2(this, ScResId(FT_SHEETSTATUS2)),
56 maBtnRetypeSheet2(this, ScResId(BTN_RETYPE_SHEET2)),
57
58 maTextSheetName3(this, ScResId(FT_SHEETNAME3)),
59 maTextSheetStatus3(this, ScResId(FT_SHEETSTATUS3)),
60 maBtnRetypeSheet3(this, ScResId(BTN_RETYPE_SHEET3)),
61
62 maTextSheetName4(this, ScResId(FT_SHEETNAME4)),
63 maTextSheetStatus4(this, ScResId(FT_SHEETSTATUS4)),
64 maBtnRetypeSheet4(this, ScResId(BTN_RETYPE_SHEET4)),
65
66 maScrollBar (this, ScResId(SB_SCROLL)),
67
68 maTextNotProtected(ScResId(STR_NOT_PROTECTED)),
69 maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED)),
70 maTextHashBad(ScResId(STR_HASH_BAD)),
71 maTextHashGood(ScResId(STR_HASH_GOOD)),
72 maTextHashRegen(ScResId(STR_HASH_REGENERATED)),
73
74 mpDocItem(static_cast<ScDocProtection*>(NULL)),
75 mnCurScrollPos(0),
76 meDesiredHash(PASSHASH_OOO)
77 {
78 Init();
79 }
80
~ScRetypePassDlg()81 ScRetypePassDlg::~ScRetypePassDlg()
82 {
83 }
84
Execute()85 short ScRetypePassDlg::Execute()
86 {
87 PopulateDialog();
88 CheckHashStatus();
89 return ModalDialog::Execute();
90 }
91
SetDataFromDocument(const ScDocument & rDoc)92 void ScRetypePassDlg::SetDataFromDocument(const ScDocument& rDoc)
93 {
94 const ScDocProtection* pDocProtect = rDoc.GetDocProtection();
95 if (pDocProtect && pDocProtect->isProtected())
96 mpDocItem.reset(new ScDocProtection(*pDocProtect));
97
98 SCTAB nTabCount = rDoc.GetTableCount();
99 maTableItems.reserve(nTabCount);
100 for (SCTAB i = 0; i < nTabCount; ++i)
101 {
102 TableItem aTabItem;
103 rDoc.GetName(i, aTabItem.maName);
104
105 const ScTableProtection* pTabProtect = rDoc.GetTabProtection(i);
106 if (pTabProtect && pTabProtect->isProtected())
107 aTabItem.mpProtect.reset(new ScTableProtection(*pTabProtect));
108
109 maTableItems.push_back(aTabItem);
110 }
111 }
112
SetDesiredHash(ScPasswordHash eHash)113 void ScRetypePassDlg::SetDesiredHash(ScPasswordHash eHash)
114 {
115 meDesiredHash = eHash;
116 }
117
WriteNewDataToDocument(ScDocument & rDoc) const118 void ScRetypePassDlg::WriteNewDataToDocument(ScDocument& rDoc) const
119 {
120 if (mpDocItem.get())
121 rDoc.SetDocProtection(mpDocItem.get());
122
123 size_t nTabCount = static_cast<size_t>(rDoc.GetTableCount());
124 size_t n = maTableItems.size();
125 for (size_t i = 0; i < n; ++i)
126 {
127 if (i >= nTabCount)
128 break;
129
130 ScTableProtection* pTabProtect = maTableItems[i].mpProtect.get();
131 if (pTabProtect)
132 rDoc.SetTabProtection(static_cast<SCTAB>(i), pTabProtect);
133 }
134 }
135
Init()136 void ScRetypePassDlg::Init()
137 {
138 Link aLink = LINK( this, ScRetypePassDlg, OKHdl );
139 maBtnOk.SetClickHdl(aLink);
140
141 aLink = LINK( this, ScRetypePassDlg, RetypeBtnHdl );
142 maBtnRetypeDoc.SetClickHdl(aLink);
143 maBtnRetypeSheet1.SetClickHdl(aLink);
144 maBtnRetypeSheet2.SetClickHdl(aLink);
145 maBtnRetypeSheet3.SetClickHdl(aLink);
146 maBtnRetypeSheet4.SetClickHdl(aLink);
147
148 maTextDocStatus.SetText(maTextNotProtected);
149 maTextSheetStatus1.SetText(maTextNotProtected);
150 maTextSheetStatus2.SetText(maTextNotProtected);
151 maTextSheetStatus3.SetText(maTextNotProtected);
152 maTextSheetStatus4.SetText(maTextNotProtected);
153 maBtnRetypeDoc.Disable();
154
155 // Make all sheet rows invisible.
156
157 maTextSheetName1.Show(false);
158 maTextSheetStatus1.Show(false);
159 maBtnRetypeSheet1.Show(false);
160 maBtnRetypeSheet1.Disable();
161
162 maTextSheetName2.Show(false);
163 maTextSheetStatus2.Show(false);
164 maBtnRetypeSheet2.Show(false);
165 maBtnRetypeSheet2.Disable();
166
167 maTextSheetName3.Show(false);
168 maTextSheetStatus3.Show(false);
169 maBtnRetypeSheet3.Show(false);
170 maBtnRetypeSheet3.Disable();
171
172 maTextSheetName4.Show(false);
173 maTextSheetStatus4.Show(false);
174 maBtnRetypeSheet4.Show(false);
175 maBtnRetypeSheet4.Disable();
176
177 maScrollBar.Show(false);
178
179 maScrollBar.SetEndScrollHdl( LINK( this, ScRetypePassDlg, ScrollHdl ) );
180 maScrollBar.SetScrollHdl( LINK( this, ScRetypePassDlg, ScrollHdl ) );
181
182 maScrollBar.SetPageSize(4);
183 maScrollBar.SetVisibleSize(4);
184 maScrollBar.SetLineSize(1);
185 }
186
PopulateDialog()187 void ScRetypePassDlg::PopulateDialog()
188 {
189 // Document protection first.
190 SetDocData();
191
192 // Sheet protection next. We're only interested in the first 4 sheets
193 // (or less).
194 size_t n = maTableItems.size();
195 for (size_t i = 0; i < n && i < 4; ++i)
196 SetTableData(i, static_cast< SCTAB >( i ));
197
198 if (n > 4)
199 {
200 maScrollBar.Show(true);
201 maScrollBar.SetRange(Range(0, n));
202 }
203 }
204
SetDocData()205 void ScRetypePassDlg::SetDocData()
206 {
207 bool bBtnEnabled = false;
208 if (mpDocItem.get() && mpDocItem->isProtected())
209 {
210 if (mpDocItem->isPasswordEmpty())
211 maTextDocStatus.SetText(maTextNotPassProtected);
212 else if (mpDocItem->hasPasswordHash(meDesiredHash))
213 maTextDocStatus.SetText(maTextHashGood);
214 else
215 {
216 // incompatible hash
217 maTextDocStatus.SetText(maTextHashBad);
218 bBtnEnabled = true;
219 }
220 }
221 maBtnRetypeDoc.Enable(bBtnEnabled);
222 }
223
SetTableData(size_t nRowPos,SCTAB nTab)224 void ScRetypePassDlg::SetTableData(size_t nRowPos, SCTAB nTab)
225 {
226 if (nRowPos >= 4)
227 return;
228
229 FixedText* pName = NULL;
230 FixedText* pStatus = NULL;
231 PushButton* pBtn = NULL;
232 switch (nRowPos)
233 {
234 case 0:
235 pName = &maTextSheetName1;
236 pStatus = &maTextSheetStatus1;
237 pBtn = &maBtnRetypeSheet1;
238 break;
239 case 1:
240 pName = &maTextSheetName2;
241 pStatus = &maTextSheetStatus2;
242 pBtn = &maBtnRetypeSheet2;
243 break;
244 case 2:
245 pName = &maTextSheetName3;
246 pStatus = &maTextSheetStatus3;
247 pBtn = &maBtnRetypeSheet3;
248 break;
249 case 3:
250 pName = &maTextSheetName4;
251 pStatus = &maTextSheetStatus4;
252 pBtn = &maBtnRetypeSheet4;
253 break;
254 default:
255 return;
256 }
257
258 bool bBtnEnabled = false;
259 pName->SetText(maTableItems[nTab].maName);
260 pName->Show(true);
261 const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get();
262 if (pTabProtect && pTabProtect->isProtected())
263 {
264 if (pTabProtect->isPasswordEmpty())
265 pStatus->SetText(maTextNotPassProtected);
266 else if (pTabProtect->hasPasswordHash(meDesiredHash))
267 pStatus->SetText(maTextHashGood);
268 else
269 {
270 // incompatible hash
271 pStatus->SetText(maTextHashBad);
272 bBtnEnabled = true;
273 }
274 }
275 else
276 pStatus->SetText(maTextNotProtected);
277
278 pStatus->Show(true);
279 pBtn->Show(true);
280 pBtn->Enable(bBtnEnabled);
281 }
282
ResetTableRows()283 void ScRetypePassDlg::ResetTableRows()
284 {
285 long nScrollPos = maScrollBar.GetThumbPos();
286 mnCurScrollPos = nScrollPos < 0 ? 0 : nScrollPos;
287 size_t nRowCount = maTableItems.size() - nScrollPos;
288 for (size_t i = 0; i < nRowCount; ++i)
289 SetTableData(i, static_cast< SCTAB >( i + nScrollPos ));
290 }
291
lcl_IsInGoodStatus(ScPassHashProtectable * pProtected,ScPasswordHash eDesiredHash)292 bool lcl_IsInGoodStatus(ScPassHashProtectable* pProtected, ScPasswordHash eDesiredHash)
293 {
294 if (!pProtected || !pProtected->isProtected())
295 // Not protected.
296 return true;
297
298 if (pProtected->isPasswordEmpty())
299 return true;
300
301 if (pProtected->hasPasswordHash(eDesiredHash))
302 return true;
303
304 return false;
305 }
306
CheckHashStatus()307 void ScRetypePassDlg::CheckHashStatus()
308 {
309 do
310 {
311 if (!lcl_IsInGoodStatus(mpDocItem.get(), meDesiredHash))
312 break;
313
314 bool bStatusGood = true;
315 size_t nTabCount = maTableItems.size();
316 for (size_t i = 0; i < nTabCount && bStatusGood; ++i)
317 {
318 if (!lcl_IsInGoodStatus(maTableItems[i].mpProtect.get(), meDesiredHash))
319 bStatusGood = false;
320 }
321 if (!bStatusGood)
322 break;
323
324 maBtnOk.Enable();
325 return;
326 }
327 while (false);
328
329 maBtnOk.Disable();
330 }
331
IMPL_LINK(ScRetypePassDlg,OKHdl,OKButton *,EMPTYARG)332 IMPL_LINK( ScRetypePassDlg, OKHdl, OKButton*, EMPTYARG )
333 {
334 EndDialog(RET_OK);
335 return 0;
336 }
337
IMPL_LINK(ScRetypePassDlg,RetypeBtnHdl,PushButton *,pBtn)338 IMPL_LINK( ScRetypePassDlg, RetypeBtnHdl, PushButton*, pBtn )
339 {
340 ScPassHashProtectable* pProtected = NULL;
341 if (pBtn == &maBtnRetypeDoc)
342 {
343 // document protection.
344 pProtected = mpDocItem.get();
345 }
346 else
347 {
348 // sheet protection.
349 size_t nTabPos = mnCurScrollPos;
350 if (pBtn == &maBtnRetypeSheet2)
351 nTabPos += 1;
352 else if (pBtn == &maBtnRetypeSheet3)
353 nTabPos += 2;
354 else if (pBtn == &maBtnRetypeSheet4)
355 nTabPos += 3;
356 else if (pBtn != &maBtnRetypeSheet1)
357 // This should never happen !
358 return 0;
359
360 if (nTabPos >= maTableItems.size())
361 // Likewise, this should never happen !
362 return 0;
363
364 pProtected = maTableItems[nTabPos].mpProtect.get();
365 }
366
367 if (!pProtected)
368 // What the ... !?
369 return 0;
370
371 ScRetypePassInputDlg aDlg(this, pProtected);
372 if (aDlg.Execute() == RET_OK)
373 {
374 // OK is pressed. Update the protected item.
375 if (aDlg.IsRemovePassword())
376 {
377 // Remove password from this item.
378 pProtected->setPassword(String());
379 }
380 else
381 {
382 // Set a new password.
383 String aNewPass = aDlg.GetNewPassword();
384 pProtected->setPassword(aNewPass);
385 }
386
387 SetDocData();
388 ResetTableRows();
389 CheckHashStatus();
390 }
391 return 0;
392 }
393
IMPL_LINK(ScRetypePassDlg,ScrollHdl,ScrollBar *,EMPTYARG)394 IMPL_LINK( ScRetypePassDlg, ScrollHdl, ScrollBar*, EMPTYARG )
395 {
396 ResetTableRows();
397 return 0;
398 }
399
400 // ============================================================================
401
ScRetypePassInputDlg(Window * pParent,ScPassHashProtectable * pProtected)402 ScRetypePassInputDlg::ScRetypePassInputDlg(Window* pParent, ScPassHashProtectable* pProtected) :
403 ModalDialog(pParent, ScResId(RID_SCDLG_RETYPEPASS_INPUT)),
404
405 maBtnOk (this, ScResId(BTN_OK)),
406 maBtnCancel (this, ScResId(BTN_CANCEL)),
407 maBtnHelp (this, ScResId(BTN_HELP)),
408
409 maBtnRetypePassword(this, ScResId(BTN_RETYPE_PASSWORD)),
410
411 maPassword1Text (this, ScResId(FT_PASSWORD1)),
412 maPassword1Edit (this, ScResId(ED_PASSWORD1)),
413 maPassword2Text (this, ScResId(FT_PASSWORD2)),
414 maPassword2Edit (this, ScResId(ED_PASSWORD2)),
415 maBtnMatchOldPass(this, ScResId(BTN_MATCH_OLD_PASSWORD)),
416
417 maBtnRemovePassword(this, ScResId(BTN_REMOVE_PASSWORD)),
418
419 mpProtected(pProtected)
420 {
421 Init();
422 }
423
~ScRetypePassInputDlg()424 ScRetypePassInputDlg::~ScRetypePassInputDlg()
425 {
426 }
427
Execute()428 short ScRetypePassInputDlg::Execute()
429 {
430 return ModalDialog::Execute();
431 }
432
IsRemovePassword() const433 bool ScRetypePassInputDlg::IsRemovePassword() const
434 {
435 return maBtnRemovePassword.IsChecked();
436 }
437
GetNewPassword() const438 String ScRetypePassInputDlg::GetNewPassword() const
439 {
440 return maPassword1Edit.GetText();
441 }
442
Init()443 void ScRetypePassInputDlg::Init()
444 {
445 Link aLink = LINK( this, ScRetypePassInputDlg, OKHdl );
446 maBtnOk.SetClickHdl(aLink);
447 aLink = LINK( this, ScRetypePassInputDlg, RadioBtnHdl );
448 maBtnRetypePassword.SetClickHdl(aLink);
449 maBtnRemovePassword.SetClickHdl(aLink);
450 aLink = LINK( this, ScRetypePassInputDlg, CheckBoxHdl );
451 maBtnMatchOldPass.SetClickHdl(aLink);
452 aLink = LINK( this, ScRetypePassInputDlg, PasswordModifyHdl );
453 maPassword1Edit.SetModifyHdl(aLink);
454 maPassword2Edit.SetModifyHdl(aLink);
455
456 maBtnOk.Disable();
457 maBtnRetypePassword.Check(true);
458 maBtnMatchOldPass.Check(true);
459 maPassword1Edit.GrabFocus();
460 }
461
CheckPasswordInput()462 void ScRetypePassInputDlg::CheckPasswordInput()
463 {
464 String aPass1 = maPassword1Edit.GetText();
465 String aPass2 = maPassword2Edit.GetText();
466
467 if (!aPass1.Len() || !aPass2.Len())
468 {
469 // Empty password is not allowed.
470 maBtnOk.Disable();
471 return;
472 }
473
474 if (!aPass1.Equals(aPass2))
475 {
476 // The two passwords differ.
477 maBtnOk.Disable();
478 return;
479 }
480
481 if (!maBtnMatchOldPass.IsChecked())
482 {
483 maBtnOk.Enable();
484 return;
485 }
486
487 if (!mpProtected)
488 {
489 // This should never happen!
490 maBtnOk.Disable();
491 return;
492 }
493
494 bool bPassGood = mpProtected->verifyPassword(aPass1);
495 maBtnOk.Enable(bPassGood);
496 }
497
IMPL_LINK(ScRetypePassInputDlg,OKHdl,OKButton *,EMPTYARG)498 IMPL_LINK( ScRetypePassInputDlg, OKHdl, OKButton*, EMPTYARG )
499 {
500 EndDialog(RET_OK);
501 return 0;
502 }
503
IMPL_LINK(ScRetypePassInputDlg,RadioBtnHdl,RadioButton *,pBtn)504 IMPL_LINK( ScRetypePassInputDlg, RadioBtnHdl, RadioButton*, pBtn )
505 {
506 if (pBtn == &maBtnRetypePassword)
507 {
508 maBtnRemovePassword.Check(false);
509 maPassword1Text.Enable();
510 maPassword1Edit.Enable();
511 maPassword2Text.Enable();
512 maPassword2Edit.Enable();
513 maBtnMatchOldPass.Enable();
514 CheckPasswordInput();
515 }
516 else if (pBtn == &maBtnRemovePassword)
517 {
518 maBtnRetypePassword.Check(false);
519 maPassword1Text.Disable();
520 maPassword1Edit.Disable();
521 maPassword2Text.Disable();
522 maPassword2Edit.Disable();
523 maBtnMatchOldPass.Disable();
524 maBtnOk.Enable();
525 }
526
527 return 0;
528 }
529
IMPL_LINK(ScRetypePassInputDlg,CheckBoxHdl,CheckBox *,EMPTYARG)530 IMPL_LINK( ScRetypePassInputDlg, CheckBoxHdl, CheckBox*, EMPTYARG )
531 {
532 CheckPasswordInput();
533 return 0;
534 }
535
IMPL_LINK(ScRetypePassInputDlg,PasswordModifyHdl,Edit *,EMPTYARG)536 IMPL_LINK( ScRetypePassInputDlg, PasswordModifyHdl, Edit*, EMPTYARG )
537 {
538 CheckPasswordInput();
539 return 0;
540 }
541