You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ac...@apache.org on 2007/07/02 10:10:29 UTC

svn commit: r552425 - in /poi/trunk/src: java/org/apache/poi/hssf/model/ java/org/apache/poi/hssf/record/ java/org/apache/poi/hssf/usermodel/ testcases/org/apache/poi/hssf/usermodel/

Author: acoliver
Date: Mon Jul  2 01:10:28 2007
New Revision: 552425

URL: http://svn.apache.org/viewvc?view=rev&rev=552425
Log:
Now can protect sheets with a password.  So everyone may cease whining about it
already :-)

Modified:
    poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java
    poi/trunk/src/java/org/apache/poi/hssf/record/PasswordRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/ProtectRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactory.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java?view=diff&rev=552425&r1=552424&r2=552425
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java Mon Jul  2 01:10:28 2007
@@ -93,6 +93,9 @@
     protected ProtectRecord              protect           =     null;
     protected PageBreakRecord            rowBreaks         =     null;
     protected PageBreakRecord            colBreaks         =     null;
+    protected ObjectProtectRecord        objprotect        =     null;
+    protected ScenarioProtectRecord      scenprotect       =     null;
+    protected PasswordRecord             password          =     null;
 
 	
     public static final byte PANE_LOWER_RIGHT = (byte)0;
@@ -285,6 +288,18 @@
 			{
 				retval.protect = (ProtectRecord) rec;
 			} 
+			else if ( rec.getSid() == ObjectProtectRecord.sid )
+			{
+				retval.objprotect = (ObjectProtectRecord) rec;
+			} 
+			else if ( rec.getSid() == ScenarioProtectRecord.sid )
+			{
+				retval.scenprotect = (ScenarioProtectRecord) rec;
+			} 
+			else if ( rec.getSid() == PasswordRecord.sid )
+			{
+				retval.password = (PasswordRecord) rec;
+			} 
 			else if (rec.getSid() == PageBreakRecord.HORIZONTAL_SID) 
 			{	
 				retval.rowBreaks = (PageBreakRecord)rec;				
@@ -2500,7 +2515,38 @@
         ProtectRecord retval = new ProtectRecord();
 
         retval.setProtect(false);
-        // by default even when we support encryption we won't
+        return retval;
+    }
+
+    /**
+     * creates an ObjectProtect record with protect set to false.
+     * @see org.apache.poi.hssf.record.ObjectProtectRecord
+     * @see org.apache.poi.hssf.record.Record
+     * @return an ObjectProtectRecord
+     */
+    protected ObjectProtectRecord createObjectProtect()
+    {
+        if (log.check( POILogger.DEBUG ))
+            log.log(POILogger.DEBUG, "create protect record with protection disabled");
+        ObjectProtectRecord retval = new ObjectProtectRecord();
+
+        retval.setProtect(false);
+        return retval;
+    }
+
+    /**
+     * creates a ScenarioProtect record with protect set to false.
+     * @see org.apache.poi.hssf.record.ScenarioProtectRecord
+     * @see org.apache.poi.hssf.record.Record
+     * @return a ScenarioProtectRecord
+     */
+    protected ScenarioProtectRecord createScenarioProtect()
+    {
+        if (log.check( POILogger.DEBUG ))
+            log.log(POILogger.DEBUG, "create protect record with protection disabled");
+        ScenarioProtectRecord retval = new ScenarioProtectRecord();
+
+        retval.setProtect(false);
         return retval;
     }
 
@@ -2518,6 +2564,38 @@
         return protect;
     }
 
