Author: kiwiwings
Date: Thu Jun 16 22:56:47 2022
New Revision: 1901996
URL: http://svn.apache.org/viewvc?rev=1901996&view=rev
Log:
#66115 - Some Password protected XLS files are not read
Modified:
poi/site/src/documentation/content/xdocs/changes.xml
poi/trunk/poi-integration/src/test/java/org/apache/poi/stress/ExcInfo.java
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffViewer.java
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestEFBiffViewer.java
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestFormulaViewer.java
poi/trunk/test-data/spreadsheet/stress.xls
Modified: poi/site/src/documentation/content/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/changes.xml?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/changes.xml (original)
+++ poi/site/src/documentation/content/xdocs/changes.xml Thu Jun 16 22:56:47
2022
@@ -99,6 +99,7 @@
<action type="add" fixes-bug="66097" context="SS_Common">Support
CEILING.PRECISE and FLOOR.PRECISE functions</action>
<action type="add" fixes-bug="66098" context="SS_Common">D*
functions should support wildcard matches</action>
<action type="add" fixes-bug="66105" context="SS_Common">Support
excel correl, covar, pearson and forecast functions</action>
+ <action type="fix" fixes-bug="66115" context="HSSF">Some Password
protected XLS files are not read</action>
</actions>
</release>
Modified:
poi/trunk/poi-integration/src/test/java/org/apache/poi/stress/ExcInfo.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi-integration/src/test/java/org/apache/poi/stress/ExcInfo.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
--- poi/trunk/poi-integration/src/test/java/org/apache/poi/stress/ExcInfo.java
(original)
+++ poi/trunk/poi-integration/src/test/java/org/apache/poi/stress/ExcInfo.java
Thu Jun 16 22:56:47 2022
@@ -90,7 +90,7 @@ public class ExcInfo {
public boolean isValid(String testName, String handler) {
return
!IGNORED_TESTS.equals(tests) &&
- (tests == null || tests.contains(testName)) &&
- (this.handler == null || this.handler.contains(handler));
+ (tests == null || (tests.contains(testName) &&
!tests.contains("!"+testName))) &&
+ (this.handler == null || (this.handler.contains(handler) &&
!this.handler.contains("!"+handler)));
}
}
Modified:
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
---
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
(original)
+++
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
Thu Jun 16 22:56:47 2022
@@ -533,4 +533,9 @@ public final class RecordInputStream imp
((InputStream)_dataInput).reset();
_currentDataOffset = _markedDataOffset;
}
+
+ @Internal
+ public boolean isEncrypted() {
+ return _dataInput instanceof Biff8DecryptingStream &&
((Biff8DecryptingStream)_dataInput).isCurrentRecordEncrypted();
+ }
}
Modified:
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
---
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
(original)
+++
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
Thu Jun 16 22:56:47 2022
@@ -17,11 +17,17 @@
package org.apache.poi.hssf.record;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Supplier;
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.GenericRecordUtil;
+import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException;
@@ -36,10 +42,14 @@ import org.apache.poi.util.StringUtil;
public final class WriteAccessRecord extends StandardRecord {
public static final short sid = 0x005C;
+ private static final BitField UTF16FLAG = BitFieldFactory.getInstance(1);
+
private static final byte PAD_CHAR = (byte) ' ';
private static final int DATA_SIZE = 112;
+ private static final int STRING_SIZE = DATA_SIZE - 3;
+
/** this record is always padded to a constant length */
- private static final byte[] PADDING = new byte[DATA_SIZE];
+ private static final byte[] PADDING = new byte[STRING_SIZE];
static {
Arrays.fill(PADDING, PAD_CHAR);
}
@@ -58,42 +68,57 @@ public final class WriteAccessRecord ext
public WriteAccessRecord(RecordInputStream in) {
if (in.remaining() > DATA_SIZE) {
- throw new RecordFormatException("Expected data size (" + DATA_SIZE
+ ") but got ("
- + in.remaining() + ")");
+ throw new RecordFormatException("Expected data size (" + DATA_SIZE
+ ") but got (" + in.remaining() + ")");
}
- // The string is always 112 characters (padded with spaces), therefore
+
+ // The string is always 109 characters (padded with spaces), therefore
// this record can not be continued.
int nChars = in.readUShort();
int is16BitFlag = in.readUByte();
- if (nChars > DATA_SIZE || (is16BitFlag & 0xFE) != 0) {
- // String header looks wrong (probably missing)
- // OOO doc says this is optional anyway.
- // reconstruct data
- byte[] data = new byte[3 + in.remaining()];
- LittleEndian.putUShort(data, 0, nChars);
- LittleEndian.putByte(data, 2, is16BitFlag);
- in.readFully(data, 3, data.length-3);
- String rawValue = new String(data, StringUtil.UTF8);
- setUsername(rawValue.trim());
- return;
- }
-
- String rawText;
- if ((is16BitFlag & 0x01) == 0x00) {
- rawText = StringUtil.readCompressedUnicode(in, nChars);
+ final byte[] data;
+ final Charset charset;
+ final int byteCnt;
+ if (nChars > STRING_SIZE || (is16BitFlag & 0xFE) != 0) {
+ // something is wrong - reconstruct data
+ if (in.isEncrypted()) {
+ // WPS Office seems to generate files with this record
unencrypted (#66115)
+ // Libre Office/Excel can read those, but Excel will convert
those back to encrypted
+ data = IOUtils.safelyAllocate(in.remaining(), STRING_SIZE);
+ in.readPlain(data, 0, data.length);
+ int i = data.length;
+ // PAD_CHAR is filled for every byte even for UTF16 strings
+ while (i>0 && data[i-1] == PAD_CHAR) {
+ i--;
+ }
+ byteCnt = i;
+ // poor mans utf16 detection ...
+ charset = (data.length > 1 && data[1] == 0) ?
StandardCharsets.UTF_16LE : StandardCharsets.ISO_8859_1;
+ } else {
+ // String header looks wrong (probably missing)
+ // OOO doc says this is optional anyway.
+ byteCnt = 3 + in.remaining();
+ data = IOUtils.safelyAllocate(byteCnt, DATA_SIZE);
+ LittleEndian.putUShort(data, 0, nChars);
+ LittleEndian.putByte(data, 2, is16BitFlag);
+ in.readFully(data, 3, byteCnt-3);
+ charset = StandardCharsets.UTF_8;
+ }
} else {
- rawText = StringUtil.readUnicodeLE(in, nChars);
+ // the normal case ...
+ data = IOUtils.safelyAllocate(in.remaining(), STRING_SIZE);
+ in.readFully(data);
+ if (UTF16FLAG.isSet(is16BitFlag)) {
+ byteCnt = Math.min(nChars * 2, data.length);
+ charset = StandardCharsets.UTF_16LE;
+ } else {
+ byteCnt = Math.min(nChars, data.length);
+ charset = StandardCharsets.ISO_8859_1;
+ }
}
- field_1_username = rawText.trim();
- // consume padding
- int padSize = in.remaining();
- while (padSize > 0) {
- // in some cases this seems to be garbage (non spaces)
- in.readUByte();
- padSize--;
- }
+ String rawValue = new String(data, 0, byteCnt, charset);
+ setUsername(rawValue.trim());
}
/**
@@ -104,9 +129,8 @@ public final class WriteAccessRecord ext
*/
public void setUsername(String username) {
boolean is16bit = StringUtil.hasMultibyte(username);
- int encodedByteCount = 3 + username.length() * (is16bit ? 2 : 1);
- int paddingSize = DATA_SIZE - encodedByteCount;
- if (paddingSize < 0) {
+ int encodedByteCount = username.length() * (is16bit ? 2 : 1);
+ if (encodedByteCount > STRING_SIZE) {
throw new IllegalArgumentException("Name is too long: " +
username);
}
@@ -131,14 +155,14 @@ public final class WriteAccessRecord ext
out.writeShort(username.length());
out.writeByte(is16bit ? 0x01 : 0x00);
+
+ byte[] buf = PADDING.clone();
if (is16bit) {
- StringUtil.putUnicodeLE(username, out);
+ StringUtil.putUnicodeLE(username, buf, 0);
} else {
- StringUtil.putCompressedUnicode(username, out);
+ StringUtil.putCompressedUnicode(username, buf, 0);
}
- int encodedByteCount = 3 + username.length() * (is16bit ? 2 : 1);
- int paddingSize = DATA_SIZE - encodedByteCount;
- out.write(PADDING, 0, paddingSize);
+ out.write(buf);
}
@Override
Modified:
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
---
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
(original)
+++
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
Thu Jun 16 22:56:47 2022
@@ -26,6 +26,7 @@ import org.apache.poi.poifs.crypt.Chunke
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInput;
@@ -208,4 +209,8 @@ public final class Biff8DecryptingStream
ccis.readPlain(b, off, len);
}
+ @Internal
+ public boolean isCurrentRecordEncrypted() {
+ return !shouldSkipEncryptionOnCurrentRecord;
+ }
}
Modified:
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
---
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java
(original)
+++
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffDrawingToXml.java
Thu Jun 16 22:56:47 2022
@@ -53,6 +53,7 @@ class TestBiffDrawingToXml extends BaseT
// HSSFWorkbook cannot open it as well
excludes.put("43493.xls",
RecordInputStream.LeftoverDataException.class);
excludes.put("44958_1.xls",
RecordInputStream.LeftoverDataException.class);
+ excludes.put("protected_66115.xls", EncryptedDocumentException.class);
return excludes;
}
Modified:
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffViewer.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffViewer.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffViewer.java
(original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestBiffViewer.java Thu
Jun 16 22:56:47 2022
@@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.util.Map;
+import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.util.RecordFormatException;
class TestBiffViewer extends BaseTestIteratingXLS {
@@ -41,6 +42,7 @@ class TestBiffViewer extends BaseTestIte
excludes.put("61300.xls", IndexOutOfBoundsException.class);
excludes.put("poi-fuzz.xls", RecordFormatException.class);
+ excludes.put("protected_66115.xls", RecordFormatException.class);
return excludes;
}
Modified:
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestEFBiffViewer.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestEFBiffViewer.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestEFBiffViewer.java
(original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestEFBiffViewer.java
Thu Jun 16 22:56:47 2022
@@ -26,6 +26,7 @@ import org.apache.poi.hssf.eventusermode
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.RecordFormatException;
import org.junit.jupiter.api.Assertions;
class TestEFBiffViewer extends BaseTestIteratingXLS {
@@ -37,6 +38,7 @@ class TestEFBiffViewer extends BaseTestI
excludes.put("51832.xls", EncryptedDocumentException.class);
excludes.put("xor-encryption-abc.xls",
EncryptedDocumentException.class);
excludes.put("password.xls", EncryptedDocumentException.class);
+ excludes.put("protected_66115.xls", EncryptedDocumentException.class);
// HSSFWorkbook cannot open it as well
excludes.put("43493.xls",
RecordInputStream.LeftoverDataException.class);
excludes.put("44958_1.xls",
RecordInputStream.LeftoverDataException.class);
Modified:
poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestFormulaViewer.java
URL:
http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestFormulaViewer.java?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestFormulaViewer.java
(original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/dev/TestFormulaViewer.java
Thu Jun 16 22:56:47 2022
@@ -44,6 +44,7 @@ class TestFormulaViewer extends BaseTest
excludes.put("password.xls", EncryptedDocumentException.class);
excludes.put("43493.xls",
RecordInputStream.LeftoverDataException.class); // HSSFWorkbook cannot open it
as well
excludes.put("44958_1.xls",
RecordInputStream.LeftoverDataException.class);
+ excludes.put("protected_66115.xls", EncryptedDocumentException.class);
return excludes;
}
Modified: poi/trunk/test-data/spreadsheet/stress.xls
URL:
http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/stress.xls?rev=1901996&r1=1901995&r2=1901996&view=diff
==============================================================================
Binary files - no diff available.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]