From a748887d6ba61dba2df57c45de7f78d5476d8a45 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Mon, 28 Jul 2008 21:27:16 +0000 Subject: [PATCH] Merged revisions 638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-639917,639919-640056,640058-640710,640712-641156,641158-641184,641186-641795,641797-641798,641800-641933,641935-641963,641965-641966,641968-641995,641997-642230,642232-642562,642564-642565,642568-642570,642572-642573,642576-642736,642739-642877,642879,642881-642890,642892-642903,642905-642945,642947-643624,643626-643653,643655-643669,643671,643673-643830,643832-643833,643835-644342,644344-644472,644474-644508,644510-645347,645349-645351,645353-645559,645561-645565,645568-645951,645953-646193,646195-646311,646313-646404,646406-646665,646667-646853,646855-646869,646871-647151,647153-647185,647187-647277,647279-647566,647568-647573,647575,647578-647711,647714-647737,647739-647823,647825-648155,648157-648202,648204-648273,648275,648277-648302,648304-648333,648335-648588,648590-648622,648625-648673,648675-649141,649144,649146-649556,649558-649795,649799,649801-649910,649912-649913,649915-650128,650131-650132,650134-650137,650140-650914,650916-651991,651993-652284,652286-652287,652289,652291,652293-652297,652299-652328,652330-652425,652427-652445,652447-652560,652562-652933,652935,652937-652993,652995-653116,653118-653124,653126-653483,653487-653519,653522-653550,653552-653607,653609-653667,653669-653674,653676-653814,653817-653830,653832-653891,653893-653944,653946-654055,654057-654355,654357-654365,654367-654648,654651-655215,655217-655277,655279-655281,655283-655911,655913-656212,656214,656216-656251,656253-656698,656700-656756,656758-656892,656894-657135,657137-657165,657168-657179,657181-657354,657356-657357,657359-657701,657703-657874,657876-658032,658034-658284,658286,658288-658301,658303-658307,658309-658321,658323-658335,658337-658348,658351,658353-658832,658834-658983,658985,658987-659066,659068-659402,659404-659428,659430-659451,659453-659454,659456-659461,659463-659477,659479-659524,659526-659571,659574,659576-660255,660257-660262,660264-660279,660281-660343,660345-660473,660475-660827,660829-660833,660835-660888,660890-663321,663323-663435,663437-663764,663766-663854,663856-664219,664221-664489,664494-664514,664516-668013,668015-668142,668144-668152,668154,668156-668256,668258,668260-669139,669141-669455,669457-669657,669659-669808,669810-670189,670191-671321,671323-672229,672231-672549,672551-672552,672554-672561,672563-672566,672568,672571-673049,673051-673852,673854-673862,673864-673986,673988-673996,673998-674347,674349-674890,674892-674910,674912-674936,674938-674952,674954-675078,675080-675085,675087-675217,675219-675660,675662-675670,675672-675716,675718-675726,675728-675733,675735-675775,675777-675782,675784,675786-675791,675794-675852,675854-676200,676202,676204,676206-676220,676222-676309,676311-676456,676458-676994,676996-677027,677030-677040,677042-677056,677058-677375,677377-677968,677970-677971,677973,677975-677994,677996-678286,678288-680505 via svnmerge from https://svn.apache.org:443/repos/asf/poi/trunk ........ r678539 | nick | 2008-07-21 20:35:47 +0100 (Mon, 21 Jul 2008) | 1 line Fix bug #45437 - Detect encrypted word documents, and throw an EncryptedDocumentException instead of a OOM ........ r680394 | nick | 2008-07-28 17:41:47 +0100 (Mon, 28 Jul 2008) | 1 line Fix for DataFormatter on some JVMs ........ r680470 | josh | 2008-07-28 21:08:15 +0100 (Mon, 28 Jul 2008) | 1 line More tweaks for bug 45404. Fixes for JDK 1.4, improved member scoping and formatting. ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@680509 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + src/documentation/content/xdocs/status.xml | 1 + .../poi/EncryptedDocumentException.java | 24 + .../poi/hssf/usermodel/HSSFDataFormatter.java | 718 +++++++++--------- .../EncryptedPowerPointFileException.java | 11 +- .../src/org/apache/poi/hwpf/HWPFDocument.java | 7 +- .../poi/hwpf/data/PasswordProtected.doc | Bin 0 -> 19968 bytes .../poi/hwpf/usermodel/TestProblems.java | 15 + .../poi/hssf/usermodel/AllUserModelTests.java | 1 + .../hssf/usermodel/TestHSSFDataFormatter.java | 335 ++++---- 10 files changed, 567 insertions(+), 546 deletions(-) create mode 100644 src/java/org/apache/poi/EncryptedDocumentException.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hwpf/data/PasswordProtected.doc diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 43d6bb7b16..12bce0ccf5 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -51,6 +51,7 @@ Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx + 45437 - Detect encrypted word documents, and throw an EncryptedDocumentException instead of a OOM 45404 - New class, hssf.usermodel.HSSFDataFormatter, for formatting numbers and dates in the same way that Excel does 45414 - Don't add too many UncalcedRecords to sheets with charts in them 45398 - Support detecting date formats containing "am/pm" as date times diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index f1f81d0699..3b6644db96 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -48,6 +48,7 @@ Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx + 45437 - Detect encrypted word documents, and throw an EncryptedDocumentException instead of a OOM 45404 - New class, hssf.usermodel.HSSFDataFormatter, for formatting numbers and dates in the same way that Excel does 45414 - Don't add too many UncalcedRecords to sheets with charts in them 45398 - Support detecting date formats containing "am/pm" as date times diff --git a/src/java/org/apache/poi/EncryptedDocumentException.java b/src/java/org/apache/poi/EncryptedDocumentException.java new file mode 100644 index 0000000000..4922d1c81d --- /dev/null +++ b/src/java/org/apache/poi/EncryptedDocumentException.java @@ -0,0 +1,24 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi; + +public class EncryptedDocumentException extends IllegalStateException +{ + public EncryptedDocumentException(String s) { + super(s); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java index c1701e22b3..67291a22f1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java @@ -68,78 +68,64 @@ import java.util.regex.Pattern; * can override the default format pattern with * HSSFDataFormatter.setDefaultNumberFormat(Format). Note: the * default format will only be used when a Format cannot be created from the - * cell's data format string. - * + * cell's data format string. + * * @author James May (james dot may at fmr dot com) * */ -public class HSSFDataFormatter { +public final class HSSFDataFormatter { /** Pattern to find a number format: "0" or "#" */ - protected Pattern numPattern; - + private static final Pattern numPattern = Pattern.compile("[0#]+"); + /** Pattern to find days of week as text "ddd...." */ - protected Pattern daysAsText; - + private static final Pattern daysAsText = Pattern.compile("([d]{3,})", Pattern.CASE_INSENSITIVE); + /** Pattern to find "AM/PM" marker */ - protected Pattern amPmPattern; + private static final Pattern amPmPattern = Pattern.compile("((A|P)[M/P]*)", Pattern.CASE_INSENSITIVE); /** A regex to find patterns like [$$-1009] and [$�-452]. */ - protected Pattern specialPatternGroup; - + private static final Pattern specialPatternGroup = Pattern.compile("(\\[\\$[^-\\]]*-[0-9A-Z]+\\])"); + /** General format for whole numbers. */ - protected Format generalWholeNumFormat; - + private static final Format generalWholeNumFormat = new DecimalFormat("#"); + /** General format for decimal numbers. */ - protected Format generalDecimalNumFormat; - + private static final Format generalDecimalNumFormat = new DecimalFormat("#.##########"); + /** A default format to use when a number pattern cannot be parsed. */ - protected Format defaultNumFormat; - - /** + private Format defaultNumFormat; + + /** * A map to cache formats. * Map formats */ - protected Map formats; - + private final Map formats; /** * Constructor */ public HSSFDataFormatter() { - numPattern = Pattern.compile("[0#]+"); - daysAsText = Pattern.compile("([d]{3,})", Pattern.CASE_INSENSITIVE); - amPmPattern = Pattern.compile("((A|P)[M/P]*)", Pattern.CASE_INSENSITIVE); - specialPatternGroup = Pattern.compile("(\\[\\$[^-\\]]*-[0-9A-Z]+\\])"); - generalWholeNumFormat = new DecimalFormat("#"); - generalDecimalNumFormat = new DecimalFormat("#.##########"); formats = new HashMap(); - + // init built-in formats - init(); - } - /** - * Initialize the formatter. Called after construction. - */ - protected void init() { - - ZipPlusFourFormat zipFormat = new ZipPlusFourFormat(); + Format zipFormat = ZipPlusFourFormat.instance; addFormat("00000\\-0000", zipFormat); addFormat("00000-0000", zipFormat); - - PhoneFormat phoneFormat = new PhoneFormat(); + + Format phoneFormat = PhoneFormat.instance; // allow for format string variations addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat); addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat); addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat); - addFormat("###-####;(###) ###-####", phoneFormat); - - SSNFormat ssnFormat = new SSNFormat(); - addFormat("000\\-00\\-0000", ssnFormat); - addFormat("000-00-0000", ssnFormat); + addFormat("###-####;(###) ###-####", phoneFormat); + + Format ssnFormat = SSNFormat.instance; + addFormat("000\\-00\\-0000", ssnFormat); + addFormat("000-00-0000", ssnFormat); } - + /** * Return a Format for the given cell if one exists, otherwise try to * create one. This method will return null if the any of the @@ -149,15 +135,15 @@ public class HSSFDataFormatter { *
  • the style's data format string is null or empty
  • *
  • the format string cannot be recognized as either a number or date
  • * - * + * * @param cell The cell to retrieve a Format for * @return A Format for the format String */ - protected Format getFormat(HSSFCell cell) { + private Format getFormat(HSSFCell cell) { if ( cell.getCellStyle() == null) { return null; } - + int formatIndex = cell.getCellStyle().getDataFormat(); String formatStr = cell.getCellStyle().getDataFormatString(); if(formatStr == null || formatStr.trim().length() == 0) { @@ -165,380 +151,375 @@ public class HSSFDataFormatter { } return getFormat(cell.getNumericCellValue(), formatIndex, formatStr); } - + private Format getFormat(double cellValue, int formatIndex, String formatStr) { Format format = (Format)formats.get(formatStr); if (format != null) { return format; - } else if (formatStr.equals("General")) { + } + if (formatStr.equals("General")) { if (HSSFDataFormatter.isWholeNumber(cellValue)) { return generalWholeNumFormat; - } else { - return generalDecimalNumFormat; } - } else { - format = createFormat(cellValue, formatIndex, formatStr); - formats.put(formatStr, format); - return format; + return generalDecimalNumFormat; } + format = createFormat(cellValue, formatIndex, formatStr); + formats.put(formatStr, format); + return format; } - + /** * Create and return a Format based on the format string from a cell's * style. If the pattern cannot be parsed, return a default pattern. - * + * * @param cell The Excel cell * @return A Format representing the excel format. May return null. */ - protected Format createFormat(HSSFCell cell) { - String sFormat = cell.getCellStyle().getDataFormatString(); - + public Format createFormat(HSSFCell cell) { + int formatIndex = cell.getCellStyle().getDataFormat(); String formatStr = cell.getCellStyle().getDataFormatString(); - return createFormat(cell.getNumericCellValue(), formatIndex, formatStr); + return createFormat(cell.getNumericCellValue(), formatIndex, formatStr); } - + private Format createFormat(double cellValue, int formatIndex, String sFormat) { // remove color formatting if present String formatStr = sFormat.replaceAll("\\[[a-zA-Z]*\\]", ""); - + // try to extract special characters like currency - Matcher m = specialPatternGroup.matcher(formatStr); - try { - while(m.find()) { - String match = m.group(); - String symbol = match.substring(match.indexOf('$') + 1, match.indexOf('-')); - if (symbol.indexOf('$') > -1) { - StringBuffer sb = new StringBuffer(); - sb.append(symbol.substring(0, symbol.indexOf('$'))); - sb.append('\\'); - sb.append(symbol.substring(symbol.indexOf('$'), symbol.length())); - symbol = sb.toString(); - } - formatStr = m.replaceAll(symbol); + Matcher m = specialPatternGroup.matcher(formatStr); + while(m.find()) { + String match = m.group(); + String symbol = match.substring(match.indexOf('$') + 1, match.indexOf('-')); + if (symbol.indexOf('$') > -1) { + StringBuffer sb = new StringBuffer(); + sb.append(symbol.substring(0, symbol.indexOf('$'))); + sb.append('\\'); + sb.append(symbol.substring(symbol.indexOf('$'), symbol.length())); + symbol = sb.toString(); } - } catch (Exception e) { - return getDefaultFormat(cellValue); + formatStr = m.replaceAll(symbol); + m = specialPatternGroup.matcher(formatStr); } - + if(formatStr == null || formatStr.trim().length() == 0) { return getDefaultFormat(cellValue); } - Format returnVal = null; - StringBuffer sb = null; - - if(HSSFDateUtil.isADateFormat(formatIndex,formatStr) && - HSSFDateUtil.isValidExcelDate(cellValue)) { - formatStr = formatStr.replaceAll("\\\\-","-"); - formatStr = formatStr.replaceAll("\\\\,",","); - formatStr = formatStr.replaceAll("\\\\ "," "); - formatStr = formatStr.replaceAll(";@", ""); - boolean hasAmPm = false; - Matcher amPmMatcher = amPmPattern.matcher(formatStr); - while (amPmMatcher.find()) { - formatStr = amPmMatcher.replaceAll("a"); - hasAmPm = true; - } - - Matcher dateMatcher = daysAsText.matcher(formatStr); - if (dateMatcher.find()) { - String match = dateMatcher.group(0); - formatStr = dateMatcher.replaceAll(match.toUpperCase().replaceAll("D", "E")); - } - - // Convert excel date format to SimpleDateFormat. - // Excel uses lower case 'm' for both minutes and months. - // From Excel help: - /* - The "m" or "mm" code must appear immediately after the "h" or"hh" - code or immediately before the "ss" code; otherwise, Microsoft - Excel displays the month instead of minutes." - */ - - sb = new StringBuffer(); - char[] chars = formatStr.toCharArray(); - boolean mIsMonth = true; - List ms = new ArrayList(); - for(int j=0; j -1 && sb.charAt(idx -1) == '_') { - sb.deleteCharAt(idx); - sb.deleteCharAt(idx - 1); - sb.deleteCharAt(i); - i--; + + if(HSSFDateUtil.isADateFormat(formatIndex,formatStr) && + HSSFDateUtil.isValidExcelDate(cellValue)) { + return createDateFormat(formatStr, cellValue); + } + if (numPattern.matcher(formatStr).find()) { + return createNumberFormat(formatStr, cellValue); + } + // TODO - when does this occur? + return null; + } + + private Format createDateFormat(String pFormatStr, double cellValue) { + String formatStr = pFormatStr; + formatStr = formatStr.replaceAll("\\\\-","-"); + formatStr = formatStr.replaceAll("\\\\,",","); + formatStr = formatStr.replaceAll("\\\\ "," "); + formatStr = formatStr.replaceAll(";@", ""); + boolean hasAmPm = false; + Matcher amPmMatcher = amPmPattern.matcher(formatStr); + while (amPmMatcher.find()) { + formatStr = amPmMatcher.replaceAll("@"); + hasAmPm = true; + amPmMatcher = amPmPattern.matcher(formatStr); + } + formatStr = formatStr.replaceAll("@", "a"); + + + Matcher dateMatcher = daysAsText.matcher(formatStr); + if (dateMatcher.find()) { + String match = dateMatcher.group(0); + formatStr = dateMatcher.replaceAll(match.toUpperCase().replaceAll("D", "E")); + } + + // Convert excel date format to SimpleDateFormat. + // Excel uses lower case 'm' for both minutes and months. + // From Excel help: + /* + The "m" or "mm" code must appear immediately after the "h" or"hh" + code or immediately before the "ss" code; otherwise, Microsoft + Excel displays the month instead of minutes." + */ + + StringBuffer sb = new StringBuffer(); + char[] chars = formatStr.toCharArray(); + boolean mIsMonth = true; + List ms = new ArrayList(); + for(int j=0; j 0 && sb.charAt(i - 1) == '_') { - sb.deleteCharAt(i); - sb.deleteCharAt(i - 1); - i--; - // remove quotes and back slashes - } else if (c == '\\' || c == '"') { - sb.deleteCharAt(i); - i--; - - // for scientific/engineering notation - } else if (c == '+' && i > 0 && sb.charAt(i - 1) == 'E') { + } + mIsMonth = true; + ms.clear(); + } + else if (Character.isLetter(c)) { + mIsMonth = true; + ms.clear(); + if (c == 'y' || c == 'Y') { + sb.append('y'); + } + else if (c == 'd' || c == 'D') { + sb.append('d'); + } + else { + sb.append(c); + } + } + else { + sb.append(c); + } + } + formatStr = sb.toString(); + + try { + return new SimpleDateFormat(formatStr); + } catch(IllegalArgumentException iae) { + + // the pattern could not be parsed correctly, + // so fall back to the default number format + return getDefaultFormat(cellValue); + } + + } + + private Format createNumberFormat(String formatStr, double cellValue) { + StringBuffer sb = new StringBuffer(formatStr); + for (int i = 0; i < sb.length(); i++) { + char c = sb.charAt(i); + //handle (#,##0_); + if (c == '(') { + int idx = sb.indexOf(")", i); + if (idx > -1 && sb.charAt(idx -1) == '_') { + sb.deleteCharAt(idx); + sb.deleteCharAt(idx - 1); sb.deleteCharAt(i); i--; - } - } - formatStr = sb.toString(); - try { - returnVal = new DecimalFormat(formatStr); - } catch(IllegalArgumentException iae) { + } + } else if (c == ')' && i > 0 && sb.charAt(i - 1) == '_') { + sb.deleteCharAt(i); + sb.deleteCharAt(i - 1); + i--; + // remove quotes and back slashes + } else if (c == '\\' || c == '"') { + sb.deleteCharAt(i); + i--; - // the pattern could not be parsed correctly, - // so fall back to the default number format - return getDefaultFormat(cellValue); + // for scientific/engineering notation + } else if (c == '+' && i > 0 && sb.charAt(i - 1) == 'E') { + sb.deleteCharAt(i); + i--; } } - return returnVal; + + try { + return new DecimalFormat(sb.toString()); + } catch(IllegalArgumentException iae) { + + // the pattern could not be parsed correctly, + // so fall back to the default number format + return getDefaultFormat(cellValue); + } } - + /** * Return true if the double value represents a whole number * @param d the double value to check - * @return true if d is a whole number + * @return true if d is a whole number */ private static boolean isWholeNumber(double d) { return d == Math.floor(d); } - + /** * Returns a default format for a cell. * @param cell The cell * @return a default format */ - protected Format getDefaultFormat(HSSFCell cell) { + public Format getDefaultFormat(HSSFCell cell) { return getDefaultFormat(cell.getNumericCellValue()); } private Format getDefaultFormat(double cellValue) { // for numeric cells try user supplied default if (defaultNumFormat != null) { return defaultNumFormat; - - // otherwise use general format - } else if (isWholeNumber(cellValue)){ + + // otherwise use general format + } + if (isWholeNumber(cellValue)){ return generalWholeNumFormat; - } else { - return generalDecimalNumFormat; } + return generalDecimalNumFormat; } - + /** * Returns the formatted value of an Excel date as a String based * on the cell's DataFormat. i.e. "Thursday, January 02, 2003" * , "01/02/2003" , "02-Jan" , etc. - * + * * @param cell The cell * @return a formatted date string - */ - protected String getFormattedDateString(HSSFCell cell) { - Format dateFormat = getFormat(cell); - Date d = cell.getDateCellValue(); - if (dateFormat != null) { - return dateFormat.format(d); - } else { - return d.toString(); - } - } - + */ + private String getFormattedDateString(HSSFCell cell) { + Format dateFormat = getFormat(cell); + Date d = cell.getDateCellValue(); + if (dateFormat != null) { + return dateFormat.format(d); + } + return d.toString(); + } + /** * Returns the formatted value of an Excel number as a String * based on the cell's DataFormat. Supported formats include * currency, percents, decimals, phone number, SSN, etc.: * "61.54%", "$100.00", "(800) 555-1234". - * + * * @param cell The cell * @return a formatted number string - */ - protected String getFormattedNumberString(HSSFCell cell) { - - Format numberFormat = getFormat(cell); - double d = cell.getNumericCellValue(); - if (numberFormat != null) { - return numberFormat.format(new Double(d)); - } else { - return String.valueOf(d); - } - } - - /** - * Formats the given raw cell value, based on the supplied - * format index and string, according to excel style rules. - * @see #formatCellValue(HSSFCell) - */ - public String formatRawCellContents(double value, int formatIndex, String formatString) { - // Is it a date? - if(HSSFDateUtil.isADateFormat(formatIndex,formatString) && - HSSFDateUtil.isValidExcelDate(value)) { - - Format dateFormat = getFormat(value, formatIndex, formatString); - Date d = HSSFDateUtil.getJavaDate(value); - if (dateFormat != null) { - return dateFormat.format(d); - } else { - return d.toString(); - } - } else { - // Number - Format numberFormat = getFormat(value, formatIndex, formatString); - if (numberFormat != null) { - return numberFormat.format(new Double(value)); - } else { - return String.valueOf(value); - } - } - } - + */ + private String getFormattedNumberString(HSSFCell cell) { + + Format numberFormat = getFormat(cell); + double d = cell.getNumericCellValue(); + if (numberFormat == null) { + return String.valueOf(d); + } + return numberFormat.format(new Double(d)); + } + + /** + * Formats the given raw cell value, based on the supplied + * format index and string, according to excel style rules. + * @see #formatCellValue(HSSFCell) + */ + public String formatRawCellContents(double value, int formatIndex, String formatString) { + // Is it a date? + if(HSSFDateUtil.isADateFormat(formatIndex,formatString) && + HSSFDateUtil.isValidExcelDate(value)) { + + Format dateFormat = getFormat(value, formatIndex, formatString); + Date d = HSSFDateUtil.getJavaDate(value); + if (dateFormat == null) { + return d.toString(); + } + return dateFormat.format(d); + } + // else Number + Format numberFormat = getFormat(value, formatIndex, formatString); + if (numberFormat == null) { + return String.valueOf(value); + } + return numberFormat.format(new Double(value)); + } + /** *

    * Returns the formatted value of a cell as a String regardless * of the cell type. If the Excel format pattern cannot be parsed then the - * cell value will be formatted using a default format. + * cell value will be formatted using a default format. *

    *

    When passed a null or blank cell, this method will return an empty * String (""). Formulas in formula type cells will not be evaluated. *

    - * + * * @param cell The cell * @return the formatted cell value as a String */ public String formatCellValue(HSSFCell cell) { return formatCellValue(cell, null); } - + /** *

    * Returns the formatted value of a cell as a String regardless * of the cell type. If the Excel format pattern cannot be parsed then the - * cell value will be formatted using a default format. + * cell value will be formatted using a default format. *

    *

    When passed a null or blank cell, this method will return an empty * String (""). Formula cells will be evaluated using the given * {@link HSSFFormulaEvaluator} if the evaluator is non-null. If the * evaluator is null, then the formula String will be returned. The caller - * is responsible for setting the currentRow on the evaluator, otherwise an - * IllegalArgumentException may be thrown. + * is responsible for setting the currentRow on the evaluator *

    - * - * @param cell The cell + * + * @param cell The cell (can be null) * @param evaluator The HSSFFormulaEvaluator (can be null) * @return a string value of the cell - * @throws IllegalArgumentException if cell type is - * HSSFCell.CELL_TYPE_FORMULA and evaluator is not null - * and the evlaluator's currentRow has not been set. */ - public String formatCellValue(HSSFCell cell, + public String formatCellValue(HSSFCell cell, HSSFFormulaEvaluator evaluator) throws IllegalArgumentException { - String value = ""; if (cell == null) { - return value; + return ""; } - + int cellType = cell.getCellType(); if (evaluator != null && cellType == HSSFCell.CELL_TYPE_FORMULA) { try { cellType = evaluator.evaluateFormulaCell(cell); - } catch (Throwable t) { - throw new IllegalArgumentException("Did you forget to set the current" + - " row on the HSSFFormulaEvaluator?", t); + } catch (RuntimeException e) { + throw new RuntimeException("Did you forget to set the current" + + " row on the HSSFFormulaEvaluator?", e); } - } + } switch (cellType) - { - case HSSFCell.CELL_TYPE_FORMULA : - // should only occur if evaluator is null - value = cell.getCellFormula(); - break; - - case HSSFCell.CELL_TYPE_NUMERIC : - - if (HSSFDateUtil.isCellDateFormatted(cell)) { - value = getFormattedDateString(cell); - } else { - value = getFormattedNumberString(cell); - } - break; - - case HSSFCell.CELL_TYPE_STRING : - value = cell.getRichStringCellValue().getString(); - break; - - case HSSFCell.CELL_TYPE_BOOLEAN : - value = String.valueOf(cell.getBooleanCellValue()); - } - return value; + { + case HSSFCell.CELL_TYPE_FORMULA : + // should only occur if evaluator is null + return cell.getCellFormula(); + + case HSSFCell.CELL_TYPE_NUMERIC : + + if (HSSFDateUtil.isCellDateFormatted(cell)) { + return getFormattedDateString(cell); + } + return getFormattedNumberString(cell); + + case HSSFCell.CELL_TYPE_STRING : + return cell.getRichStringCellValue().getString(); + + case HSSFCell.CELL_TYPE_BOOLEAN : + return String.valueOf(cell.getBooleanCellValue()); + case HSSFCell.CELL_TYPE_BLANK : + return ""; + } + throw new RuntimeException("Unexpected celltype (" + cellType + ")"); } - - + + /** *

    * Sets a default number format to be used when the Excel format cannot be @@ -552,7 +533,7 @@ public class HSSFDataFormatter { * numeric cell. Therefore the code in the format method should expect a * Number value. *

    - * + * * @param format A Format instance to be used as a default * @see java.text.Format#format */ @@ -566,8 +547,8 @@ public class HSSFDataFormatter { } } defaultNumFormat = format; - } - + } + /** * Adds a new format to the available formats. *

    @@ -575,7 +556,7 @@ public class HSSFDataFormatter { * by java.text.Format#format) will be a double value from a * numeric cell. Therefore the code in the format method should expect a * Number value. - *

    + *

    * @param excelFormatStr The data format string * @param format A Format instance */ @@ -584,24 +565,30 @@ public class HSSFDataFormatter { } // Some custom formats - + + /** + * @return a DecimalFormat with parseIntegerOnly set true + */ + /* package */ static DecimalFormat createIntegerOnlyFormat(String fmt) { + DecimalFormat result = new DecimalFormat(fmt); + result.setParseIntegerOnly(true); + return result; + } /** * Format class for Excel's SSN format. This class mimics Excel's built-in * SSN formatting. - * + * * @author James May */ - static class SSNFormat extends Format { - private DecimalFormat df; - - /** Constructor */ - public SSNFormat() { - df = new DecimalFormat("000000000"); - df.setParseIntegerOnly(true); - } - + private static final class SSNFormat extends Format { + public static final Format instance = new SSNFormat(); + private static final DecimalFormat df = createIntegerOnlyFormat("000000000"); + private SSNFormat() { + // enforce singleton + } + /** Format a number as an SSN */ - public String format(Number num) { + public static String format(Number num) { String result = df.format(num); StringBuffer sb = new StringBuffer(); sb.append(result.substring(0, 3)).append('-'); @@ -609,66 +596,60 @@ public class HSSFDataFormatter { sb.append(result.substring(5, 9)); return sb.toString(); } - - public StringBuffer format(Object obj, StringBuffer toAppendTo, - FieldPosition pos) { + + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { return toAppendTo.append(format((Number)obj)); } - + public Object parseObject(String source, ParsePosition pos) { return df.parseObject(source, pos); } } - + /** * Format class for Excel Zip + 4 format. This class mimics Excel's * built-in formatting for Zip + 4. * @author James May - */ - static class ZipPlusFourFormat extends Format { - private DecimalFormat df; - - /** Constructor */ - public ZipPlusFourFormat() { - df = new DecimalFormat("000000000"); - df.setParseIntegerOnly(true); - } - + */ + private static final class ZipPlusFourFormat extends Format { + public static final Format instance = new ZipPlusFourFormat(); + private static final DecimalFormat df = createIntegerOnlyFormat("000000000"); + private ZipPlusFourFormat() { + // enforce singleton + } + /** Format a number as Zip + 4 */ - public String format(Number num) { + public static String format(Number num) { String result = df.format(num); StringBuffer sb = new StringBuffer(); sb.append(result.substring(0, 5)).append('-'); sb.append(result.substring(5, 9)); return sb.toString(); } - - public StringBuffer format(Object obj, StringBuffer toAppendTo, - FieldPosition pos) { + + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { return toAppendTo.append(format((Number)obj)); } - + public Object parseObject(String source, ParsePosition pos) { return df.parseObject(source, pos); } - } - + } + /** * Format class for Excel phone number format. This class mimics Excel's * built-in phone number formatting. * @author James May - */ - static class PhoneFormat extends Format { - private DecimalFormat df; - - /** Constructor */ - public PhoneFormat() { - df = new DecimalFormat("##########"); - df.setParseIntegerOnly(true); + */ + private static final class PhoneFormat extends Format { + public static final Format instance = new PhoneFormat(); + private static final DecimalFormat df = createIntegerOnlyFormat("##########"); + private PhoneFormat() { + // enforce singleton } - + /** Format a number as a phone number */ - public String format(Number num) { + public static String format(Number num) { String result = df.format(num); StringBuffer sb = new StringBuffer(); String seg1, seg2, seg3; @@ -676,28 +657,27 @@ public class HSSFDataFormatter { if (len <= 4) { return result; } - + seg3 = result.substring(len - 4, len); - seg2 = result.substring(Math.max(0, len - 7), len - 4); + seg2 = result.substring(Math.max(0, len - 7), len - 4); seg1 = result.substring(Math.max(0, len - 10), Math.max(0, len - 7)); - + if(seg1 != null && seg1.trim().length() > 0) { sb.append('(').append(seg1).append(") "); } if(seg2 != null && seg2.trim().length() > 0) { - sb.append(seg2).append('-'); + sb.append(seg2).append('-'); } sb.append(seg3); return sb.toString(); } - - public StringBuffer format(Object obj, StringBuffer toAppendTo, - FieldPosition pos) { + + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { return toAppendTo.append(format((Number)obj)); } - + public Object parseObject(String source, ParsePosition pos) { return df.parseObject(source, pos); } - } + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java b/src/scratchpad/src/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java index 77f93a10f6..08eabd223b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java +++ b/src/scratchpad/src/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.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,19 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - - - package org.apache.poi.hslf.exceptions; +import org.apache.poi.EncryptedDocumentException; + /** * This exception is thrown when we try to open a PowerPoint file, and * discover that it is encrypted - * - * @author Nick Burch */ - -public class EncryptedPowerPointFileException extends IllegalStateException +public class EncryptedPowerPointFileException extends EncryptedDocumentException { public EncryptedPowerPointFileException(String s) { super(s); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java b/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java index a43357f021..c97d6a8bf0 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java @@ -28,6 +28,7 @@ import java.io.ByteArrayInputStream; import java.util.Iterator; +import org.apache.poi.EncryptedDocumentException; import org.apache.poi.POIDocument; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; @@ -174,9 +175,13 @@ public class HWPFDocument extends POIDocument directory.createDocumentInputStream("WordDocument").read(_mainStream); - // use the fib to determine the name of the table stream. + // Create our FIB, and check for the doc being encrypted _fib = new FileInformationBlock(_mainStream); + if(_fib.isFEncrypted()) { + throw new EncryptedDocumentException("Cannot process encrypted word files!"); + } + // use the fib to determine the name of the table stream. String name = "0Table"; if (_fib.isFWhichTblStm()) { diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/PasswordProtected.doc b/src/scratchpad/testcases/org/apache/poi/hwpf/data/PasswordProtected.doc new file mode 100644 index 0000000000000000000000000000000000000000..0d6c1690636e91f877a889c0a62d82fd689354c8 GIT binary patch literal 19968 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 -1); } @@ -184,70 +184,70 @@ public class TestHSSFDataFormatter extends TestCase { // test number formats row = wb.getSheetAt(0).getRow(1); it = row.cellIterator(); - System.out.println("\n==== VALID NUMBER FORMATS ===="); + log("\n==== VALID NUMBER FORMATS ===="); while (it.hasNext()) { HSSFCell cell = (HSSFCell) it.next(); - System.out.println(formatter.formatCellValue(cell)); - + log(formatter.formatCellValue(cell)); + // should not be equal to "1234567890.12345" assertTrue( ! "1234567890.12345".equals(formatter.formatCellValue(cell))); } - + // test bad number formats row = wb.getSheetAt(0).getRow(2); it = row.cellIterator(); - System.out.println("\n==== INVALID NUMBER FORMATS ===="); + log("\n==== INVALID NUMBER FORMATS ===="); while (it.hasNext()) { HSSFCell cell = (HSSFCell) it.next(); - System.out.println(formatter.formatCellValue(cell)); + log(formatter.formatCellValue(cell)); // should be equal to "1234567890.12345" assertEquals("1234567890.12345", formatter.formatCellValue(cell)); } - + // test Zip+4 format row = wb.getSheetAt(0).getRow(3); HSSFCell cell = row.getCell(0); - System.out.println("\n==== ZIP FORMAT ===="); - System.out.println(formatter.formatCellValue(cell)); + log("\n==== ZIP FORMAT ===="); + log(formatter.formatCellValue(cell)); assertEquals("12345-6789", formatter.formatCellValue(cell)); - + // test phone number format row = wb.getSheetAt(0).getRow(4); cell = row.getCell(0); - System.out.println("\n==== PHONE FORMAT ===="); - System.out.println(formatter.formatCellValue(cell)); + log("\n==== PHONE FORMAT ===="); + log(formatter.formatCellValue(cell)); assertEquals("(555) 123-4567", formatter.formatCellValue(cell)); - + // test SSN format row = wb.getSheetAt(0).getRow(5); cell = row.getCell(0); - System.out.println("\n==== SSN FORMAT ===="); - System.out.println(formatter.formatCellValue(cell)); - assertEquals("444-55-1234", formatter.formatCellValue(cell)); - + log("\n==== SSN FORMAT ===="); + log(formatter.formatCellValue(cell)); + assertEquals("444-55-1234", formatter.formatCellValue(cell)); + // null test-- null cell should result in empty String assertEquals(formatter.formatCellValue(null), ""); - + // null test-- null cell should result in empty String - assertEquals(formatter.formatCellValue(null), ""); - + assertEquals(formatter.formatCellValue(null), ""); + } public void testGetFormattedCellValueHSSFCellHSSFFormulaEvaluator() { // test formula format HSSFRow row = wb.getSheetAt(0).getRow(6); HSSFCell cell = row.getCell(0); - System.out.println("\n==== FORMULA CELL ===="); - + log("\n==== FORMULA CELL ===="); + // first without a formula evaluator - System.out.println(formatter.formatCellValue(cell) + "\t (without evaluator)"); - assertEquals("SUM(12.25,12.25)/100", formatter.formatCellValue(cell)); - - // now with a formula evaluator + log(formatter.formatCellValue(cell) + "\t (without evaluator)"); + assertEquals("SUM(12.25,12.25)/100", formatter.formatCellValue(cell)); + + // now with a formula evaluator HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb.getSheetAt(0), wb); //! must set current row ! evaluator.setCurrentRow(row); - System.out.println(formatter.formatCellValue(cell, evaluator) + "\t\t\t (with evaluator)"); + log(formatter.formatCellValue(cell, evaluator) + "\t\t\t (with evaluator)"); assertEquals("24.50%", formatter.formatCellValue(cell,evaluator)); } @@ -259,24 +259,23 @@ public class TestHSSFDataFormatter extends TestCase { */ public void testSetDefaultNumberFormat() { HSSFRow row = wb.getSheetAt(0).getRow(2); - Iterator it = row.cellIterator(); + Iterator it = row.cellIterator(); Format defaultFormat = new DecimalFormat("Balance $#,#00.00 USD;Balance -$#,#00.00 USD"); formatter.setDefaultNumberFormat(defaultFormat); double value = 10d; - System.out.println("\n==== DEFAULT NUMBER FORMAT ===="); + log("\n==== DEFAULT NUMBER FORMAT ===="); while (it.hasNext()) { - HSSFCell cell = (HSSFCell) it.next(); + HSSFCell cell = (HSSFCell) it.next(); cell.setCellValue(cell.getNumericCellValue() * Math.random() / 1000000 - 1000); - System.out.println(formatter.formatCellValue(cell)); + log(formatter.formatCellValue(cell)); assertTrue(formatter.formatCellValue(cell).startsWith("Balance ")); assertTrue(formatter.formatCellValue(cell).endsWith(" USD")); - } + } } - public static void main(String [] args) { - System.out - .println("Testing org.apache.poi.hssf.usermodel.TestHSSFDataFormatter"); - junit.textui.TestRunner.run(TestHSSFDataFormatter.class); - } - + private static void log(String msg) { + if (false) { // successful tests should be silent + System.out.println(msg); + } + } } -- 2.39.5