+    /** Returns the PasswordRecord.
+     * If one is not contained in the sheet, then one is created.
+     */
+    public PasswordRecord getPassword()
+    {
+    	if (password == null) {
+    		password = createPassword();
+    		//Insert the newly created password record at the end of the record (just before the EOF)
+    		int loc = findFirstRecordLocBySid(EOFRecord.sid);
+    		records.add(loc, password);    		
+    	}
+        return password;
+    }
+
+    /**
+     * creates a Password record with password set to 00.
+     * @see org.apache.poi.hssf.record.PasswordRecord
+     * @see org.apache.poi.hssf.record.Record
+     * @return a PasswordRecord
+     */
+    protected PasswordRecord createPassword()
+    {
+        if (log.check( POILogger.DEBUG ))
+            log.log(POILogger.DEBUG, "create password record with 00 password");
+        PasswordRecord retval = new PasswordRecord();
+
+        retval.setPassword((short)00);
+        return retval;
+    }
+
+    /**
+
     /**
      * Sets whether the gridlines are shown in a viewer.
      * @param show whether to show gridlines or not
@@ -2791,6 +2869,68 @@
         }
     }
 
+    /**
+     * protect a spreadsheet with a password (not encypted, just sets protect
+     * flags and the password.
+     * @param password to set
+     * @param objects are protected
+     * @param scenarios are protected
+     */
+    public void protectSheet( String password, boolean objects, boolean scenarios ) {
+        int protIdx = -1;
+        ProtectRecord prec = getProtect();
+        PasswordRecord pass = getPassword();
+        prec.setProtect(true);
+        pass.setPassword(PasswordRecord.hashPassword(password));
+        if((objprotect == null && objects) || (scenprotect != null && scenarios)) {
+            protIdx = records.indexOf( protect );
+        }
+        if(objprotect == null && objects) {
+            ObjectProtectRecord rec = createObjectProtect();
+            rec.setProtect(true);
+            records.add(protIdx+1,rec);
+            objprotect = rec;
+        }
+        if(scenprotect == null && scenarios) {
+            ScenarioProtectRecord srec = createScenarioProtect();
+            srec.setProtect(true);
+            records.add(protIdx+2,srec);
+            scenprotect = srec;
+        }
+    }    
+
+    /**
+     * unprotect objects in the sheet (will not protect them, but any set to false are 
+     * unprotected.
+     * @param sheet is unprotected (false = unprotect)
+     * @param objects are unprotected (false = unprotect)
+     * @param scenarios are unprotected (false = unprotect)
+     */
+    public void unprotectSheet( boolean sheet, boolean objects, boolean scenarios ) {
+        int protIdx = -1;
+        if (!sheet) {
+           ProtectRecord prec = getProtect();
+           prec.setProtect(sheet);
+           PasswordRecord pass = getPassword();
+           pass.setPassword((short)00);
+        } 
+        if(objprotect != null && !objects) {
+            objprotect.setProtect(false);
+        }
+        if(scenprotect != null && !scenarios) {
+            scenprotect.setProtect(false);
+        }
+    }    
+
+    /**
+     * @return {sheet is protected, objects are proteced, scenarios are protected}
+     */
+    public boolean[] isProtected() {
+        return new boolean[] { (protect != null && protect.getProtect()), 
+                             (objprotect != null && objprotect.getProtect()),
+                             (scenprotect != null && scenprotect.getProtect())};
+    }
+ 
 //    private void collapseColumn( short columnNumber )
 //    {
 //        int idx = findColumnIdx( columnNumber, 0 );

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/PasswordRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/PasswordRecord.java?view=diff&rev=552425&r1=552424&r2=552425
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/PasswordRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/PasswordRecord.java Mon Jul  2 01:10:28 2007
@@ -29,14 +29,11 @@
  * @version 2.0-pre
  */
 
