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