From 74964614ab8c375bd09546eae2588a198de1950c Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Thu, 1 May 2008 07:42:18 +0000 Subject: [PATCH] 44914 - Fix/suppress warning message - WARN. Unread n bytes of record 0xNN git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@652446 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + src/documentation/content/xdocs/status.xml | 1 + .../poi/hssf/record/ColumnInfoRecord.java | 39 +-- .../poi/hssf/record/FileSharingRecord.java | 90 ++---- .../apache/poi/hssf/record/FormulaRecord.java | 7 +- .../apache/poi/hssf/record/formula/Ptg.java | 292 +++++++++--------- 6 files changed, 206 insertions(+), 224 deletions(-) diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 55308a758b..a295fdb223 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + 44914 - Fix/suppress warning message "WARN. Unread n bytes of record 0xNN" 44892 - made HSSFWorkbook.getSheet(String) case insensitive 44886] - Correctly process PICT metafile in EscherMetafileBlip 44893 - Correctly handle merged regions in HSSFSheet.autoSizeColumn diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 58a560996d..f97a4d7f21 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 44914 - Fix/suppress warning message "WARN. Unread n bytes of record 0xNN" 44892 - made HSSFWorkbook.getSheet(String) case insensitive 44886] - Correctly process PICT metafile in EscherMetafileBlip 44893 - Correctly handle merged regions in HSSFSheet.autoSizeColumn diff --git a/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java b/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java index 932c4547a1..b77dca3e17 100644 --- a/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java +++ b/src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -15,13 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - -/* - * ColumnInfoRecord.java - * - * Created on December 8, 2001, 8:44 AM - */ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndian; @@ -29,29 +22,28 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; /** - * Title: ColumnInfo Record

- * Description: Defines with width and formatting for a range of columns

- * REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * Title: COLINFO Record

+ * Description: Defines with width and formatting for a range of columns

+ * REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

* @author Andrew C. Oliver (acoliver at apache dot org) * @version 2.0-pre */ - -public class ColumnInfoRecord - extends Record -{ +public final class ColumnInfoRecord extends Record { public static final short sid = 0x7d; private short field_1_first_col; private short field_2_last_col; private short field_3_col_width; private short field_4_xf_index; private short field_5_options; - static final private BitField hidden = BitFieldFactory.getInstance(0x01); - static final private BitField outlevel = BitFieldFactory.getInstance(0x0700); - static final private BitField collapsed = BitFieldFactory.getInstance(0x1000); + private static final BitField hidden = BitFieldFactory.getInstance(0x01); + private static final BitField outlevel = BitFieldFactory.getInstance(0x0700); + private static final BitField collapsed = BitFieldFactory.getInstance(0x1000); + // Excel seems write values 2, 10, and 260, even though spec says "must be zero" private short field_6_reserved; public ColumnInfoRecord() { + field_6_reserved = 2; // seems to be the most common value } /** @@ -71,7 +63,18 @@ public class ColumnInfoRecord field_3_col_width = in.readShort(); field_4_xf_index = in.readShort(); field_5_options = in.readShort(); - field_6_reserved = in.readShort(); + switch(in.remaining()) { + case 2: // usual case + field_6_reserved = in.readShort(); + break; + case 1: + // often COLINFO gets encoded 1 byte short + // shouldn't matter because this field is unused + field_6_reserved = in.readByte(); + break; + default: + throw new RuntimeException("Unusual record size remaining=(" + in.remaining() + ")"); + } } protected void validateSid(short id) diff --git a/src/java/org/apache/poi/hssf/record/FileSharingRecord.java b/src/java/org/apache/poi/hssf/record/FileSharingRecord.java index 2f56eb092a..e375af3657 100644 --- a/src/java/org/apache/poi/hssf/record/FileSharingRecord.java +++ b/src/java/org/apache/poi/hssf/record/FileSharingRecord.java @@ -14,31 +14,26 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; import org.apache.poi.util.StringUtil; /** - * Title: FileSharing

+ * Title: FILESHARING

* Description: stores the encrypted readonly for a workbook (write protect) - * REFERENCE: PG 314 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * This functionality is accessed from the options dialog box available when performing 'Save As'.

+ * REFERENCE: PG 314 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

* @author Andrew C. Oliver (acoliver at apache dot org) */ +public final class FileSharingRecord extends Record { -public class FileSharingRecord extends Record { - private static POILogger logger = POILogFactory.getLogger(FileSharingRecord.class); - public final static short sid = 0x5b; private short field_1_readonly; private short field_2_password; - private byte field_3_username_length; - private short field_4_unknown; // not documented - private String field_5_username; + private byte field_3_username_unicode_options; + private String field_3_username_value; public FileSharingRecord() {} @@ -61,23 +56,15 @@ public class FileSharingRecord extends Record { protected void fillFields(RecordInputStream in) { field_1_readonly = in.readShort(); field_2_password = in.readShort(); - field_3_username_length = in.readByte(); - // Is this really correct? The latest docs - // seem to hint there's nothing between the - // username length and the username string - field_4_unknown = in.readShort(); + int nameLen = in.readShort(); - // Ensure we don't try to read more data than - // there actually is - if(field_3_username_length > in.remaining()) { - logger.log(POILogger.WARN, "FileSharingRecord defined a username of length " + field_3_username_length + ", but only " + in.remaining() + " bytes were left, truncating"); - field_3_username_length = (byte)in.remaining(); - } - if(field_3_username_length > 0) { - field_5_username = in.readCompressedUnicode(field_3_username_length); + if(nameLen > 0) { + // TODO - Current examples(3) from junits only have zero length username. + field_3_username_unicode_options = in.readByte(); + field_3_username_value = in.readCompressedUnicode(nameLen); } else { - field_5_username = ""; + field_3_username_value = ""; } } @@ -135,45 +122,24 @@ public class FileSharingRecord extends Record { /** * @returns byte representing the length of the username field */ - public byte getUsernameLength() { - return field_3_username_length ; - } - - /** - * @param byte representing the length of the username field - */ - public void setUsernameLength(byte length) { - this.field_3_username_length = length; + public short getUsernameLength() { + return (short) field_3_username_value.length(); } /** * @returns username of the user that created the file */ public String getUsername() { - return this.field_5_username; + return field_3_username_value; } /** * @param username of the user that created the file */ public void setUsername(String username) { - this.field_5_username = username; - this.field_3_username_length = (byte)username.length(); - } - - /** - * @return short value of a "bonus field" in Excel that was not doc'd - */ - public short getUnknown() { - return field_4_unknown; + field_3_username_value = username; } - /** - * @param unknown field value to set (bonus field that is not doc'd) - */ - public void setUnknown(short unk) { - field_4_unknown = unk; - } public String toString() { StringBuffer buffer = new StringBuffer(); @@ -183,10 +149,6 @@ public class FileSharingRecord extends Record { .append(getReadOnly() == 1 ? "true" : "false").append("\n"); buffer.append(" .password = ") .append(Integer.toHexString(getPassword())).append("\n"); - buffer.append(" .userlen = ") - .append(Integer.toHexString(getUsernameLength())).append("\n"); - buffer.append(" .unknown = ") - .append(Integer.toHexString(getUnknown())).append("\n"); buffer.append(" .username = ") .append(getUsername()).append("\n"); buffer.append("[/FILESHARING]\n"); @@ -194,18 +156,25 @@ public class FileSharingRecord extends Record { } public int serialize(int offset, byte [] data) { + // TODO - junit LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize()-4)); LittleEndian.putShort(data, 4 + offset, getReadOnly()); LittleEndian.putShort(data, 6 + offset, getPassword()); - data[ 8 + offset ] = getUsernameLength(); - LittleEndian.putShort(data, 9 + offset, getUnknown()); - StringUtil.putCompressedUnicode( getUsername(), data, 11 + offset ); + LittleEndian.putShort(data, 8 + offset, getUsernameLength()); + if(getUsernameLength() > 0) { + LittleEndian.putByte(data, 10 + offset, field_3_username_unicode_options); + StringUtil.putCompressedUnicode( getUsername(), data, 11 + offset ); + } return getRecordSize(); } public int getRecordSize() { - return 11+getUsernameLength(); + short nameLen = getUsernameLength(); + if (nameLen < 1) { + return 10; + } + return 11+nameLen; } public short getSid() { @@ -219,10 +188,7 @@ public class FileSharingRecord extends Record { FileSharingRecord clone = new FileSharingRecord(); clone.setReadOnly(field_1_readonly); clone.setPassword(field_2_password); - clone.setUsernameLength(field_3_username_length); - clone.setUnknown(field_4_unknown); - clone.setUsername(field_5_username); + clone.setUsername(field_3_username_value); return clone; } - } diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index c405f901bd..c20f5e6d32 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -40,7 +40,7 @@ import org.apache.poi.util.LittleEndian; * @version 2.0-pre */ -public class FormulaRecord +public final class FormulaRecord extends Record implements CellValueRecordInterface, Comparable { @@ -108,6 +108,11 @@ public class FormulaRecord } catch (java.lang.UnsupportedOperationException uoe) { throw new RecordFormatException(uoe); } + if (in.remaining() == 10) { + // TODO - this seems to occur when IntersectionPtg is present + // 10 extra bytes are just 0x01 and 0x00 + // This causes POI stderr: "WARN. Unread 10 bytes of record 0x6" + } } //public void setRow(short row) diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java index 0e8c7741ac..fe8702c4ab 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -30,24 +30,23 @@ import org.apache.poi.hssf.record.RecordInputStream; * @author avik * @author Jason Height (jheight at chariot dot net dot au) */ - public abstract class Ptg { - + /* convert infix order ptg list to rpn order ptg list * @return List ptgs in RPN order * @param infixPtgs List of ptgs in infix order */ - + /* DO NOT REMOVE *we keep this method in case we wish to change the way we parse *It needs a getPrecedence in OperationsPtg - + public static List ptgsToRpn(List infixPtgs) { java.util.Stack operands = new java.util.Stack(); java.util.List retval = new java.util.Stack(); - + java.util.ListIterator i = infixPtgs.listIterator(); Object p; OperationPtg o ; @@ -61,13 +60,13 @@ public abstract class Ptg weHaveABracket = true; } else { o = (OperationPtg) operands.pop(); - while (!(o instanceof ParenthesisPtg)) { + while (!(o instanceof ParenthesisPtg)) { retval.add(o); } weHaveABracket = false; } } else { - + while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative retval.add(operands.pop()); } @@ -82,12 +81,16 @@ public abstract class Ptg //throw some error } else { retval.add(operands.pop()); - } + } } return retval; } */ + /** + * Reads size bytes of the input stream, to create an array of Ptgs. + * Extra data (beyond size) may be read if and ArrayPtgs are present. + */ public static Stack createParsedExpressionTokens(short size, RecordInputStream in ) { Stack stack = new Stack(); @@ -97,22 +100,25 @@ public abstract class Ptg { Ptg ptg = Ptg.createPtg( in ); if (ptg instanceof ArrayPtg) { - if (arrayPtgs == null) - arrayPtgs = new ArrayList(5); - arrayPtgs.add(ptg); - pos += 8; + if (arrayPtgs == null) + arrayPtgs = new ArrayList(5); + arrayPtgs.add(ptg); + pos += 8; } else pos += ptg.getSize(); stack.push( ptg ); } + if(pos != size) { + throw new RuntimeException("Ptg array size mismatch"); + } if (arrayPtgs != null) { - for (int i=0;i 0x60) { retval.setClass(CLASS_ARRAY); } else if (id > 0x40) { @@ -371,35 +377,35 @@ public abstract class Ptg } return retval; - + } - + public static int serializePtgStack(Stack expression, byte[] array, int offset) { - int pos = 0; - int size = 0; - if (expression != null) - size = expression.size(); - - List arrayPtgs = null; - - for (int k = 0; k < size; k++) { - Ptg ptg = ( Ptg ) expression.get(k); - - ptg.writeBytes(array, pos + offset); - if (ptg instanceof ArrayPtg) { - if (arrayPtgs == null) - arrayPtgs = new ArrayList(5); - arrayPtgs.add(ptg); - pos += 8; - } else pos += ptg.getSize(); - } - if (arrayPtgs != null) { - for (int i=0;i