LCOV - code coverage report
Current view: top level - sfx2/source/dialog - securitypage.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 190 0.5 %
Date: 2014-11-03 Functions: 2 21 9.5 %
Legend: Lines: hit not hit

          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             : 
      21             : #include <sfx2/securitypage.hxx>
      22             : 
      23             : #include <sfx2/sfxresid.hxx>
      24             : 
      25             : #include <sfx2/sfx.hrc>
      26             : #include <sfx2/sfxsids.hrc>
      27             : #include <sfx2/objsh.hxx>
      28             : #include <sfx2/viewsh.hxx>
      29             : #include <sfx2/dispatch.hxx>
      30             : #include <sfx2/passwd.hxx>
      31             : 
      32             : #include <vcl/button.hxx>
      33             : #include <vcl/edit.hxx>
      34             : #include <vcl/fixed.hxx>
      35             : #include <vcl/msgbox.hxx>
      36             : #include <svl/eitem.hxx>
      37             : #include <svl/poolitem.hxx>
      38             : #include <svl/intitem.hxx>
      39             : #include <svl/PasswordHelper.hxx>
      40             : #include <svtools/xwindowitem.hxx>
      41             : 
      42             : #include "../appl/app.hrc"
      43             : 
      44             : 
      45             : using namespace ::com::sun::star;
      46             : 
      47             : 
      48             : 
      49             : namespace
      50             : {
      51             :     enum RedliningMode  { RL_NONE, RL_WRITER, RL_CALC };
      52             :     enum RedlineFunc    { RF_ON, RF_PROTECT };
      53             : 
      54           0 :     bool QueryState( sal_uInt16 _nSlot, bool& _rValue )
      55             :     {
      56           0 :         bool bRet = false;
      57           0 :         SfxViewShell* pViewSh = SfxViewShell::Current();
      58           0 :         if (pViewSh)
      59             :         {
      60             :             const SfxPoolItem* pItem;
      61           0 :             SfxDispatcher* pDisp = pViewSh->GetDispatcher();
      62           0 :             SfxItemState nState = pDisp->QueryState( _nSlot, pItem );
      63           0 :             bRet = SfxItemState::DEFAULT <= nState;
      64           0 :             if (bRet)
      65           0 :                 _rValue = ( static_cast< const SfxBoolItem* >( pItem ) )->GetValue();
      66             :         }
      67           0 :         return bRet;
      68             :     }
      69             : 
      70             : 
      71           0 :     bool QueryRecordChangesProtectionState( RedliningMode _eMode, bool& _rValue )
      72             :     {
      73           0 :         bool bRet = false;
      74           0 :         if (_eMode != RL_NONE)
      75             :         {
      76           0 :             sal_uInt16 nSlot = _eMode == RL_WRITER ? FN_REDLINE_PROTECT : SID_CHG_PROTECT;
      77           0 :             bRet = QueryState( nSlot, _rValue );
      78             :         }
      79           0 :         return bRet;
      80             :     }
      81             : 
      82             : 
      83           0 :     bool QueryRecordChangesState( RedliningMode _eMode, bool& _rValue )
      84             :     {
      85           0 :         bool bRet = false;
      86           0 :         if (_eMode != RL_NONE)
      87             :         {
      88           0 :             sal_uInt16 nSlot = _eMode == RL_WRITER ? FN_REDLINE_ON : FID_CHG_RECORD;
      89           0 :             bRet = QueryState( nSlot, _rValue );
      90             :         }
      91           0 :         return bRet;
      92             :     }
      93             : }
      94             : 
      95             : 
      96           0 : static bool lcl_GetPassword(
      97             :     vcl::Window *pParent,
      98             :     bool bProtect,
      99             :     /*out*/OUString &rPassword )
     100             : {
     101           0 :     bool bRes = false;
     102           0 :     SfxPasswordDialog aPasswdDlg( pParent );
     103           0 :     aPasswdDlg.SetMinLen( 1 );
     104           0 :     if (bProtect)
     105           0 :         aPasswdDlg.ShowExtras( SHOWEXTRAS_CONFIRM );
     106           0 :     if (RET_OK == aPasswdDlg.Execute() && !aPasswdDlg.GetPassword().isEmpty())
     107             :     {
     108           0 :         rPassword = aPasswdDlg.GetPassword();
     109           0 :         bRes = true;
     110             :     }
     111           0 :     return bRes;
     112             : }
     113             : 
     114             : 
     115           0 : static bool lcl_IsPasswordCorrect( const OUString &rPassword )
     116             : {
     117           0 :     bool bRes = false;
     118             : 
     119           0 :     SfxObjectShell* pCurDocShell = SfxObjectShell::Current();
     120           0 :     uno::Sequence< sal_Int8 >   aPasswordHash;
     121           0 :     pCurDocShell->GetProtectionHash( aPasswordHash );
     122             : 
     123             :     // check if supplied password was correct
     124           0 :     uno::Sequence< sal_Int8 > aNewPasswd( aPasswordHash );
     125           0 :     SvPasswordHelper::GetHashPassword( aNewPasswd, rPassword );
     126           0 :     if (SvPasswordHelper::CompareHashPassword( aPasswordHash, rPassword ))
     127           0 :         bRes = true;    // password was correct
     128             :     else
     129           0 :         InfoBox( NULL, SFX2_RESSTR(RID_SVXSTR_INCORRECT_PASSWORD) ).Execute();
     130             : 
     131           0 :     return bRes;
     132             : }
     133             : 
     134             : 
     135             : struct SfxSecurityPage_Impl
     136             : {
     137             :     SfxSecurityPage &   m_rMyTabPage;
     138             : 
     139             :     CheckBox*           m_pOpenReadonlyCB;
     140             :     CheckBox*           m_pRecordChangesCB;         // for record changes
     141             :     PushButton*         m_pProtectPB;               // for record changes
     142             :     PushButton*         m_pUnProtectPB;             // for record changes
     143             :     RedliningMode       m_eRedlingMode;             // for record changes
     144             : 
     145             :     bool                m_bOrigPasswordIsConfirmed;
     146             :     bool                m_bNewPasswordIsValid;
     147             :     OUString            m_aNewPassword;
     148             : 
     149             :     OUString            m_aEndRedliningWarning;
     150             :     bool                m_bEndRedliningWarningDone;
     151             : 
     152             :     DECL_LINK( RecordChangesCBToggleHdl, void* );
     153             :     DECL_LINK( ChangeProtectionPBHdl, void* );
     154             : 
     155             :     SfxSecurityPage_Impl( SfxSecurityPage &rDlg, const SfxItemSet &rItemSet );
     156             :     ~SfxSecurityPage_Impl();
     157             : 
     158             :     bool    FillItemSet_Impl( SfxItemSet & );
     159             :     void    Reset_Impl( const SfxItemSet & );
     160             : };
     161             : 
     162             : 
     163           0 : SfxSecurityPage_Impl::SfxSecurityPage_Impl( SfxSecurityPage &rTabPage, const SfxItemSet & ) :
     164             :     m_rMyTabPage                    (rTabPage),
     165             :     m_eRedlingMode                  ( RL_NONE ),
     166             :     m_bOrigPasswordIsConfirmed      ( false ),
     167             :     m_bNewPasswordIsValid           ( false ),
     168             :     m_aEndRedliningWarning          ( SFX2_RESSTR(RID_SVXSTR_END_REDLINING_WARNING) ),
     169           0 :     m_bEndRedliningWarningDone      ( false )
     170             : {
     171           0 :     rTabPage.get(m_pOpenReadonlyCB, "readonly");
     172           0 :     rTabPage.get(m_pRecordChangesCB, "recordchanges");
     173           0 :     rTabPage.get(m_pProtectPB, "protect");
     174           0 :     rTabPage.get(m_pUnProtectPB, "unprotect");
     175           0 :     m_pProtectPB->Show();
     176           0 :     m_pUnProtectPB->Hide();
     177             : 
     178             :     // force toggle hdl called before visual change of checkbox
     179           0 :     m_pRecordChangesCB->SetStyle( m_pRecordChangesCB->GetStyle() | WB_EARLYTOGGLE );
     180           0 :     m_pRecordChangesCB->SetToggleHdl( LINK( this, SfxSecurityPage_Impl, RecordChangesCBToggleHdl ) );
     181           0 :     m_pProtectPB->SetClickHdl( LINK( this, SfxSecurityPage_Impl, ChangeProtectionPBHdl ) );
     182           0 :     m_pUnProtectPB->SetClickHdl( LINK( this, SfxSecurityPage_Impl, ChangeProtectionPBHdl ) );
     183           0 : }
     184             : 
     185             : 
     186           0 : SfxSecurityPage_Impl::~SfxSecurityPage_Impl()
     187             : {
     188           0 : }
     189             : 
     190             : 
     191           0 : bool SfxSecurityPage_Impl::FillItemSet_Impl( SfxItemSet & )
     192             : {
     193           0 :     bool bModified = false;
     194             : 
     195           0 :     SfxObjectShell* pCurDocShell = SfxObjectShell::Current();
     196           0 :     if (pCurDocShell&& !pCurDocShell->IsReadOnly())
     197             :     {
     198           0 :         if (m_eRedlingMode != RL_NONE )
     199             :         {
     200           0 :             const bool bDoRecordChanges     = m_pRecordChangesCB->IsChecked();
     201           0 :             const bool bDoChangeProtection  = m_pUnProtectPB->IsVisible();
     202             : 
     203             :             // sanity checks
     204             :             DBG_ASSERT( bDoRecordChanges || !bDoChangeProtection, "no change recording should imply no change protection" );
     205             :             DBG_ASSERT( bDoChangeProtection || !bDoRecordChanges, "no change protection should imply no change recording" );
     206             :             DBG_ASSERT( !bDoChangeProtection || !m_aNewPassword.isEmpty(), "change protection should imply password length is > 0" );
     207             :             DBG_ASSERT( bDoChangeProtection || m_aNewPassword.isEmpty(), "no change protection should imply password length is 0" );
     208             : 
     209             :             // change recording
     210           0 :             if (bDoRecordChanges != pCurDocShell->IsChangeRecording())
     211             :             {
     212           0 :                 pCurDocShell->SetChangeRecording( bDoRecordChanges );
     213           0 :                 bModified = true;
     214             :             }
     215             : 
     216             :             // change record protection
     217           0 :             if (m_bNewPasswordIsValid &&
     218           0 :                 bDoChangeProtection != pCurDocShell->HasChangeRecordProtection())
     219             :             {
     220             :                 DBG_ASSERT( !bDoChangeProtection || bDoRecordChanges,
     221             :                         "change protection requires record changes to be active!" );
     222           0 :                 pCurDocShell->SetProtectionPassword( m_aNewPassword );
     223           0 :                 bModified = true;
     224             :             }
     225             :         }
     226             : 
     227             :         // open read-only?
     228           0 :         const bool bDoOpenReadonly = m_pOpenReadonlyCB->IsChecked();
     229           0 :         if (pCurDocShell->HasSecurityOptOpenReadOnly() &&
     230           0 :             bDoOpenReadonly != pCurDocShell->IsSecurityOptOpenReadOnly())
     231             :         {
     232           0 :             pCurDocShell->SetSecurityOptOpenReadOnly( bDoOpenReadonly );
     233           0 :             bModified = true;
     234             :         }
     235             :     }
     236             : 
     237           0 :     return bModified;
     238             : }
     239             : 
     240             : 
     241           0 : void SfxSecurityPage_Impl::Reset_Impl( const SfxItemSet & )
     242             : {
     243           0 :     SfxObjectShell* pCurDocShell = SfxObjectShell::Current();
     244             : 
     245           0 :     if (!pCurDocShell)
     246             :     {
     247             :         // no doc -> hide document settings
     248           0 :         m_pOpenReadonlyCB->Disable();
     249           0 :         m_pRecordChangesCB->Disable();
     250           0 :         m_pProtectPB->Show();
     251           0 :         m_pProtectPB->Disable();
     252           0 :         m_pUnProtectPB->Hide();
     253           0 :         m_pUnProtectPB->Disable();
     254             :     }
     255             :     else
     256             :     {
     257           0 :         bool bIsHTMLDoc = false;
     258           0 :         bool bProtect = true, bUnProtect = false;
     259           0 :         SfxViewShell* pViewSh = SfxViewShell::Current();
     260           0 :         if (pViewSh)
     261             :         {
     262             :             const SfxPoolItem* pItem;
     263           0 :             SfxDispatcher* pDisp = pViewSh->GetDispatcher();
     264           0 :             if (SfxItemState::DEFAULT <= pDisp->QueryState( SID_HTML_MODE, pItem ))
     265             :             {
     266           0 :                 sal_uInt16 nMode = static_cast< const SfxUInt16Item* >( pItem )->GetValue();
     267           0 :                 bIsHTMLDoc = ( ( nMode & HTMLMODE_ON ) != 0 );
     268             :             }
     269             :         }
     270             : 
     271           0 :         bool bIsReadonly = pCurDocShell->IsReadOnly();
     272           0 :         if (pCurDocShell->HasSecurityOptOpenReadOnly() && !bIsHTMLDoc)
     273             :         {
     274           0 :             m_pOpenReadonlyCB->Check( pCurDocShell->IsSecurityOptOpenReadOnly() );
     275           0 :             m_pOpenReadonlyCB->Enable( !bIsReadonly );
     276             :         }
     277             :         else
     278           0 :             m_pOpenReadonlyCB->Disable();
     279             : 
     280             :         bool bRecordChanges;
     281           0 :         if (QueryRecordChangesState( RL_WRITER, bRecordChanges ) && !bIsHTMLDoc)
     282           0 :             m_eRedlingMode = RL_WRITER;
     283           0 :         else if (QueryRecordChangesState( RL_CALC, bRecordChanges ))
     284           0 :             m_eRedlingMode = RL_CALC;
     285             :         else
     286           0 :             m_eRedlingMode = RL_NONE;
     287             : 
     288           0 :         if (m_eRedlingMode != RL_NONE)
     289             :         {
     290           0 :             bool bProtection(false);
     291           0 :             QueryRecordChangesProtectionState( m_eRedlingMode, bProtection );
     292             : 
     293           0 :             m_pProtectPB->Enable( !bIsReadonly );
     294           0 :             m_pUnProtectPB->Enable( !bIsReadonly );
     295             :             // set the right text
     296           0 :             if (bProtection)
     297             :             {
     298           0 :                 bProtect = false;
     299           0 :                 bUnProtect = true;
     300             :             }
     301             : 
     302           0 :             m_pRecordChangesCB->Check( bRecordChanges );
     303           0 :             m_pRecordChangesCB->Enable( /*!bProtection && */!bIsReadonly );
     304             : 
     305           0 :             m_bOrigPasswordIsConfirmed = true;   // default case if no password is set
     306           0 :             uno::Sequence< sal_Int8 > aPasswordHash;
     307             :             // check if password is available
     308           0 :             if (pCurDocShell->GetProtectionHash( aPasswordHash ) &&
     309           0 :                 aPasswordHash.getLength() > 0)
     310           0 :                 m_bOrigPasswordIsConfirmed = false;  // password found, needs to be confirmed later on
     311             :         }
     312             :         else
     313             :         {
     314             :             // A Calc document that is shared will have 'm_eRedlingMode == RL_NONE'
     315             :             // In shared documents change recording and protection must be disabled,
     316             :             // similar to documents that do not support change recording at all.
     317           0 :             m_pRecordChangesCB->Check( false );
     318           0 :             m_pRecordChangesCB->Disable();
     319           0 :             m_pProtectPB->Check( false );
     320           0 :             m_pUnProtectPB->Check( false );
     321           0 :             m_pProtectPB->Disable();
     322           0 :             m_pUnProtectPB->Disable();
     323             :         }
     324             : 
     325           0 :         m_pProtectPB->Show(bProtect);
     326           0 :         m_pUnProtectPB->Show(bUnProtect);
     327             :     }
     328           0 : }
     329             : 
     330             : 
     331           0 : IMPL_LINK_NOARG(SfxSecurityPage_Impl, RecordChangesCBToggleHdl)
     332             : {
     333             :     // when change recording gets disabled protection must be disabled as well
     334           0 :     if (!m_pRecordChangesCB->IsChecked())    // the new check state is already present, thus the '!'
     335             :     {
     336           0 :         bool bAlreadyDone = false;
     337           0 :         if (!m_bEndRedliningWarningDone)
     338             :         {
     339             :             WarningBox aBox( m_rMyTabPage.GetParent(), WinBits(WB_YES_NO | WB_DEF_NO),
     340           0 :                     m_aEndRedliningWarning );
     341           0 :             if (aBox.Execute() != RET_YES)
     342           0 :                 bAlreadyDone = true;
     343             :             else
     344           0 :                 m_bEndRedliningWarningDone = true;
     345             :         }
     346             : 
     347           0 :         const bool bNeedPasssword = !m_bOrigPasswordIsConfirmed
     348           0 :                 && m_pProtectPB->IsVisible();
     349           0 :         if (!bAlreadyDone && bNeedPasssword)
     350             :         {
     351           0 :             OUString aPasswordText;
     352             : 
     353             :             // dialog canceled or no password provided
     354           0 :             if (!lcl_GetPassword( m_rMyTabPage.GetParent(), false, aPasswordText ))
     355           0 :                 bAlreadyDone = true;
     356             : 
     357             :             // ask for password and if dialog is canceled or no password provided return
     358           0 :             if (lcl_IsPasswordCorrect( aPasswordText ))
     359           0 :                 m_bOrigPasswordIsConfirmed = true;
     360             :             else
     361           0 :                 bAlreadyDone = true;
     362             :         }
     363             : 
     364           0 :         if (bAlreadyDone)
     365           0 :             m_pRecordChangesCB->Check( true );     // restore original state
     366             :         else
     367             :         {
     368             :             // remember required values to change protection and change recording in
     369             :             // FillItemSet_Impl later on if password was correct.
     370           0 :             m_bNewPasswordIsValid = true;
     371           0 :             m_aNewPassword = "";
     372           0 :             m_pProtectPB->Show();
     373           0 :             m_pUnProtectPB->Hide();
     374             :         }
     375             :     }
     376             : 
     377           0 :     return 0;
     378             : }
     379             : 
     380             : 
     381           0 : IMPL_LINK_NOARG(SfxSecurityPage_Impl, ChangeProtectionPBHdl)
     382             : {
     383           0 :     if (m_eRedlingMode == RL_NONE)
     384           0 :         return 0;
     385             : 
     386             :     // the push button text is always the opposite of the current state. Thus:
     387           0 :     const bool bCurrentProtection = m_pUnProtectPB->IsVisible();
     388             : 
     389             :     // ask user for password (if still necessary)
     390           0 :     OUString aPasswordText;
     391           0 :     bool bNewProtection = !bCurrentProtection;
     392           0 :     const bool bNeedPassword = bNewProtection || !m_bOrigPasswordIsConfirmed;
     393           0 :     if (bNeedPassword)
     394             :     {
     395             :         // ask for password and if dialog is canceled or no password provided return
     396           0 :         if (!lcl_GetPassword( m_rMyTabPage.GetParent(), bNewProtection, aPasswordText ))
     397           0 :             return 0;
     398             : 
     399             :         // provided password still needs to be checked?
     400           0 :         if (!bNewProtection && !m_bOrigPasswordIsConfirmed)
     401             :         {
     402           0 :             if (lcl_IsPasswordCorrect( aPasswordText ))
     403           0 :                 m_bOrigPasswordIsConfirmed = true;
     404             :             else
     405           0 :                 return 0;
     406             :         }
     407             :     }
     408             :     DBG_ASSERT( m_bOrigPasswordIsConfirmed, "ooops... this should not have happened!" );
     409             : 
     410             :     // remember required values to change protection and change recording in
     411             :     // FillItemSet_Impl later on if password was correct.
     412           0 :     m_bNewPasswordIsValid = true;
     413           0 :     m_aNewPassword = bNewProtection? aPasswordText : OUString();
     414             : 
     415           0 :     m_pRecordChangesCB->Check( bNewProtection );
     416             : 
     417           0 :     m_pUnProtectPB->Show(bNewProtection);
     418           0 :     m_pProtectPB->Show(!bNewProtection);
     419             : 
     420           0 :     return 0;
     421             : }
     422             : 
     423             : 
     424           0 : SfxTabPage* SfxSecurityPage::Create( vcl::Window * pParent, const SfxItemSet * rItemSet )
     425             : {
     426           0 :     return new SfxSecurityPage( pParent, *rItemSet );
     427             : }
     428             : 
     429             : 
     430           0 : SfxSecurityPage::SfxSecurityPage( vcl::Window* pParent, const SfxItemSet& rItemSet )
     431           0 :     : SfxTabPage(pParent, "SecurityInfoPage", "sfx/ui/securityinfopage.ui", &rItemSet)
     432             : {
     433           0 :     m_pImpl.reset(new SfxSecurityPage_Impl( *this, rItemSet ));
     434           0 : }
     435             : 
     436             : 
     437           0 : SfxSecurityPage::~SfxSecurityPage()
     438             : {
     439           0 : }
     440             : 
     441             : 
     442           0 : bool SfxSecurityPage::FillItemSet( SfxItemSet * rItemSet )
     443             : {
     444           0 :     bool bModified = false;
     445             :     DBG_ASSERT( m_pImpl.get(), "implementation pointer is 0. Still in c-tor?" );
     446           0 :     if (m_pImpl.get() != 0)
     447           0 :         bModified =  m_pImpl->FillItemSet_Impl( *rItemSet );
     448           0 :     return bModified;
     449             : }
     450             : 
     451             : 
     452           0 : void SfxSecurityPage::Reset( const SfxItemSet * rItemSet )
     453             : {
     454             :     DBG_ASSERT( m_pImpl.get(), "implementation pointer is 0. Still in c-tor?" );
     455           0 :     if (m_pImpl.get() != 0)
     456           0 :         m_pImpl->Reset_Impl( *rItemSet );
     457         951 : }
     458             : 
     459             : 
     460             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10