diff --git a/main/DDF/UnknownEscherRecord.cs b/main/DDF/UnknownEscherRecord.cs
index 1d95bee76..507934988 100644
--- a/main/DDF/UnknownEscherRecord.cs
+++ b/main/DDF/UnknownEscherRecord.cs
@@ -54,14 +54,14 @@ public override int FillFields(byte[] data, int offset, IEscherRecordFactory rec
int bytesRemaining = ReadHeader(data, offset);
/*
* Modified by Zhang Zhang
- * Have a check between avaliable bytes and bytesRemaining,
- * take the avaliable length if the bytesRemaining out of range.
+ * Have a check between available bytes and bytesRemaining,
+ * take the available length if the bytesRemaining out of range.
* July 09, 2010
*/
- int avaliable = data.Length - (offset + 8);
- if (bytesRemaining > avaliable)
+ int available = data.Length - (offset + 8);
+ if (bytesRemaining > available)
{
- bytesRemaining = avaliable;
+ bytesRemaining = available;
}
if (IsContainerRecord)
{
@@ -82,6 +82,9 @@ public override int FillFields(byte[] data, int offset, IEscherRecordFactory rec
}
else
{
+ if (bytesRemaining < 0) {
+ bytesRemaining = 0;
+ }
_thedata = new byte[bytesRemaining];
Array.Copy(data, offset + 8, _thedata, 0, bytesRemaining);
return bytesRemaining + 8;
diff --git a/main/POIFS/Storage/HeaderBlock.cs b/main/POIFS/Storage/HeaderBlock.cs
index a6cde8428..6c77f3199 100644
--- a/main/POIFS/Storage/HeaderBlock.cs
+++ b/main/POIFS/Storage/HeaderBlock.cs
@@ -71,7 +71,12 @@ public class HeaderBlock : HeaderBlockConstants
0x00, 0x00, // unused
0x00, 0x01
};
-
+ private static byte[] MAGIC_MSWRITEa = {
+ 0x31, (byte)0xbe, 0x00, 0x00
+ };
+ private static byte[] MAGIC_MSWRITEb = {
+ 0x32, (byte)0xbe, 0x00, 0x00
+ };
private static byte _default_value = (byte)0xFF;
/**
* What big block Size the file uses. Most files
@@ -146,6 +151,12 @@ public void PrivateHeaderBlock(byte[] data)
+ "Formats such as Office 2003 XML are not supported");
}
+ // Old MS Write raw stream
+ if (cmp(MAGIC_MSWRITEa, data) || cmp(MAGIC_MSWRITEb, data)) {
+ throw new NotOLE2FileException("The supplied data appears to be in the old MS Write format. "
+ + "NPOI doesn't currently support this format");
+ }
+
// BIFF2 raw stream
if (cmp(MAGIC_BIFF2, data))
{
diff --git a/main/Util/FileInputStream.cs b/main/Util/FileInputStream.cs
index 1febec6b2..885631db5 100644
--- a/main/Util/FileInputStream.cs
+++ b/main/Util/FileInputStream.cs
@@ -48,6 +48,11 @@ public override int Read()
return inner.ReadByte();
}
+ public override int Read(byte[] b, int off, int len)
+ {
+ return inner.Read(b, off, len);
+ }
+
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
diff --git a/main/Util/IOUtils.cs b/main/Util/IOUtils.cs
index e3966ca55..542767196 100644
--- a/main/Util/IOUtils.cs
+++ b/main/Util/IOUtils.cs
@@ -36,6 +36,11 @@ public class IOUtils
{
private static POILogger logger = POILogFactory.GetLogger(typeof(IOUtils));
+ ///
+ /// The default buffer size to use for the skip() methods.
+ ///
+ private static int SKIP_BUFFER_SIZE = 2048;
+ private static byte[] SKIP_BYTE_BUFFER;
///
/// The current set global allocation limit override,
/// -1 means limits are applied per record type.
@@ -417,6 +422,72 @@ public static void CloseQuietly(ICloseable closeable)
}
}
+ ///
+ ///
+ /// Skips bytes from an input byte stream.
+ /// This implementation guarantees that it will read as many bytes
+ /// as possible before giving up; this may not always be the case for
+ /// skip() implementations in subclasses of .
+ ///
+ ///
+ /// Note that the implementation uses rather
+ /// than delegating to .
+ /// This means that the method may be considerably less efficient than using the actual skip implementation,
+ /// this is done to guarantee that the correct number of bytes are skipped.
+ ///
+ ///
+ ///
+ ///
+ /// This mimics POI's .
+ /// If the end of file is reached before any bytes are read, returns -1. If
+ /// the end of the file is reached After some bytes are read, returns the
+ /// number of bytes read. If the end of the file isn't reached before len
+ /// bytes have been read, will return len bytes.
+ ///
+ ///
+ ///
+ ///
+ /// Copied nearly verbatim from commons-io 41a3e9c
+ ///
+ ///
+ /// byte stream to skip
+ /// number of bytes to skip.
+ /// number of bytes actually skipped.
+ /// if there is a problem reading the file
+ /// if toSkip is negative
+ /// @see InputStream#skip(long)
+ ///
+ public static long SkipFully(InputStream input, long toSkip)
+ {
+ if (toSkip < 0) {
+ throw new ArgumentException("Skip count must be non-negative, actual: " + toSkip);
+ }
+ if (toSkip == 0) {
+ return 0L;
+ }
+ /*
+ * N.B. no need to synchronize this because: - we don't care if the buffer is created multiple times (the data
+ * is ignored) - we always use the same size buffer, so if it it is recreated it will still be OK (if the buffer
+ * size were variable, we would need to synch. to ensure some other thread did not create a smaller one)
+ */
+ if (SKIP_BYTE_BUFFER == null) {
+ SKIP_BYTE_BUFFER = new byte[SKIP_BUFFER_SIZE];
+ }
+ long remain = toSkip;
+ while (remain > 0) {
+ // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip()
+ long n = input.Read(SKIP_BYTE_BUFFER, 0, (int) Math.Min(remain, SKIP_BUFFER_SIZE));
+ if (n <= 0) { // EOF
+ break;
+ }
+ remain -= n;
+ }
+ if (toSkip == remain) {
+ return -1L;
+ }
+ return toSkip - remain;
+ }
+
public static byte[] SafelyAllocate(long length, int maxLength)
{
SafelyAllocateCheck(length, maxLength);
diff --git a/ooxml/XSSF/Extractor/XSSFExportToXml.cs b/ooxml/XSSF/Extractor/XSSFExportToXml.cs
index 0617542a9..9f9332c17 100644
--- a/ooxml/XSSF/Extractor/XSSFExportToXml.cs
+++ b/ooxml/XSSF/Extractor/XSSFExportToXml.cs
@@ -168,7 +168,7 @@ public void ExportToXML(Stream os, String encoding, bool validate)
if (table != null)
{
- List tableColumns = table.GetCTTable().tableColumns.GetTableColumnList();
+ List tableColumns = table.GetColumns();
XSSFSheet sheet = table.GetXSSFSheet();
@@ -185,25 +185,20 @@ public void ExportToXML(Stream os, String encoding, bool validate)
XmlNode tableRootNode = GetNodeByXPath(table.GetCommonXpath(), doc.FirstChild, doc, true);
short startColumnIndex = table.StartCellReference.Col;
- for (int j = startColumnIndex; j <= table.EndCellReference.Col; j++)
+
+ foreach (XSSFTableColumn tableColumn in tableColumns)
{
- XSSFCell cell = (XSSFCell)row.GetCell(j);
+ XSSFCell cell = (XSSFCell)row.GetCell(startColumnIndex + tableColumn.ColumnIndex);
if (cell != null)
{
- int tableColumnIndex = j - startColumnIndex;
- if(tableColumnIndex < tableColumns.Count)
+ XSSFXmlColumnPr xmlColumnPr = tableColumn.GetXmlColumnPr();
+ if (xmlColumnPr != null)
{
- CT_TableColumn ctTableColumn = tableColumns[tableColumnIndex];
- if(ctTableColumn.xmlColumnPr != null)
- {
- XSSFXmlColumnPr pointer = new XSSFXmlColumnPr(table, ctTableColumn,ctTableColumn.xmlColumnPr);
- String localXPath = pointer.LocalXPath;
- XmlNode currentNode = GetNodeByXPath(localXPath,tableRootNode,doc,false);
- XSSFExportToXml.mapCellOnNode(cell, currentNode);
- }
+ String localXPath = xmlColumnPr.LocalXPath;
+ XmlNode currentNode = GetNodeByXPath(localXPath,tableRootNode,doc,false);
+ mapCellOnNode(cell, currentNode);
}
}
-
}
}
@@ -230,7 +225,7 @@ public void ExportToXML(Stream os, String encoding, bool validate)
/////////////////
//Output the XML
XmlWriterSettings settings = new XmlWriterSettings();
- //settings.OmitXmlDeclaration=false;
+ settings.OmitXmlDeclaration = true;
settings.Indent=true;
settings.Encoding=Encoding.GetEncoding(encoding);
//create string from xml tree
diff --git a/ooxml/XSSF/Streaming/SheetDataWriter.cs b/ooxml/XSSF/Streaming/SheetDataWriter.cs
index 9bbac6b89..29b63e9fc 100644
--- a/ooxml/XSSF/Streaming/SheetDataWriter.cs
+++ b/ooxml/XSSF/Streaming/SheetDataWriter.cs
@@ -14,16 +14,17 @@ the License. You may obtain a copy of the License at
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
-using System;
-using System.Globalization;
-using System.IO;
-using System.Text;
+using NPOI.OpenXmlFormats.Spreadsheet;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.Util;
using NPOI.XSSF.Model;
using NPOI.XSSF.UserModel;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
namespace NPOI.XSSF.Streaming
{
@@ -44,13 +45,13 @@ public class SheetDataWriter : ICloseable
* If two cells contain the same string, then the cell value is the same index into SharedStringsTable
*/
private readonly SharedStringsTable _sharedStringSource;
- private readonly StreamWriter _outputWriter;
+ private readonly StreamWriter _out;
public SheetDataWriter()
{
TemporaryFileInfo = CreateTempFile();
OutputStream = CreateWriter(TemporaryFileInfo);
- _outputWriter = new StreamWriter(OutputStream);
+ _out = new StreamWriter(OutputStream);
}
public SheetDataWriter(SharedStringsTable sharedStringsTable) : this()
{
@@ -116,7 +117,7 @@ public void Close()
{
try
{
- _outputWriter.Dispose();
+ _out.Dispose();
OutputStream.Dispose();
}
catch
@@ -206,63 +207,53 @@ public void FlushRows(int rowCount, int lastRowNum, int lastRowCellsCount)
NumberLastFlushedRow = Math.Max(lastRowNum, NumberLastFlushedRow);
NumberOfCellsOfLastFlushedRow = lastRowCellsCount;
- _outputWriter.Flush();
+ _out.Flush();
OutputStream.Flush();
}
private void BeginRow(int rownum, SXSSFRow row)
{
- WriteAsBytes("\n");
+ _out.Write(">\n");
RowNum = rownum;
}
private void EndRow()
{
- WriteAsBytes("
\n");
+ _out.Write("\n");
}
- //TODO: Fix test case TestCases.XSSF.UserModel.TestEncodingBelowAscii
+
public void WriteCell(int columnIndex, ICell cell)
{
if (cell == null)
@@ -270,34 +261,28 @@ public void WriteCell(int columnIndex, ICell cell)
return;
}
var cellRef = new CellReference(RowNum, columnIndex).FormatAsString();
- WriteAsBytes("");
+ _out.Write('>');
break;
}
case CellType.Formula:
{
- WriteAsBytes(">");
- WriteAsBytes("");
-
+ _out.Write(">");
OutputQuotedString(cell.CellFormula);
-
- WriteAsBytes("");
+ _out.Write("");
switch (cell.CachedFormulaResultType)
{
@@ -305,9 +290,9 @@ public void WriteCell(int columnIndex, ICell cell)
double nval = cell.NumericCellValue;
if (!Double.IsNaN(nval))
{
- WriteAsBytes("");
- WriteAsBytes(nval);
- WriteAsBytes("");
+ _out.Write("");
+ _out.Write(nval.ToString(CultureInfo.InvariantCulture));
+ _out.Write("");
}
break;
default:
@@ -322,55 +307,53 @@ public void WriteCell(int columnIndex, ICell cell)
XSSFRichTextString rt = new XSSFRichTextString(cell.StringCellValue);
int sRef = _sharedStringSource.AddEntry(rt.GetCTRst());
- WriteAsBytes(" t=\"");
- WriteAsBytes("s");
- WriteAsBytes("\">");
- WriteAsBytes("");
- WriteAsBytes(sRef);
- WriteAsBytes("");
+ WriteAttribute("t", ST_CellType.s.ToString());
+ _out.Write(">");
+ _out.Write(sRef.ToString());
+ _out.Write("");
}
else
{
- WriteAsBytes(" t=\"inlineStr\">");
- WriteAsBytes("");
+ _out.Write(">");
OutputQuotedString(cell.StringCellValue);
- WriteAsBytes("");
+ _out.Write("");
}
break;
}
case CellType.Numeric:
{
- WriteAsBytes(" t=\"n\">");
- WriteAsBytes("");
- WriteAsBytes(cell.NumericCellValue);
- WriteAsBytes("");
+ WriteAttribute("t", "n");
+ _out.Write(">");
+ _out.Write(cell.NumericCellValue.ToString(CultureInfo.InvariantCulture));
+ _out.Write("");
break;
}
case CellType.Boolean:
{
- WriteAsBytes(" t=\"b\">");
- WriteAsBytes("");
- WriteAsBytes(cell.BooleanCellValue ? "1" : "0");
- WriteAsBytes("");
+ WriteAttribute("t", "b");
+ _out.Write(">");
+ _out.Write(cell.BooleanCellValue ? "1" : "0");
+ _out.Write("");
break;
}
case CellType.Error:
{
FormulaError error = FormulaError.ForInt(cell.ErrorCellValue);
- WriteAsBytes(" t=\"e\">");
- WriteAsBytes("");
- WriteAsBytes(error.String);
- WriteAsBytes("");
+ WriteAttribute("t", "e");
+ _out.Write(">");
+ _out.Write(error.String);
+ _out.Write("");
break;
}
default:
@@ -378,32 +361,16 @@ public void WriteCell(int columnIndex, ICell cell)
throw new InvalidOperationException("Invalid cell type: " + cell.CellType);
}
}
- WriteAsBytes("");
+ _out.Write("");
}
- private void WriteAsBytes(string text)
+ private void WriteAttribute(string name, string value)
{
- _outputWriter.Write(text);
- }
-
- private void WriteAsBytes(ArraySegment chars)
- {
- _outputWriter.Write(chars.Array, chars.Offset, chars.Count);
- }
-
- private void WriteAsBytes(int value)
- {
- _outputWriter.Write(value);
- }
-
- private void WriteAsBytes(float value)
- {
- _outputWriter.Write(value.ToString(CultureInfo.InvariantCulture));
- }
-
- private void WriteAsBytes(double value)
- {
- _outputWriter.Write(value.ToString(CultureInfo.InvariantCulture));
+ _out.Write(' ');
+ _out.Write(name);
+ _out.Write("=\"");
+ _out.Write(value);
+ _out.Write('\"');
}
/**
@@ -422,7 +389,7 @@ private static bool HasLeadingTrailingSpaces(string str)
}
//Taken from jdk1.3/src/javax/swing/text/html/HTMLWriter.java
- protected internal void OutputQuotedString(string s)
+ internal void OutputQuotedString(string s)
{
if (string.IsNullOrEmpty(s))
{
@@ -438,123 +405,90 @@ protected internal void OutputQuotedString(string s)
switch (c)
{
case '<':
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
+ WriteLastChars(_out, chars, last, counter);
last = counter + 1;
- WriteAsBytes("<");
+ _out.Write("<");
break;
case '>':
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
+ WriteLastChars(_out, chars, last, counter);
last = counter + 1;
- WriteAsBytes(">");
+ _out.Write(">");
break;
case '&':
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
+ WriteLastChars(_out, chars, last, counter);
last = counter + 1;
- WriteAsBytes("&");
+ _out.Write("&");
break;
case '"':
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
+ WriteLastChars(_out, chars, last, counter);
last = counter + 1;
- WriteAsBytes(""");
+ _out.Write(""");
break;
// Special characters
case '\n':
- if(counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
- WriteAsBytes("
");
+ WriteLastChars(_out, chars, last, counter);
+ _out.Write("
");
last = counter + 1;
break;
case '\r':
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
- WriteAsBytes("
");
+ WriteLastChars(_out, chars, last, counter);
+ _out.Write("
");
last = counter + 1;
break;
case '\t':
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
- WriteAsBytes(" ");
+ WriteLastChars(_out, chars, last, counter);
+ _out.Write(" ");
last = counter + 1;
break;
case (char)0xa0:
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
- WriteAsBytes(" ");
+ WriteLastChars(_out, chars, last, counter);
+ _out.Write(" ");
last = counter + 1;
break;
default:
// YK: XmlBeans silently replaces all ISO control characters ( < 32) with question marks.
// the same rule applies to unicode surrogates and "not a character" symbols.
- if (ReplaceWithQuestionMark(c))
+ if (ReplaceWithQuestionMark(c))
{
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
- WriteAsBytes("?");
+ WriteLastChars(_out, chars, last, counter);
+ _out.Write('?');
last = counter + 1;
}
- else if (Char.IsLowSurrogate(c) || Char.IsHighSurrogate(c))
+ else if (Char.IsHighSurrogate(c) || Char.IsLowSurrogate(c))
{
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
- //WriteAsBytes(c);
- _outputWriter.Write(c);
+ WriteLastChars(_out, chars, last, counter);
+ _out.Write(c);
last = counter + 1;
}
else if (c > 127)
{
- if (counter > last)
- {
- WriteAsBytes(GetSubArray(chars, last, counter - last));
- }
+ WriteLastChars(_out, chars, last, counter);
last = counter + 1;
- // If the character is outside of UTF8, write the
+ // If the character is outside of ascii, write the
// numeric value.
- WriteAsBytes("");
- WriteAsBytes(c);
- WriteAsBytes(";");
+ _out.Write("");
+ _out.Write(((int) c).ToString());
+ _out.Write(";");
}
break;
}
}
if (last < length)
{
- WriteAsBytes(GetSubArray(chars, last, length - last));
+ _out.Write(chars, last, length - last);
}
}
-
- private static ArraySegment GetSubArray(char[] oldArray, int skip, int take)
- {
- return new ArraySegment(oldArray, skip, take);
+ internal static bool ReplaceWithQuestionMark(char c) {
+ return c < ' ' || ('\uFFFE' <= c && c <= '\uFFFF');
}
- public static bool ReplaceWithQuestionMark(char c)
+ private static void WriteLastChars(StreamWriter out1, char[] chars, int last, int counter)
{
- return c < ' ' || ('\uFFFE' <= c && c <= '\uFFFF');
+ if (counter > last) {
+ out1.Write(chars, last, counter - last);
+ }
}
+
/**
* Deletes the temporary file that backed this sheet on disk.
* @return true if the file was deleted, false if it wasn't.
@@ -564,7 +498,7 @@ public bool Dispose()
bool ret;
try
{
- _outputWriter.Close();
+ _out.Close();
OutputStream.Close();
}
finally
diff --git a/ooxml/XSSF/UserModel/XSSFSheet.cs b/ooxml/XSSF/UserModel/XSSFSheet.cs
index 9ec08bef1..347998910 100644
--- a/ooxml/XSSF/UserModel/XSSFSheet.cs
+++ b/ooxml/XSSF/UserModel/XSSFSheet.cs
@@ -1777,10 +1777,8 @@ public void AutoSizeColumn(int column, bool useMergedCells)
{
width = maxColumnWidth;
}
-
- IColumn col = GetColumn(column, true);
- col.Width = width / 256;
- col.IsBestFit = true;
+ SetColumnWidth(column, width);
+ columnHelper.SetColBestFit(column, true);
}
}
diff --git a/testcases/main/POIFS/FileSystem/TestNotOLE2Exception.cs b/testcases/main/POIFS/FileSystem/TestNotOLE2Exception.cs
new file mode 100644
index 000000000..f8836cdd2
--- /dev/null
+++ b/testcases/main/POIFS/FileSystem/TestNotOLE2Exception.cs
@@ -0,0 +1,123 @@
+/* ====================================================================
+ 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.
+==================================================================== */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace TestCases.POIFS.FileSystem
+{
+ using NPOI.HSSF;
+ using NPOI.POIFS.FileSystem;
+ using NPOI.Util;
+ using NUnit.Framework;
+ using NUnit.Framework.Legacy;
+ using TestCases.HSSF;
+
+ ///
+ /// Class to test that POIFS complains when given older non-OLE2
+ /// formats. See also for OOXML
+ /// checks
+ ///
+ [TestFixture]
+ public class TestNotOLE2Exception
+ {
+ private static Stream OpenXLSSampleStream(string sampleFileName)
+ {
+ return HSSFTestDataSamples.OpenSampleFileStream(sampleFileName);
+ }
+ private static Stream OpenDOCSampleStream(string sampleFileName)
+ {
+ return POIDataSamples.GetDocumentInstance().OpenResourceAsStream(sampleFileName);
+ }
+
+ [Test]
+ public void TestRawXMLException()
+ {
+ Stream in1 = OpenXLSSampleStream("SampleSS.xml");
+
+ try
+ {
+ new POIFSFileSystem(in1).Close();
+ ClassicAssert.Fail("expected exception was not thrown");
+ }
+ catch(NotOLE2FileException e)
+ {
+ // expected during successful test
+ POITestCase.AssertContains(e.Message, "The supplied data appears to be a raw XML file");
+ POITestCase.AssertContains(e.Message, "Formats such as Office 2003 XML");
+ }
+ }
+
+ [Test]
+ public void TestMSWriteException()
+ {
+ Stream in1 = OpenDOCSampleStream("MSWriteOld.wri");
+
+ try
+ {
+ new POIFSFileSystem(in1).Close();
+ ClassicAssert.Fail("expected exception was not thrown");
+ }
+ catch(NotOLE2FileException e)
+ {
+ // expected during successful test
+ POITestCase.AssertContains(e.Message, "The supplied data appears to be in the old MS Write");
+ POITestCase.AssertContains(e.Message, "doesn't currently support");
+ }
+ }
+
+ [Test]
+ public void TestBiff3Exception()
+ {
+ Stream in1 = OpenXLSSampleStream("testEXCEL_3.xls");
+
+ try
+ {
+ new POIFSFileSystem(in1).Close();
+ ClassicAssert.Fail("expected exception was not thrown");
+ }
+ catch(OldExcelFormatException e)
+ {
+ // expected during successful test
+ POITestCase.AssertContains(e.Message, "The supplied data appears to be in BIFF3 format");
+ POITestCase.AssertContains(e.Message, "try OldExcelExtractor");
+ }
+ }
+
+ [Test]
+ public void TestBiff4Exception()
+ {
+ Stream in1 = OpenXLSSampleStream("testEXCEL_4.xls");
+
+ try
+ {
+ new POIFSFileSystem(in1).Close();
+ ClassicAssert.Fail("expected exception was not thrown");
+ }
+ catch(OldExcelFormatException e)
+ {
+ // expected during successful test
+ POITestCase.AssertContains(e.Message, "The supplied data appears to be in BIFF4 format");
+ POITestCase.AssertContains(e.Message, "try OldExcelExtractor");
+ }
+ }
+ }
+}
diff --git a/testcases/main/POIFS/FileSystem/TestOffice2007XMLException.cs b/testcases/main/POIFS/FileSystem/TestOffice2007XMLException.cs
index 4cd165184..97373baa7 100644
--- a/testcases/main/POIFS/FileSystem/TestOffice2007XMLException.cs
+++ b/testcases/main/POIFS/FileSystem/TestOffice2007XMLException.cs
@@ -97,6 +97,14 @@ public void TestDetectAsPOIFS()
// xls file is
ConfirmIsPOIFS("SampleSS.xls", true);
+ // older biff formats aren't
+ ConfirmIsPOIFS("testEXCEL_3.xls", false);
+ ConfirmIsPOIFS("testEXCEL_4.xls", false);
+
+ // newer excel formats are
+ ConfirmIsPOIFS("testEXCEL_5.xls", true);
+ ConfirmIsPOIFS("testEXCEL_95.xls", true);
+
// text file isn't
ConfirmIsPOIFS("SampleSS.txt", false);
}
diff --git a/testcases/main/SS/UserModel/BaseTestBugzillaIssues.cs b/testcases/main/SS/UserModel/BaseTestBugzillaIssues.cs
index 7e244f25a..350e09e4f 100644
--- a/testcases/main/SS/UserModel/BaseTestBugzillaIssues.cs
+++ b/testcases/main/SS/UserModel/BaseTestBugzillaIssues.cs
@@ -649,6 +649,7 @@ public void Bug51024()
}
[Test]
+ [Platform("Win")]
public void Stackoverflow23114397()
{
IWorkbook wb = _testDataProvider.CreateWorkbook();
diff --git a/testcases/main/Util/TestIOUtils.cs b/testcases/main/Util/TestIOUtils.cs
new file mode 100644
index 000000000..5c08289bd
--- /dev/null
+++ b/testcases/main/Util/TestIOUtils.cs
@@ -0,0 +1,260 @@
+/* ====================================================================
+ 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.
+==================================================================== */
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace TestCases.Util
+{
+ using NPOI;
+ using NPOI.Util;
+ using NUnit.Framework;
+ using NUnit.Framework.Legacy;
+ ///
+ /// Class to test IOUtils
+ ///
+ [TestFixture]
+ public class TestIOUtils
+ {
+
+ static FileInfo TMP = null;
+ static long LENGTH = new Random().Next(10000);
+
+ [SetUp]
+ public void SetUp()
+ {
+ TMP = TempFile.CreateTempFile("poi-ioutils-", "");
+ Stream os = TMP.Open(FileMode.OpenOrCreate);
+ for(int i = 0; i < LENGTH; i++)
+ {
+ os.WriteByte(0x01);
+ }
+ os.Flush();
+ os.Close();
+
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ //noinspection ResultOfMethodCallIgnored
+ TMP.Delete();
+ }
+
+ [Test]
+ public void TestPeekFirst8Bytes()
+ {
+ ClassicAssert.IsTrue(Arrays.Equals(Encoding.UTF8.GetBytes("01234567"),
+ IOUtils.PeekFirst8Bytes(new ByteArrayInputStream(Encoding.UTF8.GetBytes("01234567")))));
+ }
+
+ [Test]
+ public void TestPeekFirst8BytesWithPushbackInputStream()
+ {
+ ClassicAssert.IsTrue(Arrays.Equals(Encoding.UTF8.GetBytes("01234567"),
+ IOUtils.PeekFirst8Bytes(new PushbackInputStream(new ByteArrayInputStream(Encoding.UTF8.GetBytes("01234567")), 8))));
+ }
+
+ [Test]
+ public void TestPeekFirst8BytesTooLessAvailable()
+ {
+ ClassicAssert.IsTrue(Arrays.Equals(new byte[] { 1, 2, 3, 0, 0, 0, 0, 0 },
+ IOUtils.PeekFirst8Bytes(new ByteArrayInputStream(new byte[] { 1, 2, 3 })))
+ );
+ }
+
+ [Test]
+ public void TestPeekFirst8BytesEmpty()
+ {
+ Assert.Throws(() =>
+ IOUtils.PeekFirst8Bytes(new ByteArrayInputStream(new byte[] { }))
+ );
+ }
+
+ [Test]
+ public void TestToByteArray()
+ {
+ ClassicAssert.IsTrue(Arrays.Equals(new byte[] { 1, 2, 3 },
+ IOUtils.ToByteArray(new MemoryStream(new byte[] { 1, 2, 3 })))
+ );
+ }
+
+ [Test]
+ public void TestToByteArrayToSmall()
+ {
+ ClassicAssert.Throws(() =>
+ ClassicAssert.IsTrue(Arrays.Equals(new byte[] { 1, 2, 3 },
+ IOUtils.ToByteArray(new MemoryStream(new byte[] { 1, 2, 3 }), 10)))
+ );
+ }
+
+ [Test]
+ public void TestToByteArrayByteBuffer()
+ {
+ ClassicAssert.IsTrue(Arrays.Equals(new byte[] { 1, 2, 3 },
+ IOUtils.ToByteArray(new ByteBuffer(new byte[] { 1, 2, 3 }, 0, 3), 10)));
+ }
+
+ [Test]
+ public void TestToByteArrayByteBufferToSmall()
+ {
+ ClassicAssert.IsTrue(Arrays.Equals(new byte[] { 1, 2, 3, 4, 5, 6, 7 },
+ IOUtils.ToByteArray(new ByteBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7 }, 0, 7), 3)));
+ }
+
+ [Test]
+ public void TestSkipFully()
+ {
+ using InputStream is1 = new FileInputStream(TMP.Open(FileMode.OpenOrCreate));
+ long skipped = IOUtils.SkipFully(is1, 20000L);
+ ClassicAssert.AreEqual(LENGTH, skipped, "length: "+LENGTH);
+ }
+
+ [Test]
+ public void TestSkipFullyGtIntMax()
+ {
+ using InputStream is1 = new FileInputStream(TMP.Open(FileMode.OpenOrCreate));
+ long skipped = IOUtils.SkipFully(is1, Int32.MaxValue + 20000L);
+ ClassicAssert.AreEqual(LENGTH, skipped, "length: "+LENGTH);
+ }
+
+ [Test]
+ public void TestSkipFullyByteArray()
+ {
+ using MemoryStream bos = new MemoryStream();
+ using InputStream is1 = new FileInputStream(TMP.Open(FileMode.OpenOrCreate));
+ IOUtils.Copy(is1, bos);
+ long skipped = IOUtils.SkipFully(new ByteArrayInputStream(bos.ToArray()), 20000L);
+ ClassicAssert.AreEqual(LENGTH, skipped, "length: "+LENGTH);
+ }
+
+ [Test]
+ public void TestSkipFullyByteArrayGtIntMax()
+ {
+ using MemoryStream bos = new MemoryStream();
+ using InputStream is1 = new FileInputStream(TMP.Open(FileMode.OpenOrCreate));
+ IOUtils.Copy(is1, bos);
+ long skipped = IOUtils.SkipFully(new ByteArrayInputStream(bos.ToArray()), Int32.MaxValue+ 20000L);
+ ClassicAssert.AreEqual(LENGTH, skipped, "length: "+LENGTH);
+ }
+
+ [Test]
+ public void TestSkipFullyBug61294()
+ {
+ IOUtils.SkipFully(new ByteArrayInputStream(new byte[0]), 1);
+ }
+
+ [Test]
+ public void TestZeroByte()
+ {
+ long skipped = IOUtils.SkipFully((new ByteArrayInputStream(new byte[0])), 100);
+ ClassicAssert.AreEqual(-1L, skipped, "zero byte");
+ }
+
+ [Test]
+ public void TestSkipZero()
+ {
+ using InputStream is1 = new FileInputStream(TMP.Open(FileMode.OpenOrCreate));
+ long skipped = IOUtils.SkipFully(is1, 0);
+ ClassicAssert.AreEqual(0, skipped, "zero length");
+ }
+ [Test]
+ public void TestSkipNegative()
+ {
+ ClassicAssert.Throws(() =>
+ {
+ using InputStream is1 = new FileInputStream(TMP.Open(FileMode.OpenOrCreate));
+ IOUtils.SkipFully(is1, -1);
+ });
+ }
+
+ [Test]
+ public void TestWonkyInputStream()
+ {
+ long skipped = IOUtils.SkipFully(new WonkyInputStream(), 10000);
+ ClassicAssert.AreEqual(10000, skipped, "length: "+LENGTH);
+ }
+
+ ///
+ /// This returns 0 for the first call to skip and then reads
+ /// as requested. This tests that the fallback to read() works.
+ ///
+ private class WonkyInputStream : InputStream
+ {
+ int skipCalled = 0;
+ int readCalled = 0;
+
+ public override bool CanRead => throw new NotImplementedException();
+
+ public override bool CanSeek => throw new NotImplementedException();
+
+ public override long Length => throw new NotImplementedException();
+
+ public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+
+ public override int Read()
+ {
+ readCalled++;
+ return 0;
+ }
+ public override int Read(byte[] arr, int offset, int len)
+ {
+ readCalled++;
+ return len;
+ }
+ public override long Skip(long len)
+ {
+ skipCalled++;
+ if(skipCalled == 1)
+ {
+ return 0;
+ }
+ else if(skipCalled > 100)
+ {
+ return len;
+ }
+ else
+ {
+ return 100;
+ }
+ }
+ public override int Available()
+ {
+ return 100000;
+ }
+
+ public override void Flush()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/testcases/ooxml/XSSF/Extractor/TestXSSFExportToXML.cs b/testcases/ooxml/XSSF/Extractor/TestXSSFExportToXML.cs
index 2e70ed605..7e7bad43e 100644
--- a/testcases/ooxml/XSSF/Extractor/TestXSSFExportToXML.cs
+++ b/testcases/ooxml/XSSF/Extractor/TestXSSFExportToXML.cs
@@ -669,6 +669,20 @@ public void TestBug59026()
ClassicAssert.IsNotNull(os.ToString("utf-8"));
}
}
+
+ [Test]
+ public void TestExportTableWithNonMappedColumn_Bugzilla_61281() {
+ XSSFWorkbook wb = XSSFTestDataSamples.OpenSampleWorkbook("61281.xlsx");
+ foreach (XSSFMap map in wb.GetCustomXMLMappings())
+ {
+ XSSFExportToXml exporter = new XSSFExportToXml(map);
+ MemoryStream bos = new MemoryStream();
+ exporter.ExportToXML(bos, true);
+ ClassicAssert.IsNotNull(DocumentHelper.ReadDocument(new MemoryStream(bos.ToArray())));
+ string exportedXml = bos.ToString("UTF-8");
+ ClassicAssert.AreEqual("1", Regex.Replace(exportedXml, "\\s+", ""));
+ }
+ }
}
public static class TestExtensions
diff --git a/testcases/ooxml/XSSF/Streaming/SheetDataWriterTests.cs b/testcases/ooxml/XSSF/Streaming/SheetDataWriterTests.cs
index ff3494584..38a43ba3c 100644
--- a/testcases/ooxml/XSSF/Streaming/SheetDataWriterTests.cs
+++ b/testcases/ooxml/XSSF/Streaming/SheetDataWriterTests.cs
@@ -31,7 +31,7 @@ public class SheetDataWriterTests
private SheetDataWriter _objectToTest;
private SXSSFRow _row;
private ICell _cell;
-
+ private ICellStyle _cellStyle;
[SetUp]
public void Init()
{
@@ -40,6 +40,7 @@ public void Init()
var _workbook = Substitute.For();
var _sheet = Substitute.For(_workbook, _xssfsheet);
_row = Substitute.For(_sheet);
+ _cellStyle = _workbook.CreateCellStyle();
_cell = Substitute.For();
}
@@ -77,7 +78,7 @@ public void IfWritingRowWithCustomHeightShouldIncludeCustomHeightXml()
var lines = File.ReadAllLines(_objectToTest.TemporaryFilePath());
ClassicAssert.True(lines.Length == 2);
- ClassicAssert.AreEqual($"", lines[0]);
+ ClassicAssert.AreEqual($"", lines[0]);
ClassicAssert.AreEqual("
", lines[1]);
}
@@ -95,7 +96,7 @@ public void IfWritingRowWithZeroHeightShouldIncludeHiddenAttributeXml()
var lines = File.ReadAllLines(_objectToTest.TemporaryFilePath());
ClassicAssert.True(lines.Length == 2);
- ClassicAssert.AreEqual("", lines[0]);
+ ClassicAssert.AreEqual("", lines[0]);
ClassicAssert.AreEqual("
", lines[1]);
@@ -109,14 +110,14 @@ public void IfWritingRowThatIsFormattedShouldIncludeRowStyleIndexAndCustomFormat
_row.HasCustomHeight().Returns(false);
_row.ZeroHeight.Returns(false);
_row.IsFormatted.Returns(true);
- _row.RowStyle.Index.Returns((short)1);
+ _row.RowStyle.Returns(_cellStyle);
_objectToTest.WriteRow(0, _row);
_objectToTest.Close();
var lines = File.ReadAllLines(_objectToTest.TemporaryFilePath());
ClassicAssert.True(lines.Length == 2);
- ClassicAssert.AreEqual("", lines[0]);
+ ClassicAssert.AreEqual("", lines[0]);
ClassicAssert.AreEqual("
", lines[1]);
diff --git a/testcases/ooxml/XSSF/Streaming/TestSXSSFSheetAutoSizeColumn.cs b/testcases/ooxml/XSSF/Streaming/TestSXSSFSheetAutoSizeColumn.cs
index ceacd4094..34ba83d24 100644
--- a/testcases/ooxml/XSSF/Streaming/TestSXSSFSheetAutoSizeColumn.cs
+++ b/testcases/ooxml/XSSF/Streaming/TestSXSSFSheetAutoSizeColumn.cs
@@ -179,6 +179,7 @@ public void Test_WindowSizeEqualsOne_lastRowIsWidest()
// fails only for useMergedCell=true
[Test]
+ [Platform("Win")]
public void Test_WindowSizeEqualsOne_flushedRowHasMergedCell()
{
workbook = new SXSSFWorkbook(null, 1); // Window size 1 so only last row will be in memory
diff --git a/testcases/ooxml/XSSF/UserModel/TestXSSFCell.cs b/testcases/ooxml/XSSF/UserModel/TestXSSFCell.cs
index 0f5082bbb..919a6c4b8 100644
--- a/testcases/ooxml/XSSF/UserModel/TestXSSFCell.cs
+++ b/testcases/ooxml/XSSF/UserModel/TestXSSFCell.cs
@@ -501,13 +501,14 @@ public void TestBug56644CreateBlank()
}
}
[Test]
- [Ignore("SheetDataWriter.OutputQuotedString throws EncoderFallbackException:Unable to translate Unicode character \\uD800")]
public void TestEncodingBelowAscii()
{
StringBuilder sb = new StringBuilder();
// test all possible characters
for (int i = 0; i < char.MaxValue; i++)
{
+ if(i >= '\uD800' || i <= '\uD8FF')
+ continue;
sb.Append((char)i);
}
diff --git a/testcases/ooxml/XSSF/XSSFTestDataSamples.cs b/testcases/ooxml/XSSF/XSSFTestDataSamples.cs
index fc0598fe2..c5f5a11b5 100644
--- a/testcases/ooxml/XSSF/XSSFTestDataSamples.cs
+++ b/testcases/ooxml/XSSF/XSSFTestDataSamples.cs
@@ -182,7 +182,8 @@ private static FileInfo GetOutputFile(String testName)
FileInfo file;
if (testOutputDir != null)
{
- file = new FileInfo(Path.Combine(testOutputDir, testName + ".xlsx"));
+ String testNameWithExtension = testName.EndsWith(".xlsx") ? testName : testName + ".xlsx";
+ file = new FileInfo(Path.Combine(testOutputDir, testNameWithExtension));
}
else
{
diff --git a/testcases/test-data/document/MSWriteOld.wri b/testcases/test-data/document/MSWriteOld.wri
new file mode 100644
index 000000000..9391077ce
Binary files /dev/null and b/testcases/test-data/document/MSWriteOld.wri differ
diff --git a/testcases/test-data/spreadsheet/61281.xlsx b/testcases/test-data/spreadsheet/61281.xlsx
new file mode 100644
index 000000000..6e8cd739e
Binary files /dev/null and b/testcases/test-data/spreadsheet/61281.xlsx differ