ooo-build r12011 - in trunk: . patches/test



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]