summaryrefslogtreecommitdiff
path: root/sfx2/source/dialog/securitypage.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/dialog/securitypage.cxx')
-rwxr-xr-xsfx2/source/dialog/securitypage.cxx523
1 files changed, 523 insertions, 0 deletions
diff --git a/sfx2/source/dialog/securitypage.cxx b/sfx2/source/dialog/securitypage.cxx
new file mode 100755
index 000000000000..d32ee843cbf2
--- /dev/null
+++ b/sfx2/source/dialog/securitypage.cxx
@@ -0,0 +1,523 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sfx2.hxx"
+
+#include "sfx2/securitypage.hxx"
+
+#include "securitypage.hrc"
+#include "sfxresid.hxx"
+
+#include <sfx2/sfx.hrc>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/passwd.hxx>
+
+#include <vcl/button.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/fixed.hxx>
+#include <vcl/msgbox.hxx>
+#include <svl/eitem.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/PasswordHelper.hxx>
+#include <svtools/xwindowitem.hxx>
+
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////
+
+
+namespace
+{
+ enum RedliningMode { RL_NONE, RL_WRITER, RL_CALC };
+ enum RedlineFunc { RF_ON, RF_PROTECT };
+
+/*
+ bool QueryIsEnabled( USHORT _nSlot )
+ {
+ bool bRes = false;
+ SfxViewShell* pViewSh = SfxViewShell::Current();
+ if (pViewSh)
+ {
+ const SfxPoolItem* pItem;
+ SfxDispatcher* pDisp = pViewSh->GetDispatcher();
+ SfxItemState eState = pDisp->QueryState( _nSlot, pItem );
+ bRes = (eState & SFX_ITEM_DISABLED) == 0;
+ }
+ return bRes;
+ }
+*/
+
+ bool QueryState( USHORT _nSlot, bool& _rValue )
+ {
+ bool bRet = false;
+ SfxViewShell* pViewSh = SfxViewShell::Current();
+ if (pViewSh)
+ {
+ const SfxPoolItem* pItem;
+ SfxDispatcher* pDisp = pViewSh->GetDispatcher();
+ SfxItemState nState = pDisp->QueryState( _nSlot, pItem );
+ bRet = SFX_ITEM_AVAILABLE <= nState;
+ if (bRet)
+ _rValue = ( static_cast< const SfxBoolItem* >( pItem ) )->GetValue();
+ }
+ return bRet;
+ }
+
+
+ bool QueryRecordChangesProtectionState( RedliningMode _eMode, bool& _rValue )
+ {
+ bool bRet = false;
+ if (_eMode != RL_NONE)
+ {
+ USHORT nSlot = _eMode == RL_WRITER ? FN_REDLINE_PROTECT : SID_CHG_PROTECT;
+ bRet = QueryState( nSlot, _rValue );
+ }
+ return bRet;
+ }
+
+
+ bool QueryRecordChangesState( RedliningMode _eMode, bool& _rValue )
+ {
+ bool bRet = false;
+ if (_eMode != RL_NONE)
+ {
+ USHORT nSlot = _eMode == RL_WRITER ? FN_REDLINE_ON : FID_CHG_RECORD;
+ bRet = QueryState( nSlot, _rValue );
+ }
+ return bRet;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+static short lcl_GetPassword(
+ Window *pParent,
+ bool bProtect,
+ /*out*/String &rPassword )
+{
+ bool bRes = false;
+ SfxPasswordDialog aPasswdDlg( pParent );
+ const String aTitle( SfxResId( bProtect ? RID_SFX_PROTECT_RECORDS : RID_SFX_UNPROTECT_RECORDS ) );
+ aPasswdDlg.SetText( aTitle );
+ aPasswdDlg.SetMinLen( 1 );
+ if (bProtect)
+ aPasswdDlg.ShowExtras( SHOWEXTRAS_CONFIRM );
+ if (RET_OK == aPasswdDlg.Execute() && aPasswdDlg.GetPassword().Len() > 0)
+ {
+ rPassword = aPasswdDlg.GetPassword();
+ bRes = true;
+ }
+ return bRes;
+}
+
+
+static bool lcl_IsPasswordCorrect( const String &rPassword )
+{
+ bool bRes = false;
+
+ SfxObjectShell* pCurDocShell = SfxObjectShell::Current();
+ uno::Sequence< sal_Int8 > aPasswordHash;
+ pCurDocShell->GetProtectionHash( aPasswordHash );
+
+ // check if supplied password was correct
+ uno::Sequence< sal_Int8 > aNewPasswd( aPasswordHash );
+ SvPasswordHelper::GetHashPassword( aNewPasswd, rPassword );
+ if (SvPasswordHelper::CompareHashPassword( aPasswordHash, rPassword ))
+ bRes = true; // password was correct
+ else
+ InfoBox( NULL, String( SfxResId( RID_SFX_INCORRECT_PASSWORD ) ) ).Execute();
+
+ return bRes;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+struct SfxSecurityPage_Impl
+{
+ SfxSecurityPage & m_rMyTabPage;
+
+ FixedLine m_aNewPasswordToOpenFL;
+ FixedText m_aNewPasswordToOpenFT;
+ Edit m_aNewPasswordToOpenED;
+ FixedText m_aConfirmPasswordToOpenFT;
+ Edit m_aConfirmPasswordToOpenED;
+ FixedText m_aNewPasswordInfoFT;
+
+ FixedLine m_aNewPasswordToModifyFL;
+ FixedText m_aNewPasswordToModifyFT;
+ Edit m_aNewPasswordToModifyED;
+ FixedText m_aConfirmPasswordToModifyFT;
+ Edit m_aConfirmPasswordToModifyED;
+
+ FixedLine m_aOptionsFL;
+ CheckBox m_aOpenReadonlyCB;
+ CheckBox m_aRecordChangesCB; // for record changes
+ PushButton m_aChangeProtectionPB; // for record changes
+ String m_aProtectSTR; // for record changes
+ String m_aUnProtectSTR; // for record changes
+ RedliningMode m_eRedlingMode; // for record changes
+
+ bool m_bOrigPasswordIsConfirmed;
+ bool m_bNewPasswordIsValid;
+ String m_aNewPassword;
+
+ String m_aEndRedliningWarning;
+ bool m_bEndRedliningWarningDone;
+
+ DECL_LINK( RecordChangesCBToggleHdl, void* );
+ DECL_LINK( ChangeProtectionPBHdl, void* );
+
+ SfxSecurityPage_Impl( SfxSecurityPage &rDlg, const SfxItemSet &rItemSet );
+ ~SfxSecurityPage_Impl();
+
+ BOOL FillItemSet_Impl( SfxItemSet & );
+ void Reset_Impl( const SfxItemSet & );
+};
+
+
+SfxSecurityPage_Impl::SfxSecurityPage_Impl( SfxSecurityPage &rTabPage, const SfxItemSet & ) :
+ m_rMyTabPage (rTabPage),
+ m_aNewPasswordToOpenFL (&rTabPage, SfxResId( PASSWORD_TO_OPEN_FL ) ),
+ m_aNewPasswordToOpenFT (&rTabPage, SfxResId( PASSWORD_TO_OPEN_FT ) ),
+ m_aNewPasswordToOpenED (&rTabPage, SfxResId( PASSWORD_TO_OPEN_ED ) ),
+ m_aConfirmPasswordToOpenFT (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_OPEN_FT ) ),
+ m_aConfirmPasswordToOpenED (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_OPEN_ED ) ),
+ m_aNewPasswordInfoFT (&rTabPage, SfxResId( PASSWORD_INFO_FT ) ),
+ m_aNewPasswordToModifyFL (&rTabPage, SfxResId( PASSWORD_TO_MODIFY_FL ) ),
+ m_aNewPasswordToModifyFT (&rTabPage, SfxResId( PASSWORD_TO_MODIFY_FT ) ),
+ m_aNewPasswordToModifyED (&rTabPage, SfxResId( PASSWORD_TO_MODIFY_ED ) ),
+ m_aConfirmPasswordToModifyFT (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_MODIFY_FT ) ),
+ m_aConfirmPasswordToModifyED (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_MODIFY_ED ) ),
+ m_aOptionsFL (&rTabPage, SfxResId( OPTIONS_FL ) ),
+ m_aOpenReadonlyCB (&rTabPage, SfxResId( OPEN_READONLY_CB ) ),
+ m_aRecordChangesCB (&rTabPage, SfxResId( RECORD_CHANGES_CB ) ),
+ m_aChangeProtectionPB (&rTabPage, SfxResId( CHANGE_PROTECTION_PB ) ),
+ m_aProtectSTR ( SfxResId( STR_PROTECT ) ),
+ m_aUnProtectSTR ( SfxResId( STR_UNPROTECT ) ),
+ m_eRedlingMode ( RL_NONE ),
+ m_bOrigPasswordIsConfirmed ( false ),
+ m_bNewPasswordIsValid ( false ),
+ m_aEndRedliningWarning ( SfxResId( STR_END_REDLINING_WARNING ) ),
+ m_bEndRedliningWarningDone ( false )
+{
+ m_aChangeProtectionPB.SetText( m_aProtectSTR );
+ // adjust button width if necessary
+ long nBtnTextWidth = 0;
+ long nTemp = m_aChangeProtectionPB.GetCtrlTextWidth( m_aChangeProtectionPB.GetText() );
+ if (nTemp > nBtnTextWidth)
+ nBtnTextWidth = nTemp;
+
+ // force toggle hdl called before visual change of checkbox
+ m_aRecordChangesCB.SetStyle( m_aRecordChangesCB.GetStyle() | WB_EARLYTOGGLE );
+ m_aRecordChangesCB.SetToggleHdl( LINK( this, SfxSecurityPage_Impl, RecordChangesCBToggleHdl ) );
+ m_aChangeProtectionPB.SetClickHdl( LINK( this, SfxSecurityPage_Impl, ChangeProtectionPBHdl ) );
+}
+
+
+SfxSecurityPage_Impl::~SfxSecurityPage_Impl()
+{
+}
+
+
+BOOL SfxSecurityPage_Impl::FillItemSet_Impl( SfxItemSet & )
+{
+ bool bModified = false;
+
+ SfxObjectShell* pCurDocShell = SfxObjectShell::Current();
+ if (pCurDocShell&& !pCurDocShell->IsReadOnly())
+ {
+ if (m_eRedlingMode != RL_NONE )
+ {
+ const bool bDoRecordChanges = m_aRecordChangesCB.IsChecked();
+ const bool bDoChangeProtection = m_aChangeProtectionPB.GetText() != m_aProtectSTR;
+
+ // sanity checks
+ DBG_ASSERT( bDoRecordChanges || !bDoChangeProtection, "no change recording should imply no change protection" );
+ DBG_ASSERT( bDoChangeProtection || !bDoRecordChanges, "no change protection should imply no change recording" );
+ DBG_ASSERT( !bDoChangeProtection || m_aNewPassword.Len() > 0, "change protection should imply password length is > 0" );
+ DBG_ASSERT( bDoChangeProtection || m_aNewPassword.Len() == 0, "no change protection should imply password length is 0" );
+
+ // change recording
+ if (bDoRecordChanges != pCurDocShell->IsChangeRecording())
+ {
+ pCurDocShell->SetChangeRecording( bDoRecordChanges );
+ bModified = true;
+ }
+
+ // change record protection
+ if (m_bNewPasswordIsValid &&
+ bDoChangeProtection != pCurDocShell->HasChangeRecordProtection())
+ {
+ DBG_ASSERT( !bDoChangeProtection || bDoRecordChanges,
+ "change protection requires record changes to be active!" );
+ pCurDocShell->SetProtectionPassword( m_aNewPassword );
+ bModified = true;
+ }
+ }
+
+ // open read-only?
+ const sal_Bool bDoOpenReadonly = m_aOpenReadonlyCB.IsChecked();
+ if (pCurDocShell->HasSecurityOptOpenReadOnly() &&
+ bDoOpenReadonly != pCurDocShell->IsSecurityOptOpenReadOnly())
+ {
+ pCurDocShell->SetSecurityOptOpenReadOnly( bDoOpenReadonly );
+ bModified = true;
+ }
+ }
+
+ return bModified;
+}
+
+
+void SfxSecurityPage_Impl::Reset_Impl( const SfxItemSet & )
+{
+ SfxObjectShell* pCurDocShell = SfxObjectShell::Current();
+
+ String sNewText = m_aProtectSTR;
+ if (!pCurDocShell)
+ {
+ // no doc -> hide document settings
+ m_aOpenReadonlyCB.Disable();
+ m_aRecordChangesCB.Disable();
+ m_aChangeProtectionPB.Disable();
+ }
+ else
+ {
+ bool bIsHTMLDoc = false;
+ SfxViewShell* pViewSh = SfxViewShell::Current();
+ if (pViewSh)
+ {
+ const SfxPoolItem* pItem;
+ SfxDispatcher* pDisp = pViewSh->GetDispatcher();
+ if (SFX_ITEM_AVAILABLE <= pDisp->QueryState( SID_HTML_MODE, pItem ))
+ {
+ USHORT nMode = static_cast< const SfxUInt16Item* >( pItem )->GetValue();
+ bIsHTMLDoc = ( ( nMode & HTMLMODE_ON ) != 0 );
+ }
+ }
+
+ sal_Bool bIsReadonly = pCurDocShell->IsReadOnly();
+ if (pCurDocShell->HasSecurityOptOpenReadOnly() && !bIsHTMLDoc)
+ {
+ m_aOpenReadonlyCB.Check( pCurDocShell->IsSecurityOptOpenReadOnly() );
+ m_aOpenReadonlyCB.Enable( !bIsReadonly );
+ }
+ else
+ m_aOpenReadonlyCB.Disable();
+
+ bool bRecordChanges;
+ if (QueryRecordChangesState( RL_WRITER, bRecordChanges ) && !bIsHTMLDoc)
+ m_eRedlingMode = RL_WRITER;
+ else if (QueryRecordChangesState( RL_CALC, bRecordChanges ))
+ m_eRedlingMode = RL_CALC;
+ else
+ m_eRedlingMode = RL_NONE;
+
+ if (m_eRedlingMode != RL_NONE)
+ {
+ bool bProtection;
+ QueryRecordChangesProtectionState( m_eRedlingMode, bProtection );
+
+ m_aChangeProtectionPB.Enable( !bIsReadonly );
+ // set the right text
+ if (bProtection)
+ sNewText = m_aUnProtectSTR;
+
+ m_aRecordChangesCB.Check( bRecordChanges );
+ m_aRecordChangesCB.Enable( /*!bProtection && */!bIsReadonly );
+
+ m_bOrigPasswordIsConfirmed = true; // default case if no password is set
+ uno::Sequence< sal_Int8 > aPasswordHash;
+ // check if password is available
+ if (pCurDocShell->GetProtectionHash( aPasswordHash ) &&
+ aPasswordHash.getLength() > 0)
+ m_bOrigPasswordIsConfirmed = false; // password found, needs to be confirmed later on
+ }
+ else
+ {
+ // A Calc document that is shared will have 'm_eRedlingMode == RL_NONE'
+ // In shared documents change recording and protection must be disabled,
+ // similar to documents that do not support change recording at all.
+ m_aRecordChangesCB.Check( FALSE );
+ m_aRecordChangesCB.Disable();
+ m_aChangeProtectionPB.Check( FALSE );
+ m_aChangeProtectionPB.Disable();
+ }
+ }
+
+ m_aChangeProtectionPB.SetText( sNewText );
+}
+
+
+IMPL_LINK( SfxSecurityPage_Impl, RecordChangesCBToggleHdl, void*, EMPTYARG )
+{
+ // when change recording gets disabled protection must be disabled as well
+ if (!m_aRecordChangesCB.IsChecked()) // the new check state is already present, thus the '!'
+ {
+ bool bAlreadyDone = false;
+ if (!m_bEndRedliningWarningDone)
+ {
+ WarningBox aBox( m_rMyTabPage.GetParent(), WinBits(WB_YES_NO | WB_DEF_NO),
+ m_aEndRedliningWarning );
+ if (aBox.Execute() != RET_YES)
+ bAlreadyDone = true;
+ else
+ m_bEndRedliningWarningDone = true;
+ }
+
+ const bool bNeedPasssword = !m_bOrigPasswordIsConfirmed
+ && m_aChangeProtectionPB.GetText() != m_aProtectSTR;
+ if (!bAlreadyDone && bNeedPasssword)
+ {
+ String aPasswordText;
+
+ // dialog canceled or no password provided
+ if (!lcl_GetPassword( m_rMyTabPage.GetParent(), false, aPasswordText ))
+ bAlreadyDone = true;
+
+ // ask for password and if dialog is canceled or no password provided return
+ if (lcl_IsPasswordCorrect( aPasswordText ))
+ m_bOrigPasswordIsConfirmed = true;
+ else
+ bAlreadyDone = true;
+ }
+
+ if (bAlreadyDone)
+ m_aRecordChangesCB.Check( true ); // restore original state
+ else
+ {
+ // remember required values to change protection and change recording in
+ // FillItemSet_Impl later on if password was correct.
+ m_bNewPasswordIsValid = true;
+ m_aNewPassword = String();
+
+ m_aChangeProtectionPB.SetText( m_aProtectSTR );
+ }
+ }
+
+ return 0;
+}
+
+
+IMPL_LINK( SfxSecurityPage_Impl, ChangeProtectionPBHdl, void*, EMPTYARG )
+{
+ if (m_eRedlingMode == RL_NONE)
+ return 0;
+
+ // the push button text is always the opposite of the current state. Thus:
+ const bool bCurrentProtection = m_aChangeProtectionPB.GetText() != m_aProtectSTR;
+
+ // ask user for password (if still necessary)
+ String aPasswordText;
+ bool bNewProtection = !bCurrentProtection;
+ const bool bNeedPassword = bNewProtection || !m_bOrigPasswordIsConfirmed;
+ if (bNeedPassword)
+ {
+ // ask for password and if dialog is canceled or no password provided return
+ if (!lcl_GetPassword( m_rMyTabPage.GetParent(), bNewProtection, aPasswordText ))
+ return 0;
+
+ // provided password still needs to be checked?
+ if (!bNewProtection && !m_bOrigPasswordIsConfirmed)
+ {
+ if (lcl_IsPasswordCorrect( aPasswordText ))
+ m_bOrigPasswordIsConfirmed = true;
+ else
+ return 0;
+ }
+ }
+ DBG_ASSERT( m_bOrigPasswordIsConfirmed, "ooops... this should not have happened!" );
+
+ // remember required values to change protection and change recording in
+ // FillItemSet_Impl later on if password was correct.
+ m_bNewPasswordIsValid = true;
+ m_aNewPassword = bNewProtection? aPasswordText : String();
+
+// // RecordChangesCB is enabled if protection is off
+// m_aRecordChangesCB.Enable( !bNewProtection );
+ m_aRecordChangesCB.Check( bNewProtection );
+ // toggle text of button "Protect" <-> "Unprotect"
+ m_aChangeProtectionPB.SetText( bNewProtection ? m_aUnProtectSTR : m_aProtectSTR );
+
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+
+SfxTabPage* SfxSecurityPage::Create( Window * pParent, const SfxItemSet & rItemSet )
+{
+ return new SfxSecurityPage( pParent, rItemSet );
+}
+
+
+SfxSecurityPage::SfxSecurityPage( Window* pParent, const SfxItemSet& rItemSet ) :
+ SfxTabPage( pParent, SfxResId( TP_DOCINFOSECURITY ), rItemSet )
+{
+ m_pImpl = std::auto_ptr< SfxSecurityPage_Impl >(new SfxSecurityPage_Impl( *this, rItemSet ));
+
+ FreeResource();
+}
+
+
+SfxSecurityPage::~SfxSecurityPage()
+{
+}
+
+
+BOOL SfxSecurityPage::FillItemSet( SfxItemSet & rItemSet )
+{
+ bool bModified = false;
+ DBG_ASSERT( m_pImpl.get(), "implementation pointer is 0. Still in c-tor?" );
+ if (m_pImpl.get() != 0)
+ bModified = m_pImpl->FillItemSet_Impl( rItemSet );
+ return bModified;
+}
+
+
+void SfxSecurityPage::Reset( const SfxItemSet & rItemSet )
+{
+ DBG_ASSERT( m_pImpl.get(), "implementation pointer is 0. Still in c-tor?" );
+ if (m_pImpl.get() != 0)
+ m_pImpl->Reset_Impl( rItemSet );
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+