-public class PasswordRecord
-    extends Record
-{
+public class PasswordRecord extends Record {
     public final static short sid = 0x13;
     private short             field_1_password;   // not sure why this is only 2 bytes, but it is... go figure
 
-    public PasswordRecord()
-    {
+    public PasswordRecord() {
     }
 
     /**
@@ -44,32 +41,46 @@
      * @param in the RecordInputstream to read the record from
      */
 
-    public PasswordRecord(RecordInputStream in)
-    {
+    public PasswordRecord(RecordInputStream in) {
         super(in);
     }
 
-    protected void validateSid(short id)
-    {
-        if (id != sid)
-        {
+    protected void validateSid(short id) {
+        if (id != sid) {
             throw new RecordFormatException("NOT A PASSWORD RECORD");
         }
     }
 
-    protected void fillFields(RecordInputStream in)
-    {
+    protected void fillFields(RecordInputStream in) {
         field_1_password = in.readShort();
     }
 
+    //this is the world's lamest "security".  thanks to Wouter van Vugt for making me
+    //not have to try real hard.  -ACO
+    public static short hashPassword(String password) {
+        byte[] passwordCharacters = password.getBytes();
+        int hash = 0;
+        if (passwordCharacters.length > 0) {
+            int charIndex = passwordCharacters.length;
+            while (charIndex-- > 0) {
+                hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
+                hash ^= passwordCharacters[charIndex];
+            }
+            // also hash with charcount
+            hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
+            hash ^= passwordCharacters.length;
+            hash ^= (0x8000 | ('N' << 8) | 'K');
+        }
+        return (short)hash;
+    } 
+
     /**
      * set the password
      *
      * @param password  representing the password
      */
 
-    public void setPassword(short password)
-    {
+    public void setPassword(short password) {
         field_1_password = password;
     }
 
@@ -78,14 +89,11 @@
      *
      * @return short  representing the password
      */
-
-    public short getPassword()
-    {
+    public short getPassword() {
         return field_1_password;
     }
 
-    public String toString()
-    {
+    public String toString() {
         StringBuffer buffer = new StringBuffer();
 
         buffer.append("[PASSWORD]\n");
@@ -95,8 +103,7 @@
         return buffer.toString();
     }
 
-    public int serialize(int offset, byte [] data)
-    {
+    public int serialize(int offset, byte [] data) {
         LittleEndian.putShort(data, 0 + offset, sid);
         LittleEndian.putShort(data, 2 + offset,
                               (( short ) 0x02));   // 2 bytes (6 total)
@@ -104,13 +111,11 @@
         return getRecordSize();
     }
 
-    public int getRecordSize()
-    {
+    public int getRecordSize() {
         return 6;
     }
 
-    public short getSid()
-    {
+    public short getSid() {
         return sid;
     }
 

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/ProtectRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/ProtectRecord.java?view=diff&rev=552425&r1=552424&r2=552425
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/ProtectRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/ProtectRecord.java Mon Jul  2 01:10:28 2007
@@ -26,9 +26,10 @@
  * Description:  defines whether a sheet or workbook is protected (HSSF DOES NOT SUPPORT ENCRYPTION)<P>
  * (kindly ask the US government to stop having arcane stupid encryption laws and we'll support it) <P>
  * (after all terrorists will all use US-legal encrypton right??)<P>
+ * HSSF now supports the simple "protected" sheets (where they are not encrypted and open office et al
+ * ignore the password record entirely).
  * REFERENCE:  PG 373 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
  * @author Andrew C. Oliver (acoliver at apache dot org)
- * @version 2.0-pre
  */
 
 public class ProtectRecord

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactory.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactory.java?view=diff&rev=552425&r1=552424&r2=552425
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactory.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactory.java Mon Jul  2 01:10:28 2007
@@ -74,7 +74,7 @@
                 PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class,
                 HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class, 
                 WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
-                NoteRecord.class
+                NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class
             };
     }
     private static Map           recordsMap  = recordsToMap(records);

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java?view=diff&rev=552425&r1=552424&r2=552425
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java Mon Jul  2 01:10:28 2007
@@ -872,16 +872,48 @@
 	 * @return true => protection enabled; false => protection disabled
 	 */
 	public boolean getProtect() {
-		return getSheet().getProtect().getProtect();
+		return getSheet().isProtected()[0];
+	}
+
+	/**
+	 * @return hashed password
+	 */
+	public short getPassword() {
+		return getSheet().getPassword().getPassword();
+	}
+
+	/**
+	 * Answer whether object protection is enabled or disabled
+	 * @return true => protection enabled; false => protection disabled
+	 */
+	public boolean getObjectProtect() {
+		return getSheet().isProtected()[1];
+	}
+
+	/**
+	 * Answer whether scenario protection is enabled or disabled
+	 * @return true => protection enabled; false => protection disabled
+	 */
+	public boolean getScenarioProtect() {
+		return getSheet().isProtected()[2];
 	}
 
 	/**
 	 * Sets the protection on enabled or disabled
 	 * @param protect true => protection enabled; false => protection disabled
+         * @deprecated use protectSheet(String, boolean, boolean)
 	 */
 	public void setProtect(boolean protect) {
 		getSheet().getProtect().setProtect(protect);
 	}
+
+        /**
+         * Sets the protection enabled as well as the password
+         * @param password to set for protection
+         */
+        public void protectSheet(String password) {
+                getSheet().protectSheet(password, true, true); //protect objs&scenarios(normal)
+        }
 
     /**
      * Sets the zoom magnication for the sheet.  The zoom is expressed as a

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java?view=diff&rev=552425&r1=552424&r2=552425
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java Mon Jul  2 01:10:28 2007
@@ -26,6 +26,7 @@
 import org.apache.poi.hssf.model.Sheet;
 import org.apache.poi.hssf.record.HCenterRecord;
 import org.apache.poi.hssf.record.ProtectRecord;
+import org.apache.poi.hssf.record.PasswordRecord;
 import org.apache.poi.hssf.record.SCLRecord;
 import org.apache.poi.hssf.record.VCenterRecord;
 import org.apache.poi.hssf.record.WSBoolRecord;
@@ -38,6 +39,7 @@
  *
  *
  * @author Glen Stampoultzis (glens at apache.org)
+ * @author Andrew C. Oliver (acoliver apache org)
  */
 
 public class TestHSSFSheet
@@ -241,6 +243,20 @@
 		assertNotNull(cloned.getProtect());
 		assertTrue(hssfSheet.getProtect());
 	}
+
+    public void testProtectSheet() {
+        short expected = (short)0xfef1;
+	HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFSheet s = wb.createSheet();
+        s.protectSheet("abcdefghij");
+        Sheet sheet = s.getSheet();
+	ProtectRecord protect = sheet.getProtect();
+	PasswordRecord pass = sheet.getPassword();
+        assertTrue("protection should be on",protect.getProtect());
+        assertTrue("object protection should be on",sheet.isProtected()[1]);
+        assertTrue("scenario protection should be on",sheet.isProtected()[2]);
+        assertEquals("well known value for top secret hash should be "+Integer.toHexString(expected).substring(4),expected,pass.getPassword());
+    }
 
 
     public void testZoom()



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org