From: Yegor Kozlov Date: Wed, 18 Aug 2010 12:49:05 +0000 (+0000) Subject: support for protecting a XSSF workbook, see Bugzilla #48900 X-Git-Tag: REL_3_7_BETA3~55 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=faa64fa1f42d6204a841a6e4b6e172dfc4a892b4;p=poi.git support for protecting a XSSF workbook, see Bugzilla #48900 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@986649 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 842b64b718..ad5baeebdd 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 48900 - support for protecting a XSSF workbook 49725 - fixed FormulaParser to correctly process defined names with underscore 48526 - added implementation for RANDBETWEEN() 49725 - avoid exception in OperandResolver.parseDouble when input is minus ("-") diff --git a/src/java/org/apache/poi/ss/usermodel/Sheet.java b/src/java/org/apache/poi/ss/usermodel/Sheet.java index b4a1dbc0e6..b3eb1ee2a8 100644 --- a/src/java/org/apache/poi/ss/usermodel/Sheet.java +++ b/src/java/org/apache/poi/ss/usermodel/Sheet.java @@ -455,7 +455,13 @@ public interface Sheet extends Iterable { * @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 null to remove protection + */ + public void protectSheet(String password); + /** * Answer whether scenario protection is enabled or disabled * diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 815a351663..55f16a2d2b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -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 null 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. diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java index a07e5c20b9..7eec1794ab 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java @@ -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()); + } + } diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java index 7613da4d87..da3eb8564f 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java @@ -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()); + + } + + }