]> source.dussan.org Git - poi.git/commitdiff
support for protecting a XSSF workbook, see Bugzilla #48900
authorYegor Kozlov <yegor@apache.org>
Wed, 18 Aug 2010 12:49:05 +0000 (12:49 +0000)
committerYegor Kozlov <yegor@apache.org>
Wed, 18 Aug 2010 12:49:05 +0000 (12:49 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@986649 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/ss/usermodel/Sheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java
src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java

index 842b64b71861a16e581945f1fab442d45549a6c4..ad5baeebdd61e250da7fe5c930cef294826bf6c8 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.7-beta3" date="2010-??-??">
+           <action dev="POI-DEVELOPERS" type="add">48900 - support for protecting a XSSF workbook</action>
            <action dev="POI-DEVELOPERS" type="fix">49725 - fixed FormulaParser to correctly process defined names with underscore</action>
            <action dev="POI-DEVELOPERS" type="add">48526 - added implementation for RANDBETWEEN()</action>
            <action dev="POI-DEVELOPERS" type="fix">49725 - avoid exception in OperandResolver.parseDouble when input is minus ("-")</action>
index b4a1dbc0e6008abfc8cbceb2e24c73faa51406c9..b3eb1ee2a8d8156a92a770e34dc154e93c582451 100644 (file)
@@ -455,7 +455,13 @@ public interface Sheet extends Iterable<Row> {
      * @return true => protection enabled; false => protection disabled
      */
     boolean getProtect();
-
+    
+    /**
+     * Sets the protection enabled as well as the password
+     * @param password to set for protection. Pass <code>null</code> to remove protection
+     */
+    public void protectSheet(String password);
+    
     /**
      * Answer whether scenario protection is enabled or disabled
      *
index 815a351663f6c805dd2b43e08c6b9a26835f5c7e..55f16a2d2bb55a728cbe2a41c76c3095db74e467 100644 (file)
@@ -32,6 +32,7 @@ import javax.xml.namespace.QName;
 
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.POIXMLException;
+import org.apache.poi.hssf.record.PasswordRecord;
 import org.apache.poi.hssf.record.formula.FormulaShifter;
 import org.apache.poi.hssf.util.PaneInformation;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
@@ -52,6 +53,7 @@ import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellRangeAddressList;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.util.SSCellRange;
+import org.apache.poi.util.HexDump;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -941,7 +943,41 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
     public boolean getProtect() {
         return worksheet.isSetSheetProtection() && sheetProtectionEnabled();
     }
+    /**
+     * Enables sheet protection and sets the password for the sheet.
+     * Also sets some attributes on the {@link CTSheetProtection} that correspond to
+     * the default values used by Excel
+     * 
+     * @param password to set for protection. Pass <code>null</code> to remove protection
+     */
+    @Override
+    public void protectSheet(String password) {
+               
+       if(password != null) {
+               CTSheetProtection sheetProtection = worksheet.addNewSheetProtection();
+               sheetProtection.xsetPassword(stringToExcelPassword(password));
+               sheetProtection.setSheet(true);
+               sheetProtection.setScenarios(true);
+               sheetProtection.setObjects(true);
+       } else {
+               worksheet.unsetSheetProtection();
+       }
+    }
 
+       /**
+        * Converts a String to a {@link STUnsignedShortHex} value that contains the {@link PasswordRecord#hashPassword(String)}
+        * value in hexadecimal format
+        *  
+        * @param password the password string you wish convert to an {@link STUnsignedShortHex}
+        * @return {@link STUnsignedShortHex} that contains Excel hashed password in Hex format
+        */
+       private STUnsignedShortHex stringToExcelPassword(String password) {
+               STUnsignedShortHex hexPassword = STUnsignedShortHex.Factory.newInstance();
+               hexPassword.setStringValue(String.valueOf(HexDump.shortToHex(PasswordRecord.hashPassword(password))).substring(2));
+               return hexPassword;
+       }
+       
     /**
      * Returns the logical row ( 0-based).  If you ask for a row that is not
      * defined you get a null.  This is to say row 4 represents the fifth row on a sheet.
index a07e5c20b9aeb09d0164cb0bee44a48fad803535..7eec1794ab9226a8bb4f099c10c8c96e19e07e30 100644 (file)
@@ -24,6 +24,8 @@ import org.apache.poi.xssf.XSSFTestDataSamples;
 import org.apache.poi.xssf.model.CommentsTable;
 import org.apache.poi.xssf.model.StylesTable;
 import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
+import org.apache.poi.util.HexDump;
+import org.apache.poi.hssf.record.PasswordRecord;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
 
 
@@ -979,4 +981,25 @@ public final class TestXSSFSheet extends BaseTestSheet {
 
         assertEquals("A1:D100", sheet.getCTWorksheet().getAutoFilter().getRef());
     }
+
+    public void testProtectSheet_lowlevel() {
+
+       XSSFWorkbook wb = new XSSFWorkbook();
+       XSSFSheet sheet = wb.createSheet();
+        CTSheetProtection pr = sheet.getCTWorksheet().getSheetProtection();
+        assertNull("CTSheetProtection should be null by default", pr);
+        String password = "Test";
+        sheet.protectSheet(password);
+        pr = sheet.getCTWorksheet().getSheetProtection();
+        assertNotNull("CTSheetProtection should be not null", pr);
+        assertTrue("sheet protection should be on", pr.isSetSheet());
+        assertTrue("object protection should be on", pr.isSetObjects());
+        assertTrue("scenario protection should be on", pr.isSetScenarios());
+        String hash = String.valueOf(HexDump.shortToHex(PasswordRecord.hashPassword(password))).substring(2);
+        assertEquals("well known value for top secret hash should be "+ hash, hash, pr.xgetPassword().getStringValue());
+
+        sheet.protectSheet(null);
+        assertNull("protectSheet(null) should unset CTSheetProtection", sheet.getCTWorksheet().getSheetProtection());
+    }
+
 }
index 7613da4d87a6d87b4b0d526573aeb04fb6627de9..da3eb8564f65d9985975d92c5fdf4313d3808821 100644 (file)
@@ -640,4 +640,18 @@ public abstract class BaseTestSheet extends TestCase {
         sheet.setColumnHidden(2, true);
         assertTrue(sheet.isColumnHidden(2));
     }
+
+    public void testProtectSheet() {
+
+       Workbook wb = _testDataProvider.createWorkbook();
+       Sheet sheet = wb.createSheet();
+        assertFalse(sheet.getProtect());
+       sheet.protectSheet("Test");  
+       assertTrue(sheet.getProtect());
+       sheet.protectSheet(null);
+       assertFalse(sheet.getProtect());
+
+    }
+
+
 }