ooo-build r12011 - in trunk: . patches/test
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r12011 - in trunk: . patches/test
- Date: Wed, 26 Mar 2008 14:27:10 +0000 (GMT)
Author: kyoshida
Date: Wed Mar 26 14:27:10 2008
New Revision: 12011
URL: http://svn.gnome.org/viewvc/ooo-build?rev=12011&view=rev
Log:
2008-03-26 Kohei Yoshida <kyoshida novell com>
* patches/test/calc-protection-sc.diff:
* patches/test/calc-protection-sfx2.diff:
* patches/test/calc-protection-svx.diff: on-going work for Excel export
protection & some initial work for sheet protection options. Making
backup as I had trouble resyncing to the latest milestone due to SRC680
-> DEV300 master tree change.
Added:
trunk/patches/test/calc-protection-sc.diff
trunk/patches/test/calc-protection-sfx2.diff
trunk/patches/test/calc-protection-svx.diff
Modified:
trunk/ChangeLog
Added: trunk/patches/test/calc-protection-sc.diff
==============================================================================
--- (empty file)
+++ trunk/patches/test/calc-protection-sc.diff Wed Mar 26 14:27:10 2008
@@ -0,0 +1,5635 @@
+? sc/sc.vpj
+Index: sc/inc/document.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/document.hxx,v
+retrieving revision 1.107
+retrieving revision 1.102.40.5
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.107 -r1.102.40.5
+--- sc/inc/document.hxx 29 Jan 2008 15:15:18 -0000 1.107
++++ sc/inc/document.hxx 15 Feb 2008 00:41:33 -0000 1.102.40.5
+@@ -118,6 +118,7 @@
+ class ScDetOpData;
+ class ScDetOpList;
+ class ScDocOptions;
++class ScDocProtection;
+ class ScDocumentPool;
+ class ScDrawLayer;
+ class ScExtDocOptions;
+@@ -133,6 +134,7 @@
+ class ScStyleSheet;
+ class ScStyleSheetPool;
+ class ScTable;
++class ScTableProtection;
+ class ScTokenArray;
+ class ScValidationData;
+ class ScValidationDataList;
+@@ -305,7 +307,7 @@
+
+ ScFieldEditEngine* pCacheFieldEditEngine;
+
+- com::sun::star::uno::Sequence<sal_Int8> aProtectPass;
++ ::std::auto_ptr<ScDocProtection> pDocProtection;
+ String aDocName; // opt: Dokumentname
+ ScRangePairListRef xColNameRanges;
+ ScRangePairListRef xRowNameRanges;
+@@ -360,7 +362,6 @@
+
+ ScLkUpdMode eLinkMode;
+
+- BOOL bProtected;
+ BOOL bAutoCalc; // Automatisch Berechnen
+ BOOL bAutoCalcShellDisabled; // in/von/fuer ScDocShell disabled
+ // ob noch ForcedFormulas berechnet werden muessen,
+@@ -539,13 +540,16 @@
+ inline SCTAB GetTableCount() const { return nMaxTableNumber; }
+ SvNumberFormatterIndexTable* GetFormatExchangeList() const { return pFormatExchangeList; }
+
+- void SetDocProtection( BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass );
+- void SetTabProtection( SCTAB nTab, BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass );
++ ScDocProtection* GetDocProtection() const;
++ void SetDocProtection(bool bProtect, const String& aPassText);
++ void SetDocProtection(const ScDocProtection* pProtect);
+ BOOL IsDocProtected() const;
+ BOOL IsDocEditable() const;
+ BOOL IsTabProtected( SCTAB nTab ) const;
+- const com::sun::star::uno::Sequence <sal_Int8>& GetDocPassword() const;
+- const com::sun::star::uno::Sequence <sal_Int8>& GetTabPassword( SCTAB nTab ) const;
++ ScTableProtection* GetTabProtection( SCTAB nTab ) const;
++ void SetTabProtection(SCTAB nTab, bool bProtect, const String& aPassText);
++ void SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect);
++ void CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest);
+
+ void LockTable(SCTAB nTab);
+ void UnlockTable(SCTAB nTab);
+@@ -1494,6 +1498,8 @@
+
+
+ private:
++ ScDocument(const ScDocument& r); // disabled with no definition
++
+ void SetAutoFilterFlags();
+ void FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
+ SCCOL nX1, SCCOL nX2 ) const;
+Index: sc/inc/scextopt.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/scextopt.hxx,v
+retrieving revision 1.12
+retrieving revision 1.12.534.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.12 -r1.12.534.1
+--- sc/inc/scextopt.hxx 8 Sep 2005 17:53:33 -0000 1.12
++++ sc/inc/scextopt.hxx 5 Jan 2008 06:16:07 -0000 1.12.534.1
+@@ -61,7 +61,6 @@
+ double mfTabBarWidth; /// Width of the tabbar, relative to frame window width (0.0 ... 1.0).
+ sal_uInt32 mnLinkCnt; /// Recursive counter for loading external documents.
+ SCTAB mnDisplTab; /// Index of displayed sheet.
+- bool mbWinProtected; /// true = Window properties are protected.
+ bool mbEncrypted; /// true = Imported file was encrypted.
+
+ explicit ScExtDocSettings();
+Index: sc/inc/table.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/table.hxx,v
+retrieving revision 1.33
+retrieving revision 1.31.180.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.33 -r1.31.180.4
+--- sc/inc/table.hxx 12 Feb 2008 13:23:01 -0000 1.33
++++ sc/inc/table.hxx 15 Feb 2008 00:41:37 -0000 1.31.180.4
+@@ -58,6 +58,8 @@
+ #include "compressedarray.hxx"
+ #endif
+
++#include <memory>
++
+ namespace utl {
+ class SearchParam;
+ class TextSearch;
+@@ -84,6 +86,7 @@
+ class ScSortInfoArray;
+ class ScStyleSheet;
+ class ScTableLink;
++class ScTableProtection;
+ class ScUserListData;
+ class ScIndexMap;
+ struct RowInfo;
+@@ -121,8 +124,7 @@
+ SCROW nRepeatStartY;
+ SCROW nRepeatEndY;
+
+- BOOL bProtected;
+- com::sun::star::uno::Sequence<sal_Int8> aProtectPass;
++ ::std::auto_ptr<ScTableProtection> pTabProtection;
+
+ USHORT* pColWidth;
+ ScSummableCompressedArray< SCROW, USHORT>* pRowHeight;
+@@ -237,10 +239,12 @@
+ void SetPageStyle( const String& rName );
+ void PageStyleModified( const String& rNewName );
+
+- BOOL IsProtected() const { return bProtected; }
+- const com::sun::star::uno::Sequence<sal_Int8>& GetPassword() const { return aProtectPass; }
+- void SetProtection( BOOL bProtect, const com::sun::star::uno::Sequence<sal_Int8>& rPasswd )
+- { bProtected = bProtect; aProtectPass = rPasswd; }
++ BOOL IsProtected() const;
++ com::sun::star::uno::Sequence<sal_Int8> GetPassword() const;
++ void SetProtection(BOOL bProtect, const com::sun::star::uno::Sequence<sal_Int8>& rPasswd);
++ void SetProtection(bool bProtect, const String& aPassText);
++ void SetProtection(const ScTableProtection* pProtect);
++ ScTableProtection* GetProtection();
+
+ Size GetPageSize() const;
+ void SetPageSize( const Size& rSize );
+Index: sc/inc/tabprotection.hxx
+===================================================================
+RCS file: sc/inc/tabprotection.hxx
+diff -N sc/inc/tabprotection.hxx
+--- /dev/null 1 Jan 1970 00:00:00 -0000
++++ sc/inc/tabprotection.hxx 3 Jan 2008 16:57:32 -0000 1.1.2.2
+@@ -0,0 +1,142 @@
++/*************************************************************************
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: tabprotection.hxx,v $
++ *
++ * $Revision: 1.1.2.2 $
++ *
++ * last change: $Author: kohei $ $Date: 2008/01/03 16:57:32 $
++ *
++ * The Contents of this file are made available subject to
++ * the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ * GNU Lesser General Public License Version 2.1
++ * =============================================
++ * Copyright 2005 by Sun Microsystems, Inc.
++ * 901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License version 2.1, as published by the Free Software Foundation.
++ *
++ * This library 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 for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ ************************************************************************/
++
++#ifndef SC_TAB_PROTECTION_HXX
++#define SC_TAB_PROTECTION_HXX
++
++#include "sal/types.h"
++#include <com/sun/star/uno/Sequence.hxx>
++
++#include "global.hxx"
++#include <vector>
++#include <memory>
++
++class ScTableProtectionImpl;
++
++enum ScPasswordHash
++{
++ PASSHASH_OOO = 0,
++ PASSHASH_XL
++};
++
++// ============================================================================
++
++class ScDocProtection
++{
++public:
++ enum Option
++ {
++ STRUCTURE = 0,
++ WINDOWS,
++ CONTENT,
++ NONE // last item - used to resize the vector
++ };
++
++ explicit ScDocProtection();
++ explicit ScDocProtection(const ScDocProtection& r);
++ ~ScDocProtection();
++
++ bool isProtected() const;
++ bool isProtectedWithPass() const;
++ void setProtected(bool bProtected);
++
++ void setPassword(const String& aPassText);
++ ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
++ void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash = PASSHASH_OOO);
++ bool verifyPassword(const String& aPassText) const;
++
++ bool isOptionEnabled(Option eOption) const;
++ void setOption(Option eOption, bool bEnabled);
++
++private:
++ ::std::auto_ptr<ScTableProtectionImpl> mpImpl;
++};
++
++// ============================================================================
++
++/** sheet protection state container
++
++ This class stores sheet's protection state: 1) whether the protection
++ is on, 2) password and/or password hash, and 3) any associated
++ protection options. This class is also used as a protection state
++ container for the undo/redo stack, in which case the password, hash and
++ the options need to be preserved even when the protection flag is
++ off. */
++class ScTableProtection
++{
++public:
++ enum Option
++ {
++ AUTOFILTER = 0,
++ DELETE_COLUMNS,
++ DELETE_ROWS,
++ FORMAT_CELLS,
++ FORMAT_COLUMNS,
++ FORMAT_ROWS,
++ INSERT_COLUMNS,
++ INSERT_HYPERLINKS,
++ INSERT_ROWS,
++ OBJECTS,
++ PIVOT_TABLES,
++ SCENARIOS,
++ SELECT_LOCKED_CELLS,
++ SELECT_UNLOCKED_CELLS,
++ SHEET,
++ SORT,
++ NONE // last item - used to resize the vector
++ };
++
++ explicit ScTableProtection();
++ explicit ScTableProtection(const ScTableProtection& r);
++ ~ScTableProtection();
++
++ bool isProtected() const;
++ bool isProtectedWithPass() const;
++ void setProtected(bool bProtected);
++
++ void setPassword(const String& aPassText);
++ ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
++ void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash = PASSHASH_OOO);
++ bool verifyPassword(const String& aPassText) const;
++
++ bool isOptionEnabled(Option eOption) const;
++ void setOption(Option eOption, bool bEnabled);
++
++private:
++ ::std::auto_ptr<ScTableProtectionImpl> mpImpl;
++};
++
++
++#endif
+Index: sc/source/core/data/documen2.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/documen2.cxx,v
+retrieving revision 1.70
+retrieving revision 1.67.80.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.70 -r1.67.80.2
+--- sc/source/core/data/documen2.cxx 12 Feb 2008 13:23:44 -0000 1.70
++++ sc/source/core/data/documen2.cxx 15 Feb 2008 00:42:24 -0000 1.67.80.2
+@@ -151,6 +151,7 @@
+ pChangeViewSettings( NULL ),
+ pScriptTypeData( NULL ),
+ pCacheFieldEditEngine( NULL ),
++ pDocProtection( NULL ),
+ pViewOptions( NULL ),
+ pDocOptions( NULL ),
+ pExtDocOptions( NULL ),
+@@ -174,7 +175,6 @@
+ nHardRecalcState(0),
+ nVisibleTab( 0 ),
+ eLinkMode(LM_UNKNOWN),
+- bProtected( FALSE ),
+ bAutoCalc( eMode == SCDOCMODE_DOCUMENT ),
+ bAutoCalcShellDisabled( FALSE ),
+ bForcedFormulaPending( FALSE ),
+@@ -636,11 +636,10 @@
+
+ rStream >> nVersion; // 312 abwaerts
+ rStream.ReadByteString( aPageStyle, rStream.GetStreamCharSet() );
+- rStream >> bProtected; // Dokument geschuetzt
++ BOOL bProtectedTemp;
++ rStream >> bProtectedTemp; // Dokument geschuetzt
+ String aPass;
+ rStream.ReadByteString( aPass, rStream.GetStreamCharSet() );
+- if (aPass.Len())
+- SvPasswordHelper::GetHashPassword(aProtectPass, aPass);
+ if ( aFlagsHdr.BytesLeft() )
+ {
+ rStream >> nEnumDummy;
+@@ -1009,7 +1008,7 @@
+ rStream.WriteByteString(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_STANDARD)),
+ rStream.GetStreamCharSet() );
+- rStream << bProtected; // Dokument geschuetzt
++ rStream << false; // Dokument geschuetzt
+ String aPass;
+ //rStream.WriteByteString( aProtectPass, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aPass, rStream.GetStreamCharSet() );
+Index: sc/source/core/data/documen3.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/documen3.cxx,v
+retrieving revision 1.40
+retrieving revision 1.37.40.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.40 -r1.37.40.4
+--- sc/source/core/data/documen3.cxx 29 Jan 2008 15:17:42 -0000 1.40
++++ sc/source/core/data/documen3.cxx 15 Feb 2008 00:42:28 -0000 1.37.40.4
+@@ -83,6 +83,8 @@
+ #include "listenercalls.hxx"
+ #include "editutil.hxx" // ScPostIt EditTextObject
+ #include "postit.hxx"
++#include "svtools/PasswordHelper.hxx"
++#include "tabprotection.hxx"
+
+ using namespace com::sun::star;
+
+@@ -1690,28 +1692,37 @@
+ ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
+ }
+
+-void ScDocument::SetDocProtection( BOOL bProtect, const uno::Sequence<sal_Int8>& rPasswd )
++ScDocProtection* ScDocument::GetDocProtection() const
+ {
+- bProtected = bProtect;
+- aProtectPass = rPasswd;
++ return pDocProtection.get();
+ }
+
+-void ScDocument::SetTabProtection( SCTAB nTab, BOOL bProtect, const uno::Sequence<sal_Int8>& rPasswd )
++void ScDocument::SetDocProtection(bool bProtect, const String& aPassText)
+ {
+- if (VALIDTAB(nTab))
+- if (pTab[nTab])
+- pTab[nTab]->SetProtection( bProtect, rPasswd );
++ if (!pDocProtection.get())
++ pDocProtection.reset(new ScDocProtection);
++
++ pDocProtection->setProtected(bProtect);
++ pDocProtection->setPassword(aPassText);
++}
++
++void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
++{
++ if (pProtect)
++ pDocProtection.reset(new ScDocProtection(*pProtect));
++ else
++ pDocProtection.reset(NULL);
+ }
+
+ BOOL ScDocument::IsDocProtected() const
+ {
+- return bProtected;
++ return pDocProtection.get() && pDocProtection->isProtected();
+ }
+
+ BOOL ScDocument::IsDocEditable() const
+ {
+ // import into read-only document is possible
+- return !bProtected && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
++ return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
+ }
+
+ BOOL ScDocument::IsTabProtected( SCTAB nTab ) const
+@@ -1724,19 +1735,34 @@
+ return FALSE;
+ }
+
+-const uno::Sequence<sal_Int8>& ScDocument::GetDocPassword() const
++ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
+ {
+- return aProtectPass;
++ if (VALIDTAB(nTab) && pTab[nTab])
++ return pTab[nTab]->GetProtection();
++
++ return NULL;
+ }
+
+-const uno::Sequence<sal_Int8>& ScDocument::GetTabPassword( SCTAB nTab ) const
++void ScDocument::SetTabProtection(SCTAB nTab, bool bProtect, const String& aPassText)
+ {
+- if (VALIDTAB(nTab))
+- if (pTab[nTab])
+- return pTab[nTab]->GetPassword();
++ if (ValidTab(nTab) && pTab[nTab])
++ pTab[nTab]->SetProtection(bProtect, aPassText);
++}
+
+- DBG_ERROR("Falsche Tabellennummer");
+- return aProtectPass;
++void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
++{
++ if (!ValidTab(nTab))
++ return;
++
++ pTab[nTab]->SetProtection(pProtect);
++}
++
++void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
++{
++ if (!ValidTab(nTabSrc) || !ValidTab(nTabDest))
++ return;
++
++ pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() );
+ }
+
+ const ScDocOptions& ScDocument::GetDocOptions() const
+Index: sc/source/core/data/document.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/document.cxx,v
+retrieving revision 1.84
+retrieving revision 1.80.82.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.84 -r1.80.82.2
+--- sc/source/core/data/document.cxx 12 Feb 2008 14:24:19 -0000 1.84
++++ sc/source/core/data/document.cxx 15 Feb 2008 00:42:37 -0000 1.80.82.2
+@@ -99,6 +99,7 @@
+ #include "autonamecache.hxx"
+ #include "bcaslot.hxx"
+ #include "postit.hxx"
++#include "tabprotection.hxx"
+
+ struct ScDefaultAttr
+ {
+Index: sc/source/core/data/makefile.mk
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/makefile.mk,v
+retrieving revision 1.22
+retrieving revision 1.21.166.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.22 -r1.21.166.2
+--- sc/source/core/data/makefile.mk 12 Feb 2008 13:24:18 -0000 1.22
++++ sc/source/core/data/makefile.mk 15 Feb 2008 00:42:20 -0000 1.21.166.2
+@@ -111,6 +111,7 @@
+ $(SLO)$/table4.obj \
+ $(SLO)$/table5.obj \
+ $(SLO)$/table6.obj \
++ $(SLO)$/tabprotection.obj \
+ $(SLO)$/userdat.obj \
+ $(SLO)$/validat.obj \
+ $(SLO)$/postit.obj
+Index: sc/source/core/data/table1.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/table1.cxx,v
+retrieving revision 1.23
+retrieving revision 1.20.166.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.23 -r1.20.166.3
+--- sc/source/core/data/table1.cxx 12 Feb 2008 14:24:59 -0000 1.23
++++ sc/source/core/data/table1.cxx 15 Feb 2008 00:42:32 -0000 1.20.166.3
+@@ -119,6 +119,7 @@
+ #include "progress.hxx"
+ #include "hints.hxx" // fuer Paint-Broadcast
+ #include "prnsave.hxx"
++#include "tabprotection.hxx"
+
+ // STATIC DATA -----------------------------------------------------------
+
+@@ -137,7 +138,7 @@
+ bPageSizeValid( FALSE ),
+ nRepeatStartX( SCCOL_REPEAT_NONE ),
+ nRepeatStartY( SCROW_REPEAT_NONE ),
+- bProtected( FALSE ),
++ pTabProtection( NULL ),
+ pColWidth( NULL ),
+ pRowHeight( NULL ),
+ pColFlags( NULL ),
+Index: sc/source/core/data/table2.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/table2.cxx,v
+retrieving revision 1.39
+retrieving revision 1.37.164.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.39 -r1.37.164.3
+--- sc/source/core/data/table2.cxx 29 Jan 2008 15:20:21 -0000 1.39
++++ sc/source/core/data/table2.cxx 15 Feb 2008 00:42:42 -0000 1.37.164.3
+@@ -303,7 +303,7 @@
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+- if ( bProtected && (nDelFlag & IDF_ATTRIB) )
++ if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
+ {
+ ScPatternAttr aPattern(pDocument->GetPool());
+ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) );
+@@ -329,7 +329,7 @@
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+- if ( bProtected && (nDelFlag & IDF_ATTRIB) )
++ if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
+ {
+ ScDocumentPool* pPool = pDocument->GetPool();
+ SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END );
+@@ -372,7 +372,7 @@
+
+ // ggf. Formeln durch Werte ersetzen
+
+- if (bProtected)
++ if ( IsProtected() )
+ for (i = nCol1; i <= nCol2; i++)
+ pTable->aCol[i].RemoveProtected(nRow1, nRow2);
+ }
+@@ -417,7 +417,7 @@
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+- if ( bProtected && (nInsFlag & IDF_ATTRIB) )
++ if ( IsProtected() && (nInsFlag & IDF_ATTRIB) )
+ {
+ ScPatternAttr aPattern(pDocument->GetPool());
+ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) );
+@@ -1447,7 +1447,7 @@
+ BOOL bIsEditable = TRUE;
+ if ( nLockCount )
+ bIsEditable = FALSE;
+- else if ( bProtected && !pDocument->IsScenario(nTab) )
++ else if ( IsProtected() && !pDocument->IsScenario(nTab) )
+ {
+ if((bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED )) != FALSE)
+ {
+@@ -1514,7 +1514,7 @@
+ BOOL bIsEditable = TRUE;
+ if ( nLockCount )
+ bIsEditable = FALSE;
+- else if ( bProtected && !pDocument->IsScenario(nTab))
++ else if ( IsProtected() && !pDocument->IsScenario(nTab) )
+ {
+ if((bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED )) != FALSE)
+ {
+@@ -2818,11 +2818,16 @@
+ rStream >> bScenario;
+ rStream.ReadByteString( aComment, rStream.GetStreamCharSet() );
+
++ BOOL bProtected;
+ rStream >> bProtected;
+ String aPass;
+ rStream.ReadByteString( aPass, rStream.GetStreamCharSet() );
+ if (aPass.Len())
++ {
++ ::com::sun::star::uno::Sequence<sal_Int8> aProtectPass;
+ SvPasswordHelper::GetHashPassword(aProtectPass, aPass);
++ SetProtection(bProtected, aProtectPass);
++ }
+
+ BOOL bOutline;
+ rStream >> bOutline;
+@@ -3094,6 +3099,7 @@
+ rStream << bScenario;
+ rStream.WriteByteString( aComment, rStream.GetStreamCharSet() );
+
++ BOOL bProtected = IsProtected();
+ rStream << bProtected;
+ String aPass;
+ //rStream.WriteByteString( aProtectPass, rStream.GetStreamCharSet() );
+Index: sc/source/core/data/table5.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/table5.cxx,v
+retrieving revision 1.13
+retrieving revision 1.13.166.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.13 -r1.13.166.2
+--- sc/source/core/data/table5.cxx 27 Feb 2007 12:10:06 -0000 1.13
++++ sc/source/core/data/table5.cxx 3 Jan 2008 16:57:33 -0000 1.13.166.2
+@@ -56,8 +56,11 @@
+ #include "stlpool.hxx"
+ #include "stlsheet.hxx"
+ #include "brdcst.hxx"
++#include "tabprotection.hxx"
+ #include "globstr.hrc"
+
++using ::com::sun::star::uno::Sequence;
++
+ // STATIC DATA -----------------------------------------------------------
+
+ #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
+@@ -278,6 +281,52 @@
+ bPageSizeValid = FALSE;
+ }
+
++BOOL ScTable::IsProtected() const
++{
++ return pTabProtection.get() && pTabProtection->isProtected();
++}
++
++Sequence<sal_Int8> ScTable::GetPassword() const
++{
++ if (!pTabProtection.get())
++ {
++ Sequence<sal_Int8> aEmpty;
++ return aEmpty;
++ }
++ return pTabProtection->getPasswordHash(PASSHASH_OOO);
++}
++
++void ScTable::SetProtection(BOOL bProtect, const com::sun::star::uno::Sequence<sal_Int8>& rPasswd)
++{
++ if (!pTabProtection.get())
++ pTabProtection.reset(new ScTableProtection);
++
++ pTabProtection->setProtected( bProtect );
++ pTabProtection->setPasswordHash(rPasswd, PASSHASH_OOO);
++}
++
++void ScTable::SetProtection(bool bProtect, const String& aPassText)
++{
++ if (!pTabProtection.get())
++ pTabProtection.reset(new ScTableProtection);
++
++ pTabProtection->setProtected( bProtect );
++ pTabProtection->setPassword(aPassText);
++}
++
++void ScTable::SetProtection(const ScTableProtection* pProtect)
++{
++ if (pProtect)
++ pTabProtection.reset(new ScTableProtection(*pProtect));
++ else
++ pTabProtection.reset(NULL);
++}
++
++ScTableProtection* ScTable::GetProtection()
++{
++ return pTabProtection.get();
++}
++
+ Size ScTable::GetPageSize() const
+ {
+ if ( bPageSizeValid )
+Index: sc/source/core/data/tabprotection.cxx
+===================================================================
+RCS file: sc/source/core/data/tabprotection.cxx
+diff -N sc/source/core/data/tabprotection.cxx
+--- /dev/null 1 Jan 1970 00:00:00 -0000
++++ sc/source/core/data/tabprotection.cxx 29 Jan 2008 17:35:16 -0000 1.1.2.5
+@@ -0,0 +1,371 @@
++/*************************************************************************
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: tabprotection.cxx,v $
++ *
++ * $Revision: 1.1.2.5 $
++ *
++ * last change: $Author: kohei $ $Date: 2008/01/29 17:35:16 $
++ *
++ * The Contents of this file are made available subject to
++ * the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ * GNU Lesser General Public License Version 2.1
++ * =============================================
++ * Copyright 2005 by Sun Microsystems, Inc.
++ * 901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License version 2.1, as published by the Free Software Foundation.
++ *
++ * This library 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 for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ ************************************************************************/
++
++#include "tabprotection.hxx"
++#include "tools/debug.hxx"
++#include "svtools/PasswordHelper.hxx"
++
++using namespace ::com::sun::star;
++using ::com::sun::star::uno::Sequence;
++using ::rtl::OUString;
++
++static sal_uInt16 lcl_getXLHashFromChar(const sal_Char* szPassword)
++{
++ sal_uInt16 cchPassword = strlen(szPassword);
++ sal_uInt16 wPasswordHash = 0;
++ if (!cchPassword)
++ return wPasswordHash;
++
++ const char* pch = &szPassword[cchPassword];
++ while (pch-- != szPassword)
++ {
++ wPasswordHash = ((wPasswordHash >> 14) & 0x01) |
++ ((wPasswordHash << 1) & 0x7fff);
++ wPasswordHash ^= *pch;
++ }
++
++ wPasswordHash = ((wPasswordHash >> 14) & 0x01) |
++ ((wPasswordHash << 1) & 0x7fff);
++
++ wPasswordHash ^= (0x8000 | ('N' << 8) | 'K');
++ wPasswordHash ^= cchPassword;
++
++ return wPasswordHash;
++}
++
++static Sequence<sal_Int8> lcl_getXLHash(const String& aPassText)
++{
++ const sal_Char* szBuf = OUStringToOString(OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr();
++ sal_uInt16 nHash = lcl_getXLHashFromChar(szBuf);
++ Sequence<sal_Int8> aHash(2);
++ aHash[0] = (nHash >> 8) & 0xFF;
++ aHash[1] = nHash & 0xFF;
++ return aHash;
++}
++
++class ScTableProtectionImpl
++{
++public:
++ static ::com::sun::star::uno::Sequence<sal_Int8> hashPassword(const String& aPassText, ScPasswordHash eHash = PASSHASH_OOO);
++
++ explicit ScTableProtectionImpl(SCSIZE nOptSize);
++ explicit ScTableProtectionImpl(const ScTableProtectionImpl& r);
++
++ bool isProtected() const;
++ bool isProtectedWithPass() const;
++ void setProtected(bool bProtected);
++
++ void setPassword(const String& aPassText);
++ ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
++ void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash = PASSHASH_OOO);
++ bool verifyPassword(const String& aPassText) const;
++
++ bool isOptionEnabled(SCSIZE nOptId) const;
++ void setOption(SCSIZE nOptId, bool bEnabled);
++
++private:
++ String maPassText;
++ ::com::sun::star::uno::Sequence<sal_Int8> maPassHash;
++ ::std::vector<bool> maOptions;
++ bool mbEmptyPass;
++ bool mbProtected;
++ ScPasswordHash meHash;
++};
++
++Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const String& aPassText, ScPasswordHash eHash)
++{
++ Sequence<sal_Int8> aHash;
++ switch (eHash)
++ {
++ case PASSHASH_XL:
++ aHash = lcl_getXLHash(aPassText);
++ break;
++ case PASSHASH_OOO:
++ default:
++ SvPasswordHelper::GetHashPassword(aHash, aPassText);
++ break;
++ }
++ return aHash;
++}
++
++ScTableProtectionImpl::ScTableProtectionImpl(SCSIZE nOptSize) :
++ maOptions(nOptSize),
++ mbEmptyPass(true),
++ mbProtected(false),
++ meHash(PASSHASH_OOO)
++{
++}
++
++ScTableProtectionImpl::ScTableProtectionImpl(const ScTableProtectionImpl& r) :
++ maPassText(r.maPassText),
++ maPassHash(r.maPassHash),
++ maOptions(r.maOptions),
++ mbEmptyPass(r.mbEmptyPass),
++ mbProtected(r.mbProtected),
++ meHash(r.meHash)
++{
++}
++
++bool ScTableProtectionImpl::isProtected() const
++{
++ return mbProtected;
++}
++
++bool ScTableProtectionImpl::isProtectedWithPass() const
++{
++ if (!mbProtected)
++ return false;
++
++ return maPassText.Len() || maPassHash.getLength();
++}
++
++void ScTableProtectionImpl::setProtected(bool bProtected)
++{
++ mbProtected = bProtected;
++ // We need to keep the old password even when the protection is off. So,
++ // don't erase the password data here.
++}
++
++void ScTableProtectionImpl::setPassword(const String& aPassText)
++{
++ // We can't hash it here because we don't know whether this document will
++ // get saved to Excel or ODF, depending on which we will need to use a
++ // different hashing algorithm. One alternative is to hash it using all
++ // hash algorithms that we support, and store them all.
++
++ maPassText = aPassText;
++ mbEmptyPass = aPassText.Len() == 0;
++ if (mbEmptyPass)
++ {
++ maPassHash = Sequence<sal_Int8>();
++ }
++}
++
++Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(ScPasswordHash eHash) const
++{
++ if (mbEmptyPass)
++ // Flaged as empty.
++ return Sequence<sal_Int8>();
++
++ if (maPassText.Len())
++ // Cleartext password exists. Hash it.
++ return hashPassword(maPassText, eHash);
++
++ if (meHash == eHash)
++ // Stored hash exists.
++ return maPassHash;
++
++ // Failed to find a matching hash.
++ return Sequence<sal_Int8>();
++}
++
++void ScTableProtectionImpl::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
++{
++ fprintf(stdout, "ScTableProtectionImpl::setPasswordHash: --begin\n");fflush(stdout);
++ sal_Int32 nLen = aPassword.getLength();
++ mbEmptyPass = nLen <= 0 ? true : false;
++ meHash = eHash;
++ maPassHash = aPassword;
++
++ for (sal_Int32 i = 0; i < nLen; ++i)
++ printf("%2.2X ", static_cast<sal_uInt8>(aPassword[i]));
++ printf("\n");
++}
++
++bool ScTableProtectionImpl::verifyPassword(const String& aPassText) const
++{
++ fprintf(stdout, "ScTableProtectionImpl::verifyPassword: input = '%s'\n",
++ OUStringToOString(rtl::OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr());fflush(stdout);
++ if (mbEmptyPass)
++ return aPassText.Len() == 0;
++
++ if (maPassText.Len())
++ // Clear text password exists, and this one takes precedence.
++ return aPassText.Equals(maPassText);
++
++ Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash);
++ for (sal_Int32 i = 0; i < aHash.getLength(); ++i)
++ printf("%2.2X ", static_cast<sal_uInt8>(aHash[i]));
++ printf("\n");
++ return aHash == maPassHash;
++}
++
++bool ScTableProtectionImpl::isOptionEnabled(SCSIZE nOptId) const
++{
++ if ( maOptions.size() <= static_cast<size_t>(nOptId) )
++ {
++ DBG_ERROR("ScTableProtectionImpl::isOptionEnabled: wrong size");
++ return false;
++ }
++
++ return maOptions[nOptId];
++}
++
++void ScTableProtectionImpl::setOption(SCSIZE nOptId, bool bEnabled)
++{
++ if ( maOptions.size() <= static_cast<size_t>(nOptId) )
++ {
++ DBG_ERROR("ScTableProtectionImpl::setOption: wrong size");
++ return;
++ }
++
++ maOptions[nOptId] = bEnabled;
++}
++
++// ============================================================================
++
++ScDocProtection::ScDocProtection() :
++ mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScDocProtection::NONE)))
++{
++}
++
++ScDocProtection::ScDocProtection(const ScDocProtection& r) :
++ mpImpl(new ScTableProtectionImpl(*r.mpImpl.get()))
++{
++}
++
++ScDocProtection::~ScDocProtection()
++{
++}
++
++bool ScDocProtection::isProtected() const
++{
++ return mpImpl->isProtected();
++}
++
++bool ScDocProtection::isProtectedWithPass() const
++{
++ return mpImpl->isProtectedWithPass();
++}
++
++void ScDocProtection::setProtected(bool bProtected)
++{
++ mpImpl->setProtected(bProtected);
++}
++
++void ScDocProtection::setPassword(const String& aPassText)
++{
++ mpImpl->setPassword(aPassText);
++}
++
++uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash) const
++{
++ return mpImpl->getPasswordHash(eHash);
++}
++
++void ScDocProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
++{
++ mpImpl->setPasswordHash(aPassword, eHash);
++}
++
++bool ScDocProtection::verifyPassword(const String& aPassText) const
++{
++ return mpImpl->verifyPassword(aPassText);
++}
++
++bool ScDocProtection::isOptionEnabled(Option eOption) const
++{
++ return mpImpl->isOptionEnabled(eOption);
++}
++
++void ScDocProtection::setOption(Option eOption, bool bEnabled)
++{
++ mpImpl->setOption(eOption, bEnabled);
++}
++
++// ============================================================================
++
++ScTableProtection::ScTableProtection() :
++ mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScTableProtection::NONE)))
++{
++ // Set default values for the options.
++ mpImpl->setOption(SELECT_LOCKED_CELLS, true);
++ mpImpl->setOption(SELECT_UNLOCKED_CELLS, true);
++}
++
++ScTableProtection::ScTableProtection(const ScTableProtection& r) :
++ mpImpl(new ScTableProtectionImpl(*r.mpImpl.get()))
++{
++}
++
++ScTableProtection::~ScTableProtection()
++{
++}
++
++bool ScTableProtection::isProtected() const
++{
++ return mpImpl->isProtected();
++}
++
++bool ScTableProtection::isProtectedWithPass() const
++{
++ return mpImpl->isProtectedWithPass();
++}
++
++void ScTableProtection::setProtected(bool bProtected)
++{
++ mpImpl->setProtected(bProtected);
++}
++
++void ScTableProtection::setPassword(const String& aPassText)
++{
++ mpImpl->setPassword(aPassText);
++}
++
++Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash) const
++{
++ return mpImpl->getPasswordHash(eHash);
++}
++
++void ScTableProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
++{
++ mpImpl->setPasswordHash(aPassword, eHash);
++}
++
++bool ScTableProtection::verifyPassword(const String& aPassText) const
++{
++ return mpImpl->verifyPassword(aPassText);
++}
++
++bool ScTableProtection::isOptionEnabled(Option eOption) const
++{
++ return mpImpl->isOptionEnabled(eOption);
++}
++
++void ScTableProtection::setOption(Option eOption, bool bEnabled)
++{
++ mpImpl->setOption(eOption, bEnabled);
++}
++
+Index: sc/source/filter/excel/excdoc.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/excdoc.cxx,v
+retrieving revision 1.67
+retrieving revision 1.67.124.10
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.67 -r1.67.124.10
+--- sc/source/filter/excel/excdoc.cxx 22 May 2007 19:44:28 -0000 1.67
++++ sc/source/filter/excel/excdoc.cxx 19 Jan 2008 04:52:42 -0000 1.67.124.10
+@@ -35,7 +35,7 @@
+
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+-
++#include <stdio.h>
+
+ //------------------------------------------------------------------------
+
+@@ -78,7 +78,6 @@
+ #include "excdoc.hxx"
+ #include "namebuff.hxx"
+
+-#include "xcl97dum.hxx"
+ #include "xcl97rec.hxx"
+ #include "xcl97esc.hxx"
+
+@@ -111,6 +110,8 @@
+ #include "XclExpChangeTrack.hxx"
+ #endif
+
++#include "tabprotection.hxx"
++
+
+ static String lcl_GetVbaTabName( SCTAB n )
+ {
+@@ -176,7 +177,24 @@
+ Add( new ExcDummy_00 );
+ else
+ {
+- Add( new ExcDummy8_00a );
++ if ( IsPasswordProtected() )
++ {
++ // TODO: Using the new encrypter class, I need to generate these
++ // three values from the password. Right now, the user supplied
++ // password is ignored and the default pass 'VelvetSweatShop' is
++ // used.
++
++ Add( new XclExpFilePass(GetRoot()) ); // 002F
++
++ }
++
++ Add( new XclExpInterfaceHdr );
++ Add( new XclExpMMS );
++ Add( new XclExpInterfaceEnd );
++ Add( new XclExpWriteAccess );
++ Add( new XclExpCodePage );
++ Add( new XclExpDSF );
++ Add( new XclExpUnknown01C0 );
+ rR.pTabId = new XclExpChTrTabId( Max( nExcTabCount, nCodenames ) );
+ Add( rR.pTabId );
+ if( HasVbaStorage() )
+@@ -186,7 +204,8 @@
+ if( rCodeName.Len() )
+ Add( new XclCodename( rCodeName ) );
+ }
+- Add( new ExcDummy8_00b );
++
++ Add( new XclExpFnGroupCount );
+ }
+
+ // erst Namen- und Tabellen-Eintraege aufbauen
+@@ -206,15 +225,29 @@
+ aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
+ }
+
+- aRecList.AppendNewRecord( new XclExpWindowProtection( GetExtDocOptions().GetDocSettings().mbWinProtected ) );
+- aRecList.AppendNewRecord( new XclExpDocProtection( rDoc.IsDocProtected() ) );
+- aRecList.AppendNewRecord( new XclExpBoolRecord( EXC_ID_PASSWORD, false ) );
++ // document protection options
++ const ScDocProtection* pProtect = GetDoc().GetDocProtection();
++ if (pProtect && pProtect->isProtected())
++ {
++ Add( new XclExpWindowProtection(pProtect->isOptionEnabled(ScDocProtection::WINDOWS)) );
++ Add( new XclExpProtection(pProtect->isOptionEnabled(ScDocProtection::STRUCTURE)) );
++ Add( new XclExpPassHash(pProtect->getPasswordHash(PASSHASH_XL)) );
++ }
+
+ if( GetBiff() == EXC_BIFF8 )
+- Add( new ExcDummy8_040 );
++ {
++ Add( new XclExpProt4Rev );
++ Add( new XclExpProt4RevPass );
++ }
+
+ aRecList.AppendNewRecord( new XclExpWindow1( GetRoot() ) );
+
++ if ( GetBiff() == EXC_BIFF8 )
++ {
++ Add( new XclExpBoolRecord(0x0040, false) ); // BACKUP
++ Add( new XclExpBoolRecord(0x008D, false) ); // HIDEOBJ
++ }
++
+ if( GetBiff() <= EXC_BIFF5 )
+ {
+ Add( new ExcDummy_040 );
+@@ -223,9 +256,11 @@
+ }
+ else
+ {
++ // BIFF8
+ Add( new Exc1904( rDoc ) );
+ Add( new XclExpBoolRecord( 0x000E, !rDoc.GetDocOptions().IsCalcAsShown() ) );
+- Add( new ExcDummy8_041 );
++ Add( new XclExpBoolRecord(0x01B7, false) ); // REFRESHALL
++ Add( new XclExpBoolRecord(0x00DA, false) ); // BOOKBOOL
+ }
+
+ // Formatting: FONT, FORMAT, XF, STYLE, PALETTE
+@@ -284,10 +319,14 @@
+ aRecList.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET ) );
+ aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
+
++ Add( new XclExpUnknown01C1 );
++
+ // MSODRAWINGGROUP per-document data
+ Add( new XclMsodrawinggroup( rR, ESCHER_DggContainer ) );
+ // Shared string table: SST, EXTSST
+ aRecList.AppendRecord( CreateRecord( EXC_ID_SST ) );
++
++ Add( new XclExpUnknown0863 );
+ }
+
+ Add( new ExcEof );
+@@ -329,7 +368,7 @@
+ Add( new XclRefmode( rDoc ) );
+ Add( new XclIteration( rDoc ) );
+ Add( new XclDelta( rDoc ) );
+- Add( new ExcDummy8_02 );
++ Add( new XclExpBoolRecord(0x005F, true) ); // SAVERECALC
+ }
+
+ // GUTS (count & size of outline icons)
+@@ -346,8 +385,14 @@
+ // page settings (SETUP and various other records)
+ aRecList.AppendRecord( xPageSett );
+
+- if( rDoc.IsTabProtected( mnScTab ) )
+- Add( new XclProtection() );
++ const ScTableProtection* pTabProtect = rDoc.GetTabProtection(mnScTab);
++ if (pTabProtect && pTabProtect->isProtected())
++ {
++ Add( new XclExpProtection(true) );
++ Add( new XclExpBoolRecord(0x00DD, pTabProtect->isOptionEnabled(ScTableProtection::SCENARIOS)) );
++ Add( new XclExpBoolRecord(0x0063, pTabProtect->isOptionEnabled(ScTableProtection::OBJECTS)) );
++ Add( new XclExpPassHash(pTabProtect->getPasswordHash(PASSHASH_XL)) );
++ }
+
+ // local link table: EXTERNCOUNT, EXTERNSHEET
+ if( eBiff <= EXC_BIFF5 )
+@@ -393,6 +438,9 @@
+
+ if( eBiff == EXC_BIFF8 )
+ {
++ // sheet protection options
++ Add( new XclExpSheetProtectOptions( GetRoot(), mnScTab ) );
++
+ // web queries
+ Add( new XclExpWebQueryBuffer( GetRoot() ) );
+
+Index: sc/source/filter/excel/excimp8.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/excimp8.cxx,v
+retrieving revision 1.123
+retrieving revision 1.120.64.7
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.123 -r1.120.64.7
+--- sc/source/filter/excel/excimp8.cxx 26 Feb 2008 14:52:34 -0000 1.123
++++ sc/source/filter/excel/excimp8.cxx 6 Mar 2008 15:00:35 -0000 1.120.64.7
+@@ -199,12 +199,6 @@
+ }
+
+
+-void ImportExcel8:: WinProtection( void )
+-{
+- if( aIn.ReaduInt16() != 0 )
+- GetExtDocOptions().GetDocSettings().mbWinProtected = true;
+-}
+-
+ void ImportExcel8::Note( void )
+ {
+ GetObjectManager().ReadNote( maStrm );
+@@ -220,6 +214,8 @@
+ aIn >> nGrbit >> nLen;
+
+ String aName( aIn.ReadUniString( nLen ) );
++ fprintf(stdout, "ImportExcel8::Boundsheet: name = '%s'\n",
++ OUStringToOString(rtl::OUString(aName), RTL_TEXTENCODING_UTF8).getStr());fflush(stdout);
+ GetTabInfo().AppendXclTabName( aName, nBdshtTab );
+
+ ScfTools::ConvertToScSheetName( aName );
+@@ -295,6 +291,11 @@
+ }
+ }
+
++void ImportExcel8::SheetProtection( void )
++{
++ GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
++}
++
+ bool lcl_hasVBAEnabled()
+ {
+ uno::Reference< beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY);
+@@ -339,6 +340,8 @@
+ pExcRoot->pAutoFilterBuffer->Apply();
+
+ GetWebQueryBuffer().Apply(); //! test if extant
++ GetSheetProtectBuffer().Apply();
++ GetDocProtectBuffer().Apply();
+
+ ImportExcel::PostDocLoad();
+
+Index: sc/source/filter/excel/excrecds.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/excrecds.cxx,v
+retrieving revision 1.87
+retrieving revision 1.87.126.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.87 -r1.87.126.3
+--- sc/source/filter/excel/excrecds.cxx 22 May 2007 19:45:31 -0000 1.87
++++ sc/source/filter/excel/excrecds.cxx 18 Jan 2008 17:07:08 -0000 1.87.126.3
+@@ -117,7 +117,7 @@
+
+ #include "xcl97rec.hxx"
+
+-
++using ::com::sun::star::uno::Sequence;
+
+ //--------------------------------------------------------- class ExcDummy_00 -
+ const BYTE ExcDummy_00::pMyData[] = {
+@@ -437,7 +437,9 @@
+ void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
+ {
+ rStrm.SetSvStreamPos( nOwnPos );
++ rStrm.DisableEncryption();
+ rStrm << static_cast<sal_uInt32>(nStrPos);
++ rStrm.EnableEncryption();
+ }
+
+
+@@ -513,15 +515,32 @@
+ // XclExpWindowProtection ===============================================================
+
+ XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
+- XclExpBoolRecord(EXC_ID_WINDOWPROTECT,bValue)
++ XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
+ {
+ }
+
+ // XclExpDocProtection ===============================================================
+
+-XclExpDocProtection::XclExpDocProtection(bool bValue) :
+- XclExpBoolRecord(EXC_ID_PROTECT,bValue)
++XclExpProtection::XclExpProtection(bool bValue) :
++ XclExpBoolRecord(EXC_ID_PROTECT, bValue)
++{
++}
++
++// ============================================================================
++
++XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) :
++ XclExpRecord(EXC_ID_PASSWORD, 2),
++ mnHash(aHash.getLength() >= 2 ? ((aHash[0] << 8) | aHash[1]) : 0x0000)
++{
++}
++
++XclExpPassHash::~XclExpPassHash()
++{
++}
++
++void XclExpPassHash::WriteBody(XclExpStream& rStrm)
+ {
++ rStrm << mnHash;
+ }
+
+ // ============================================================================
+Index: sc/source/filter/excel/impop.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/impop.cxx,v
+retrieving revision 1.91
+retrieving revision 1.90.22.5
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.91 -r1.90.22.5
+--- sc/source/filter/excel/impop.cxx 29 Jan 2008 15:24:30 -0000 1.91
++++ sc/source/filter/excel/impop.cxx 15 Feb 2008 00:43:08 -0000 1.90.22.5
+@@ -95,6 +95,7 @@
+ #include "xiview.hxx"
+ #include "xilink.hxx"
+ #include "xiescher.hxx"
++#include "xicontent.hxx"
+
+ #include "excimp8.hxx"
+ #include "excform.hxx"
+@@ -423,14 +424,9 @@
+ }
+
+
+-BOOL ImportExcel::Password( void )
++void ImportExcel::SheetPassword( void )
+ {
+- // POST: return = TRUE, wenn Password <> 0
+- UINT16 nPasswd;
+-
+- aIn >> nPasswd;
+-
+- return nPasswd != 0x0000;
++ GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() );
+ }
+
+
+@@ -445,6 +441,12 @@
+ }
+
+
++void ImportExcel:: WinProtection( void )
++{
++ GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn );
++}
++
++
+ void ImportExcel::Note( void )
+ {
+ XclAddress aXclPos;
+@@ -590,27 +592,24 @@
+ }
+
+
+-void ImportExcel::Protect( void )
++void ImportExcel::SheetProtect( void )
+ {
+- if( aIn.ReaduInt16() )
+- {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- GetDoc().SetTabProtection( GetCurrScTab(), TRUE, aEmptyPass );
+- }
++ GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() );
+ }
+
+ void ImportExcel::DocProtect( void )
+ {
+- if( aIn.ReaduInt16() )
+- {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- GetDoc().SetDocProtection( TRUE, aEmptyPass );
+- }
++ GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn );
+ }
+
++void ImportExcel::DocPasssword( void )
++{
++ GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn );
++}
+
+ void ImportExcel::Codepage( void )
+ {
++ maStrm.EnableDecryption();
+ SetCodePage( maStrm.ReaduInt16() );
+ }
+
+Index: sc/source/filter/excel/read.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/read.cxx,v
+retrieving revision 1.69
+retrieving revision 1.68.72.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.69 -r1.68.72.4
+--- sc/source/filter/excel/read.cxx 29 Jan 2008 15:25:03 -0000 1.69
++++ sc/source/filter/excel/read.cxx 15 Feb 2008 00:43:01 -0000 1.68.72.4
+@@ -396,7 +396,7 @@
+ Eof();
+ eAkt = Z_Ende;
+ break;
+- case 0x12: Protect(); break; // SHEET PROTECTION
++ case 0x12: SheetProtect(); break; // SHEET PROTECTION
+ case 0x14:
+ case 0x15: rPageSett.ReadHeaderFooter( maStrm ); break;
+ case 0x17: Externsheet(); break; // EXTERNSHEET [ 2345]
+@@ -510,7 +510,7 @@
+ Eof();
+ eAkt = Z_Biff4E;
+ break;
+- case 0x12: Protect(); break; // SHEET PROTECTION
++ case 0x12: SheetProtect(); break; // SHEET PROTECTION
+ case 0x14:
+ case 0x15: rPageSett.ReadHeaderFooter( maStrm ); break;
+ case 0x1A:
+@@ -636,7 +636,7 @@
+ eAkt = Z_Biff5T;
+ aIn.SeekGlobalPosition(); // und zurueck an alte Position
+ break;
+- case 0x12: Protect(); break; // SHEET PROTECTION
++ case 0x12: SheetProtect(); break; // SHEET PROTECTION
+ case 0x1A:
+ case 0x1B: rPageSett.ReadPageBreaks( maStrm ); break;
+ case 0x1D: rTabViewSett.ReadSelection( maStrm ); break;
+@@ -935,6 +935,7 @@
+ }
+ break;
+ case 0x12: DocProtect(); break; // PROTECT [ 5678]
++ case 0x13: DocPasssword(); break;
+ case 0x19: WinProtection(); break;
+ case 0x2F: // FILEPASS [ 2345 ]
+ eLastErr = XclImpDecryptHelper::ReadFilepass( maStrm );
+@@ -1079,7 +1080,8 @@
+ eAkt = EXC_STATE_SHEET;
+ aIn.SeekGlobalPosition(); // und zurueck an alte Position
+ break;
+- case 0x12: Protect(); break;
++ case 0x12: SheetProtect(); break;
++ case 0x13: SheetPassword(); break;
+ case 0x42: Codepage(); break; // CODEPAGE [ 2345 ]
+ case 0x55: DefColWidth(); break;
+ case 0x7D: Colinfo(); break; // COLINFO [ 345 ]
+@@ -1095,6 +1097,7 @@
+ case 0x0221: Array34(); break; // ARRAY [ 34 ]
+ case 0x0225: Defrowheight345();break;//DEFAULTROWHEI[ 345 ]
+ case 0x04BC: Shrfmla(); break; // SHRFMLA [ 5 ]
++ case 0x0867: SheetProtection(); break; // SHEETPROTECTION
+ }
+ }
+ break;
+Index: sc/source/filter/excel/xecontent.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xecontent.cxx,v
+retrieving revision 1.22
+retrieving revision 1.21.126.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.22 -r1.21.126.3
+--- sc/source/filter/excel/xecontent.cxx 29 Jan 2008 15:25:29 -0000 1.22
++++ sc/source/filter/excel/xecontent.cxx 15 Feb 2008 00:43:15 -0000 1.21.126.3
+@@ -299,9 +299,7 @@
+ rStrm.EndRecord();
+
+ // *** write the EXTSST record ***
+-
+ rStrm.StartRecord( EXC_ID_EXTSST, 0 );
+-
+ rStrm << nPerBucket;
+ rStrm.SetSliceSize( 8 ); // size of one bucket info
+ aExtSst.Seek( STREAM_SEEK_TO_BEGIN );
+Index: sc/source/filter/excel/xerecord.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xerecord.cxx,v
+retrieving revision 1.9
+retrieving revision 1.9.126.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.9 -r1.9.126.2
+Index: sc/source/filter/excel/xeroot.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xeroot.cxx,v
+retrieving revision 1.22
+retrieving revision 1.22.54.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.22 -r1.22.54.2
+--- sc/source/filter/excel/xeroot.cxx 23 Oct 2007 14:44:34 -0000 1.22
++++ sc/source/filter/excel/xeroot.cxx 14 Mar 2008 21:47:05 -0000 1.22.54.2
+@@ -40,13 +40,16 @@
+ #include "xeroot.hxx"
+ #endif
+
+-#ifndef _SFXDOCFILE_HXX
+ #include <sfx2/docfile.hxx>
+-#endif
++#include <sfx2/sfxsids.hrc>
++
+ #ifndef INCLUDED_SVTOOLS_SAVEOPT_HXX
+ #include <svtools/saveopt.hxx>
+ #endif
+
++#include <svtools/itemset.hxx>
++#include <svtools/stritem.hxx>
++
+ #ifndef SC_XLTRACER_HXX
+ #include "xltracer.hxx"
+ #endif
+@@ -251,6 +254,35 @@
+ return xRec;
+ }
+
++bool XclExpRoot::IsPasswordProtected() const
++{
++ String aPass = GetPassword();
++ return aPass.Len() > 0;
++}
++
++const String XclExpRoot::GetPassword() const
++{
++ do
++ {
++ SfxItemSet* pSet = GetMedium().GetItemSet();
++ if (!pSet)
++ break;
++
++ const SfxPoolItem* pItem = NULL;
++ if (SFX_ITEM_SET != pSet->GetItemState(SID_PASSWORD, sal_True, &pItem))
++ break;
++
++ const SfxStringItem* pStrItem = dynamic_cast<const SfxStringItem*>(pItem);
++ if (!pStrItem)
++ break;
++
++ return pStrItem->GetValue();
++ }
++ while (false);
++
++ return String();
++}
++
+ XclExpRootData::XclExpLinkMgrRef XclExpRoot::GetLocalLinkMgrRef() const
+ {
+ return IsInGlobals() ? mrExpData.mxGlobLinkMgr : mrExpData.mxLocLinkMgr;
+Index: sc/source/filter/excel/xestream.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xestream.cxx,v
+retrieving revision 1.10
+retrieving revision 1.10.166.8
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.10 -r1.10.166.8
+--- sc/source/filter/excel/xestream.cxx 27 Feb 2007 12:25:23 -0000 1.10
++++ sc/source/filter/excel/xestream.cxx 30 Jan 2008 16:47:01 -0000 1.10.166.8
+@@ -47,6 +47,7 @@
+ #include "xeroot.hxx"
+ #endif
+
++using ::std::vector;
+
+ // ============================================================================
+
+@@ -76,16 +77,19 @@
+ void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_Size nRecSize )
+ {
+ DBG_ASSERT( !mbInRec, "XclExpStream::StartRecord - another record still open" );
++ DisableEncryption();
+ mnMaxContSize = mnCurrMaxSize = mnMaxRecSize;
+ mnPredictSize = nRecSize;
+ mbInRec = true;
+ InitRecord( nRecId );
+ SetSliceSize( 0 );
++ EnableEncryption();
+ }
+
+ void XclExpStream::EndRecord()
+ {
+ DBG_ASSERT( mbInRec, "XclExpStream::EndRecord - no record open" );
++ DisableEncryption();
+ UpdateRecSize();
+ mrStrm.Seek( STREAM_SEEK_TO_END );
+ mbInRec = false;
+@@ -97,6 +101,86 @@
+ mnSliceSize = 0;
+ }
+
++XclExpStream& XclExpStream::operator<<( sal_Int8 nValue )
++{
++ PrepareWrite( 1 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue )
++{
++ PrepareWrite( 1 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_Int16 nValue )
++{
++ PrepareWrite( 2 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue )
++{
++ PrepareWrite( 2 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_Int32 nValue )
++{
++ PrepareWrite( 4 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue )
++{
++ PrepareWrite( 4 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( float fValue )
++{
++ PrepareWrite( 4 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, fValue);
++ else
++ mrStrm << fValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( double fValue )
++{
++ PrepareWrite( 8 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, fValue);
++ else
++ mrStrm << fValue;
++ return *this;
++}
++
+ sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes )
+ {
+ sal_Size nRet = 0;
+@@ -111,9 +195,21 @@
+ while( bValid && (nBytesLeft > 0) )
+ {
+ sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
+- sal_Size nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
++ sal_Size nWriteRet = nWriteLen;
++ if (mbUseEncrypter && HasValidEncrypter())
++ {
++ DBG_ASSERT(nWriteLen > 0, "XclExpStream::Write: write length is 0!");
++ vector<sal_uInt8> aBytes(nWriteLen);
++ memcpy(&aBytes[0], pBuffer, nWriteLen);
++ mxEncrypter->EncryptBytes(mrStrm, aBytes);
++ // TODO: How do I check if all the bytes have been successfully written ?
++ }
++ else
++ {
++ nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
+ bValid = (nWriteLen == nWriteRet);
+ DBG_ASSERT( bValid, "XclExpStream::Write - stream write error" );
++ }
+ pBuffer += nWriteRet;
+ nRet += nWriteRet;
+ nBytesLeft -= nWriteRet;
+@@ -249,6 +345,26 @@
+ Write( &rBuffer[ 0 ], rBuffer.size() );
+ }
+
++void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter )
++{
++ mxEncrypter = xEncrypter;
++}
++
++bool XclExpStream::HasValidEncrypter() const
++{
++ return mxEncrypter.is() && mxEncrypter->IsValid();
++}
++
++void XclExpStream::EnableEncryption( bool bEnable )
++{
++ mbUseEncrypter = bEnable && HasValidEncrypter();
++}
++
++void XclExpStream::DisableEncryption()
++{
++ EnableEncryption(false);
++}
++
+ sal_Size XclExpStream::SetSvStreamPos( sal_Size nPos )
+ {
+ DBG_ASSERT( !mbInRec, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
+@@ -340,3 +456,168 @@
+
+ // ============================================================================
+
++XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot& rRoot, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16], const sal_uInt8 nSaltHash[16] ) :
++ mrRoot(rRoot),
++ mnOldPos(STREAM_SEEK_TO_END),
++ mbValid(false)
++{
++ fprintf(stdout, "XclExpBiff8Encrypter::XclExpBiff8Encrypter: real password is '%s', but I'm using the default password for now.\n",
++ OUStringToOString(rtl::OUString(mrRoot.GetPassword()), RTL_TEXTENCODING_UTF8).getStr());fflush(stdout);
++ Init(String::CreateFromAscii("VelvetSweatshop"), nDocId, nSalt, nSaltHash);
++}
++
++XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
++{
++}
++
++bool XclExpBiff8Encrypter::IsValid() const
++{
++ return mbValid;
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt8 nData )
++{
++ vector<sal_uInt8> aByte(1);
++ aByte[0] = nData;
++ EncryptBytes(rStrm, aByte);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt16 nData )
++{
++ ::std::vector<sal_uInt8> pnBytes(2);
++ pnBytes[0] = nData & 0xFF;
++ pnBytes[1] = (nData >> 8) & 0xFF;
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt32 nData )
++{
++ ::std::vector<sal_uInt8> pnBytes(4);
++ pnBytes[0] = nData & 0xFF;
++ pnBytes[1] = (nData >> 8) & 0xFF;
++ pnBytes[2] = (nData >> 16) & 0xFF;
++ pnBytes[3] = (nData >> 24) & 0xFF;
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, float fValue )
++{
++ ::std::vector<sal_uInt8> pnBytes(4);
++ memcpy(&pnBytes[0], &fValue, 4);
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, double fValue )
++{
++ ::std::vector<sal_uInt8> pnBytes(8);
++ memcpy(&pnBytes[0], &fValue, 8);
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int8 nData )
++{
++ Encrypt(rStrm, static_cast<sal_uInt8>(nData));
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int16 nData )
++{
++ Encrypt(rStrm, static_cast<sal_uInt16>(nData));
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int32 nData )
++{
++ Encrypt(rStrm, static_cast<sal_uInt32>(nData));
++}
++
++void XclExpBiff8Encrypter::Init( const String& aPass, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16], const sal_uInt8 nSaltHash[16] )
++{
++ xub_StrLen nLen = aPass.Len();
++ bool bValid = (0 < nLen) && (nLen < 16);
++ if ( bValid )
++ {
++ // transform String to sal_uInt16 array
++ memset(mnPassw, 0, sizeof(mnPassw));
++ for (xub_StrLen nChar = 0; nChar < nLen; ++nChar)
++ mnPassw[nChar] = static_cast<sal_uInt16>(aPass.GetChar(nChar));
++
++ // copy document ID
++ memcpy(mnDocId, nDocId, sizeof(mnDocId));
++
++ // init codec
++ maCodec.InitKey(mnPassw, mnDocId);
++ bValid = maCodec.VerifyKey(nSalt, nSaltHash);
++ }
++
++ fprintf(stdout, "XclExpBiff8Encrypter::Init: is valid? (%s)\n", bValid?"yes":"no");fflush(stdout);
++ mbValid = bValid;
++}
++
++sal_uInt32 XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos ) const
++{
++ return static_cast<sal_uInt32>(nStrmPos / EXC_ENCR_BLOCKSIZE);
++}
++
++sal_uInt16 XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos ) const
++{
++ return static_cast<sal_uInt16>(nStrmPos % EXC_ENCR_BLOCKSIZE);
++}
++
++void XclExpBiff8Encrypter::EncryptBytes( SvStream& rStrm, vector<sal_uInt8>& aBytes )
++{
++ sal_Size nStrmPos = rStrm.Tell();
++ sal_uInt16 nBlockOffset = GetOffsetInBlock(nStrmPos);
++ sal_uInt16 nBlockPos = GetBlockPos(nStrmPos);
++
++ fprintf(stdout, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n",
++ nStrmPos, nBlockOffset, nBlockPos);
++
++ sal_uInt16 nSize = aBytes.size();
++ if (nSize == 0)
++ return;
++
++ fprintf(stdout, "RAW: ");
++ for (sal_uInt16 i = 0; i < nSize; ++i)
++ fprintf(stdout, "%2.2X ", aBytes[i]);
++ fprintf(stdout, "\n");
++
++ if (mnOldPos != nStrmPos)
++ {
++ sal_uInt16 nOldOffset = GetOffsetInBlock(mnOldPos);
++ sal_uInt16 nOldBlockPos = GetBlockPos(mnOldPos);
++
++ if ( (nBlockPos != nOldBlockPos) || (nBlockOffset < nOldOffset) )
++ {
++ maCodec.InitCipher(nBlockPos);
++ nOldOffset = 0;
++ }
++
++ if (nBlockOffset > nOldOffset)
++ maCodec.Skip(nBlockOffset - nOldOffset);
++ }
++
++ sal_uInt16 nBytesLeft = nSize;
++ sal_uInt16 nPos = 0;
++ while (nBytesLeft > 0)
++ {
++ sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - nBlockOffset;
++ sal_uInt16 nEncBytes = ::std::min(nBlockLeft, nBytesLeft);
++
++ bool bRet = maCodec.Encode(&aBytes[nPos], nEncBytes, &aBytes[nPos], nEncBytes);
++ DBG_ASSERT(bRet, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
++
++ sal_Size nRet = rStrm.Write(&aBytes[nPos], nEncBytes);
++ DBG_ASSERT(nRet == nEncBytes, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
++
++ nStrmPos = rStrm.Tell();
++ nBlockOffset = GetOffsetInBlock(nStrmPos);
++ nBlockPos = GetBlockPos(nStrmPos);
++ if (nBlockOffset == 0)
++ maCodec.InitCipher(nBlockPos);
++
++ nBytesLeft -= nEncBytes;
++ nPos += nEncBytes;
++ }
++ mnOldPos = nStrmPos;
++}
+Index: sc/source/filter/excel/xestyle.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xestyle.cxx,v
+retrieving revision 1.32
+retrieving revision 1.30.62.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.32 -r1.30.62.3
+Index: sc/source/filter/excel/xetable.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xetable.cxx,v
+retrieving revision 1.17
+retrieving revision 1.16.126.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.17 -r1.16.126.4
+--- sc/source/filter/excel/xetable.cxx 29 Jan 2008 15:26:29 -0000 1.17
++++ sc/source/filter/excel/xetable.cxx 15 Feb 2008 00:43:24 -0000 1.16.126.4
+@@ -2245,5 +2245,3 @@
+ maRowBfr.Save( rStrm );
+ }
+
+-// ============================================================================
+-
+Index: sc/source/filter/excel/xicontent.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xicontent.cxx,v
+retrieving revision 1.30
+retrieving revision 1.29.42.9
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.30 -r1.29.42.9
+--- sc/source/filter/excel/xicontent.cxx 29 Jan 2008 15:26:57 -0000 1.30
++++ sc/source/filter/excel/xicontent.cxx 15 Feb 2008 00:43:11 -0000 1.29.42.9
+@@ -147,6 +147,13 @@
+ #endif
+
+ #include "excform.hxx"
++#include "tabprotection.hxx"
++
++#include <memory>
++#include <stdio.h>
++
++using ::com::sun::star::uno::Sequence;
++using ::std::auto_ptr;
+
+ // Shared string table ========================================================
+
+@@ -160,12 +167,21 @@
+ sal_uInt32 nStrCount;
+ rStrm.Ignore( 4 );
+ rStrm >> nStrCount;
++ fprintf(stdout, "XclImpSst::ReadSst: string count = %ld\n", nStrCount);fflush(stdout);
+ maStrings.clear();
++ // TODO: temporarily disable further processing when the string count is too large.
++ if (nStrCount > 1000000)
++ {
++ fprintf(stdout, "XclImpSst::ReadSst: TODO: disabled!!!\n");fflush(stdout);
++ return;
++ }
+ maStrings.reserve( static_cast< size_t >( nStrCount ) );
+ while( (nStrCount > 0) && rStrm.IsValid() )
+ {
+ XclImpString aString;
+ aString.Read( rStrm );
++ fprintf(stdout, "XclImpSst::ReadSst: text = '%s'\n",
++ OUStringToOString(rtl::OUString(aString.GetText()), RTL_TEXTENCODING_UTF8).getStr());fflush(stdout);
+ maStrings.push_back( aString );
+ --nStrCount;
+ }
+@@ -1082,8 +1098,20 @@
+ sal_uInt8 pnSaltData[ 16 ];
+ sal_uInt8 pnSaltHash[ 16 ];
+ rStrm.Read( pnDocId, 16 );
++ printf("doc ID:\n");
++ for (int i = 0; i < 16; ++i)
++ printf("%2.2x ", pnDocId[i]);
++ printf("\n");
+ rStrm.Read( pnSaltData, 16 );
++ printf("salt:\n");
++ for (int i = 0; i < 16; ++i)
++ printf("%2.2x ", pnSaltData[i]);
++ printf("\n");
+ rStrm.Read( pnSaltHash, 16 );
++ printf("salt hash:\n");
++ for (int i = 0; i < 16; ++i)
++ printf("%2.2x ", pnSaltHash[i]);
++ printf("\n");
+ xDecr.reset( new XclImpBiff8Decrypter(
+ rStrm.GetRoot(), pnDocId, pnSaltData, pnSaltHash ) );
+ }
+@@ -1140,6 +1168,7 @@
+
+ ErrCode XclImpDecryptHelper::ReadFilepass( XclImpStream& rStrm )
+ {
++ fprintf(stdout, "XclImpDecryptHelper::ReadFilepass: --begin\n");fflush(stdout);
+ XclImpDecrypterRef xDecr;
+ rStrm.DisableDecryption();
+
+@@ -1156,9 +1185,177 @@
+ rStrm.SetDecrypter( xDecr );
+ // remember encryption for export
+ rStrm.GetRoot().GetExtDocOptions().GetDocSettings().mbEncrypted = true;
+-
++ fprintf(stdout, "XclImpDecryptHelper::ReadFilepass: --end\n");fflush(stdout);
+ return xDecr.is() ? xDecr->GetError() : EXC_ENCR_ERROR_UNSUPP_CRYPT;
+ }
+
++// Document protection ========================================================
++
++XclImpDocProtectBuffer::XclImpDocProtectBuffer( const XclImpRoot& rRoot ) :
++ XclImpRoot( rRoot ),
++ mnPassHash(0x0000),
++ mbDocProtect(false),
++ mbWinProtect(false)
++{
++}
++
++void XclImpDocProtectBuffer::ReadDocProtect( XclImpStream& rStrm )
++{
++ mbDocProtect = rStrm.ReaduInt16() ? true : false;
++}
++
++void XclImpDocProtectBuffer::ReadWinProtect( XclImpStream& rStrm )
++{
++ mbWinProtect = rStrm.ReaduInt16() ? true : false;
++}
++
++void XclImpDocProtectBuffer::ReadPasswordHash( XclImpStream& rStrm )
++{
++ rStrm.EnableDecryption();
++ mnPassHash = rStrm.ReaduInt16();
++}
++
++void XclImpDocProtectBuffer::Apply() const
++{
++ fprintf(stdout, "XclImpDocProtectBuffer::Apply: structure = %d window = %d passhash = %4.4X\n",
++ mbDocProtect, mbWinProtect, mnPassHash);fflush(stdout);
++
++ if (!mbDocProtect && !mbWinProtect)
++ // Excel requires either the structure or windows protection is set.
++ // If neither is set then the document is not protected at all.
++ return;
++
++ auto_ptr<ScDocProtection> pProtect(new ScDocProtection);
++ pProtect->setProtected(true);
++
++ if (mnPassHash)
++ {
++ // 16-bit password pash.
++ Sequence<sal_Int8> aPass(2);
++ aPass[0] = (mnPassHash >> 8) & 0xFF;
++ aPass[1] = mnPassHash & 0xFF;
++ pProtect->setPasswordHash(aPass, PASSHASH_XL);
++ }
++
++ // document protection options
++ pProtect->setOption(ScDocProtection::STRUCTURE, mbDocProtect);
++ pProtect->setOption(ScDocProtection::WINDOWS, mbWinProtect);
++
++ GetDoc().SetDocProtection(pProtect.get());
++}
++
++// Sheet Protection ===========================================================
++
++XclImpSheetProtectBuffer::Sheet::Sheet() :
++ mbProtected(false),
++ mnPasswordHash(0x0000),
++ mnOptions(0x4400)
++{
++}
++
++// ----------------------------------------------------------------------------
++
++XclImpSheetProtectBuffer::Sheet::Sheet(const Sheet& r) :
++ mbProtected(r.mbProtected),
++ mnPasswordHash(r.mnPasswordHash),
++ mnOptions(r.mnOptions)
++{
++}
++
++XclImpSheetProtectBuffer::XclImpSheetProtectBuffer( const XclImpRoot& rRoot ) :
++ XclImpRoot( rRoot )
++{
++}
++
++void XclImpSheetProtectBuffer::ReadProtect( XclImpStream& rStrm, SCTAB nTab )
++{
++ if ( rStrm.ReaduInt16() )
++ {
++ Sheet* pSheet = GetSheetItem(nTab);
++ if (pSheet)
++ pSheet->mbProtected = true;
++ }
++}
++
++void XclImpSheetProtectBuffer::ReadOptions( XclImpStream& rStrm, SCTAB nTab )
++{
++ rStrm.Ignore(19);
++ sal_uInt16 nOptions;
++ rStrm >> nOptions;
++
++ Sheet* pSheet = GetSheetItem(nTab);
++ if (pSheet)
++ pSheet->mnOptions = nOptions;
++}
++
++void XclImpSheetProtectBuffer::ReadPasswordHash( XclImpStream& rStrm, SCTAB nTab )
++{
++ sal_uInt16 nHash;
++ rStrm >> nHash;
++ Sheet* pSheet = GetSheetItem(nTab);
++ if (pSheet)
++ pSheet->mnPasswordHash = nHash;
++}
++
++void XclImpSheetProtectBuffer::Apply() const
++{
++ for (ProtectedSheetMap::const_iterator itr = maProtectedSheets.begin(), itrEnd = maProtectedSheets.end();
++ itr != itrEnd; ++itr)
++ {
++ if (!itr->second.mbProtected)
++ // This sheet is (for whatever reason) not protected.
++ continue;
++
++ auto_ptr<ScTableProtection> pProtect(new ScTableProtection);
++ pProtect->setProtected(true);
++
++ // 16-bit hash password
++ const sal_uInt16 nHash = itr->second.mnPasswordHash;
++ if (nHash)
++ {
++ Sequence<sal_Int8> aPass(2);
++ aPass[0] = (nHash >> 8) & 0xFF;
++ aPass[1] = nHash & 0xFF;
++ pProtect->setPasswordHash(aPass, PASSHASH_XL);
++ }
++
++ // sheet protection options
++ const sal_uInt16 nOptions = itr->second.mnOptions;
++ pProtect->setOption( ScTableProtection::OBJECTS, (nOptions & 0x0001) );
++ pProtect->setOption( ScTableProtection::SCENARIOS, (nOptions & 0x0002) );
++ pProtect->setOption( ScTableProtection::FORMAT_CELLS, (nOptions & 0x0004) );
++ pProtect->setOption( ScTableProtection::FORMAT_COLUMNS, (nOptions & 0x0008) );
++ pProtect->setOption( ScTableProtection::FORMAT_ROWS, (nOptions & 0x0010) );
++ pProtect->setOption( ScTableProtection::INSERT_COLUMNS, (nOptions & 0x0020) );
++ pProtect->setOption( ScTableProtection::INSERT_ROWS, (nOptions & 0x0040) );
++ pProtect->setOption( ScTableProtection::INSERT_HYPERLINKS, (nOptions & 0x0080) );
++ pProtect->setOption( ScTableProtection::DELETE_COLUMNS, (nOptions & 0x0100) );
++ pProtect->setOption( ScTableProtection::DELETE_ROWS, (nOptions & 0x0200) );
++ pProtect->setOption( ScTableProtection::SELECT_LOCKED_CELLS, (nOptions & 0x0400) );
++ pProtect->setOption( ScTableProtection::SORT, (nOptions & 0x0800) );
++ pProtect->setOption( ScTableProtection::AUTOFILTER, (nOptions & 0x1000) );
++ pProtect->setOption( ScTableProtection::PIVOT_TABLES, (nOptions & 0x2000) );
++ pProtect->setOption( ScTableProtection::SELECT_UNLOCKED_CELLS, (nOptions & 0x4000) );
++
++ // all done. now commit.
++ GetDoc().SetTabProtection(itr->first, pProtect.get());
++ }
++}
++
++XclImpSheetProtectBuffer::Sheet* XclImpSheetProtectBuffer::GetSheetItem( SCTAB nTab )
++{
++ ProtectedSheetMap::iterator itr = maProtectedSheets.find(nTab);
++ if (itr == maProtectedSheets.end())
++ {
++ // new sheet
++ if ( !maProtectedSheets.insert( ProtectedSheetMap::value_type(nTab, Sheet()) ).second )
++ return NULL;
++
++ itr = maProtectedSheets.find(nTab);
++ }
++
++ return &itr->second;
++}
++
+ // ============================================================================
+
+Index: sc/source/filter/excel/xilink.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xilink.cxx,v
+retrieving revision 1.22
+retrieving revision 1.22.72.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.22 -r1.22.72.1
+--- sc/source/filter/excel/xilink.cxx 27 Jun 2007 12:44:39 -0000 1.22
++++ sc/source/filter/excel/xilink.cxx 17 Jan 2008 23:01:21 -0000 1.22.72.1
+@@ -288,6 +288,7 @@
+ DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
+ if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
+ {
++ rStrm.EnableDecryption();
+ sal_Size nReadCount = rStrm.GetRecLeft() / 2;
+ DBG_ASSERT( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
+ maTabIdVec.clear();
+Index: sc/source/filter/excel/xiroot.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xiroot.cxx,v
+retrieving revision 1.23
+retrieving revision 1.23.126.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.23 -r1.23.126.2
+--- sc/source/filter/excel/xiroot.cxx 22 May 2007 19:50:21 -0000 1.23
++++ sc/source/filter/excel/xiroot.cxx 3 Jan 2008 22:28:50 -0000 1.23.126.2
+@@ -120,6 +120,8 @@
+ GetOldRoot().pAutoFilterBuffer = new XclImpAutoFilterBuffer;
+ mrImpData.mxWebQueryBfr.reset( new XclImpWebQueryBuffer( GetRoot() ) );
+ mrImpData.mxPTableMgr.reset( new XclImpPivotTableManager( GetRoot() ) );
++ mrImpData.mxTabProtect.reset( new XclImpSheetProtectBuffer( GetRoot() ) );
++ mrImpData.mxDocProtect.reset( new XclImpDocProtectBuffer( GetRoot() ) );
+ }
+
+ mrImpData.mxPageSett.reset( new XclImpPageSettings( GetRoot() ) );
+@@ -258,6 +260,18 @@
+ return *mrImpData.mxPTableMgr;
+ }
+
++XclImpSheetProtectBuffer& XclImpRoot::GetSheetProtectBuffer() const
++{
++ DBG_ASSERT( mrImpData.mxTabProtect.is(), "XclImpRoot::GetSheetProtectBuffer - invalid call, wrong BIFF" );
++ return *mrImpData.mxTabProtect;
++}
++
++XclImpDocProtectBuffer& XclImpRoot::GetDocProtectBuffer() const
++{
++ DBG_ASSERT( mrImpData.mxDocProtect.is(), "XclImpRoot::GetDocProtectBuffer - invalid call, wrong BIFF" );
++ return *mrImpData.mxDocProtect;
++}
++
+ XclImpPageSettings& XclImpRoot::GetPageSettings() const
+ {
+ return *mrImpData.mxPageSett;
+Index: sc/source/filter/excel/xistream.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xistream.cxx,v
+retrieving revision 1.21
+retrieving revision 1.21.164.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.21 -r1.21.164.3
+--- sc/source/filter/excel/xistream.cxx 27 Feb 2007 12:28:06 -0000 1.21
++++ sc/source/filter/excel/xistream.cxx 17 Jan 2008 23:01:21 -0000 1.21.164.3
+@@ -49,6 +49,9 @@
+ #include "xiroot.hxx"
+ #endif
+
++#include <stdio.h>
++#include <vector>
++
+ // ============================================================================
+ // Decryption
+ // ============================================================================
+@@ -194,6 +197,7 @@
+ memcpy( mpnPassw, rSrc.mpnPassw, sizeof( mpnPassw ) );
+ memcpy( mpnDocId, rSrc.mpnDocId, sizeof( mpnDocId ) );
+ maCodec.InitKey( mpnPassw, mpnDocId );
++ maCodec2.InitKey( mpnPassw, mpnDocId );
+ }
+ }
+
+@@ -216,12 +220,16 @@
+ if( (nNewBlock != nOldBlock) || (nNewOffset < nOldOffset) )
+ {
+ maCodec.InitCipher( nNewBlock );
++ maCodec2.InitCipher( nNewBlock );
+ nOldOffset = 0; // reset nOldOffset for next if() statement
+ }
+
+ /* Seek to correct offset. */
+ if( nNewOffset > nOldOffset )
++ {
+ maCodec.Skip( nNewOffset - nOldOffset );
++ maCodec2.Skip( nNewOffset - nOldOffset );
++ }
+ }
+ }
+
+@@ -238,10 +246,40 @@
+
+ // read the block from stream
+ nRet = nRet + static_cast< sal_uInt16 >( rStrm.Read( pnCurrData, nDecBytes ) );
++// fprintf(stdout, "RAW: ");
++// for (sal_uInt16 i = 0; i < nDecBytes; ++i)
++// fprintf(stdout, "%2.2x ", pnCurrData[i]);
++// fprintf(stdout, "\n");
++
+ // decode the block inplace
+ maCodec.Decode( pnCurrData, nDecBytes, pnCurrData, nDecBytes );
++ fprintf(stdout, "DEC: ");
++ for (sal_uInt16 i = 0; i < nDecBytes; ++i)
++ fprintf(stdout, "%2.2x ", pnCurrData[i]);
++ fprintf(stdout, "\n");
++
++// if (nDecBytes)
++// {
++// ::std::vector<sal_uInt8> pnEncData(nDecBytes);
++// bool result = maCodec2.Encode(pnCurrData, nDecBytes, &pnEncData[0], nDecBytes);
++// if (result)
++// {
++// fprintf(stdout, "re-encoded bytes:\n");
++// for (sal_uInt16 i = 0; i < nDecBytes; ++i)
++// fprintf(stdout, "%2.2x ", pnEncData.at(i));
++// fprintf(stdout, "\n");
++// }
++// else
++// {
++// fprintf(stdout, "re-encoding failed\n");
++// }
++// }
++
+ if( GetOffset( rStrm.Tell() ) == 0 )
++ {
+ maCodec.InitCipher( GetBlock( rStrm.Tell() ) );
++ maCodec2.InitCipher( GetBlock( rStrm.Tell() ) );
++ }
+
+ pnCurrData += nDecBytes;
+ nBytesLeft = nBytesLeft - nDecBytes;
+@@ -254,6 +292,8 @@
+ const String& rPass, sal_uInt8 pnDocId[ 16 ],
+ sal_uInt8 pnSaltData[ 16 ], sal_uInt8 pnSaltHash[ 16 ] )
+ {
++ fprintf(stdout, "XclImpBiff8Decrypter::Init: password = '%s'\n",
++ OUStringToOString(rtl::OUString(rPass), RTL_TEXTENCODING_UTF8).getStr());fflush(stdout);
+ xub_StrLen nLen = rPass.Len();
+ bool bValid = (0 < nLen) && (nLen < 16);
+
+@@ -268,6 +308,8 @@
+ // init codec
+ maCodec.InitKey( mpnPassw, mpnDocId );
+ bValid = maCodec.VerifyKey( pnSaltData, pnSaltHash );
++ maCodec2.InitKey( mpnPassw, mpnDocId );
++ bValid = maCodec2.VerifyKey( pnSaltData, pnSaltHash );
+ }
+
+ SetHasValidPassword( bValid );
+@@ -1007,11 +1049,37 @@
+
+ bool XclImpStream::ReadNextRawRecHeader()
+ {
++#if 0
+ mrStrm.Seek( mnNextRecPos );
+ bool bRet = mnNextRecPos + 4 <= mnStreamSize;
+ if( bRet )
+ mrStrm >> mnRawRecId >> mnRawRecSize;
+ return bRet;
++#else
++ mrStrm.Seek( mnNextRecPos );
++ bool bRet = mnNextRecPos + 4 <= mnStreamSize;
++ if( bRet )
++ {
++ mrStrm >> mnRawRecId >> mnRawRecSize;
++ fprintf(stdout, "---------- record (%4.4X) (size = %d; pos = %ld) -----\n",
++ mnRawRecId, mnRawRecSize, mrStrm.Tell());
++ for (sal_uInt16 i = 0; i < mnRawRecSize; ++i)
++ {
++ if ((i+1) % 16 == 1)
++ printf("%4.4X: ", mnRawRecId);
++
++ sal_uInt8 byte;
++ mrStrm >> byte;
++ printf("%2.2X ", byte);
++ if ((i+1) % 16 == 0)
++ printf("\n");
++ }
++ printf("\n");
++ fflush(stdout);
++ mrStrm.Seek( mnNextRecPos+4 );
++ }
++ return bRet;
++#endif
+ }
+
+ void XclImpStream::SetupDecrypter()
+Index: sc/source/filter/excel/xlroot.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/excel/xlroot.cxx,v
+retrieving revision 1.31
+retrieving revision 1.31.72.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.31 -r1.31.72.1
+--- sc/source/filter/excel/xlroot.cxx 3 Jul 2007 15:52:14 -0000 1.31
++++ sc/source/filter/excel/xlroot.cxx 3 Jan 2008 16:57:34 -0000 1.31.72.1
+@@ -264,6 +264,8 @@
+ mrData.maPassw = ScfApiHelper::QueryPasswordForMedium( GetMedium() );
+ // set to true, even if dialog has been cancelled (never ask twice)
+ mrData.mbHasPassw = true;
++ fprintf(stdout, "XclRoot::QueryPassword: password = '%s'\n",
++ OUStringToOString(rtl::OUString(mrData.maPassw), RTL_TEXTENCODING_UTF8).getStr());fflush(stdout);
+ }
+ return mrData.maPassw;
+ }
+Index: sc/source/filter/inc/excdoc.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/excdoc.hxx,v
+retrieving revision 1.17
+retrieving revision 1.17.534.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.17 -r1.17.534.2
+Index: sc/source/filter/inc/excimp8.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/excimp8.hxx,v
+retrieving revision 1.69
+retrieving revision 1.68.164.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.69 -r1.68.164.3
+--- sc/source/filter/inc/excimp8.hxx 29 Jan 2008 15:29:45 -0000 1.69
++++ sc/source/filter/inc/excimp8.hxx 15 Feb 2008 00:42:48 -0000 1.68.164.3
+@@ -79,7 +79,6 @@
+ void Delta( void ); // 0x10
+ void Iteration( void ); // 0x11
+ void Note( void ); // 0x1C
+- void WinProtection( void ); // 0x19
+ void Boundsheet( void ); // 0x85
+ void FilterMode( void ); // 0x9B
+ void AutoFilterInfo( void ); // 0x9D
+@@ -91,6 +90,7 @@
+
+ void Hlink( void ); // 0x01B8
+ void Codename( BOOL bWBGlobals ); // 0x01BA
++ void SheetProtection( void ); // 0x0867
+
+ virtual void EndSheet( void );
+ virtual void PostDocLoad( void );
+Index: sc/source/filter/inc/excrecds.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/excrecds.hxx,v
+retrieving revision 1.49
+retrieving revision 1.49.166.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.49 -r1.49.166.1
+--- sc/source/filter/inc/excrecds.hxx 27 Feb 2007 12:32:42 -0000 1.49
++++ sc/source/filter/inc/excrecds.hxx 5 Jan 2008 06:16:08 -0000 1.49.166.1
+@@ -282,10 +282,23 @@
+ };
+
+ // EXC_ID_PROTECT Document Protection
+-class XclExpDocProtection : public XclExpBoolRecord
++class XclExpProtection : public XclExpBoolRecord
+ {
+ public:
+- XclExpDocProtection(bool bValue);
++ XclExpProtection(bool bValue);
++};
++
++class XclExpPassHash : public XclExpRecord
++{
++public:
++ XclExpPassHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aHash);
++ virtual ~XclExpPassHash();
++
++private:
++ virtual void WriteBody(XclExpStream& rStrm);
++
++private:
++ sal_uInt16 mnHash;
+ };
+
+
+Index: sc/source/filter/inc/fdumper.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/fdumper.hxx,v
+retrieving revision 1.7
+retrieving revision 1.7.162.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.7 -r1.7.162.1
+--- sc/source/filter/inc/fdumper.hxx 27 Feb 2007 12:33:04 -0000 1.7
++++ sc/source/filter/inc/fdumper.hxx 3 Jan 2008 17:41:45 -0000 1.7.162.1
+@@ -36,7 +36,8 @@
+ #ifndef SC_FDUMPER_HXX
+ #define SC_FDUMPER_HXX
+
+-#define SCF_INCL_DUMPER (OSL_DEBUG_LEVEL > 0)
++//#define SCF_INCL_DUMPER (OSL_DEBUG_LEVEL > 0)
++#define SCF_INCL_DUMPER 0 // TODO: causes linker error when debug=true.
+
+ #if SCF_INCL_DUMPER
+
+Index: sc/source/filter/inc/imp_op.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/imp_op.hxx,v
+retrieving revision 1.41
+retrieving revision 1.41.126.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.41 -r1.41.126.2
+--- sc/source/filter/inc/imp_op.hxx 22 May 2007 19:55:08 -0000 1.41
++++ sc/source/filter/inc/imp_op.hxx 3 Jan 2008 22:28:50 -0000 1.41.126.2
+@@ -162,9 +162,11 @@
+ void Bof2( void ); // 0x09
+ void Eof( void ); // 0x0A
+ void DocProtect( void ); // 0x12
+- void Protect( void ); // 0x12 Sheet Protection
+- BOOL Password( void ); // 0x13
++ void SheetProtect( void ); // 0x12 Sheet Protection
++ void DocPasssword( void ); // 0x13 document password
++ void SheetPassword( void ); // 0x13 sheet password
+ void Externsheet( void ); // 0x17
++ void WinProtection( void ); // 0x19
+ void Note( void ); // 0x1C
+ void Columndefault( void ); // 0x20
+ void Array25( void ); // 0x21
+Index: sc/source/filter/inc/xcl97dum.hxx
+===================================================================
+RCS file: sc/source/filter/inc/xcl97dum.hxx
+diff -N sc/source/filter/inc/xcl97dum.hxx
+--- sc/source/filter/inc/xcl97dum.hxx 22 Jan 2007 13:20:35 -0000 1.10
++++ /dev/null 1 Jan 1970 00:00:00 -0000
+@@ -1,100 +0,0 @@
+-/*************************************************************************
+- *
+- * OpenOffice.org - a multi-platform office productivity suite
+- *
+- * $RCSfile: xcl97dum.hxx,v $
+- *
+- * $Revision: 1.10 $
+- *
+- * last change: $Author: obo $ $Date: 2007/01/22 13:20:35 $
+- *
+- * The Contents of this file are made available subject to
+- * the terms of GNU Lesser General Public License Version 2.1.
+- *
+- *
+- * GNU Lesser General Public License Version 2.1
+- * =============================================
+- * Copyright 2005 by Sun Microsystems, Inc.
+- * 901 San Antonio Road, Palo Alto, CA 94303, USA
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License version 2.1, as published by the Free Software Foundation.
+- *
+- * This library 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 for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+- * MA 02111-1307 USA
+- *
+- ************************************************************************/
+-
+-#ifndef _XCL97DUM_HXX
+-#define _XCL97DUM_HXX
+-
+-
+-#include "excrecds.hxx"
+-
+-
+-// --- class ExcDummy8_xx --------------------------------------------
+-
+-class ExcDummy8_00a : public ExcDummyRec
+-{
+-private:
+- static const BYTE pMyData[];
+- static const sal_Size nMyLen;
+-public:
+- virtual sal_Size GetLen() const;
+- virtual const BYTE* GetData() const;
+-};
+-
+-
+-class ExcDummy8_00b : public ExcDummyRec
+-{
+-private:
+- static const BYTE pMyData[];
+- static const sal_Size nMyLen;
+-public:
+- virtual sal_Size GetLen() const;
+- virtual const BYTE* GetData() const;
+-};
+-
+-
+-class ExcDummy8_040 : public ExcDummyRec
+-{
+-private:
+- static const BYTE pMyData[];
+- static const sal_Size nMyLen;
+-public:
+- virtual sal_Size GetLen() const;
+- virtual const BYTE* GetData() const;
+-};
+-
+-
+-class ExcDummy8_041 : public ExcDummyRec
+-{
+-private:
+- static const BYTE pMyData[];
+- static const sal_Size nMyLen;
+-public:
+- virtual sal_Size GetLen() const;
+- virtual const BYTE* GetData() const;
+-};
+-
+-
+-class ExcDummy8_02 : public ExcDummyRec
+-{
+-private:
+- static const BYTE pMyData[];
+- static const sal_Size nMyLen;
+-public:
+- virtual sal_Size GetLen() const;
+- virtual const BYTE* GetData() const;
+-};
+-
+-
+-#endif // _XCL97DUM_HXX
+Index: sc/source/filter/inc/xcl97rec.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xcl97rec.hxx,v
+retrieving revision 1.47
+retrieving revision 1.47.180.10
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.47 -r1.47.180.10
+--- sc/source/filter/inc/xcl97rec.hxx 22 Jan 2007 13:20:49 -0000 1.47
++++ sc/source/filter/inc/xcl97rec.hxx 30 Jan 2008 17:22:52 -0000 1.47.180.10
+@@ -43,6 +43,8 @@
+ #include "xlstyle.hxx"
+ #endif
+
++#include <vector>
++
+ // --- class XclMsodrawing_Base --------------------------------------
+
+ class XclMsodrawing_Base
+@@ -65,29 +67,26 @@
+
+ // --- class XclMsodrawinggroup --------------------------------------
+
+-class XclMsodrawinggroup : public XclMsodrawing_Base, public ExcRecord
++class XclMsodrawinggroup : public XclMsodrawing_Base, public XclExpRecord
+ {
+ private:
+
+- virtual void SaveCont( XclExpStream& rStrm );
++ virtual void WriteBody( XclExpStream& rStrm );
+
+ public:
+ XclMsodrawinggroup( RootData& rRoot,
+ UINT16 nEscherType = 0 );
+ virtual ~XclMsodrawinggroup();
+-
+- virtual UINT16 GetNum() const;
+- virtual sal_Size GetLen() const;
+ };
+
+
+ // --- class XclMsodrawing -------------------------------------------
+
+-class XclMsodrawing : public XclMsodrawing_Base, public ExcRecord
++class XclMsodrawing : public XclMsodrawing_Base, public XclExpRecord
+ {
+ private:
+
+- virtual void SaveCont( XclExpStream& rStrm );
++ virtual void WriteBody( XclExpStream& rStrm );
+
+ public:
+ XclMsodrawing(
+@@ -95,9 +94,6 @@
+ UINT16 nEscherType = 0,
+ sal_Size nInitialSize = 0 );
+ virtual ~XclMsodrawing();
+-
+- virtual UINT16 GetNum() const;
+- virtual sal_Size GetLen() const;
+ };
+
+
+@@ -492,23 +488,24 @@
+ virtual sal_Size GetLen() const;
+ };
+
++// ============================================================================
+
+-// ---- class XclProtection ------------------------------------------
+-
+-class XclProtection : public ExcDummyRec
++/** Represents a SHEETPROTECTION record that stores sheet protection
++ options. Note that a sheet still needs to save its sheet protection
++ options even when it's not protected. */
++class XclExpSheetProtectOptions : public XclExpRecord
+ {
+- // replacement for records PROTECT, SCENPROTECT, OBJPROTECT...
+-private:
+- static const BYTE pMyData[];
+- static const sal_Size nMyLen;
+ public:
+- virtual sal_Size GetLen( void ) const;
+- virtual const BYTE* GetData( void ) const;
+-};
++ explicit XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab );
+
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
+
+-// -------------------------------------------------------------------
++private:
++ sal_uInt16 mnOptions; /// Encoded sheet protection options.
++};
+
++// ============================================================================
+
+ class XclCalccount : public ExcRecord
+ {
+@@ -564,5 +561,162 @@
+ XclRefmode( const ScDocument& );
+ };
+
++// ============================================================================
++
++class XclExpFilePass : public XclExpRecord
++{
++public:
++ explicit XclExpFilePass( const XclExpRoot& rRoot );
++ virtual ~XclExpFilePass();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++
++private:
++ const XclExpRoot& mrRoot;
++};
++
++// ============================================================================
++
++class XclExpFnGroupCount : public XclExpRecord
++{
++public:
++ explicit XclExpFnGroupCount();
++ virtual ~XclExpFnGroupCount();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** Beginning of User Interface Records */
++class XclExpInterfaceHdr : public XclExpRecord
++{
++public:
++ explicit XclExpInterfaceHdr();
++ virtual ~XclExpInterfaceHdr();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** Beginning of User Interface Records */
++class XclExpInterfaceEnd : public XclExpRecord
++{
++public:
++ explicit XclExpInterfaceEnd();
++ virtual ~XclExpInterfaceEnd();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** ADDMENU/DELMENU Record Group Count */
++class XclExpMMS : public XclExpRecord
++{
++public:
++ explicit XclExpMMS();
++ virtual ~XclExpMMS();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** Write Access User Name - This record contains the user name, which is
++ the name you type when you install Excel. */
++class XclExpWriteAccess : public XclExpRecord
++{
++public:
++ explicit XclExpWriteAccess();
++ virtual ~XclExpWriteAccess();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpCodePage : public XclExpRecord
++{
++public:
++ explicit XclExpCodePage();
++ virtual ~XclExpCodePage();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpDSF : public XclExpRecord
++{
++public:
++ explicit XclExpDSF();
++ virtual ~XclExpDSF();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpProt4Rev : public XclExpRecord
++{
++public:
++ explicit XclExpProt4Rev();
++ virtual ~XclExpProt4Rev();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpProt4RevPass : public XclExpRecord
++{
++public:
++ explicit XclExpProt4RevPass();
++ virtual ~XclExpProt4RevPass();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** What's this record for? It is a zero-byte record. */
++class XclExpUnknown01C0 : public XclExpRecord
++{
++public:
++ explicit XclExpUnknown01C0();
++ virtual ~XclExpUnknown01C0();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpUnknown01C1 : public XclExpDummyRecord
++{
++public:
++ explicit XclExpUnknown01C1();
++};
++
++// ============================================================================
++
++class XclExpUnknown0863 : public XclExpDummyRecord
++{
++public:
++ explicit XclExpUnknown0863();
++};
++
+
+ #endif // _XCL97REC_HXX
+Index: sc/source/filter/inc/xerecord.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xerecord.hxx,v
+retrieving revision 1.13
+retrieving revision 1.13.126.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.13 -r1.13.126.2
+Index: sc/source/filter/inc/xeroot.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xeroot.hxx,v
+retrieving revision 1.20
+retrieving revision 1.20.220.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.20 -r1.20.220.1
+--- sc/source/filter/inc/xeroot.hxx 19 Dec 2006 13:24:06 -0000 1.20
++++ sc/source/filter/inc/xeroot.hxx 17 Jan 2008 23:01:22 -0000 1.20.220.1
+@@ -161,6 +161,10 @@
+ @param nRecId Identifier that specifies which record is returned. */
+ XclExpRecordRef CreateRecord( sal_uInt16 nRecId ) const;
+
++ bool IsPasswordProtected() const;
++
++ const String GetPassword() const;
++
+ private:
+ /** Returns the local or global link manager, depending on current context. */
+ XclExpRootData::XclExpLinkMgrRef GetLocalLinkMgrRef() const;
+Index: sc/source/filter/inc/xestream.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xestream.hxx,v
+retrieving revision 1.7
+retrieving revision 1.7.334.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.7 -r1.7.334.6
+--- sc/source/filter/inc/xestream.hxx 10 Jul 2006 13:56:03 -0000 1.7
++++ sc/source/filter/inc/xestream.hxx 30 Jan 2008 16:47:01 -0000 1.7.334.6
+@@ -41,6 +41,9 @@
+ #ifndef SC_XLSTREAM_HXX
+ #include "xlstream.hxx"
+ #endif
++#include <stdio.h>
++#include <svx/mscodec.hxx>
++#include <vector>
+
+ /* ============================================================================
+ Output stream class for Excel export
+@@ -49,6 +52,8 @@
+ ============================================================================ */
+
+ class XclExpRoot;
++class XclExpBiff8Encrypter;
++typedef ScfRef< XclExpBiff8Encrypter > XclExpEncrypterRef;
+
+ /** This class is used to export Excel record streams.
+ @descr An instance is constructed with an SvStream and the maximum size of Excel
+@@ -107,14 +112,14 @@
+ /** Sets data slice length. 0 = no slices. */
+ void SetSliceSize( sal_uInt16 nSize );
+
+- inline XclExpStream& operator<<( sal_Int8 nValue );
+- inline XclExpStream& operator<<( sal_uInt8 nValue );
+- inline XclExpStream& operator<<( sal_Int16 nValue );
+- inline XclExpStream& operator<<( sal_uInt16 nValue );
+- inline XclExpStream& operator<<( sal_Int32 nValue );
+- inline XclExpStream& operator<<( sal_uInt32 nValue );
+- inline XclExpStream& operator<<( float fValue );
+- inline XclExpStream& operator<<( double fValue );
++ XclExpStream& operator<<( sal_Int8 nValue );
++ XclExpStream& operator<<( sal_uInt8 nValue );
++ XclExpStream& operator<<( sal_Int16 nValue );
++ XclExpStream& operator<<( sal_uInt16 nValue );
++ XclExpStream& operator<<( sal_Int32 nValue );
++ XclExpStream& operator<<( sal_uInt32 nValue );
++ XclExpStream& operator<<( float fValue );
++ XclExpStream& operator<<( double fValue );
+
+ /** Writes nBytes bytes from memory. */
+ sal_Size Write( const void* pData, sal_Size nBytes );
+@@ -155,6 +160,14 @@
+ /** Returns the absolute position of the system stream. */
+ inline sal_Size GetSvStreamPos() const { return mrStrm.Tell(); }
+
++ void SetEncrypter( XclExpEncrypterRef xEncrypter );
++
++ bool HasValidEncrypter() const;
++
++ void EnableEncryption( bool bEnable = true );
++
++ void DisableEncryption();
++
+ private:
+ /** Writes header data, internal setup. */
+ void InitRecord( sal_uInt16 nRecId );
+@@ -177,6 +190,9 @@
+ SvStream& mrStrm; /// Reference to the system output stream.
+ const XclExpRoot& mrRoot; /// Filter root data.
+
++ bool mbUseEncrypter;
++ XclExpEncrypterRef mxEncrypter;
++
+ // length data
+ sal_uInt16 mnMaxRecSize; /// Maximum size of record content.
+ sal_uInt16 mnMaxContSize; /// Maximum size of CONTINUE content.
+@@ -194,64 +210,48 @@
+
+ // ----------------------------------------------------------------------------
+
+-inline XclExpStream& XclExpStream::operator<<( sal_Int8 nValue )
+-{
+- PrepareWrite( 1 );
+- mrStrm << nValue;
+- return *this;
+-}
+
+-inline XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue )
+-{
+- PrepareWrite( 1 );
+- mrStrm << nValue;
+- return *this;
+-}
++// ============================================================================
+
+-inline XclExpStream& XclExpStream::operator<<( sal_Int16 nValue )
++class XclExpBiff8Encrypter
+ {
+- PrepareWrite( 2 );
+- mrStrm << nValue;
+- return *this;
+-}
++public:
++ explicit XclExpBiff8Encrypter( const XclExpRoot& rRoot, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16], const sal_uInt8 nSaltHash[16] );
++ ~XclExpBiff8Encrypter();
+
+-inline XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue )
+-{
+- PrepareWrite( 2 );
+- mrStrm << nValue;
+- return *this;
+-}
++ bool IsValid() const;
+
+-inline XclExpStream& XclExpStream::operator<<( sal_Int32 nValue )
+-{
+- PrepareWrite( 4 );
+- mrStrm << nValue;
+- return *this;
+-}
++ void Encrypt( SvStream& rStrm, sal_uInt8 nData );
++ void Encrypt( SvStream& rStrm, sal_uInt16 nData );
++ void Encrypt( SvStream& rStrm, sal_uInt32 nData );
+
+-inline XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue )
+-{
+- PrepareWrite( 4 );
+- mrStrm << nValue;
+- return *this;
+-}
++ void Encrypt( SvStream& rStrm, sal_Int8 nData );
++ void Encrypt( SvStream& rStrm, sal_Int16 nData );
++ void Encrypt( SvStream& rStrm, sal_Int32 nData );
+
+-inline XclExpStream& XclExpStream::operator<<( float fValue )
+-{
+- PrepareWrite( 4 );
+- mrStrm << fValue;
+- return *this;
+-}
++ void Encrypt( SvStream& rStrm, float fValue );
++ void Encrypt( SvStream& rStrm, double fValue );
+
+-inline XclExpStream& XclExpStream::operator<<( double fValue )
+-{
+- PrepareWrite( 8 );
+- mrStrm << fValue;
+- return *this;
+-}
++ void EncryptBytes( SvStream& rStrm, ::std::vector<sal_uInt8>& aBytes );
++
++private:
++ void Init( const String& aPass, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16], const sal_uInt8 nSaltHash[16] );
+
++ sal_uInt32 GetBlockPos( sal_Size nStrmPos ) const;
++ sal_uInt16 GetOffsetInBlock( sal_Size nStrmPos ) const;
+
+-// ============================================================================
++
++private:
++ ::svx::MSCodec_Std97 maCodec; /// Crypto algorithm implementation.
++ sal_uInt16 mnPassw[16]; /// Cached password data for copy construction.
++ sal_uInt8 mnDocId[16]; /// Cached document ID for copy construction.
++
++ const XclExpRoot& mrRoot;
++ sal_Size mnOldPos; /// Last known stream position
++ bool mbValid;
++};
+
+ #endif
+
+Index: sc/source/filter/inc/xetable.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xetable.hxx,v
+retrieving revision 1.10
+retrieving revision 1.9.126.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.10 -r1.9.126.3
+--- sc/source/filter/inc/xetable.hxx 29 Jan 2008 15:30:56 -0000 1.10
++++ sc/source/filter/inc/xetable.hxx 15 Feb 2008 00:42:45 -0000 1.9.126.3
+@@ -1090,7 +1090,5 @@
+ XclExpDvalRef mxDval; /// Data validation with DVAL and DV records.
+ };
+
+-// ============================================================================
+-
+ #endif
+
+Index: sc/source/filter/inc/xicontent.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xicontent.hxx,v
+retrieving revision 1.15
+retrieving revision 1.14.68.5
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.15 -r1.14.68.5
+--- sc/source/filter/inc/xicontent.hxx 29 Jan 2008 15:31:23 -0000 1.15
++++ sc/source/filter/inc/xicontent.hxx 15 Feb 2008 00:42:51 -0000 1.14.68.5
+@@ -53,6 +53,8 @@
+ #include "xiroot.hxx"
+ #endif
+
++#include <map>
++
+ /* ============================================================================
+ Classes to import the big Excel document contents (related to several cells or
+ globals for the document).
+@@ -265,5 +267,64 @@
+
+ // ============================================================================
+
++// Document protection ========================================================
++
++class XclImpDocProtectBuffer : protected XclImpRoot
++{
++public:
++ explicit XclImpDocProtectBuffer( const XclImpRoot& rRoot );
++
++ /** document structure protection flag */
++ void ReadDocProtect( XclImpStream& rStrm );
++
++ /** document windows properties protection flag */
++ void ReadWinProtect( XclImpStream& rStrm );
++
++ void ReadPasswordHash( XclImpStream& rStrm );
++
++ void Apply() const;
++
++private:
++ sal_uInt16 mnPassHash;
++ bool mbDocProtect:1;
++ bool mbWinProtect:1;
++};
++
++// Sheet protection ===========================================================
++
++class XclImpSheetProtectBuffer : protected XclImpRoot
++{
++public:
++ explicit XclImpSheetProtectBuffer( const XclImpRoot& rRoot );
++
++ void ReadProtect( XclImpStream& rStrm, SCTAB nTab );
++
++ void ReadOptions( XclImpStream& rStrm, SCTAB nTab );
++
++ void ReadPasswordHash( XclImpStream& rStrm, SCTAB nTab );
++
++ void Apply() const;
++
++private:
++ struct Sheet
++ {
++ bool mbProtected;
++ sal_uInt16 mnPasswordHash;
++ sal_uInt16 mnOptions;
++
++ Sheet();
++ Sheet(const Sheet& r);
++ };
++
++ Sheet* GetSheetItem( SCTAB nTab );
++
++private:
++ typedef ::std::map<SCTAB, Sheet> ProtectedSheetMap;
++ ProtectedSheetMap maProtectedSheets;
++};
++
++
++// ============================================================================
++
+ #endif
+
+Index: sc/source/filter/inc/xiroot.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xiroot.hxx,v
+retrieving revision 1.21
+retrieving revision 1.21.220.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.21 -r1.21.220.2
+--- sc/source/filter/inc/xiroot.hxx 19 Dec 2006 13:24:31 -0000 1.21
++++ sc/source/filter/inc/xiroot.hxx 3 Jan 2008 22:28:50 -0000 1.21.220.2
+@@ -68,6 +68,8 @@
+ class XclImpPageSettings;
+ class XclImpDocViewSettings;
+ class XclImpTabViewSettings;
++class XclImpSheetProtectBuffer;
++class XclImpDocProtectBuffer;
+
+ class _ScRangeListTabs;
+ class ExcelToSc;
+@@ -94,6 +96,8 @@
+ typedef ScfRef< XclImpPageSettings > XclImpPageSettRef;
+ typedef ScfRef< XclImpDocViewSettings > XclImpDocViewSettRef;
+ typedef ScfRef< XclImpTabViewSettings > XclImpTabViewSettRef;
++ typedef ScfRef< XclImpSheetProtectBuffer > XclImpTabProtectRef;
++ typedef ScfRef< XclImpDocProtectBuffer > XclImpDocProtectRef;
+
+ XclImpAddrConvRef mxAddrConv; /// The address converter.
+ XclImpFmlaCompRef mxFmlaComp; /// The formula compiler.
+@@ -117,6 +121,8 @@
+ XclImpPageSettRef mxPageSett; /// Page settings for current sheet.
+ XclImpDocViewSettRef mxDocViewSett; /// View settings for entire document.
+ XclImpTabViewSettRef mxTabViewSett; /// View settings for current sheet.
++ XclImpTabProtectRef mxTabProtect; /// Sheet protection options for current sheet.
++ XclImpDocProtectRef mxDocProtect; /// Document protection options.
+
+ bool mbHasCodePage; /// true = CODEPAGE record exists.
+
+@@ -188,6 +194,10 @@
+ XclImpWebQueryBuffer& GetWebQueryBuffer() const;
+ /** Returns the pivot table manager. */
+ XclImpPivotTableManager& GetPivotTableManager() const;
++ /** Returns the sheet protection options of the current sheet. */
++ XclImpSheetProtectBuffer& GetSheetProtectBuffer() const;
++ /** Returns the document protection options. */
++ XclImpDocProtectBuffer& GetDocProtectBuffer() const;
+
+ /** Returns the page settings of the current sheet. */
+ XclImpPageSettings& GetPageSettings() const;
+Index: sc/source/filter/inc/xistream.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/inc/xistream.hxx,v
+retrieving revision 1.12
+retrieving revision 1.12.166.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.12 -r1.12.166.1
+--- sc/source/filter/inc/xistream.hxx 27 Feb 2007 12:37:18 -0000 1.12
++++ sc/source/filter/inc/xistream.hxx 3 Jan 2008 16:57:34 -0000 1.12.166.1
+@@ -176,6 +176,7 @@
+
+ private:
+ ::svx::MSCodec_Std97 maCodec; /// Crypto algorithm implementation.
++ ::svx::MSCodec_Std97 maCodec2; /// Crypto algorithm implementation.
+ sal_uInt16 mpnPassw[ 16 ]; /// Cached password data for copy construction.
+ sal_uInt8 mpnDocId[ 16 ]; /// Cached document ID for copy construction.
+ };
+Index: sc/source/filter/starcalc/scflt.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/starcalc/scflt.cxx,v
+retrieving revision 1.23
+retrieving revision 1.21.22.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.23 -r1.21.22.2
+--- sc/source/filter/starcalc/scflt.cxx 12 Feb 2008 14:25:27 -0000 1.23
++++ sc/source/filter/starcalc/scflt.cxx 15 Feb 2008 00:43:28 -0000 1.21.22.2
+@@ -1153,9 +1153,9 @@
+ //rStream.Read(&SheetProtect, sizeof(SheetProtect));
+ lcl_ReadSheetProtect(rStream, SheetProtect);
+ nError = rStream.GetError();
+- uno::Sequence<sal_Int8> aPass;
+- SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( SheetProtect.PassWord ));
+- pDoc->SetDocProtection( SheetProtect.Protect, aPass);
++// uno::Sequence<sal_Int8> aPass;
++// SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( SheetProtect.PassWord ));
++// pDoc->SetDocProtection( SheetProtect.Protect, SC10TOSTRING( SheetProtect.PassWord ));
+ }
+
+
+@@ -1507,10 +1507,10 @@
+
+ //rStream.Read(&TabProtect, sizeof(TabProtect));
+ lcl_ReadTabProtect(rStream, TabProtect);
+- uno::Sequence<sal_Int8> aPass;
+- SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( TabProtect.PassWord ));
++// uno::Sequence<sal_Int8> aPass;
++// SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( TabProtect.PassWord ));
+
+- pDoc->SetTabProtection( static_cast<SCTAB>(Tab), TabProtect.Protect, aPass);
++ pDoc->SetTabProtection( static_cast<SCTAB>(Tab), TabProtect.Protect, SC10TOSTRING( TabProtect.PassWord ));
+
+ rStream >> TabNo;
+
+Index: sc/source/filter/xcl97/XclExpChangeTrack.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/xcl97/XclExpChangeTrack.cxx,v
+retrieving revision 1.25
+retrieving revision 1.25.166.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.25 -r1.25.166.1
+--- sc/source/filter/xcl97/XclExpChangeTrack.cxx 27 Feb 2007 12:42:44 -0000 1.25
++++ sc/source/filter/xcl97/XclExpChangeTrack.cxx 17 Jan 2008 23:01:22 -0000 1.25.166.1
+@@ -507,6 +507,7 @@
+
+ void XclExpChTrTabId::SaveCont( XclExpStream& rStrm )
+ {
++ rStrm.EnableEncryption();
+ if( pBuffer )
+ for( sal_uInt16* pElem = pBuffer; pElem < (pBuffer + nTabCount); pElem++ )
+ rStrm << *pElem;
+Index: sc/source/filter/xcl97/makefile.mk
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/xcl97/makefile.mk,v
+retrieving revision 1.15
+retrieving revision 1.15.166.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.15 -r1.15.166.1
+--- sc/source/filter/xcl97/makefile.mk 27 Feb 2007 12:42:55 -0000 1.15
++++ sc/source/filter/xcl97/makefile.mk 19 Jan 2008 04:38:59 -0000 1.15.166.1
+@@ -54,7 +54,6 @@
+ # --- Files --------------------------------------------------------
+
+ SLOFILES = \
+- $(SLO)$/xcl97dum.obj \
+ $(SLO)$/xcl97esc.obj \
+ $(SLO)$/xcl97rec.obj \
+ $(SLO)$/XclImpChangeTrack.obj \
+Index: sc/source/filter/xcl97/xcl97dum.cxx
+===================================================================
+RCS file: sc/source/filter/xcl97/xcl97dum.cxx
+diff -N sc/source/filter/xcl97/xcl97dum.cxx
+--- sc/source/filter/xcl97/xcl97dum.cxx 22 Jan 2007 13:22:46 -0000 1.20
++++ /dev/null 1 Jan 1970 00:00:00 -0000
+@@ -1,171 +0,0 @@
+-/*************************************************************************
+- *
+- * OpenOffice.org - a multi-platform office productivity suite
+- *
+- * $RCSfile: xcl97dum.cxx,v $
+- *
+- * $Revision: 1.20 $
+- *
+- * last change: $Author: obo $ $Date: 2007/01/22 13:22:46 $
+- *
+- * The Contents of this file are made available subject to
+- * the terms of GNU Lesser General Public License Version 2.1.
+- *
+- *
+- * GNU Lesser General Public License Version 2.1
+- * =============================================
+- * Copyright 2005 by Sun Microsystems, Inc.
+- * 901 San Antonio Road, Palo Alto, CA 94303, USA
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License version 2.1, as published by the Free Software Foundation.
+- *
+- * This library 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 for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+- * MA 02111-1307 USA
+- *
+- ************************************************************************/
+-
+-// MARKER(update_precomp.py): autogen include statement, do not remove
+-#include "precompiled_sc.hxx"
+-
+-
+-
+-
+-#include "xcl97dum.hxx"
+-
+-
+-// --- ExcDummy8_xx Data ---------------------------------------------
+-
+-// ... (8+) := neu in Biff8, ... (8*) := anders in Biff8
+-
+-const BYTE ExcDummy8_00a::pMyData[] = {
+- 0xe1, 0x00, 0x02, 0x00, 0xb0, 0x04, // INTERFACEHDR
+- 0xc1, 0x00, 0x02, 0x00, 0x00, 0x00, // MMS
+- 0xe2, 0x00, 0x00, 0x00, // INTERFACEEND
+- 0x5c, 0x00, 0x70, 0x00, // WRITEACCESS (8*)
+- 0x04, 0x00, 0x00, 'C', 'a', 'l', 'c', 0x20, // "Calc"
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+- 0x42, 0x00, 0x02, 0x00, 0xb0, 0x04, // CODEPAGE
+- 0x61, 0x01, 0x02, 0x00, 0x00, 0x00 // DSF (8+)
+-};
+-const sal_Size ExcDummy8_00a::nMyLen = sizeof(ExcDummy8_00a::pMyData);
+-
+- // TABID (8+): ExcTabid
+-
+-const BYTE ExcDummy8_00b::pMyData[] = {
+- 0x9c, 0x00, 0x02, 0x00, 0x0e, 0x00 // FNGROUPCOUNT
+-};
+-const sal_Size ExcDummy8_00b::nMyLen = sizeof(ExcDummy8_00b::pMyData);
+-
+-
+-const BYTE ExcDummy8_040::pMyData[] = {
+- 0xaf, 0x01, 0x02, 0x00, 0x00, 0x00, // PROT4REV (8+)
+- 0xbc, 0x01, 0x02, 0x00, 0x00, 0x00, // PROT4REVPASS (8+)
+-// 0x3d, 0x00, 0x12, 0x00, 0xe0, 0x01, 0x5a, 0x00, 0xcf, // WINDOW1
+-// 0x3f, 0x4e, 0x2a, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
+-// 0x01, 0x00, 0x58, 0x02,
+- 0x40, 0x00, 0x02, 0x00, 0x00, 0x00, // BACKUP
+- 0x8d, 0x00, 0x02, 0x00, 0x00, 0x00 // HIDEOBJ
+-};
+-const sal_Size ExcDummy8_040::nMyLen = sizeof(ExcDummy8_040::pMyData);
+-
+-
+-const BYTE ExcDummy8_041::pMyData[] = {
+- 0xb7, 0x01, 0x02, 0x00, 0x00, 0x00, // REFRESHALL (8+)
+- 0xda, 0x00, 0x02, 0x00, 0x00, 0x00 // BOOKBOOL
+-};
+-const sal_Size ExcDummy8_041::nMyLen = sizeof(ExcDummy8_041::pMyData);
+-
+-
+-
+-const BYTE ExcDummy8_02::pMyData[] = {
+- 0x5f, 0x00, 0x02, 0x00, 0x01, 0x00 // SAVERECALC
+- };
+-const sal_Size ExcDummy8_02::nMyLen = sizeof(ExcDummy8_02::pMyData);
+-
+-
+-// --- class ExcDummy8_xx --------------------------------------------
+-
+-sal_Size ExcDummy8_00a::GetLen() const
+-{
+- return nMyLen;
+-}
+-
+-
+-const BYTE* ExcDummy8_00a::GetData() const
+-{
+- return pMyData;
+-}
+-
+-
+-
+-sal_Size ExcDummy8_00b::GetLen() const
+-{
+- return nMyLen;
+-}
+-
+-
+-const BYTE* ExcDummy8_00b::GetData() const
+-{
+- return pMyData;
+-}
+-
+-
+-
+-sal_Size ExcDummy8_040::GetLen() const
+-{
+- return nMyLen;
+-}
+-
+-
+-const BYTE* ExcDummy8_040::GetData() const
+-{
+- return pMyData;
+-}
+-
+-
+-
+-sal_Size ExcDummy8_041::GetLen() const
+-{
+- return nMyLen;
+-}
+-
+-
+-const BYTE* ExcDummy8_041::GetData() const
+-{
+- return pMyData;
+-}
+-
+-
+-
+-sal_Size ExcDummy8_02::GetLen() const
+-{
+- return nMyLen;
+-}
+-
+-
+-const BYTE* ExcDummy8_02::GetData() const
+-{
+- return pMyData;
+-}
+-
+Index: sc/source/filter/xcl97/xcl97rec.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/xcl97/xcl97rec.cxx,v
+retrieving revision 1.86
+retrieving revision 1.86.132.12
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.86 -r1.86.132.12
+--- sc/source/filter/xcl97/xcl97rec.cxx 10 May 2007 16:52:00 -0000 1.86
++++ sc/source/filter/xcl97/xcl97rec.cxx 30 Jan 2008 17:22:52 -0000 1.86.132.12
+@@ -36,7 +36,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+
+-
++#include <stdio.h>
+
+ #ifndef _SVDPOOL_HXX //autogen wg. SdrItemPool
+ #include <svx/svdpool.hxx>
+@@ -134,6 +134,7 @@
+ #include "scextopt.hxx"
+ #include "docoptio.hxx"
+ #include "patattr.hxx"
++#include "tabprotection.hxx"
+
+ using ::rtl::OUString;
+ using namespace ::com::sun::star;
+@@ -188,9 +189,9 @@
+
+ // --- class XclMsodrawinggroup --------------------------------------
+
+-XclMsodrawinggroup::XclMsodrawinggroup( RootData& rRoot, UINT16 nEscherType )
+- :
+- XclMsodrawing_Base( *rRoot.pEscher )
++XclMsodrawinggroup::XclMsodrawinggroup( RootData& rRoot, UINT16 nEscherType ) :
++ XclMsodrawing_Base( *rRoot.pEscher ),
++ XclExpRecord(0x00EB, 2) // bogus record size since we don't know the actual size yet.
+ {
+ if ( nEscherType )
+ {
+@@ -235,7 +236,7 @@
+ }
+
+
+-void XclMsodrawinggroup::SaveCont( XclExpStream& rStrm )
++void XclMsodrawinggroup::WriteBody( XclExpStream& rStrm )
+ {
+ DBG_ASSERT( GetEscherEx()->GetStreamPos() == GetEscherEx()->GetOffsetFromMap( nStartPos ),
+ "XclMsodrawinggroup::SaveCont: Escher stream position mismatch" );
+@@ -243,23 +244,11 @@
+ }
+
+
+-UINT16 XclMsodrawinggroup::GetNum() const
+-{
+- return 0x00EB;
+-}
+-
+-
+-sal_Size XclMsodrawinggroup::GetLen() const
+-{
+- return GetDataLen();
+-}
+-
+-
+-
+ // --- class XclMsodrawing --------------------------------------
+
+ XclMsodrawing::XclMsodrawing( const XclExpRoot& rRoot, UINT16 nEscherType, sal_Size nInitialSize ) :
+- XclMsodrawing_Base( *rRoot.GetOldRoot().pEscher, nInitialSize )
++ XclMsodrawing_Base( *rRoot.GetOldRoot().pEscher, nInitialSize ),
++ XclExpRecord( 0x00EC, nInitialSize )
+ {
+ if ( nEscherType )
+ {
+@@ -285,7 +274,7 @@
+ }
+
+
+-void XclMsodrawing::SaveCont( XclExpStream& rStrm )
++void XclMsodrawing::WriteBody( XclExpStream& rStrm )
+ {
+ DBG_ASSERT( GetEscherEx()->GetStreamPos() == GetEscherEx()->GetOffsetFromMap( nStartPos ),
+ "XclMsodrawing::SaveCont: Escher stream position mismatch" );
+@@ -293,16 +282,6 @@
+ }
+
+
+-UINT16 XclMsodrawing::GetNum() const
+-{
+- return 0x00EC;
+-}
+-
+-
+-sal_Size XclMsodrawing::GetLen() const
+-{
+- return GetDataLen();
+-}
+
+
+ // --- class XclObjList ----------------------------------------------
+@@ -939,6 +918,7 @@
+
+ void ExcBof8_Base::SaveCont( XclExpStream& rStrm )
+ {
++ rStrm.DisableEncryption();
+ rStrm << nVers << nDocType << nRupBuild << nRupYear
+ << nFileHistory << nLowestBiffVer;
+ }
+@@ -999,7 +979,10 @@
+ {
+ nOwnPos = rStrm.GetSvStreamPos();
+ // write dummy position, real position comes later
+- rStrm << sal_uInt32( 0 ) << nGrbit << aUnicodeName;
++ rStrm.DisableEncryption();
++ rStrm << sal_uInt32(0);
++ rStrm.EnableEncryption();
++ rStrm << nGrbit << aUnicodeName;
+ }
+
+
+@@ -1279,33 +1262,73 @@
+ return 8;
+ }
+
++// ============================================================================
+
+-
+-// ---- class XclProtection ------------------------------------------
+-
+-const BYTE XclProtection::pMyData[] =
++struct XclExpTabProtectOption
+ {
+- 0x12, 0x00, 0x02, 0x00, 0x01, 0x00, // PROTECT
+- 0xDD, 0x00, 0x02, 0x00, 0x01, 0x00, // SCENPROTECT
+- 0x63, 0x00, 0x02, 0x00, 0x01, 0x00 // OBJPROTECT
++ ScTableProtection::Option eOption;
++ sal_uInt16 nMask;
+ };
+-const sal_Size XclProtection::nMyLen = sizeof( XclProtection::pMyData );
+
+-sal_Size XclProtection::GetLen( void ) const
++XclExpSheetProtectOptions::XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab ) :
++ XclExpRecord( 0x0867, 23 )
+ {
+- return nMyLen;
+-}
++ static const XclExpTabProtectOption aTable[] =
++ {
++ { ScTableProtection::OBJECTS, 0x0001 },
++ { ScTableProtection::SCENARIOS, 0x0002 },
++ { ScTableProtection::FORMAT_CELLS, 0x0004 },
++ { ScTableProtection::FORMAT_COLUMNS, 0x0008 },
++ { ScTableProtection::FORMAT_ROWS, 0x0010 },
++ { ScTableProtection::INSERT_COLUMNS, 0x0020 },
++ { ScTableProtection::INSERT_ROWS, 0x0040 },
++ { ScTableProtection::INSERT_HYPERLINKS, 0x0080 },
++
++ { ScTableProtection::DELETE_COLUMNS, 0x0100 },
++ { ScTableProtection::DELETE_ROWS, 0x0200 },
++ { ScTableProtection::SELECT_LOCKED_CELLS, 0x0400 },
++ { ScTableProtection::SORT, 0x0800 },
++ { ScTableProtection::AUTOFILTER, 0x1000 },
++ { ScTableProtection::PIVOT_TABLES, 0x2000 },
++ { ScTableProtection::SELECT_UNLOCKED_CELLS, 0x4000 },
+
++ { ScTableProtection::NONE, 0x0000 }
++ };
+
+-const BYTE* XclProtection::GetData( void ) const
+-{
+- return pMyData;
++ mnOptions = 0x0000;
++ ScTableProtection* pProtect = rRoot.GetDoc().GetTabProtection(nTab);
++ if (!pProtect)
++ return;
++
++ for (int i = 0; aTable[i].nMask != 0x0000; ++i)
++ {
++ if ( pProtect->isOptionEnabled(aTable[i].eOption) )
++ mnOptions |= aTable[i].nMask;
++ }
+ }
+
++void XclExpSheetProtectOptions::WriteBody( XclExpStream& rStrm )
++{
++ sal_uInt16 nBytes = 0x0867;
++ rStrm << nBytes;
+
++ sal_uChar nZero = 0x00;
++ for (int i = 0; i < 9; ++i)
++ rStrm << nZero;
+
++ nBytes = 0x0200;
++ rStrm << nBytes;
++ nBytes = 0x0100;
++ rStrm << nBytes;
++ nBytes = 0xFFFF;
++ rStrm << nBytes << nBytes;
+
++ rStrm << mnOptions;
++ nBytes = 0;
++ rStrm << nBytes;
++}
+
++// ============================================================================
+
+
+
+@@ -1393,3 +1416,252 @@
+ XclExpBoolRecord( 0x000F, rDoc.GetAddressConvention() != ScAddress::CONV_XL_R1C1 )
+ {
+ }
++
++// ============================================================================
++
++XclExpFilePass::XclExpFilePass( const XclExpRoot& rRoot ) :
++ XclExpRecord(0x002F, 54),
++ mrRoot(rRoot)
++{
++}
++
++XclExpFilePass::~XclExpFilePass()
++{
++}
++
++void XclExpFilePass::WriteBody( XclExpStream& rStrm )
++{
++ static const sal_uInt8 nDocId[] = {
++ 0x17, 0xf7, 0x01, 0x08, 0xea, 0xad, 0x30, 0x5c,
++ 0x1a, 0x95, 0xa5, 0x75, 0xd6, 0x79, 0xcd, 0x8d };
++
++
++ static const sal_uInt8 nSalt[] = {
++ 0xa4, 0x5b, 0xf7, 0xe9, 0x9f, 0x55, 0x21, 0xc5,
++ 0xc5, 0x56, 0xa8, 0x0d, 0x39, 0x05, 0x3a, 0xb4 };
++
++
++ static const sal_uInt8 nSaltHash[] = {
++ 0x8a, 0x23, 0xac, 0x6b, 0x53, 0x90, 0xd2, 0x1f,
++ 0xba, 0xf3, 0xcf, 0x20, 0x56, 0x42, 0x57, 0x6b };
++
++ // 0x0000 - neither standard nor strong encryption
++ // 0x0001 - standard or strong encryption
++ rStrm << static_cast<sal_uInt16>(0x0001);
++
++ // 0x0000 - non standard encryption
++ // 0x0001 - standard encryption
++ sal_uInt16 nStdEnc = 0x0001;
++ rStrm << nStdEnc << nStdEnc;
++
++ rStrm.Write(nDocId, 16);
++ rStrm.Write(nSalt, 16);
++ rStrm.Write(nSaltHash, 16);
++
++ XclExpEncrypterRef xEnc( new XclExpBiff8Encrypter(mrRoot, nDocId, nSalt, nSaltHash) );
++ rStrm.SetEncrypter(xEnc);
++}
++
++// ============================================================================
++
++XclExpFnGroupCount::XclExpFnGroupCount() :
++ XclExpRecord(0x009C, 2)
++{
++}
++
++XclExpFnGroupCount::~XclExpFnGroupCount()
++{
++}
++
++void XclExpFnGroupCount::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(14);
++}
++
++// ============================================================================
++
++XclExpInterfaceHdr::XclExpInterfaceHdr() :
++ XclExpRecord(0x00E1, 2)
++{
++}
++
++XclExpInterfaceHdr::~XclExpInterfaceHdr()
++{
++}
++
++void XclExpInterfaceHdr::WriteBody( XclExpStream& rStrm )
++{
++ // The value must be the same value as the CODEPAGE record.
++ rStrm.DisableEncryption();
++ rStrm << static_cast<sal_uInt16>(0x04B0);
++}
++
++// ============================================================================
++
++XclExpInterfaceEnd::XclExpInterfaceEnd() :
++ XclExpRecord(0x00E2, 0)
++{
++}
++
++XclExpInterfaceEnd::~XclExpInterfaceEnd()
++{
++}
++
++void XclExpInterfaceEnd::WriteBody( XclExpStream& /*rStrm*/ )
++{
++}
++
++// ============================================================================
++
++XclExpMMS::XclExpMMS() :
++ XclExpRecord(0x00C1, 2)
++{
++}
++
++XclExpMMS::~XclExpMMS()
++{
++}
++
++void XclExpMMS::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpWriteAccess::XclExpWriteAccess() :
++ XclExpRecord(0x005C, 112)
++{
++}
++
++XclExpWriteAccess::~XclExpWriteAccess()
++{
++}
++
++void XclExpWriteAccess::WriteBody( XclExpStream& rStrm )
++{
++ static const sal_uInt8 aData[] = {
++ 0x04, 0x00, 0x00, 'C', 'a', 'l', 'c', 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
++
++ sal_Size nDataSize = sizeof(aData);
++ for (sal_Size i = 0; i < nDataSize; ++i)
++ rStrm << aData[i];
++}
++
++// ============================================================================
++
++XclExpCodePage::XclExpCodePage() :
++ XclExpRecord(0x0042, 2)
++{
++}
++
++XclExpCodePage::~XclExpCodePage()
++{
++}
++
++void XclExpCodePage::WriteBody( XclExpStream& rStrm )
++{
++ // 0x04B0 : UTF-16 (BIFF8)
++ rStrm << static_cast<sal_uInt16>(0x04B0);
++}
++
++// ============================================================================
++
++XclExpDSF::XclExpDSF() :
++ XclExpRecord(0x0161, 2)
++{
++}
++
++XclExpDSF::~XclExpDSF()
++{
++}
++
++void XclExpDSF::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpProt4Rev::XclExpProt4Rev() :
++ XclExpRecord(0x01AF, 2)
++{
++}
++
++XclExpProt4Rev::~XclExpProt4Rev()
++{
++}
++
++void XclExpProt4Rev::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpProt4RevPass::XclExpProt4RevPass() :
++ XclExpRecord(0x01BC, 2)
++{
++}
++
++XclExpProt4RevPass::~XclExpProt4RevPass()
++{
++}
++
++void XclExpProt4RevPass::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpUnknown01C0::XclExpUnknown01C0() :
++ XclExpRecord(0x01C0, 0)
++{
++}
++
++XclExpUnknown01C0::~XclExpUnknown01C0()
++{
++}
++
++void XclExpUnknown01C0::WriteBody( XclExpStream& /*rStrm*/ )
++{
++}
++
++// ============================================================================
++
++static const sal_uInt8 nData01C1[] = {
++ 0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00
++};
++
++XclExpUnknown01C1::XclExpUnknown01C1() :
++ XclExpDummyRecord(0x01C1, nData01C1, sizeof(nData01C1))
++{
++}
++
++// ============================================================================
++
++static const sal_uInt8 nData0863[] = {
++ 0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02
++};
++
++XclExpUnknown0863::XclExpUnknown0863() :
++ XclExpDummyRecord(0x0863, nData0863, sizeof(nData0863))
++{
++}
++
+Index: sc/source/filter/xml/xmlbodyi.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/xml/xmlbodyi.cxx,v
+retrieving revision 1.29
+retrieving revision 1.29.166.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.29 -r1.29.166.1
+--- sc/source/filter/xml/xmlbodyi.cxx 27 Feb 2007 12:49:06 -0000 1.29
++++ sc/source/filter/xml/xmlbodyi.cxx 3 Jan 2008 16:57:35 -0000 1.29.166.1
+@@ -39,9 +39,8 @@
+
+ // INCLUDE ---------------------------------------------------------------
+
+-#ifndef SC_DOCUMENT_HXX
+ #include "document.hxx"
+-#endif
++#include "tabprotection.hxx"
+
+ #include "xmlbodyi.hxx"
+ #include "xmltabi.hxx"
+@@ -99,6 +98,8 @@
+ #include <tools/debug.hxx>
+ #endif
+
++#include <memory>
++
+ using namespace com::sun::star;
+ using namespace xmloff::token;
+
+@@ -291,10 +292,17 @@
+ // #i37959# handle document protection after the sheet settings
+ if (bProtected)
+ {
++ ::std::auto_ptr<ScDocProtection> pProtection(new ScDocProtection);
++ pProtection->setProtected(true);
++
+ uno::Sequence<sal_Int8> aPass;
+ if (sPassword.getLength())
++ {
+ SvXMLUnitConverter::decodeBase64(aPass, sPassword);
+- pDoc->SetDocProtection(bProtected, aPass);
++ pProtection->setPasswordHash(aPass, PASSHASH_OOO);
++ }
++
++ pDoc->SetDocProtection(pProtection.get());
+ }
+ }
+ GetScImport().UnlockSolarMutex();
+Index: sc/source/filter/xml/xmlexprt.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/xml/xmlexprt.cxx,v
+retrieving revision 1.210
+retrieving revision 1.207.68.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.210 -r1.207.68.3
+--- sc/source/filter/xml/xmlexprt.cxx 26 Feb 2008 14:54:03 -0000 1.210
++++ sc/source/filter/xml/xmlexprt.cxx 6 Mar 2008 15:00:32 -0000 1.207.68.3
+@@ -72,6 +72,7 @@
+ #include "rangeutl.hxx"
+ #include "convuno.hxx"
+ #include "postit.hxx"
++#include "tabprotection.hxx"
+
+ #include <xmloff/xmltoken.hxx>
+ #include <xmloff/xmlnmspe.hxx>
+@@ -1404,7 +1405,11 @@
+ {
+ AddAttribute(XML_NAMESPACE_TABLE, XML_STRUCTURE_PROTECTED, XML_TRUE);
+ rtl::OUStringBuffer aBuffer;
+- SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetDocPassword());
++ uno::Sequence<sal_Int8> aPassHash;
++ const ScDocProtection* p = pDoc->GetDocProtection();
++ if (p)
++ aPassHash = p->getPasswordHash(PASSHASH_OOO);
++ SvXMLUnitConverter::encodeBase64(aBuffer, aPassHash);
+ if (aBuffer.getLength())
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+ }
+@@ -1422,11 +1427,13 @@
+ DBG_ERROR("no shared data setted");
+ }
+ ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
+- if (GetModel().is())
+- {
++ if (!GetModel().is())
++ return;
++
+ uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
+- if ( xSpreadDoc.is() )
+- {
++ if ( !xSpreadDoc.is() )
++ return;
++
+ uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
+ if ( xIndex.is() )
+ {
+@@ -1476,7 +1483,11 @@
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
+ rtl::OUStringBuffer aBuffer;
+ if (pDoc)
+- SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetTabPassword(static_cast<SCTAB>(nTable)));
++ {
++ ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
++ if (pProtect)
++ SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO));
++ }
+ if (aBuffer.getLength())
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+ }
+@@ -1581,6 +1592,7 @@
+ IncrementProgressBar(sal_False);
+ }
+ }
++
+ WriteNamedExpressions(xSpreadDoc);
+ aExportDatabaseRanges.WriteDatabaseRanges(xSpreadDoc);
+ ScXMLExportDataPilot aExportDataPilot(*this);
+@@ -1590,8 +1602,6 @@
+ aExportDDELinks.WriteDDELinks(xSpreadDoc);
+ IncrementProgressBar(sal_True, 0);
+ GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
+- }
+- }
+ }
+
+ void ScXMLExport::_ExportStyles( sal_Bool bUsed )
+Index: sc/source/filter/xml/xmlsubti.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/filter/xml/xmlsubti.cxx,v
+retrieving revision 1.47
+retrieving revision 1.47.166.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.47 -r1.47.166.2
+--- sc/source/filter/xml/xmlsubti.cxx 27 Feb 2007 12:53:21 -0000 1.47
++++ sc/source/filter/xml/xmlsubti.cxx 3 Jan 2008 17:41:45 -0000 1.47.166.2
+@@ -55,6 +55,7 @@
+ #ifndef _SC_XMLSTYLESIMPORTHELPER_HXX
+ #include "XMLStylesImportHelper.hxx"
+ #endif
++#include "tabprotection.hxx"
+
+ #include <xmloff/xmltkmap.hxx>
+ #include <xmloff/nmspmap.hxx>
+@@ -96,6 +97,10 @@
+ #include <com/sun/star/sheet/XArrayFormulaRange.hpp>
+ #endif
+
++#include <memory>
++
++using ::std::auto_ptr;
++
+ //------------------------------------------------------------------
+
+ using namespace com::sun::star;
+@@ -679,13 +684,10 @@
+ {
+ uno::Sequence<sal_Int8> aPass;
+ SvXMLUnitConverter::decodeBase64(aPass, sPassword);
+- rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), bProtection, aPass);
+- /*uno::Reference <util::XProtectable> xProtectable(xCurrentSheet, uno::UNO_QUERY);
+- if (xProtectable.is())
+- {
+- rtl::OUString sKey;
+- xProtectable->protect(sKey);
+- }*/
++ auto_ptr<ScTableProtection> pProtect(new ScTableProtection);
++ pProtect->setProtected(bProtection);
++ pProtect->setPasswordHash(aPass, PASSHASH_OOO);
++ rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), pProtect.get());
+ }
+
+ rImport.UnlockSolarMutex();
+Index: sc/source/ui/docshell/docfunc.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/docshell/docfunc.cxx,v
+retrieving revision 1.67
+retrieving revision 1.66.70.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.67 -r1.66.70.3
+--- sc/source/ui/docshell/docfunc.cxx 10 Jan 2008 13:15:26 -0000 1.67
++++ sc/source/ui/docshell/docfunc.cxx 15 Feb 2008 00:42:17 -0000 1.66.70.3
+@@ -99,7 +99,12 @@
+ #include "editable.hxx"
+ #include "compiler.hxx"
+ #include "scui_def.hxx" //CHINA001
++#include "tabprotection.hxx"
++
++#include <memory>
++
+ using namespace com::sun::star;
++using ::com::sun::star::uno::Sequence;
+
+ // STATIC DATA -----------------------------------------------------------
+
+@@ -2607,103 +2612,127 @@
+
+ //------------------------------------------------------------------------
+
+-BOOL lcl_ValidPassword( ScDocument* pDoc, SCTAB nTab,
+- const String& rPassword,
+- uno::Sequence<sal_Int8>* pReturnOld = NULL )
++BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL /*bApi*/ )
+ {
+- uno::Sequence<sal_Int8> aOldPassword;
+- if ( nTab == TABLEID_DOC )
++ ScDocument* pDoc = rDocShell.GetDocument();
++ if (nTab == TABLEID_DOC)
++ {
++ // document protection
++
++ pDoc->SetDocProtection(true, rPassword);
++ if (pDoc->IsUndoEnabled())
+ {
+- if (pDoc->IsDocProtected())
+- aOldPassword = pDoc->GetDocPassword();
++ ScDocProtection* pProtect = pDoc->GetDocProtection();
++ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
++ if (pProtect)
++ {
++ ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
++ p->setProtected(true); // just in case ...
++ rDocShell.GetUndoManager()->AddUndoAction(
++ new ScUndoDocProtect(&rDocShell, p) );
++ // ownership of auto_ptr is transferred to ScUndoDocProtect.
++ }
++ }
+ }
+ else
+ {
+- if (pDoc->IsTabProtected(nTab))
+- aOldPassword = pDoc->GetTabPassword(nTab);
++ // sheet protection
++
++ pDoc->SetTabProtection(nTab, true, rPassword);
++ if (pDoc->IsUndoEnabled())
++ {
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
++ if (pProtect)
++ {
++ ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
++ p->setProtected(true); // just in case ...
++ rDocShell.GetUndoManager()->AddUndoAction(
++ new ScUndoTabProtect(&rDocShell, nTab, p) );
++ // ownership of auto_ptr now transferred to ScUndoTabProtect.
++ }
++ }
+ }
+
+- if (pReturnOld)
+- *pReturnOld = aOldPassword;
++ rDocShell.PostPaintGridAll();
++ ScDocShellModificator aModificator( rDocShell );
++ aModificator.SetDocumentModified();
+
+- return ((aOldPassword.getLength() == 0) || SvPasswordHelper::CompareHashPassword(aOldPassword, rPassword));
++ return true;
+ }
+
+-BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL bApi )
++BOOL ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi )
+ {
+- ScDocShellModificator aModificator( rDocShell );
+-
+ ScDocument* pDoc = rDocShell.GetDocument();
+- BOOL bUndo(pDoc->IsUndoEnabled());
+- BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword);
+- if ( bOk )
+- {
+- uno::Sequence<sal_Int8> aPass;
+- if (rPassword.Len())
+- SvPasswordHelper::GetHashPassword(aPass, rPassword);
+
+- if (bUndo)
++ if (nTab == TABLEID_DOC)
+ {
+- rDocShell.GetUndoManager()->AddUndoAction(
+- new ScUndoProtect( &rDocShell, nTab, TRUE, aPass ) );
+- }
++ // document protection
+
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( TRUE, aPass );
+- else
+- pDoc->SetTabProtection( nTab, TRUE, aPass );
+-
+- rDocShell.PostPaintGridAll();
+- aModificator.SetDocumentModified();
+- }
+- else if (!bApi)
+- {
+- // different password was set before
++ ScDocProtection* pDocProtect = pDoc->GetDocProtection();
++ if (!pDocProtect || !pDocProtect->isProtected())
++ // already unprotected (should not happen)!
++ return true;
+
+-//! rDocShell.ErrorMessage(...);
++ // save the protection state before unprotect (for undo).
++ ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
+
++ if (!pDocProtect->verifyPassword(rPassword))
++ {
++ if (!bApi)
++ {
+ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+ aBox.Execute();
+ }
++ return false;
++ }
+
+- return bOk;
+-}
++ pDoc->SetDocProtection(NULL);
++ if (pDoc->IsUndoEnabled())
++ {
++ pProtectCopy->setProtected(false);
++ rDocShell.GetUndoManager()->AddUndoAction(
++ new ScUndoDocProtect(&rDocShell, pProtectCopy) );
++ // ownership of auto_ptr now transferred to ScUndoTabProtect.
++ }
++ }
++ else
++ {
++ // sheet protection
+
+-BOOL ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi )
+-{
+- ScDocShellModificator aModificator( rDocShell );
++ ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
++ if (!pTabProtect || !pTabProtect->isProtected())
++ // already unprotected (should not happen)!
++ return true;
+
+- ScDocument* pDoc = rDocShell.GetDocument();
+- BOOL bUndo(pDoc->IsUndoEnabled());
+- uno::Sequence<sal_Int8> aOldPassword;
+- uno::Sequence<sal_Int8> aPass;
+- BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword, &aOldPassword );
+- if ( bOk )
++ // save the protection state before unprotect (for undo).
++ ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
++
++ if (!pTabProtect->verifyPassword(rPassword))
+ {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( FALSE, aEmptyPass );
+- else
+- pDoc->SetTabProtection( nTab, FALSE, aEmptyPass );
++ if (!bApi)
++ {
++ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
++ aBox.Execute();
++ }
++ return false;
++ }
+
+- if (bUndo)
++ pDoc->SetTabProtection(nTab, NULL);
++ if (pDoc->IsUndoEnabled())
+ {
++ pProtectCopy->setProtected(false);
+ rDocShell.GetUndoManager()->AddUndoAction(
+- new ScUndoProtect( &rDocShell, nTab, FALSE, aOldPassword ) );
++ new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
++ // ownership of auto_ptr now transferred to ScUndoTabProtect.
++ }
+ }
+
+ rDocShell.PostPaintGridAll();
++ ScDocShellModificator aModificator( rDocShell );
+ aModificator.SetDocumentModified();
+- }
+- else if (!bApi)
+- {
+-//! rDocShell.ErrorMessage(...);
+-
+- InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+- aBox.Execute();
+- }
+
+- return bOk;
++ return true;
+ }
+
+ //------------------------------------------------------------------------
+Index: sc/source/ui/docshell/docsh.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/docshell/docsh.cxx,v
+retrieving revision 1.96
+retrieving revision 1.93.54.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.96 -r1.93.54.2
+--- sc/source/ui/docshell/docsh.cxx 5 Feb 2008 15:45:03 -0000 1.96
++++ sc/source/ui/docshell/docsh.cxx 15 Feb 2008 00:42:09 -0000 1.93.54.2
+@@ -1826,6 +1826,8 @@
+ aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
+ pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt );
+
++#if 0 // TODO: Disable this for now.
++
+ /* #115980 #If the imported document contained an encrypted password -
+ determine if we should save without it. */
+ ScExtDocSettings& rDocSett = pExtDocOpt->GetDocSettings();
+@@ -1835,6 +1837,7 @@
+ // #i42858# warn only on time
+ rDocSett.mbEncrypted = false;
+ }
++#endif
+ }
+
+ if( bDoSave )
+Index: sc/source/ui/docshell/docsh5.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/docshell/docsh5.cxx,v
+retrieving revision 1.18
+retrieving revision 1.17.166.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.18 -r1.17.166.2
+--- sc/source/ui/docshell/docsh5.cxx 29 Jan 2008 15:41:57 -0000 1.18
++++ sc/source/ui/docshell/docsh5.cxx 15 Feb 2008 00:42:12 -0000 1.17.166.2
+@@ -828,7 +828,7 @@
+ ++nAdjSource; // new position of source table after CopyTab
+
+ if ( aDocument.IsTabProtected( nAdjSource ) )
+- aDocument.SetTabProtection( nDestTab, TRUE, aDocument.GetTabPassword( nAdjSource ) );
++ aDocument.CopyTabProtection(nAdjSource, nDestTab);
+
+ if (bRecord)
+ {
+Index: sc/source/ui/inc/undotab.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/inc/undotab.hxx,v
+retrieving revision 1.9
+retrieving revision 1.9.264.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.9 -r1.9.264.3
+--- sc/source/ui/inc/undotab.hxx 18 Oct 2006 12:28:14 -0000 1.9
++++ sc/source/ui/inc/undotab.hxx 7 Jan 2008 21:50:08 -0000 1.9.264.3
+@@ -64,11 +64,15 @@
+ #include <com/sun/star/uno/Sequence.hxx>
+ #endif
+
++#include <memory>
++
+ class ScDocShell;
+ class ScDocument;
+ class SdrUndoAction;
+ class ScPrintRangeSaver;
+ class SdrObject;
++class ScDocProtection;
++class ScTableProtection;
+
+ //----------------------------------------------------------------------------
+
+@@ -348,14 +352,15 @@
+ void DoChange( BOOL bShow ) const;
+ };
+
++// ============================================================================
+
+-class ScUndoProtect : public ScSimpleUndo
++/** This class implements undo & redo of document protect & unprotect
++ operations. */
++class ScUndoDocProtect : public ScSimpleUndo
+ {
+ public:
+- TYPEINFO();
+- ScUndoProtect( ScDocShell* pShell, SCTAB nNewTab,
+- BOOL bNewProtect, const com::sun::star::uno::Sequence<sal_Int8>& rNewPassword );
+- virtual ~ScUndoProtect();
++ ScUndoDocProtect(ScDocShell* pShell, ::std::auto_ptr<ScDocProtection> pProtectSettings);
++ virtual ~ScUndoDocProtect();
+
+ virtual void Undo();
+ virtual void Redo();
+@@ -365,11 +370,34 @@
+ virtual String GetComment() const;
+
+ private:
+- SCTAB nTab;
+- BOOL bProtect;
+- com::sun::star::uno::Sequence<sal_Int8> aPassword;
++ ::std::auto_ptr<ScDocProtection> mpProtectSettings;
++
++ void DoProtect(bool bProtect);
++};
++
++// ============================================================================
++
++/** This class implements undo & redo of both protect and unprotect of
++ sheet. */
++class ScUndoTabProtect : public ScSimpleUndo
++{
++public:
++ ScUndoTabProtect(ScDocShell* pShell, SCTAB nTab,
++ ::std::auto_ptr<ScTableProtection> pProtectSettings);
++ virtual ~ScUndoTabProtect();
++
++ virtual void Undo();
++ virtual void Redo();
++ virtual void Repeat(SfxRepeatTarget& rTarget);
++ virtual BOOL CanRepeat(SfxRepeatTarget& rTarget) const;
++
++ virtual String GetComment() const;
++
++private:
++ SCTAB mnTab;
++ ::std::auto_ptr<ScTableProtection> mpProtectSettings;
+
+- void DoProtect( BOOL bDo );
++ void DoProtect(bool bProtect);
+ };
+
+
+Index: sc/source/ui/undo/undotab.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/undo/undotab.cxx,v
+retrieving revision 1.18
+retrieving revision 1.16.166.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.18 -r1.16.166.6
+--- sc/source/ui/undo/undotab.cxx 19 Feb 2008 15:34:09 -0000 1.18
++++ sc/source/ui/undo/undotab.cxx 6 Mar 2008 15:00:05 -0000 1.16.166.6
+@@ -66,6 +66,7 @@
+ #include "prnsave.hxx"
+ #include "printfun.hxx"
+ #include "chgtrack.hxx"
++#include "tabprotection.hxx"
+
+ // for ScUndoRenameObject - might me moved to another file later
+ #include <svx/svditer.hxx>
+@@ -77,6 +78,8 @@
+ extern BOOL bDrawIsInUndo; //! irgendwo als Member !!!
+
+ using namespace com::sun::star;
++using ::com::sun::star::uno::Sequence;
++using ::std::auto_ptr;
+
+ // STATIC DATA -----------------------------------------------------------
+
+@@ -90,7 +93,6 @@
+ TYPEINIT1(ScUndoImportTab, SfxUndoAction);
+ TYPEINIT1(ScUndoRemoveLink, SfxUndoAction);
+ TYPEINIT1(ScUndoShowHideTab, SfxUndoAction);
+-TYPEINIT1(ScUndoProtect, SfxUndoAction);
+ TYPEINIT1(ScUndoPrintRange, SfxUndoAction);
+ TYPEINIT1(ScUndoScenarioFlags, SfxUndoAction);
+ TYPEINIT1(ScUndoRenameObject, SfxUndoAction);
+@@ -117,12 +119,12 @@
+ SetChangeTrack();
+ }
+
+-__EXPORT ScUndoInsertTab::~ScUndoInsertTab()
++ScUndoInsertTab::~ScUndoInsertTab()
+ {
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoInsertTab::GetComment() const
++String ScUndoInsertTab::GetComment() const
+ {
+ if (bAppend)
+ return ScGlobal::GetRscString( STR_UNDO_APPEND_TAB );
+@@ -143,7 +145,7 @@
+ nEndChangeAction = 0;
+ }
+
+-void __EXPORT ScUndoInsertTab::Undo()
++void ScUndoInsertTab::Undo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ pViewShell->SetTabNo(nTab);
+@@ -164,7 +166,7 @@
+ pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) );
+ }
+
+-void __EXPORT ScUndoInsertTab::Redo()
++void ScUndoInsertTab::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
+@@ -185,14 +187,14 @@
+ SetChangeTrack();
+ }
+
+-void __EXPORT ScUndoInsertTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoInsertTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoInsertTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoInsertTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -216,7 +218,7 @@
+ SetChangeTrack();
+ }
+
+-__EXPORT ScUndoInsertTables::~ScUndoInsertTables()
++ScUndoInsertTables::~ScUndoInsertTables()
+ {
+ String *pStr=NULL;
+ if(pNameList!=NULL)
+@@ -232,7 +234,7 @@
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoInsertTables::GetComment() const
++String ScUndoInsertTables::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB );
+ }
+@@ -257,7 +259,7 @@
+ nStartChangeAction = nEndChangeAction = 0;
+ }
+
+-void __EXPORT ScUndoInsertTables::Undo()
++void ScUndoInsertTables::Undo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ pViewShell->SetTabNo(nTab);
+@@ -287,7 +289,7 @@
+ pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) );
+ }
+
+-void __EXPORT ScUndoInsertTables::Redo()
++void ScUndoInsertTables::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
+@@ -304,14 +306,14 @@
+ SetChangeTrack();
+ }
+
+-void __EXPORT ScUndoInsertTables::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoInsertTables::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoInsertTables::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoInsertTables::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -332,12 +334,12 @@
+ SetChangeTrack();
+ }
+
+-__EXPORT ScUndoDeleteTab::~ScUndoDeleteTab()
++ScUndoDeleteTab::~ScUndoDeleteTab()
+ {
+ theTabs.Remove(0,theTabs.Count());
+ }
+
+-String __EXPORT ScUndoDeleteTab::GetComment() const
++String ScUndoDeleteTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_DELETE_TAB );
+ }
+@@ -371,7 +373,7 @@
+ return nTab;
+ }
+
+-void __EXPORT ScUndoDeleteTab::Undo()
++void ScUndoDeleteTab::Undo()
+ {
+ BeginUndo();
+ int i=0;
+@@ -419,7 +421,7 @@
+ pDoc->SetVisible( nTab, pRefUndoDoc->IsVisible( nTab ) );
+
+ if ( pRefUndoDoc->IsTabProtected( nTab ) )
+- pDoc->SetTabProtection( nTab, TRUE, pRefUndoDoc->GetTabPassword( nTab ) );
++ pDoc->SetTabProtection(nTab, pRefUndoDoc->GetTabProtection(nTab));
+
+ // Drawing-Layer passiert beim MoveUndo::EndUndo
+ // pDoc->TransferDrawPage(pRefUndoDoc, nTab,nTab);
+@@ -455,7 +457,7 @@
+ // EndUndo();
+ }
+
+-void __EXPORT ScUndoDeleteTab::Redo()
++void ScUndoDeleteTab::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ pViewShell->SetTabNo( lcl_GetVisibleTabBefore( *pDocShell->GetDocument(), theTabs[0] ) );
+@@ -474,7 +476,7 @@
+ pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) );
+ }
+
+-void __EXPORT ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ {
+@@ -483,7 +485,7 @@
+ }
+ }
+
+-BOOL __EXPORT ScUndoDeleteTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoDeleteTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -505,11 +507,11 @@
+ sNewName = rNewName;
+ }
+
+-__EXPORT ScUndoRenameTab::~ScUndoRenameTab()
++ScUndoRenameTab::~ScUndoRenameTab()
+ {
+ }
+
+-String __EXPORT ScUndoRenameTab::GetComment() const
++String ScUndoRenameTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_RENAME_TAB );
+ }
+@@ -531,22 +533,22 @@
+ pViewShell->UpdateInputHandler();
+ }
+
+-void __EXPORT ScUndoRenameTab::Undo()
++void ScUndoRenameTab::Undo()
+ {
+ DoChange(nTab, sOldName);
+ }
+
+-void __EXPORT ScUndoRenameTab::Redo()
++void ScUndoRenameTab::Redo()
+ {
+ DoChange(nTab, sNewName);
+ }
+
+-void __EXPORT ScUndoRenameTab::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoRenameTab::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // Repeat macht keinen Sinn
+ }
+
+-BOOL __EXPORT ScUndoRenameTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoRenameTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -570,13 +572,13 @@
+ theNewTabs.Insert(aNewTab[sal::static_int_cast<USHORT>(i)],theNewTabs.Count());
+ }
+
+-__EXPORT ScUndoMoveTab::~ScUndoMoveTab()
++ScUndoMoveTab::~ScUndoMoveTab()
+ {
+ theNewTabs.Remove(0,theNewTabs.Count());
+ theOldTabs.Remove(0,theOldTabs.Count());
+ }
+
+-String __EXPORT ScUndoMoveTab::GetComment() const
++String ScUndoMoveTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_MOVE_TAB );
+ }
+@@ -623,22 +625,22 @@
+ pDocShell->PostDataChanged();
+ }
+
+-void __EXPORT ScUndoMoveTab::Undo()
++void ScUndoMoveTab::Undo()
+ {
+ DoChange( TRUE );
+ }
+
+-void __EXPORT ScUndoMoveTab::Redo()
++void ScUndoMoveTab::Redo()
+ {
+ DoChange( FALSE );
+ }
+
+-void __EXPORT ScUndoMoveTab::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoMoveTab::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // kein Repeat ! ? !
+ }
+
+-BOOL __EXPORT ScUndoMoveTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoMoveTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -665,12 +667,12 @@
+ theNewTabs.Insert(aNewTab[sal::static_int_cast<USHORT>(i)],theNewTabs.Count());
+ }
+
+-__EXPORT ScUndoCopyTab::~ScUndoCopyTab()
++ScUndoCopyTab::~ScUndoCopyTab()
+ {
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoCopyTab::GetComment() const
++String ScUndoCopyTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_COPY_TAB );
+ }
+@@ -689,7 +691,7 @@
+ pDocShell->PostDataChanged();
+ }
+
+-void __EXPORT ScUndoCopyTab::Undo()
++void ScUndoCopyTab::Undo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+@@ -722,7 +724,7 @@
+ DoChange();
+ }
+
+-void __EXPORT ScUndoCopyTab::Redo()
++void ScUndoCopyTab::Redo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+@@ -761,7 +763,7 @@
+ }
+
+ if ( pDoc->IsTabProtected( nAdjSource ) )
+- pDoc->SetTabProtection( nNewTab, TRUE, pDoc->GetTabPassword( nAdjSource ) );
++ pDoc->CopyTabProtection(nAdjSource, nNewTab);
+ }
+
+ RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted
+@@ -772,12 +774,12 @@
+
+ }
+
+-void __EXPORT ScUndoCopyTab::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoCopyTab::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // kein Repeat ! ? !
+ }
+
+-BOOL __EXPORT ScUndoCopyTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoCopyTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -805,17 +807,17 @@
+ {
+ }
+
+-__EXPORT ScUndoMakeScenario::~ScUndoMakeScenario()
++ScUndoMakeScenario::~ScUndoMakeScenario()
+ {
+ delete pUndoDoc;
+ }
+
+-String __EXPORT ScUndoMakeScenario::GetComment() const
++String ScUndoMakeScenario::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_MAKESCENARIO );
+ }
+
+-void __EXPORT ScUndoMakeScenario::Undo()
++void ScUndoMakeScenario::Undo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+ pDoc->DeleteTab( nDestTab );
+@@ -829,7 +831,7 @@
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ }
+
+-void __EXPORT ScUndoMakeScenario::Redo()
++void ScUndoMakeScenario::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+@@ -843,7 +845,7 @@
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ }
+
+-void __EXPORT ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ {
+@@ -851,7 +853,7 @@
+ }
+ }
+
+-BOOL __EXPORT ScUndoMakeScenario::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoMakeScenario::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -874,13 +876,13 @@
+ pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
+ }
+
+-__EXPORT ScUndoImportTab::~ScUndoImportTab()
++ScUndoImportTab::~ScUndoImportTab()
+ {
+ delete pRedoDoc;
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoImportTab::GetComment() const
++String ScUndoImportTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB );
+ }
+@@ -907,7 +909,7 @@
+ PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS );
+ }
+
+-void __EXPORT ScUndoImportTab::Undo()
++void ScUndoImportTab::Undo()
+ {
+ //! eingefuegte Bereichsnamen etc.
+
+@@ -943,7 +945,8 @@
+ }
+
+ if ( pDoc->IsTabProtected( nTabPos ) )
+- pRedoDoc->SetTabProtection( nTabPos, TRUE, pDoc->GetTabPassword( nTabPos ) );
++ pRedoDoc->SetTabProtection(nTabPos, pDoc->GetTabProtection(nTabPos));
++// pRedoDoc->SetTabProtection( nTabPos, TRUE, pDoc->GetTabPassword( nTabPos ) );
+ }
+
+ }
+@@ -958,7 +961,7 @@
+ DoChange();
+ }
+
+-void __EXPORT ScUndoImportTab::Redo()
++void ScUndoImportTab::Redo()
+ {
+ if (!pRedoDoc)
+ {
+@@ -997,7 +1000,8 @@
+ }
+
+ if ( pRedoDoc->IsTabProtected( nTabPos ) )
+- pDoc->SetTabProtection( nTabPos, TRUE, pRedoDoc->GetTabPassword( nTabPos ) );
++ pDoc->SetTabProtection(nTabPos, pRedoDoc->GetTabProtection(nTabPos));
++// pDoc->SetTabProtection( nTabPos, TRUE, pRedoDoc->GetTabPassword( nTabPos ) );
+ }
+
+ RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted
+@@ -1005,14 +1009,14 @@
+ DoChange();
+ }
+
+-void __EXPORT ScUndoImportTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoImportTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoImportTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoImportTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -1060,14 +1064,14 @@
+ }
+ }
+
+-__EXPORT ScUndoRemoveLink::~ScUndoRemoveLink()
++ScUndoRemoveLink::~ScUndoRemoveLink()
+ {
+ delete pTabs;
+ delete pModes;
+ delete[] pTabNames;
+ }
+
+-String __EXPORT ScUndoRemoveLink::GetComment() const
++String ScUndoRemoveLink::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_REMOVELINK );
+ }
+@@ -1084,22 +1088,22 @@
+ pDocShell->UpdateLinks();
+ }
+
+-void __EXPORT ScUndoRemoveLink::Undo()
++void ScUndoRemoveLink::Undo()
+ {
+ DoChange( TRUE );
+ }
+
+-void __EXPORT ScUndoRemoveLink::Redo()
++void ScUndoRemoveLink::Redo()
+ {
+ DoChange( FALSE );
+ }
+
+-void __EXPORT ScUndoRemoveLink::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoRemoveLink::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // gippsnich
+ }
+
+-BOOL __EXPORT ScUndoRemoveLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoRemoveLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -1117,7 +1121,7 @@
+ {
+ }
+
+-__EXPORT ScUndoShowHideTab::~ScUndoShowHideTab()
++ScUndoShowHideTab::~ScUndoShowHideTab()
+ {
+ }
+
+@@ -1134,17 +1138,17 @@
+ pDocShell->SetDocumentModified();
+ }
+
+-void __EXPORT ScUndoShowHideTab::Undo()
++void ScUndoShowHideTab::Undo()
+ {
+ DoChange(!bShow);
+ }
+
+-void __EXPORT ScUndoShowHideTab::Redo()
++void ScUndoShowHideTab::Redo()
+ {
+ DoChange(bShow);
+ }
+
+-void __EXPORT ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+@@ -1152,53 +1156,44 @@
+ SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoShowHideTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoShowHideTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+
+-String __EXPORT ScUndoShowHideTab::GetComment() const
++String ScUndoShowHideTab::GetComment() const
+ {
+ USHORT nId = bShow ? STR_UNDO_SHOWTAB : STR_UNDO_HIDETAB;
+ return ScGlobal::GetRscString( nId );
+ }
+
+-// -----------------------------------------------------------------------
+-//
+-// Tabelle/Dokument schuetzen oder Schutz aufheben
+-//
++// ============================================================================
+
+-ScUndoProtect::ScUndoProtect( ScDocShell* pShell, SCTAB nNewTab,
+- BOOL bNewProtect, const uno::Sequence<sal_Int8>& rNewPassword ) :
+- ScSimpleUndo( pShell ),
+- nTab( nNewTab ),
+- bProtect( bNewProtect ),
+- aPassword( rNewPassword )
++ScUndoDocProtect::ScUndoDocProtect(ScDocShell* pShell, auto_ptr<ScDocProtection> pProtectSettings) :
++ ScSimpleUndo(pShell),
++ mpProtectSettings(pProtectSettings)
+ {
+ }
+
+-__EXPORT ScUndoProtect::~ScUndoProtect()
++ScUndoDocProtect::~ScUndoDocProtect()
+ {
+ }
+
+-void ScUndoProtect::DoProtect( BOOL bDo )
++void ScUndoDocProtect::DoProtect(bool bProtect)
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+- if (bDo)
++ if (bProtect)
+ {
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( TRUE, aPassword );
+- else
+- pDoc->SetTabProtection( nTab, TRUE, aPassword );
++ // set protection.
++ auto_ptr<ScDocProtection> pCopy(new ScDocProtection(*mpProtectSettings));
++ pCopy->setProtected(true);
++ pDoc->SetDocProtection(pCopy.get());
+ }
+ else
+ {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( FALSE, aEmptyPass );
+- else
+- pDoc->SetTabProtection( nTab, FALSE, aEmptyPass );
++ // remove protection.
++ pDoc->SetDocProtection(NULL);
+ }
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+@@ -1211,37 +1206,103 @@
+ pDocShell->PostPaintGridAll();
+ }
+
+-void __EXPORT ScUndoProtect::Undo()
++void ScUndoDocProtect::Undo()
+ {
+ BeginUndo();
+- DoProtect( !bProtect );
++ DoProtect(!mpProtectSettings->isProtected());
+ EndUndo();
+ }
+
+-void __EXPORT ScUndoProtect::Redo()
++void ScUndoDocProtect::Redo()
+ {
+ BeginRedo();
+- DoProtect( bProtect );
++ DoProtect(mpProtectSettings->isProtected());
+ EndRedo();
+ }
+
+-void __EXPORT ScUndoProtect::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoDocProtect::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // gippsnich
+ }
+
+-BOOL __EXPORT ScUndoProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoDocProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE; // gippsnich
+ }
+
+-String __EXPORT ScUndoProtect::GetComment() const
++String ScUndoDocProtect::GetComment() const
+ {
+- USHORT nId;
+- if ( nTab == TABLEID_DOC )
+- nId = bProtect ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC;
++ USHORT nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC;
++ return ScGlobal::GetRscString( nId );
++}
++
++// ============================================================================
++
++ScUndoTabProtect::ScUndoTabProtect(ScDocShell* pShell, SCTAB nTab, auto_ptr<ScTableProtection> pProtectSettings) :
++ ScSimpleUndo(pShell),
++ mnTab(nTab),
++ mpProtectSettings(pProtectSettings)
++{
++}
++
++ScUndoTabProtect::~ScUndoTabProtect()
++{
++}
++
++void ScUndoTabProtect::DoProtect(bool bProtect)
++{
++ ScDocument* pDoc = pDocShell->GetDocument();
++
++ if (bProtect)
++ {
++ // set protection.
++ auto_ptr<ScTableProtection> pCopy(new ScTableProtection(*mpProtectSettings));
++ pCopy->setProtected(true);
++ pDoc->SetTabProtection(mnTab, pCopy.get());
++ }
+ else
+- nId = bProtect ? STR_UNDO_PROTECT_TAB : STR_UNDO_UNPROTECT_TAB;
++ {
++ // remove protection.
++ pDoc->SetTabProtection(mnTab, NULL);
++ }
++
++ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
++ if (pViewShell)
++ {
++ pViewShell->UpdateLayerLocks();
++ pViewShell->UpdateInputHandler(TRUE); // damit sofort wieder eingegeben werden kann
++ }
++
++ pDocShell->PostPaintGridAll();
++}
++
++void ScUndoTabProtect::Undo()
++{
++ BeginUndo();
++ DoProtect(!mpProtectSettings->isProtected());
++ EndUndo();
++}
++
++void ScUndoTabProtect::Redo()
++{
++ BeginRedo();
++ DoProtect(mpProtectSettings->isProtected());
++ EndRedo();
++}
++
++void ScUndoTabProtect::Repeat(SfxRepeatTarget& /* rTarget */)
++{
++ // gippsnich
++}
++
++BOOL ScUndoTabProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++{
++ return FALSE; // gippsnich
++}
++
++String ScUndoTabProtect::GetComment() const
++{
++ USHORT nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_TAB : STR_UNDO_UNPROTECT_TAB;
+ return ScGlobal::GetRscString( nId );
+ }
+
+@@ -1259,7 +1320,7 @@
+ {
+ }
+
+-__EXPORT ScUndoPrintRange::~ScUndoPrintRange()
++ScUndoPrintRange::~ScUndoPrintRange()
+ {
+ delete pOldRanges;
+ delete pNewRanges;
+@@ -1282,31 +1343,31 @@
+ pDocShell->PostPaint( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab), PAINT_GRID );
+ }
+
+-void __EXPORT ScUndoPrintRange::Undo()
++void ScUndoPrintRange::Undo()
+ {
+ BeginUndo();
+ DoChange( TRUE );
+ EndUndo();
+ }
+
+-void __EXPORT ScUndoPrintRange::Redo()
++void ScUndoPrintRange::Redo()
+ {
+ BeginRedo();
+ DoChange( FALSE );
+ EndRedo();
+ }
+
+-void __EXPORT ScUndoPrintRange::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoPrintRange::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // gippsnich
+ }
+
+-BOOL __EXPORT ScUndoPrintRange::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoPrintRange::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE; // gippsnich
+ }
+
+-String __EXPORT ScUndoPrintRange::GetComment() const
++String ScUndoPrintRange::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_PRINTRANGES );
+ }
+@@ -1335,16 +1396,16 @@
+ {
+ }
+
+-__EXPORT ScUndoScenarioFlags::~ScUndoScenarioFlags()
++ScUndoScenarioFlags::~ScUndoScenarioFlags()
+ {
+ }
+
+-String __EXPORT ScUndoScenarioFlags::GetComment() const
++String ScUndoScenarioFlags::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_EDITSCENARIO );
+ }
+
+-void __EXPORT ScUndoScenarioFlags::Undo()
++void ScUndoScenarioFlags::Undo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+@@ -1361,7 +1422,7 @@
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ }
+
+-void __EXPORT ScUndoScenarioFlags::Redo()
++void ScUndoScenarioFlags::Redo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+@@ -1378,12 +1439,12 @@
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ }
+
+-void __EXPORT ScUndoScenarioFlags::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoScenarioFlags::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // Repeat macht keinen Sinn
+ }
+
+-BOOL __EXPORT ScUndoScenarioFlags::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoScenarioFlags::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -1483,7 +1544,7 @@
+ {
+ }
+
+-__EXPORT ScUndoLayoutRTL::~ScUndoLayoutRTL()
++ScUndoLayoutRTL::~ScUndoLayoutRTL()
+ {
+ }
+
+@@ -1503,29 +1564,29 @@
+ pDocShell->SetInUndo( FALSE );
+ }
+
+-void __EXPORT ScUndoLayoutRTL::Undo()
++void ScUndoLayoutRTL::Undo()
+ {
+ DoChange(!bRTL);
+ }
+
+-void __EXPORT ScUndoLayoutRTL::Redo()
++void ScUndoLayoutRTL::Redo()
+ {
+ DoChange(bRTL);
+ }
+
+-void __EXPORT ScUndoLayoutRTL::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoLayoutRTL::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute( FID_TAB_RTL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoLayoutRTL::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoLayoutRTL::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+
+-String __EXPORT ScUndoLayoutRTL::GetComment() const
++String ScUndoLayoutRTL::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_TAB_RTL );
+ }
+@@ -1545,7 +1606,7 @@
+ eOldConv = pDocShell->GetDocument()->GetAddressConvention();
+ }
+
+-__EXPORT ScUndoSetAddressConvention::~ScUndoSetAddressConvention()
++ScUndoSetAddressConvention::~ScUndoSetAddressConvention()
+ {
+ }
+
+@@ -1558,17 +1619,17 @@
+ pDocShell->SetInUndo( FALSE );
+ }
+
+-void __EXPORT ScUndoSetAddressConvention::Undo()
++void ScUndoSetAddressConvention::Undo()
+ {
+ DoChange( eOldConv );
+ }
+
+-void __EXPORT ScUndoSetAddressConvention::Redo()
++void ScUndoSetAddressConvention::Redo()
+ {
+ DoChange( eNewConv );
+ }
+
+-void __EXPORT ScUndoSetAddressConvention::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoSetAddressConvention::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ #if 0
+ // erAck: 2006-09-07T23:00+0200 commented out in CWS scr1c1
+@@ -1578,12 +1639,12 @@
+ #endif
+ }
+
+-BOOL __EXPORT ScUndoSetAddressConvention::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoSetAddressConvention::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+
+-String __EXPORT ScUndoSetAddressConvention::GetComment() const
++String ScUndoSetAddressConvention::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_TAB_R1C1 );
+ }
+Index: sc/source/ui/view/gridwin.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/gridwin.cxx,v
+retrieving revision 1.91
+retrieving revision 1.83.16.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.91 -r1.83.16.6
+--- sc/source/ui/view/gridwin.cxx 19 Feb 2008 15:35:00 -0000 1.91
++++ sc/source/ui/view/gridwin.cxx 6 Mar 2008 15:00:21 -0000 1.83.16.6
+@@ -142,6 +142,7 @@
+ #include "userdat.hxx"
+ #include "drwlayer.hxx"
+ #include "attrib.hxx"
++#include "tabprotection.hxx"
+
+ // #114409#
+ #ifndef _SV_SALBTYPE_HXX
+@@ -2025,11 +2026,12 @@
+ Point aPos = rMEvt.GetPosPixel();
+ SCsCOL nPosX;
+ SCsROW nPosY;
++ SCTAB nTab = pViewData->GetTabNo();
+ pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
+- ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, pViewData->GetTabNo() );
++ ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
+ if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
+ {
+- ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
++ ScAddress aCellPos( nPosX, nPosY, nTab );
+ ScDPPositionData aData;
+ pDPObj->GetPositionData( aData, aCellPos );
+
+@@ -2066,6 +2068,23 @@
+ return;
+ }
+
++ // Check for cell protection attribute.
++ ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
++ bool bEditAllowed = true;
++ if ( pProtect && pProtect->isProtected() )
++ {
++ bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
++ bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
++ bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
++
++ if ( bSkipProtected && bSkipUnprotected )
++ bEditAllowed = false;
++ else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
++ bEditAllowed = false;
++ }
++
++ if ( bEditAllowed )
++ {
+ // edit cell contents
+ pViewData->GetViewShell()->UpdateInputHandler();
+ pScMod->SetInputMode( SC_INPUT_TABLE );
+@@ -2076,9 +2095,10 @@
+ MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
+ pEditView->MouseButtonDown( aEditEvt );
+ pEditView->MouseButtonUp( aEditEvt );
+- return;
+ }
+ }
++ return;
++ }
+
+ //
+ // Links in edit cells
+Index: sc/source/ui/view/scextopt.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/scextopt.cxx,v
+retrieving revision 1.4
+retrieving revision 1.4.326.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.4 -r1.4.326.1
+--- sc/source/ui/view/scextopt.cxx 21 Jul 2006 15:07:47 -0000 1.4
++++ sc/source/ui/view/scextopt.cxx 5 Jan 2008 06:16:09 -0000 1.4.326.1
+@@ -50,7 +50,6 @@
+ mfTabBarWidth( -1.0 ),
+ mnLinkCnt( 0 ),
+ mnDisplTab( 0 ),
+- mbWinProtected( false ),
+ mbEncrypted( false )
+ {
+ }
+Index: sc/source/ui/view/select.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/select.cxx,v
+retrieving revision 1.18
+retrieving revision 1.18.166.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.18 -r1.18.166.3
+--- sc/source/ui/view/select.cxx 27 Feb 2007 13:56:10 -0000 1.18
++++ sc/source/ui/view/select.cxx 14 Mar 2008 21:48:06 -0000 1.18.166.3
+@@ -52,6 +52,7 @@
+ //#include "dataobj.hxx"
+ #include "transobj.hxx"
+ #include "docsh.hxx"
++#include "tabprotection.hxx"
+
+ extern USHORT nScFillModeMouseModifier; // global.cxx
+
+@@ -327,6 +328,26 @@
+ {
+ ScTabView* pView = pViewData->GetView();
+ SCTAB nTab = pViewData->GetTabNo();
++ ScDocument* pDoc = pViewData->GetDocument();
++
++ if ( pDoc->IsTabProtected(nTab) )
++ {
++ if (nPosX < 0 || nPosY < 0)
++ return false;
++
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
++ bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
++
++ if ( bSkipProtected && bSkipUnprotected )
++ return FALSE;
++
++ bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
++ if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
++ // Don't select this cell!
++ return FALSE;
++ }
++
+ ScModule* pScMod = SC_MOD();
+ BOOL bRefMode = pScMod->IsFormulaMode();
+
+@@ -379,7 +400,6 @@
+
+ ScRange aDelRange;
+ BOOL bOldDelMark = pViewData->GetDelMark( aDelRange );
+- ScDocument* pDoc = pViewData->GetDocument();
+
+ if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX &&
+ nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY &&
+@@ -515,7 +535,6 @@
+ BYTE nMode = pViewData->GetFillMode();
+ if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB )
+ {
+- ScDocument* pDoc = pViewData->GetDocument();
+ DBG_ASSERT( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" );
+ ScRange aRange;
+ pDoc->GetEmbedded( aRange);
+Index: sc/source/ui/view/tabview3.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/tabview3.cxx,v
+retrieving revision 1.65
+retrieving revision 1.59.16.5
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.65 -r1.59.16.5
+--- sc/source/ui/view/tabview3.cxx 19 Feb 2008 15:36:30 -0000 1.65
++++ sc/source/ui/view/tabview3.cxx 6 Mar 2008 15:00:14 -0000 1.59.16.5
+@@ -84,6 +84,7 @@
+ #include "AccessibilityHints.hxx"
+ #include "rangeutl.hxx"
+ #include "client.hxx"
++#include "tabprotection.hxx"
+
+ #include <com/sun/star/chart2/data/HighlightedRange.hpp>
+
+@@ -1024,6 +1025,17 @@
+ ScDocument* pDoc = aViewData.GetDocument();
+ SCTAB nTab = aViewData.GetTabNo();
+
++ bool bSkipProtected = false, bSkipUnprotected = false;
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ if ( pProtect && pProtect->isProtected() )
++ {
++ bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
++ bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
++ }
++
++ if ( bSkipProtected && bSkipUnprotected )
++ return;
++
+ SCsCOL nOldX;
+ SCsROW nOldY;
+ SCsCOL nCurX;
+@@ -1043,7 +1055,7 @@
+ nCurY = (nMovY != 0) ? nOldY+nMovY : (SCsROW) aViewData.GetOldCurY();
+ }
+
+- BOOL bHidden;
++ BOOL bSkipCell = FALSE;
+ aViewData.ResetOldCursor();
+
+ if (nMovX != 0 && VALIDCOLROW(nCurX,nCurY))
+@@ -1052,15 +1064,20 @@
+ do
+ {
+ BYTE nColFlags = pDoc->GetColFlags( nCurX, nTab );
+- bHidden = (nColFlags & CR_HIDDEN) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab );
+- if (bHidden)
++ bSkipCell = (nColFlags & CR_HIDDEN) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab );
++ if (bSkipProtected && !bSkipCell)
++ bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++ if (bSkipUnprotected && !bSkipCell)
++ bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++
++ if (bSkipCell)
+ {
+ if ( nCurX<=0 || nCurX>=MAXCOL )
+ {
+ if (bHFlip)
+ {
+ nCurX = nOldX;
+- bHidden = FALSE;
++ bSkipCell = FALSE;
+ }
+ else
+ {
+@@ -1073,7 +1090,8 @@
+ if (nMovX > 0) ++nCurX; else --nCurX;
+ }
+ }
+- while (bHidden);
++ while (bSkipCell);
++
+ if (pDoc->IsVerOverlapped( nCurX, nCurY, nTab ))
+ {
+ aViewData.SetOldCursor( nCurX,nCurY );
+@@ -1088,15 +1106,20 @@
+ do
+ {
+ BYTE nRowFlags = pDoc->GetRowFlags( nCurY, nTab );
+- bHidden = (nRowFlags & CR_HIDDEN) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab );
+- if (bHidden)
++ bSkipCell = (nRowFlags & CR_HIDDEN) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab );
++ if (bSkipProtected && !bSkipCell)
++ bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++ if (bSkipUnprotected && !bSkipCell)
++ bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++
++ if (bSkipCell)
+ {
+ if ( nCurY<=0 || nCurY>=MAXROW )
+ {
+ if (bVFlip)
+ {
+ nCurY = nOldY;
+- bHidden = FALSE;
++ bSkipCell = FALSE;
+ }
+ else
+ {
+@@ -1109,7 +1132,8 @@
+ if (nMovY > 0) ++nCurY; else --nCurY;
+ }
+ }
+- while (bHidden);
++ while (bSkipCell);
++
+ if (pDoc->IsHorOverlapped( nCurX, nCurY, nTab ))
+ {
+ aViewData.SetOldCursor( nCurX,nCurY );
+Index: sc/source/ui/view/tabvwsh3.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/tabvwsh3.cxx,v
+retrieving revision 1.38
+retrieving revision 1.36.24.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.38 -r1.36.24.3
+--- sc/source/ui/view/tabvwsh3.cxx 30 Jan 2008 09:00:26 -0000 1.38
++++ sc/source/ui/view/tabvwsh3.cxx 15 Feb 2008 00:41:53 -0000 1.36.24.3
+@@ -80,6 +80,7 @@
+ #include "autofmt.hxx"
+ #include "dwfunctr.hxx"
+ #include "shtabdlg.hxx"
++#include "tabprotection.hxx"
+
+ #include <svtools/ilstitem.hxx>
+ #define _SVSTDARR_ULONGS
+@@ -976,12 +977,13 @@
+ }
+ }
+
+- if (pDoc->IsDocProtected())
++ ScDocProtection* pProtect = pDoc->GetDocProtection();
++ if (pProtect && pProtect->isProtected())
+ {
+ BOOL bCancel = FALSE;
+ String aPassword;
+
+- if (pDoc->GetDocPassword().getLength())
++ if (pProtect->isProtectedWithPass())
+ {
+ String aText( ScResId(SCSTR_PASSWORD) );
+
+@@ -1054,7 +1056,8 @@
+
+ if ( bOldProtection)
+ {
+- if (pDoc->GetTabPassword(nTab).getLength())
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ if (pProtect && pProtect->isProtectedWithPass())
+ {
+ String aText( ScResId(SCSTR_PASSWORD) );
+
+Index: sc/source/ui/view/viewfun2.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/viewfun2.cxx,v
+retrieving revision 1.37
+retrieving revision 1.35.42.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.37 -r1.35.42.4
+--- sc/source/ui/view/viewfun2.cxx 19 Feb 2008 15:39:38 -0000 1.37
++++ sc/source/ui/view/viewfun2.cxx 6 Mar 2008 15:00:09 -0000 1.35.42.4
+@@ -2152,7 +2152,7 @@
+ pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
+
+ if ( pDoc->IsTabProtected( nTab ) )
+- pUndoDoc->SetTabProtection( nTab, TRUE, pDoc->GetTabPassword( nTab ) );
++ pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab));
+
+ // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
+ // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab);
+@@ -2567,7 +2567,7 @@
+ }
+
+ if ( nErrVal > 0 && pDoc->IsTabProtected( TheTabs[i] ) )
+- pDestDoc->SetTabProtection( nDestTab1, TRUE, pDoc->GetTabPassword( TheTabs[i] ) );
++ pDestDoc->SetTabProtection(nDestTab1, pDoc->GetTabProtection(TheTabs[i]));
+
+ nDestTab1++;
+ }
+Index: sc/source/ui/view/viewfunc.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/viewfunc.cxx,v
+retrieving revision 1.40
+retrieving revision 1.38.76.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.40 -r1.38.76.4
Added: trunk/patches/test/calc-protection-sfx2.diff
==============================================================================
--- (empty file)
+++ trunk/patches/test/calc-protection-sfx2.diff Wed Mar 26 14:27:10 2008
@@ -0,0 +1,21 @@
+? sfx2/sfx2.vpj
+Index: sfx2/source/dialog/filedlghelper.cxx
+===================================================================
+RCS file: /cvs/framework/sfx2/source/dialog/filedlghelper.cxx,v
+retrieving revision 1.138
+retrieving revision 1.136.42.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.138 -r1.136.42.2
+--- sfx2/source/dialog/filedlghelper.cxx 4 Feb 2008 14:19:33 -0000 1.138
++++ sfx2/source/dialog/filedlghelper.cxx 15 Feb 2008 00:45:45 -0000 1.136.42.2
+@@ -691,6 +691,11 @@
+ {
+ sal_Bool operator() ( const SfxFilter* _pFilter )
+ {
++ if (_pFilter->GetFilterName().EqualsAscii("MS Excel 97"))
++ // temporary hack to enable password protection for Excel 97. Is
++ // there a better way to enable password protection of a filter?
++ return true;
++
+ return _pFilter && _pFilter->IsOwnFormat()
+ && _pFilter->UsesStorage()
+ && ( SOFFICE_FILEFORMAT_60 <= _pFilter->GetVersion() );
Added: trunk/patches/test/calc-protection-svx.diff
==============================================================================
--- (empty file)
+++ trunk/patches/test/calc-protection-svx.diff Wed Mar 26 14:27:10 2008
@@ -0,0 +1,202 @@
+? svx/svx.vpj
+Index: svx/inc/mscodec.hxx
+===================================================================
+RCS file: /cvs/graphics/svx/inc/mscodec.hxx,v
+retrieving revision 1.4
+retrieving revision 1.4.1138.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.4 -r1.4.1138.1
+--- svx/inc/mscodec.hxx 8 Sep 2005 18:04:23 -0000 1.4
++++ svx/inc/mscodec.hxx 8 Jan 2008 04:03:39 -0000 1.4.1138.1
+@@ -247,6 +247,10 @@
+ */
+ bool InitCipher( sal_uInt32 nCounter );
+
++ bool Encode(
++ const void* pData, sal_Size nDatLen,
++ sal_uInt8* pBuffer, sal_Size nBufLen );
++
+ /** Decodes a block of memory.
+
+ @see rtl_cipher_decode()
+Index: svx/source/msfilter/mscodec.cxx
+===================================================================
+RCS file: /cvs/graphics/svx/source/msfilter/mscodec.cxx,v
+retrieving revision 1.6
+retrieving revision 1.5.580.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.6 -r1.5.580.2
+--- svx/source/msfilter/mscodec.cxx 4 Feb 2008 13:38:53 -0000 1.6
++++ svx/source/msfilter/mscodec.cxx 15 Feb 2008 00:44:32 -0000 1.5.580.2
+@@ -45,6 +45,10 @@
+ #include <string.h>
+ #include <tools/solar.h>
+
++#include <stdio.h>
++
++#define DEBUG_MSO_ENCRYPTION_STD97 0
++
+ namespace svx {
+
+ // ============================================================================
+@@ -249,15 +253,42 @@
+ rtl_cipher_destroy (m_hCipher);
+ }
+
++static void lcl_PrintKeyData(const sal_uInt8* pKeyData, const char* msg)
++{
++#if DEBUG_MSO_ENCRYPTION_STD97
++ printf("pKeyData: (%s)\n", msg);
++ for (int j = 0; j < 4; ++j)
++ {
++ for (int i = 0; i < 16; ++i)
++ printf("%2.2x ", pKeyData[j*16+i]);
++ printf("\n");
++ }
++#endif
++}
++
++static void lcl_PrintDigest(const sal_uInt8* pDigest)
++{
++#if DEBUG_MSO_ENCRYPTION_STD97
++ printf("digest:\n");
++ for (int i = 0; i < 16; ++i)
++ printf("%2.2x ", pDigest[i]);
++ printf("\n");
++#endif
++}
++
+ void MSCodec_Std97::InitKey (
+ const sal_uInt16 pPassData[16],
+ const sal_uInt8 pUnique[16])
+ {
++#if DEBUG_MSO_ENCRYPTION_STD97
++ fprintf(stdout, "MSCodec_Std97::InitKey: --begin\n");fflush(stdout);
++#endif
+ sal_uInt8 pKeyData[64];
+ int i, n;
+
+ // Fill PassData into KeyData.
+ (void)memset (pKeyData, 0, sizeof(pKeyData));
++ lcl_PrintKeyData(pKeyData, "initial");
+ for (i = 0, n = 16; (i < n) && pPassData[i]; i++)
+ {
+ pKeyData[2*i ] = sal::static_int_cast< sal_uInt8 >(
+@@ -268,12 +299,16 @@
+ pKeyData[2*i] = 0x80;
+ pKeyData[ 56] = sal::static_int_cast< sal_uInt8 >(i << 4);
+
++ lcl_PrintKeyData(pKeyData, "password data");
++
+ // Fill raw digest of KeyData into KeyData.
+ (void)rtl_digest_updateMD5 (
+ m_hDigest, pKeyData, sizeof(pKeyData));
+ (void)rtl_digest_rawMD5 (
+ m_hDigest, pKeyData, RTL_DIGEST_LENGTH_MD5);
+
++ lcl_PrintKeyData(pKeyData, "raw digest of key data");
++
+ // Update digest with KeyData and Unique.
+ for (i = 0; i < 16; i++)
+ {
+@@ -287,6 +322,8 @@
+ pKeyData[56] = 0x80;
+ pKeyData[57] = 0x0a;
+
++ lcl_PrintKeyData(pKeyData, "update digest with padding");
++
+ rtl_digest_updateMD5 (
+ m_hDigest, &(pKeyData[16]), sizeof(pKeyData) - 16);
+
+@@ -294,6 +331,8 @@
+ rtl_digest_rawMD5 (
+ m_hDigest, m_pDigestValue, sizeof(m_pDigestValue));
+
++ lcl_PrintDigest(m_pDigestValue);
++
+ // Erase KeyData array and leave.
+ (void)memset (pKeyData, 0, sizeof(pKeyData));
+ }
+@@ -302,6 +341,11 @@
+ const sal_uInt8 pSaltData[16],
+ const sal_uInt8 pSaltDigest[16])
+ {
++ // both the salt data and salt digest (hash) come from the document being imported.
++
++#if DEBUG_MSO_ENCRYPTION_STD97
++ fprintf(stdout, "MSCodec_Std97::VerifyKey: \n");fflush(stdout);
++#endif
+ bool result = false;
+
+ if (InitCipher(0))
+@@ -313,6 +357,20 @@
+ rtl_cipher_decode (
+ m_hCipher, pSaltData, 16, pBuffer, sizeof(pBuffer));
+
++#if DEBUG_MSO_ENCRYPTION_STD97
++ fprintf(stdout, "salt:\n");
++ for (int i = 0; i < 16; ++i)
++ fprintf(stdout, "%2.2x ", pSaltData[i]);
++ fprintf(stdout, "\n");
++ fprintf(stdout, "decoded salt:\n");
++ for (int i = 0; i < 4; ++i)
++ {
++ for (int j = 0; j < 16; ++j)
++ fprintf(stdout, "%2.2x ", pBuffer[i*16+j]);
++ fprintf(stdout, "\n");
++ }
++#endif
++
+ pBuffer[16] = 0x80;
+ (void)memset (pBuffer + 17, 0, sizeof(pBuffer) - 17);
+ pBuffer[56] = 0x80;
+@@ -323,6 +381,13 @@
+ rtl_digest_rawMD5 (
+ m_hDigest, pDigest, sizeof(pDigest));
+
++#if DEBUG_MSO_ENCRYPTION_STD97
++ printf("raw digest:\n");
++ for (int i = 0; i < 16; ++i)
++ printf("%2.2x ", pDigest[i]);
++ printf("\n");
++#endif
++
+ // Decode original SaltDigest into Buffer.
+ rtl_cipher_decode (
+ m_hCipher, pSaltDigest, 16, pBuffer, sizeof(pBuffer));
+@@ -340,8 +405,9 @@
+
+ bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter)
+ {
++// fprintf(stdout, "MSCodec_Std97::InitCipher: \n");fflush(stdout);
+ rtlCipherError result;
+- sal_uInt8 pKeyData[64];
++ sal_uInt8 pKeyData[64]; // 512-bit message block
+
+ // Initialize KeyData array.
+ (void)memset (pKeyData, 0, sizeof(pKeyData));
+@@ -366,7 +432,7 @@
+
+ // Initialize Cipher with KeyData (for decoding).
+ result = rtl_cipher_init (
+- m_hCipher, rtl_Cipher_DirectionDecode,
++ m_hCipher, rtl_Cipher_DirectionBoth,
+ pKeyData, RTL_DIGEST_LENGTH_MD5, 0, 0);
+
+ // Erase KeyData array and leave.
+@@ -375,6 +441,17 @@
+ return (result == rtl_Cipher_E_None);
+ }
+
++bool MSCodec_Std97::Encode(
++ const void *pData, sal_Size nDatLen,
++ sal_uInt8 *pBuffer, sal_Size nBufLen)
++{
++ rtlCipherError result;
++ result = rtl_cipher_encode (
++ m_hCipher, pData, nDatLen, pBuffer, nBufLen);
++
++ return (result == rtl_Cipher_E_None);
++}
++
+ bool MSCodec_Std97::Decode (
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]