View | Details | Raw Unified | Return to bug 59893
Collapse All | Expand All

(-)src/examples/src/org/apache/poi/poifs/poibrowser/DocumentDescriptor.java (-16 / +13 lines)
Lines 17-24 Link Here
17
17
18
package org.apache.poi.poifs.poibrowser;
18
package org.apache.poi.poifs.poibrowser;
19
19
20
import java.io.*;
20
import java.io.IOException;
21
import org.apache.poi.poifs.filesystem.*;
21
22
import org.apache.poi.poifs.filesystem.DocumentInputStream;
23
import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
24
import org.apache.poi.util.IOUtils;
22
25
23
/**
26
/**
24
 * <p>Describes the most important (whatever that is) features of a
27
 * <p>Describes the most important (whatever that is) features of a
Lines 49-74 Link Here
49
    public DocumentDescriptor(final String name,
52
    public DocumentDescriptor(final String name,
50
                              final POIFSDocumentPath path,
53
                              final POIFSDocumentPath path,
51
                              final DocumentInputStream stream,
54
                              final DocumentInputStream stream,
52
                              final int nrOfBytes)
55
                              final int nrOfBytes) {
53
    {
54
        this.name = name;
56
        this.name = name;
55
        this.path = path;
57
        this.path = path;
56
        this.stream = stream;
58
        this.stream = stream;
57
        try
59
        try {
58
        {
60
            if (stream.markSupported()) {
59
            size = stream.available();
60
            if (stream.markSupported())
61
            {
62
                stream.mark(nrOfBytes);
61
                stream.mark(nrOfBytes);
63
                final byte[] b = new byte[nrOfBytes];
62
                bytes = IOUtils.toByteArray(stream, nrOfBytes);
64
                final int read = stream.read(b, 0, Math.min(size, b.length));
65
                bytes = new byte[read];
66
                System.arraycopy(b, 0, bytes, 0, read);
67
                stream.reset();
63
                stream.reset();
64
            } else {
65
                bytes = new byte[0];
68
            }
66
            }
69
        }
67
            size = bytes.length + stream.available();
70
        catch (IOException ex)
68
        } catch (IOException ex) {
71
        {
72
            System.out.println(ex);
69
            System.out.println(ex);
73
        }
70
        }
74
    }
71
    }
(-)src/examples/src/org/apache/poi/poifs/poibrowser/TreeReaderListener.java (-3 / +6 lines)
Lines 121-133 Link Here
121
     * reading. This method retrieves properties of the document and
121
     * reading. This method retrieves properties of the document and
122
     * adds them to a tree model.</p>
122
     * adds them to a tree model.</p>
123
     */
123
     */
124
    @Override
124
    public void processPOIFSReaderEvent(final POIFSReaderEvent event)
125
    public void processPOIFSReaderEvent(final POIFSReaderEvent event)
125
    {
126
    {
126
        DocumentDescriptor d;
127
        DocumentDescriptor d;
127
        final DocumentInputStream is = event.getStream();
128
        final DocumentInputStream is = event.getStream();
128
        if (!is.markSupported())
129
        if (!is.markSupported()) {
129
            throw new UnsupportedOperationException(is.getClass().getName() +
130
            throw new UnsupportedOperationException(is.getClass().getName() +
130
                " does not support mark().");
131
                " does not support mark().");
132
        }
131
133
132
        /* Try do handle this document as a property set. We receive
134
        /* Try do handle this document as a property set. We receive
133
         * an exception if is no property set and handle it as a
135
         * an exception if is no property set and handle it as a
Lines 149-155 Link Here
149
                ("Unexpected exception while processing " +
151
                ("Unexpected exception while processing " +
150
                event.getName() + " in " + event.getPath().toString());
152
                event.getName() + " in " + event.getPath().toString());
151
            t.printStackTrace(System.err);
153
            t.printStackTrace(System.err);
152
            throw new RuntimeException(t.getMessage());
154
            throw new RuntimeException(t);
153
        }
155
        }
154
156
155
        is.close();
157
        is.close();
Lines 180-188 Link Here
180
                                    final MutableTreeNode root)
182
                                    final MutableTreeNode root)
181
    {
183
    {
182
        MutableTreeNode n = pathToNode.get(path);
184
        MutableTreeNode n = pathToNode.get(path);
183
        if (n != null)
185
        if (n != null) {
184
            /* Node found in map, just return it. */
186
            /* Node found in map, just return it. */
185
            return n;
187
            return n;
188
        }
186
        if (path.length() == 0)
189
        if (path.length() == 0)
187
        {
190
        {
188
            /* This is the root path of the POI filesystem. Its tree
191
            /* This is the root path of the POI filesystem. Its tree
(-)src/java/org/apache/poi/hpsf/PropertySet.java (-42 / +47 lines)
Lines 26-31 Link Here
26
import org.apache.poi.hpsf.wellknown.SectionIDMap;
26
import org.apache.poi.hpsf.wellknown.SectionIDMap;
27
import org.apache.poi.util.IOUtils;
27
import org.apache.poi.util.IOUtils;
28
import org.apache.poi.util.LittleEndian;
28
import org.apache.poi.util.LittleEndian;
29
import org.apache.poi.util.LittleEndianConsts;
29
30
30
/**
31
/**
31
 * <p>Represents a property set in the Horrible Property Set Format
32
 * <p>Represents a property set in the Horrible Property Set Format
Lines 235-249 Link Here
235
        throws NoPropertySetStreamException, MarkUnsupportedException,
236
        throws NoPropertySetStreamException, MarkUnsupportedException,
236
               IOException, UnsupportedEncodingException
237
               IOException, UnsupportedEncodingException
237
    {
238
    {
238
        if (isPropertySetStream(stream))
239
        if (!isPropertySetStream(stream)) {
239
        {
240
            final int avail = stream.available();
241
            final byte[] buffer = new byte[avail];
242
            IOUtils.readFully(stream, buffer);
243
            init(buffer, 0, buffer.length);
244
        }
245
        else
246
            throw new NoPropertySetStreamException();
240
            throw new NoPropertySetStreamException();
241
        }
242
        final byte[] buffer = IOUtils.toByteArray(stream);
243
        init(buffer, 0, buffer.length);
247
    }
244
    }
248
245
249
246
Lines 266-275 Link Here
266
    public PropertySet(final byte[] stream, final int offset, final int length)
263
    public PropertySet(final byte[] stream, final int offset, final int length)
267
        throws NoPropertySetStreamException, UnsupportedEncodingException
264
        throws NoPropertySetStreamException, UnsupportedEncodingException
268
    {
265
    {
269
        if (isPropertySetStream(stream, offset, length))
266
        if (isPropertySetStream(stream, offset, length)) {
270
            init(stream, offset, length);
267
            init(stream, offset, length);
271
        else
268
        } else {
272
            throw new NoPropertySetStreamException();
269
            throw new NoPropertySetStreamException();
270
        }
273
    }
271
    }
274
272
275
273
Lines 322-346 Link Here
322
         * reset to this position if the stream does not contain a
320
         * reset to this position if the stream does not contain a
323
         * property set.
321
         * property set.
324
         */
322
         */
325
        if (!stream.markSupported())
323
        if (!stream.markSupported()) {
326
            throw new MarkUnsupportedException(stream.getClass().getName());
324
            throw new MarkUnsupportedException(stream.getClass().getName());
325
        }
327
        stream.mark(BUFFER_SIZE);
326
        stream.mark(BUFFER_SIZE);
328
327
329
        /*
328
        /*
330
         * Read a couple of bytes from the stream.
329
         * Read a couple of bytes from the stream.
331
         */
330
         */
332
        final byte[] buffer = new byte[BUFFER_SIZE];
331
        final byte[] buffer = IOUtils.toByteArray(stream, -BUFFER_SIZE);
333
        final int bytes =
334
            stream.read(buffer, 0,
335
                        Math.min(buffer.length, stream.available()));
336
        final boolean isPropertySetStream =
337
            isPropertySetStream(buffer, 0, bytes);
338
        stream.reset();
332
        stream.reset();
339
        return isPropertySetStream;
333
        return (buffer.length > 0 && isPropertySetStream(buffer, 0, buffer.length));
340
    }
334
    }
341
335
342
343
344
    /**
336
    /**
345
     * <p>Checks whether a byte array is in the Horrible Property Set
337
     * <p>Checks whether a byte array is in the Horrible Property Set
346
     * Format.</p>
338
     * Format.</p>
Lines 364-388 Link Here
364
         */
356
         */
365
        int o = offset;
357
        int o = offset;
366
        final int byteOrder = LittleEndian.getUShort(src, o);
358
        final int byteOrder = LittleEndian.getUShort(src, o);
367
        o += LittleEndian.SHORT_SIZE;
359
        o += LittleEndianConsts.SHORT_SIZE;
368
        byte[] temp = new byte[LittleEndian.SHORT_SIZE];
360
        byte[] temp = new byte[LittleEndianConsts.SHORT_SIZE];
369
        LittleEndian.putShort(temp, 0, (short) byteOrder);
361
        LittleEndian.putShort(temp, 0, (short) byteOrder);
370
        if (!Util.equal(temp, BYTE_ORDER_ASSERTION))
362
        if (!Util.equal(temp, BYTE_ORDER_ASSERTION)) {
371
            return false;
363
            return false;
364
        }
372
        final int format = LittleEndian.getUShort(src, o);
365
        final int format = LittleEndian.getUShort(src, o);
373
        o += LittleEndian.SHORT_SIZE;
366
        o += LittleEndianConsts.SHORT_SIZE;
374
        temp = new byte[LittleEndian.SHORT_SIZE];
367
        temp = new byte[LittleEndianConsts.SHORT_SIZE];
375
        LittleEndian.putShort(temp, 0, (short) format);
368
        LittleEndian.putShort(temp, 0, (short) format);
376
        if (!Util.equal(temp, FORMAT_ASSERTION))
369
        if (!Util.equal(temp, FORMAT_ASSERTION)) {
377
            return false;
370
            return false;
371
        }
378
        // final long osVersion = LittleEndian.getUInt(src, offset);
372
        // final long osVersion = LittleEndian.getUInt(src, offset);
379
        o += LittleEndian.INT_SIZE;
373
        o += LittleEndianConsts.INT_SIZE;
380
        // final ClassID classID = new ClassID(src, offset);
374
        // final ClassID classID = new ClassID(src, offset);
381
        o += ClassID.LENGTH;
375
        o += ClassID.LENGTH;
382
        final long sectionCount = LittleEndian.getUInt(src, o);
376
        final long sectionCount = LittleEndian.getUInt(src, o);
383
        o += LittleEndian.INT_SIZE;
377
        o += LittleEndianConsts.INT_SIZE;
384
        if (sectionCount < 0)
378
        if (sectionCount < 0) {
385
            return false;
379
            return false;
380
        }
386
        return true;
381
        return true;
387
    }
382
    }
388
383
Lines 411-428 Link Here
411
         */
406
         */
412
        int o = offset;
407
        int o = offset;
413
        byteOrder = LittleEndian.getUShort(src, o);
408
        byteOrder = LittleEndian.getUShort(src, o);
414
        o += LittleEndian.SHORT_SIZE;
409
        o += LittleEndianConsts.SHORT_SIZE;
415
        format = LittleEndian.getUShort(src, o);
410
        format = LittleEndian.getUShort(src, o);
416
        o += LittleEndian.SHORT_SIZE;
411
        o += LittleEndianConsts.SHORT_SIZE;
417
        osVersion = (int) LittleEndian.getUInt(src, o);
412
        osVersion = (int) LittleEndian.getUInt(src, o);
418
        o += LittleEndian.INT_SIZE;
413
        o += LittleEndianConsts.INT_SIZE;
419
        classID = new ClassID(src, o);
414
        classID = new ClassID(src, o);
420
        o += ClassID.LENGTH;
415
        o += ClassID.LENGTH;
421
        final int sectionCount = LittleEndian.getInt(src, o);
416
        final int sectionCount = LittleEndian.getInt(src, o);
422
        o += LittleEndian.INT_SIZE;
417
        o += LittleEndianConsts.INT_SIZE;
423
        if (sectionCount < 0)
418
        if (sectionCount < 0) {
424
            throw new HPSFRuntimeException("Section count " + sectionCount +
419
            throw new HPSFRuntimeException("Section count " + sectionCount +
425
                                           " is negative.");
420
                                           " is negative.");
421
        }
426
422
427
        /*
423
        /*
428
         * Read the sections, which are following the header. They
424
         * Read the sections, which are following the header. They
Lines 446-452 Link Here
446
        for (int i = 0; i < sectionCount; i++)
442
        for (int i = 0; i < sectionCount; i++)
447
        {
443
        {
448
            final Section s = new Section(src, o);
444
            final Section s = new Section(src, o);
449
            o += ClassID.LENGTH + LittleEndian.INT_SIZE;
445
            o += ClassID.LENGTH + LittleEndianConsts.INT_SIZE;
450
            sections.add(s);
446
            sections.add(s);
451
        }
447
        }
452
    }
448
    }
Lines 462-469 Link Here
462
     */
458
     */
463
    public boolean isSummaryInformation()
459
    public boolean isSummaryInformation()
464
    {
460
    {
465
        if (sections.size() <= 0)
461
        if (sections.size() <= 0) {
466
            return false;
462
            return false;
463
        }
467
        return Util.equal(sections.get(0).getFormatID().getBytes(),
464
        return Util.equal(sections.get(0).getFormatID().getBytes(),
468
                          SectionIDMap.SUMMARY_INFORMATION_ID);
465
                          SectionIDMap.SUMMARY_INFORMATION_ID);
469
    }
466
    }
Lines 479-486 Link Here
479
     */
476
     */
480
    public boolean isDocumentSummaryInformation()
477
    public boolean isDocumentSummaryInformation()
481
    {
478
    {
482
        if (sections.size() <= 0)
479
        if (sections.size() <= 0) {
483
            return false;
480
            return false;
481
        }
484
        return Util.equal(sections.get(0).getFormatID().getBytes(),
482
        return Util.equal(sections.get(0).getFormatID().getBytes(),
485
                          SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
483
                          SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
486
    }
484
    }
Lines 595-602 Link Here
595
     */
593
     */
596
    public Section getFirstSection()
594
    public Section getFirstSection()
597
    {
595
    {
598
        if (getSectionCount() < 1)
596
        if (getSectionCount() < 1) {
599
            throw new MissingSectionException("Property set does not contain any sections.");
597
            throw new MissingSectionException("Property set does not contain any sections.");
598
        }
600
        return sections.get(0);
599
        return sections.get(0);
601
    }
600
    }
602
601
Lines 611-619 Link Here
611
    public Section getSingleSection()
610
    public Section getSingleSection()
612
    {
611
    {
613
        final int sectionCount = getSectionCount();
612
        final int sectionCount = getSectionCount();
614
        if (sectionCount != 1)
613
        if (sectionCount != 1) {
615
            throw new NoSingleSectionException
614
            throw new NoSingleSectionException
616
                ("Property set contains " + sectionCount + " sections.");
615
                ("Property set contains " + sectionCount + " sections.");
616
        }
617
        return sections.get(0);
617
        return sections.get(0);
618
    }
618
    }
619
619
Lines 631-638 Link Here
631
    @Override
631
    @Override
632
    public boolean equals(final Object o)
632
    public boolean equals(final Object o)
633
    {
633
    {
634
        if (o == null || !(o instanceof PropertySet))
634
        if (o == null || !(o instanceof PropertySet)) {
635
            return false;
635
            return false;
636
        }
636
        final PropertySet ps = (PropertySet) o;
637
        final PropertySet ps = (PropertySet) o;
637
        int byteOrder1 = ps.getByteOrder();
638
        int byteOrder1 = ps.getByteOrder();
638
        int byteOrder2 = getByteOrder();
639
        int byteOrder2 = getByteOrder();
Lines 648-655 Link Here
648
            !classID1.equals(classID2)    ||
649
            !classID1.equals(classID2)    ||
649
            format1 != format2            ||
650
            format1 != format2            ||
650
            osVersion1 != osVersion2      ||
651
            osVersion1 != osVersion2      ||
651
            sectionCount1 != sectionCount2)
652
            sectionCount1 != sectionCount2) {
652
            return false;
653
            return false;
654
        }
653
655
654
        /* Compare the sections: */
656
        /* Compare the sections: */
655
        return Util.equals(getSections(), ps.getSections());
657
        return Util.equals(getSections(), ps.getSections());
Lines 660-665 Link Here
660
    /**
662
    /**
661
     * @see Object#hashCode()
663
     * @see Object#hashCode()
662
     */
664
     */
665
    @Override
663
    public int hashCode()
666
    public int hashCode()
664
    {
667
    {
665
        throw new UnsupportedOperationException("FIXME: Not yet implemented.");
668
        throw new UnsupportedOperationException("FIXME: Not yet implemented.");
Lines 670-675 Link Here
670
    /**
673
    /**
671
     * @see Object#toString()
674
     * @see Object#toString()
672
     */
675
     */
676
    @Override
673
    public String toString()
677
    public String toString()
674
    {
678
    {
675
        final StringBuilder b = new StringBuilder();
679
        final StringBuilder b = new StringBuilder();
Lines 687-694 Link Here
687
        b.append(", sectionCount: ");
691
        b.append(", sectionCount: ");
688
        b.append(sectionCount);
692
        b.append(sectionCount);
689
        b.append(", sections: [\n");
693
        b.append(", sections: [\n");
690
        for (Section section: getSections())
694
        for (Section section: getSections()) {
691
            b.append(section);
695
            b.append(section);
696
        }
692
        b.append(']');
697
        b.append(']');
693
        b.append(']');
698
        b.append(']');
694
        return b.toString();
699
        return b.toString();
(-)src/java/org/apache/poi/hssf/dev/BiffViewer.java (-6 / +8 lines)
Lines 194-203 Link Here
194
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
194
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
195
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
195
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
196
import org.apache.poi.util.HexDump;
196
import org.apache.poi.util.HexDump;
197
import org.apache.poi.util.IOUtils;
197
import org.apache.poi.util.LittleEndian;
198
import org.apache.poi.util.LittleEndian;
198
import org.apache.poi.util.POILogFactory;
199
import org.apache.poi.util.POILogFactory;
199
import org.apache.poi.util.POILogger;
200
import org.apache.poi.util.POILogger;
200
import org.apache.poi.util.StringUtil;
201
import org.apache.poi.util.StringUtil;
202
import org.apache.poi.util.SuppressForbidden;
201
203
202
/**
204
/**
203
 *  Utility for reading in BIFF8 records and displaying data from them.
205
 *  Utility for reading in BIFF8 records and displaying data from them.
Lines 567-576 Link Here
567
569
568
                try {
570
                try {
569
                    if (cmdArgs.shouldOutputRawHexOnly()) {
571
                    if (cmdArgs.shouldOutputRawHexOnly()) {
570
                        int size = is.available();
572
                        byte[] data = IOUtils.toByteArray(is);
571
                        byte[] data = new byte[size];
572
573
                        is.read(data);
574
                        HexDump.dump(data, 0, System.out, 0);
573
                        HexDump.dump(data, 0, System.out, 0);
575
                    } else {
574
                    } else {
576
                        boolean dumpInterpretedRecords = cmdArgs.shouldDumpRecordInterpretations();
575
                        boolean dumpInterpretedRecords = cmdArgs.shouldDumpRecordInterpretations();
Lines 620-626 Link Here
620
        public void processRecord(int globalOffset, int recordCounter, int sid, int dataSize,
619
        public void processRecord(int globalOffset, int recordCounter, int sid, int dataSize,
621
				byte[] data) {
620
				byte[] data) {
622
			String header = formatRecordDetails(globalOffset, sid, dataSize, recordCounter);
621
			String header = formatRecordDetails(globalOffset, sid, dataSize, recordCounter);
623
			if(!_noHeader) _headers.add(header);
622
			if(!_noHeader) {
623
                _headers.add(header);
624
            }
624
			Writer w = _hexDumpWriter;
625
			Writer w = _hexDumpWriter;
625
			if (w != null) {
626
			if (w != null) {
626
				try {
627
				try {
Lines 710-721 Link Here
710
			}
711
			}
711
			System.arraycopy(_data, _currentPos, b, off, result);
712
			System.arraycopy(_data, _currentPos, b, off, result);
712
			_currentPos += result;
713
			_currentPos += result;
713
			_overallStreamPos += result;
714
			_overallStreamPos += result; 
714
			formatBufferIfAtEndOfRec();
715
			formatBufferIfAtEndOfRec();
715
			return result;
716
			return result;
716
		}
717
		}
717
718
718
		@Override
719
		@Override
720
		@SuppressForbidden("just delegating the call")
719
		public int available() throws IOException {
721
		public int available() throws IOException {
720
			return _currentSize - _currentPos + _is.available();
722
			return _currentSize - _currentPos + _is.available();
721
		}
723
		}
(-)src/java/org/apache/poi/hssf/record/ObjRecord.java (-55 / +70 lines)
Lines 18-27 Link Here
18
package org.apache.poi.hssf.record;
18
package org.apache.poi.hssf.record;
19
19
20
import java.io.ByteArrayInputStream;
20
import java.io.ByteArrayInputStream;
21
import java.io.IOException;
22
import java.io.InputStream;
21
import java.util.ArrayList;
23
import java.util.ArrayList;
22
import java.util.List;
24
import java.util.List;
23
25
24
import org.apache.poi.util.HexDump;
26
import org.apache.poi.util.HexDump;
27
import org.apache.poi.util.IOUtils;
25
import org.apache.poi.util.LittleEndian;
28
import org.apache.poi.util.LittleEndian;
26
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
29
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
27
import org.apache.poi.util.LittleEndianInputStream;
30
import org.apache.poi.util.LittleEndianInputStream;
Lines 58-69 Link Here
58
	public ObjRecord(RecordInputStream in) {
61
	public ObjRecord(RecordInputStream in) {
59
		// TODO - problems with OBJ sub-records stream
62
		// TODO - problems with OBJ sub-records stream
60
		// MS spec says first sub-record is always CommonObjectDataSubRecord,
63
		// MS spec says first sub-record is always CommonObjectDataSubRecord,
61
		// and last is
64
		// and last is always EndSubRecord. OOO spec does not mention ObjRecord(0x005D).
62
		// always EndSubRecord. OOO spec does not mention ObjRecord(0x005D).
63
		// Existing POI test data seems to violate that rule. Some test data
65
		// Existing POI test data seems to violate that rule. Some test data
64
		// seems to contain
66
		// seems to contain garbage, and a crash is only averted by stopping at
65
		// garbage, and a crash is only averted by stopping at what looks like
67
	    // what looks like the 'EndSubRecord'
66
		// the 'EndSubRecord'
67
68
68
		// Check if this can be continued, if so then the
69
		// Check if this can be continued, if so then the
69
		// following wont work properly
70
		// following wont work properly
Lines 88-148 Link Here
88
		subrecords = new ArrayList<SubRecord>();
89
		subrecords = new ArrayList<SubRecord>();
89
		ByteArrayInputStream bais = new ByteArrayInputStream(subRecordData);
90
		ByteArrayInputStream bais = new ByteArrayInputStream(subRecordData);
90
		LittleEndianInputStream subRecStream = new LittleEndianInputStream(bais);
91
		LittleEndianInputStream subRecStream = new LittleEndianInputStream(bais);
91
		CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)SubRecord.createSubRecord(subRecStream, 0);
92
		try {
92
        subrecords.add(cmo);
93
    		CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)SubRecord.createSubRecord(subRecStream, 0);
93
        while (true) {
94
            subrecords.add(cmo);
94
			SubRecord subRecord = SubRecord.createSubRecord(subRecStream, cmo.getObjectType());
95
            SubRecord subRecord;
95
			subrecords.add(subRecord);
96
            do {
96
			if (subRecord.isTerminating()) {
97
    			subRecord = SubRecord.createSubRecord(subRecStream, cmo.getObjectType());
97
				break;
98
    			subrecords.add(subRecord);
98
			}
99
            } while (!subRecord.isTerminating());
99
		}
100
            
100
		int nRemainingBytes = bais.available();
101
            _isPaddedToQuadByteMultiple = isPaddedToQuadByteMultiple(bais, subRecordData.length);
101
		if (nRemainingBytes > 0) {
102
    		_uninterpretedData = null;
102
			// At present (Oct-2008), most unit test samples have (subRecordData.length % 2 == 0)
103
		} finally {
103
			_isPaddedToQuadByteMultiple = subRecordData.length % MAX_PAD_ALIGNMENT == 0;
104
		    try {
104
			if (nRemainingBytes >= (_isPaddedToQuadByteMultiple ? MAX_PAD_ALIGNMENT : NORMAL_PAD_ALIGNMENT)) {
105
		        subRecStream.close();
105
				if (!canPaddingBeDiscarded(subRecordData, nRemainingBytes)) {
106
		    } catch (IOException e) {
106
					String msg = "Leftover " + nRemainingBytes 
107
		        throw new RuntimeException(e);
107
						+ " bytes in subrecord data " + HexDump.toHex(subRecordData);
108
		    }
108
					throw new RecordFormatException(msg);
109
				}
110
				_isPaddedToQuadByteMultiple = false;
111
			}
112
113
        } else {
114
			_isPaddedToQuadByteMultiple = false;
115
		}
109
		}
116
		_uninterpretedData = null;
117
	}
110
	}
118
111
119
	/**
112
    /**
120
	 * Some XLS files have ObjRecords with nearly 8Kb of excessive padding. These were probably
113
     * Some XLS files have ObjRecords with nearly 8Kb of excessive padding. These were probably
121
	 * written by a version of POI (around 3.1) which incorrectly interpreted the second short of
114
     * written by a version of POI (around 3.1) which incorrectly interpreted the second short of
122
	 * the ftLbs subrecord (0x1FEE) as a length, and read that many bytes as padding (other bugs
115
     * the ftLbs subrecord (0x1FEE) as a length, and read that many bytes as padding (other bugs
123
	 * helped allow this to occur).
116
     * helped allow this to occur).
124
	 * 
117
     * 
125
	 * Excel reads files with this excessive padding OK, truncating the over-sized ObjRecord back
118
     * Excel reads files with this excessive padding OK, truncating the over-sized ObjRecord back
126
	 * to the its proper size.  POI does the same.
119
     * to the its proper size.  POI does the same.
127
	 */
120
     */
128
	private static boolean canPaddingBeDiscarded(byte[] data, int nRemainingBytes) {
121
	private static boolean isPaddedToQuadByteMultiple(InputStream remainingBytes, int subRecordDataLen) {
129
        // make sure none of the padding looks important
122
        byte nRemainingBytes[];
130
		for(int i=data.length-nRemainingBytes; i<data.length; i++) {
123
        try {
131
			if (data[i] != 0x00) {
124
            nRemainingBytes = IOUtils.toByteArray(remainingBytes);
132
				return false;
125
        } catch (IOException e) {
133
			}
126
            throw new RuntimeException(e);
134
		}
127
        }
135
		return true;
128
        if (nRemainingBytes.length == 0) {
129
            return false;
130
        }
131
132
        boolean dataInPadding = false;
133
        for (byte b : nRemainingBytes) {
134
            // make sure none of the padding looks important
135
            if (b != 0) {
136
                dataInPadding = true;
137
                break;
138
            }
139
        }
140
        
141
        // At present (Oct-2008), most unit test samples have (subRecordData.length % 2 == 0)
142
        boolean isPaddedToQuad = (subRecordDataLen % MAX_PAD_ALIGNMENT) == 0;
143
        int padAlignment = isPaddedToQuad ? MAX_PAD_ALIGNMENT : NORMAL_PAD_ALIGNMENT;
144
        
145
        if (nRemainingBytes.length >= padAlignment) {
146
            if (dataInPadding) {
147
                String msg = "Leftover bytes in subrecord data " + HexDump.toHex(nRemainingBytes);
148
                throw new RecordFormatException(msg);
149
            }
150
            isPaddedToQuad = false;
151
        }
152
153
	    return isPaddedToQuad;
136
	}
154
	}
137
155
138
	@Override
156
	@Override
139
	public String toString() {
157
	public String toString() {
140
		StringBuffer sb = new StringBuffer();
158
		StringBuilder sb = new StringBuilder();
141
159
142
		sb.append("[OBJ]\n");
160
		sb.append("[OBJ]\n");
143
		if(subrecords != null) {	// there are special cases where this can be, see comments in constructor above
161
		if(subrecords != null) {	// there are special cases where this can be, see comments in constructor above
144
    		for (int i = 0; i < subrecords.size(); i++) {
162
    		for (SubRecord record : subrecords) {
145
    			SubRecord record = subrecords.get(i);
146
    			sb.append("SUBRECORD: ").append(record.toString());
163
    			sb.append("SUBRECORD: ").append(record.toString());
147
    		}
164
    		}
148
		}
165
		}
Lines 183-190 Link Here
183
200
184
		if (_uninterpretedData == null) {
201
		if (_uninterpretedData == null) {
185
202
186
			for (int i = 0; i < subrecords.size(); i++) {
203
			for (SubRecord record : subrecords) {
187
				SubRecord record = subrecords.get(i);
188
				record.serialize(out);
204
				record.serialize(out);
189
			}
205
			}
190
			int expectedEndIx = offset+dataSize;
206
			int expectedEndIx = offset+dataSize;
Lines 223-231 Link Here
223
	public ObjRecord clone() {
239
	public ObjRecord clone() {
224
		ObjRecord rec = new ObjRecord();
240
		ObjRecord rec = new ObjRecord();
225
241
226
		for (int i = 0; i < subrecords.size(); i++) {
242
		for (SubRecord record : subrecords) {
227
			SubRecord record = subrecords.get(i);
243
			rec.addSubRecord(record.clone());
228
			rec.addSubRecord((SubRecord) record.clone());
229
		}
244
		}
230
		return rec;
245
		return rec;
231
	}
246
	}
(-)src/java/org/apache/poi/hssf/record/SubRecord.java (-9 / +29 lines)
Lines 23-28 Link Here
23
import org.apache.poi.util.LittleEndianOutputStream;
23
import org.apache.poi.util.LittleEndianOutputStream;
24
24
25
import java.io.ByteArrayOutputStream;
25
import java.io.ByteArrayOutputStream;
26
import java.io.IOException;
26
27
27
/**
28
/**
28
 * Subrecords are part of the OBJ class.
29
 * Subrecords are part of the OBJ class.
Lines 76-90 Link Here
76
	public byte[] serialize() {
77
	public byte[] serialize() {
77
		int size = getDataSize() + 4;
78
		int size = getDataSize() + 4;
78
		ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
79
		ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
79
		serialize(new LittleEndianOutputStream(baos));
80
		LittleEndianOutputStream leos = new LittleEndianOutputStream(baos);
80
		if (baos.size() != size) {
81
		try {
81
			throw new RuntimeException("write size mismatch");
82
    		serialize(leos);
83
    		if (baos.size() != size) {
84
    			throw new RuntimeException("write size mismatch");
85
    		}
86
    		return baos.toByteArray();
87
		} finally {
88
		    try {
89
		        leos.close();
90
		    } catch (IOException e) {
91
		        throw new RuntimeException(e);
92
		    }
82
		}
93
		}
83
		return baos.toByteArray();
84
	}
94
	}
85
95
86
	public abstract void serialize(LittleEndianOutput out);
96
	public abstract void serialize(LittleEndianOutput out);
87
	public abstract Object clone();
97
98
	@Override
99
	public abstract SubRecord clone();
88
100
89
    /**
101
    /**
90
     * Wether this record terminates the sub-record stream.
102
     * Wether this record terminates the sub-record stream.
Lines 109-126 Link Here
109
	    	in.readFully(buf);
121
	    	in.readFully(buf);
110
	        _data = buf;
122
	        _data = buf;
111
		}
123
		}
112
		protected int getDataSize() {
124
		
125
		@Override
126
        protected int getDataSize() {
113
			return _data.length;
127
			return _data.length;
114
		}
128
		}
115
		public void serialize(LittleEndianOutput out) {
129
		
130
		@Override
131
        public void serialize(LittleEndianOutput out) {
116
			out.writeShort(_sid);
132
			out.writeShort(_sid);
117
			out.writeShort(_data.length);
133
			out.writeShort(_data.length);
118
			out.write(_data);
134
			out.write(_data);
119
		}
135
		}
120
		public Object clone() {
136
		
137
		@Override
138
		public UnknownSubRecord clone() {
121
			return this;
139
			return this;
122
		}
140
		}
123
		public String toString() {
141
		
142
		@Override
143
        public String toString() {
124
			StringBuffer sb = new StringBuffer(64);
144
			StringBuffer sb = new StringBuffer(64);
125
			sb.append(getClass().getName()).append(" [");
145
			sb.append(getClass().getName()).append(" [");
126
			sb.append("sid=").append(HexDump.shortToHex(_sid));
146
			sb.append("sid=").append(HexDump.shortToHex(_sid));
(-)src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java (-28 / +56 lines)
Lines 35-43 Link Here
35
    
35
    
36
    private int _lastIndex = 0;
36
    private int _lastIndex = 0;
37
    private long _pos = 0;
37
    private long _pos = 0;
38
    private long _size;
38
    private final long _size;
39
    private byte[] _chunk;
39
    private final byte[] _chunk;
40
    private Cipher _cipher;
40
    private boolean _chunkValid;
41
    private final Cipher _cipher;
41
42
42
    public ChunkedCipherInputStream(LittleEndianInput stream, long size, int chunkSize)
43
    public ChunkedCipherInputStream(LittleEndianInput stream, long size, int chunkSize)
43
        throws GeneralSecurityException {
44
        throws GeneralSecurityException {
Lines 46-83 Link Here
46
        this.chunkSize = chunkSize;
47
        this.chunkSize = chunkSize;
47
        chunkMask = chunkSize-1;
48
        chunkMask = chunkSize-1;
48
        chunkBits = Integer.bitCount(chunkMask);
49
        chunkBits = Integer.bitCount(chunkMask);
49
        
50
        _chunk = new byte[chunkSize];
51
        _chunkValid = false;
50
        _cipher = initCipherForBlock(null, 0);
52
        _cipher = initCipherForBlock(null, 0);
51
    }
53
    }
52
    
54
    
53
    protected abstract Cipher initCipherForBlock(Cipher existing, int block)
55
    protected abstract Cipher initCipherForBlock(Cipher existing, int block)
54
    throws GeneralSecurityException;
56
    throws GeneralSecurityException;
55
57
58
    @Override
56
    public int read() throws IOException {
59
    public int read() throws IOException {
57
        byte[] b = new byte[1];
60
        byte[] b = { 0 };
58
        if (read(b) == 1)
61
        return (read(b) == -1) ? -1 : b[0];
59
            return b[0];
60
        return -1;
61
    }
62
    }
62
63
63
    // do not implement! -> recursion
64
    // do not implement! -> recursion
64
    // public int read(byte[] b) throws IOException;
65
    // public int read(byte[] b) throws IOException;
65
66
67
    @Override
66
    public int read(byte[] b, int off, int len) throws IOException {
68
    public int read(byte[] b, int off, int len) throws IOException {
67
        int total = 0;
69
        int total = 0;
68
        
70
        
69
        if (available() <= 0) return -1;
71
        if (remainingBytes() <= 0) {
72
            return -1;
73
        }
70
74
71
        while (len > 0) {
75
        while (len > 0) {
72
            if (_chunk == null) {
76
            int tmp = -1;
73
                try {
77
            if (!_chunkValid) {
74
                    _chunk = nextChunk();
78
                tmp = nextChunk();
75
                } catch (GeneralSecurityException e) {
79
                _chunkValid = true;
76
                    throw new EncryptedDocumentException(e.getMessage(), e);
77
                }
78
            }
80
            }
79
            int count = (int)(chunkSize - (_pos & chunkMask));
81
            int count = (int)(chunkSize - (_pos & chunkMask));
80
            int avail = available();
82
            int avail = remainingBytes();
83
            assert(tmp == chunkSize || tmp == -1 || avail <= tmp);
81
            if (avail == 0) {
84
            if (avail == 0) {
82
                return total;
85
                return total;
83
            }
86
            }
Lines 86-93 Link Here
86
            off += count;
89
            off += count;
87
            len -= count;
90
            len -= count;
88
            _pos += count;
91
            _pos += count;
89
            if ((_pos & chunkMask) == 0)
92
            if ((_pos & chunkMask) == 0) {
90
                _chunk = null;
93
                _chunkValid = false;
94
            }
91
            total += count;
95
            total += count;
92
        }
96
        }
93
97
Lines 97-112 Link Here
97
    @Override
101
    @Override
98
    public long skip(long n) throws IOException {
102
    public long skip(long n) throws IOException {
99
        long start = _pos;
103
        long start = _pos;
100
        long skip = Math.min(available(), n);
104
        long skip = Math.min(remainingBytes(), n);
101
105
102
        if ((((_pos + skip) ^ start) & ~chunkMask) != 0)
106
        if ((((_pos + skip) ^ start) & ~chunkMask) != 0) {
103
            _chunk = null;
107
            _chunkValid = false;
108
        }
104
        _pos += skip;
109
        _pos += skip;
105
        return skip;
110
        return skip;
106
    }
111
    }
107
112
108
    @Override
113
    @Override
109
    public int available() {
114
    public int available() {
115
        return remainingBytes();
116
    }
117
    
118
    // helper method (... for forbidden-apis-check :) ...)
119
    private int remainingBytes() {
110
        return (int)(_size - _pos);
120
        return (int)(_size - _pos);
111
    }
121
    }
112
    
122
    
Lines 125-141 Link Here
125
        throw new UnsupportedOperationException();
135
        throw new UnsupportedOperationException();
126
    }
136
    }
127
137
128
    private byte[] nextChunk() throws GeneralSecurityException, IOException {
138
    /**
129
        int index = (int)(_pos >> chunkBits);
139
     * Read the next chunk from the super InputStream.
130
        initCipherForBlock(_cipher, index);
140
     * This also handles non-continued reads, because of {@link #skip(long)} calls.
141
     *
142
     * @return the actual chunk size, which might be less than {@link #chunkSize}
143
     * @throws IOException if the underlying stream can't be read
144
     */
145
    private int nextChunk() throws IOException {
146
        final int index = (int)(_pos >> chunkBits);
131
        
147
        
132
        if (_lastIndex != index) {
148
        if (_lastIndex != index) {
133
            super.skip((index - _lastIndex) << chunkBits);
149
            super.skip((index - _lastIndex) << chunkBits);
134
        }
150
        }
135
136
        byte[] block = new byte[Math.min(super.available(), chunkSize)];
137
        super.read(block, 0, block.length);
138
        _lastIndex = index + 1;
151
        _lastIndex = index + 1;
139
        return _cipher.doFinal(block);
152
        
153
154
        int totalBytes = 0;
155
        for (int readBytes; totalBytes < chunkSize; totalBytes += readBytes) {
156
            readBytes = super.read(_chunk, totalBytes, chunkSize-totalBytes);
157
            if (readBytes == -1) {
158
                break;
159
            }
160
        }
161
        
162
        try {
163
            initCipherForBlock(_cipher, index);
164
            return _cipher.doFinal(_chunk, 0, totalBytes, _chunk);
165
        } catch (GeneralSecurityException e) {
166
            throw new EncryptedDocumentException(e.getMessage(), e);
167
        }
140
    }
168
    }
141
}
169
}
(-)src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (+8 lines)
Lines 53-58 Link Here
53
53
54
    private long _pos = 0;
54
    private long _pos = 0;
55
    private Cipher _cipher;
55
    private Cipher _cipher;
56
    private boolean isClosed = false;
56
    
57
    
57
    public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException {
58
    public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException {
58
        super(null);
59
        super(null);
Lines 134-139 Link Here
134
    }
135
    }
135
    
136
    
136
    public void close() throws IOException {
137
    public void close() throws IOException {
138
        if (isClosed) {
139
            logger.log(POILogger.DEBUG, "ChunkedCipherOutputStream was already closed - ignoring");
140
            return;
141
        }
142
143
        isClosed = true;
144
        
137
        try {
145
        try {
138
            writeChunk();
146
            writeChunk();
139
147
(-)src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java (-20 / +19 lines)
Lines 15-27 Link Here
15
   See the License for the specific language governing permissions and
15
   See the License for the specific language governing permissions and
16
   limitations under the License.
16
   limitations under the License.
17
==================================================================== */
17
==================================================================== */
18
        
19
18
20
package org.apache.poi.poifs.eventfilesystem;
21
19
22
import java.io.*;
20
package org.apache.poi.poifs.eventfilesystem;
23
21
24
import java.util.*;
22
import java.io.FileInputStream;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.util.Iterator;
25
26
26
import org.apache.poi.poifs.filesystem.DocumentInputStream;
27
import org.apache.poi.poifs.filesystem.DocumentInputStream;
27
import org.apache.poi.poifs.filesystem.OPOIFSDocument;
28
import org.apache.poi.poifs.filesystem.OPOIFSDocument;
Lines 34-39 Link Here
34
import org.apache.poi.poifs.storage.HeaderBlock;
35
import org.apache.poi.poifs.storage.HeaderBlock;
35
import org.apache.poi.poifs.storage.RawDataBlockList;
36
import org.apache.poi.poifs.storage.RawDataBlockList;
36
import org.apache.poi.poifs.storage.SmallBlockTableReader;
37
import org.apache.poi.poifs.storage.SmallBlockTableReader;
38
import org.apache.poi.util.IOUtils;
37
39
38
/**
40
/**
39
 * An event-driven reader for POIFS file systems. Users of this class
41
 * An event-driven reader for POIFS file systems. Users of this class
Lines 42-49 Link Here
42
 * documents. Once all the listeners have been registered, the read()
44
 * documents. Once all the listeners have been registered, the read()
43
 * method is called, which results in the listeners being notified as
45
 * method is called, which results in the listeners being notified as
44
 * their documents are read.
46
 * their documents are read.
45
 *
46
 * @author Marc Johnson (mjohnson at apache dot org)
47
 */
47
 */
48
48
49
public class POIFSReader
49
public class POIFSReader
Lines 97-104 Link Here
97
        processProperties(SmallBlockTableReader
97
        processProperties(SmallBlockTableReader
98
            .getSmallDocumentBlocks(
98
            .getSmallDocumentBlocks(
99
                  header_block.getBigBlockSize(),
99
                  header_block.getBigBlockSize(),
100
                  data_blocks, properties.getRoot(), 
100
                  data_blocks, properties.getRoot(),
101
                  header_block.getSBATStart()), 
101
                  header_block.getSBATStart()),
102
                  data_blocks, properties.getRoot()
102
                  data_blocks, properties.getRoot()
103
                        .getChildren(), new POIFSDocumentPath());
103
                        .getChildren(), new POIFSDocumentPath());
104
    }
104
    }
Lines 196-209 Link Here
196
        }
196
        }
197
197
198
        // register for all
198
        // register for all
199
        for (int j = 0; j < args.length; j++)
199
        for (String arg : args) {
200
        {
201
            POIFSReader         reader   = new POIFSReader();
200
            POIFSReader         reader   = new POIFSReader();
202
            POIFSReaderListener listener = new SampleListener();
201
            POIFSReaderListener listener = new SampleListener();
203
202
204
            reader.registerListener(listener);
203
            reader.registerListener(listener);
205
            System.out.println("reading " + args[ j ]);
204
            System.out.println("reading " + arg);
206
            FileInputStream istream = new FileInputStream(args[ j ]);
205
            FileInputStream istream = new FileInputStream(arg);
207
206
208
            reader.read(istream);
207
            reader.read(istream);
209
            istream.close();
208
            istream.close();
Lines 258-268 Link Here
258
                    while (listeners.hasNext())
257
                    while (listeners.hasNext())
259
                    {
258
                    {
260
                        POIFSReaderListener listener = listeners.next();
259
                        POIFSReaderListener listener = listeners.next();
261
260
                        DocumentInputStream dis = new DocumentInputStream(document);
262
                        listener.processPOIFSReaderEvent(
261
                        try {
263
                            new POIFSReaderEvent(
262
                            listener.processPOIFSReaderEvent(new POIFSReaderEvent(dis, path, name));
264
                                new DocumentInputStream(document), path,
263
                        } finally {
265
                                name));
264
                            dis.close();
265
                        }
266
                    }
266
                    }
267
                }
267
                }
268
                else
268
                else
Lines 300-305 Link Here
300
         * @param event
300
         * @param event
301
         */
301
         */
302
302
303
        @Override
303
        public void processPOIFSReaderEvent(final POIFSReaderEvent event)
304
        public void processPOIFSReaderEvent(final POIFSReaderEvent event)
304
        {
305
        {
305
            @SuppressWarnings("resource")
306
            @SuppressWarnings("resource")
Lines 309-317 Link Here
309
310
310
            try
311
            try
311
            {
312
            {
312
                byte[] data = new byte[ istream.available() ];
313
                byte[] data = IOUtils.toByteArray(istream);
313
314
                istream.read(data);
315
                int pathLength = path.length();
314
                int pathLength = path.length();
316
315
317
                for (int k = 0; k < pathLength; k++)
316
                for (int k = 0; k < pathLength; k++)
(-)src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java (+2 lines)
Lines 21-26 Link Here
21
import java.io.InputStream;
21
import java.io.InputStream;
22
22
23
import org.apache.poi.util.LittleEndianInput;
23
import org.apache.poi.util.LittleEndianInput;
24
import org.apache.poi.util.SuppressForbidden;
24
25
25
/**
26
/**
26
 * This class provides methods to read a DocumentEntry managed by a
27
 * This class provides methods to read a DocumentEntry managed by a
Lines 86-91 Link Here
86
   }
87
   }
87
88
88
    @Override
89
    @Override
90
    @SuppressForbidden("just delegating")
89
	public int available() {
91
	public int available() {
90
	   return delegate.available();
92
	   return delegate.available();
91
	}
93
	}
(-)src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java (-6 / +16 lines)
Lines 40-52 Link Here
40
    private int _marked_offset_count;
40
    private int _marked_offset_count;
41
41
42
    /** the Document's size */
42
    /** the Document's size */
43
    private int _document_size;
43
    private final int _document_size;
44
44
45
    /** have we been closed? */
45
    /** have we been closed? */
46
    private boolean _closed;
46
    private boolean _closed;
47
47
48
    /** the actual Document */
48
    /** the actual Document */
49
    private NPOIFSDocument _document;
49
    private final NPOIFSDocument _document;
50
50
51
    private Iterator<ByteBuffer> _data;
51
    private Iterator<ByteBuffer> _data;
52
    private ByteBuffer _buffer;
52
    private ByteBuffer _buffer;
Lines 97-108 Link Here
97
97
98
    @Override
98
    @Override
99
    public int available() {
99
    public int available() {
100
        return remainingBytes();
101
    }
102
103
    /**
104
     * Helper methods for forbidden api calls
105
     *
106
     * @return the bytes remaining until the end of the stream
107
     */
108
    private int remainingBytes() {
100
        if (_closed) {
109
        if (_closed) {
101
            throw new IllegalStateException("cannot perform requested operation on a closed stream");
110
            throw new IllegalStateException("cannot perform requested operation on a closed stream");
102
        }
111
        }
103
        return _document_size - _current_offset;
112
        return _document_size - _current_offset;
104
    }
113
    }
105
114
    
106
    @Override
115
    @Override
107
    public void close() {
116
    public void close() {
108
        _closed = true;
117
        _closed = true;
Lines 146-152 Link Here
146
        if (atEOD()) {
155
        if (atEOD()) {
147
            return EOF;
156
            return EOF;
148
        }
157
        }
149
        int limit = Math.min(available(), len);
158
        int limit = Math.min(remainingBytes(), len);
150
        readFully(b, off, limit);
159
        readFully(b, off, limit);
151
        return limit;
160
        return limit;
152
    }
161
    }
Lines 302-309 Link Here
302
		checkAvaliable(1);
311
		checkAvaliable(1);
303
      byte[] data = new byte[1];
312
      byte[] data = new byte[1];
304
      readFully(data, 0, 1);
313
      readFully(data, 0, 1);
305
      if(data[0] >= 0)
314
      if(data[0] >= 0) {
306
         return data[0];
315
        return data[0];
316
    }
307
      return data[0] + 256;
317
      return data[0] + 256;
308
	}
318
	}
309
}
319
}
(-)src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java (-3 / +3 lines)
Lines 33-45 Link Here
33
	private int _marked_offset;
33
	private int _marked_offset;
34
34
35
	/** the Document's size */
35
	/** the Document's size */
36
	private int _document_size;
36
	private final int _document_size;
37
37
38
	/** have we been closed? */
38
	/** have we been closed? */
39
	private boolean _closed;
39
	private boolean _closed;
40
40
41
	/** the actual Document */
41
	/** the actual Document */
42
	private OPOIFSDocument _document;
42
	private final OPOIFSDocument _document;
43
43
44
	/** the data block containing the current stream pointer */
44
	/** the data block containing the current stream pointer */
45
	private DataInputBlock _currentBlock;
45
	private DataInputBlock _currentBlock;
Lines 134-140 Link Here
134
		if (atEOD()) {
134
		if (atEOD()) {
135
			return EOF;
135
			return EOF;
136
		}
136
		}
137
		int limit = Math.min(available(), len);
137
		int limit = Math.min(_document_size - _current_offset, len);
138
		readFully(b, off, limit);
138
		readFully(b, off, limit);
139
		return limit;
139
		return limit;
140
	}
140
	}
(-)src/java/org/apache/poi/util/BlockingInputStream.java (-3 / +5 lines)
Lines 28-39 Link Here
28
 * data from slow (ie, non FileInputStream) sources, for example when 
28
 * data from slow (ie, non FileInputStream) sources, for example when 
29
 * reading an OLE2 Document over a network. 
29
 * reading an OLE2 Document over a network. 
30
 *
30
 *
31
 * Possible extentions: add a timeout. Curently a call to read(byte[]) on this
31
 * Possible extensions: add a timeout. Currently a call to read(byte[]) on this
32
 *    class is blocking, so use at your own peril if your underlying stream blocks. 
32
 *    class is blocking, so use at your own peril if your underlying stream blocks. 
33
 *
33
 *
34
 * @author Jens Gerhard
34
 * @deprecated in POI 3.15 - unused class
35
 * @author aviks - documentation cleanups. 
36
 */
35
 */
36
@Deprecated
37
@Removal(version="3.17")
37
public class BlockingInputStream
38
public class BlockingInputStream
38
      extends InputStream
39
      extends InputStream
39
{
40
{
Lines 44-49 Link Here
44
          this.is = is;
45
          this.is = is;
45
      }
46
      }
46
47
48
      @SuppressForbidden("just delegating the call")
47
      public int available()
49
      public int available()
48
        throws IOException
50
        throws IOException
49
      {
51
      {
(-)src/java/org/apache/poi/util/BoundedInputStream.java (+1 lines)
Lines 146-151 Link Here
146
     * {@inheritDoc}
146
     * {@inheritDoc}
147
     */
147
     */
148
    @Override
148
    @Override
149
    @SuppressForbidden("just delegating")
149
    public int available() throws IOException {
150
    public int available() throws IOException {
150
        if (max>=0 && pos>=max) {
151
        if (max>=0 && pos>=max) {
151
            return 0;
152
            return 0;
(-)src/java/org/apache/poi/util/IOUtils.java (-5 / +14 lines)
Lines 74-94 Link Here
74
74
75
    /**
75
    /**
76
     * Reads up to {@code length} bytes from the input stream, and returns the bytes read.
76
     * Reads up to {@code length} bytes from the input stream, and returns the bytes read.
77
     * 
78
     * @param stream the stream to read from
79
     * @param length the amount of bytes to be read, if {@code length} is {@value Integer.MAX_VALUE}
80
     *      or negative, the byte length is not checked
81
     * 
82
     * @return the read bytes
83
     * 
84
     * @throws IOException if {@code length} can't be read. the check is omitted, if {@code length} is negative
77
     */
85
     */
78
    public static byte[] toByteArray(InputStream stream, int length) throws IOException {
86
    public static byte[] toByteArray(InputStream stream, final int length) throws IOException {
79
        ByteArrayOutputStream baos = new ByteArrayOutputStream(length == Integer.MAX_VALUE ? 4096 : length);
87
        final int len = Math.abs(length);
88
        ByteArrayOutputStream baos = new ByteArrayOutputStream(len == Integer.MAX_VALUE ? 4096 : len);
80
89
81
        byte[] buffer = new byte[4096];
90
        byte[] buffer = new byte[4096];
82
        int totalBytes = 0, readBytes;
91
        int totalBytes = 0, readBytes;
83
        do {
92
        do {
84
            readBytes = stream.read(buffer, 0, Math.min(buffer.length, length-totalBytes));
93
            readBytes = stream.read(buffer, 0, Math.min(buffer.length, len-totalBytes));
85
            totalBytes += Math.max(readBytes,0);
94
            totalBytes += Math.max(readBytes,0);
86
            if (readBytes > 0) {
95
            if (readBytes > 0) {
87
                baos.write(buffer, 0, readBytes);
96
                baos.write(buffer, 0, readBytes);
88
            }
97
            }
89
        } while (totalBytes < length && readBytes > -1);
98
        } while (totalBytes < len && readBytes > -1);
90
99
91
        if (length != Integer.MAX_VALUE && totalBytes < length) {
100
        if (length >= 0 && len != Integer.MAX_VALUE && totalBytes < len) {
92
            throw new IOException("unexpected EOF");
101
            throw new IOException("unexpected EOF");
93
        }
102
        }
94
        
103
        
(-)src/java/org/apache/poi/util/LittleEndianInputStream.java (-11 / +20 lines)
Lines 26-39 Link Here
26
 *
26
 *
27
 * This class does not buffer any input, so the stream read position maintained
27
 * This class does not buffer any input, so the stream read position maintained
28
 * by this class is consistent with that of the inner stream.
28
 * by this class is consistent with that of the inner stream.
29
 *
30
 * @author Josh Micich
31
 */
29
 */
32
public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
30
public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
33
	public LittleEndianInputStream(InputStream is) {
31
	public LittleEndianInputStream(InputStream is) {
34
		super(is);
32
		super(is);
35
	}
33
	}
36
	
34
	
35
	@Override
36
    @SuppressForbidden("just delegating")
37
	public int available() {
37
	public int available() {
38
		try {
38
		try {
39
			return super.available();
39
			return super.available();
Lines 42-52 Link Here
42
		}
42
		}
43
	}
43
	}
44
	
44
	
45
	public byte readByte() {
45
	@Override
46
    public byte readByte() {
46
		return (byte)readUByte();
47
		return (byte)readUByte();
47
	}
48
	}
48
	
49
	
49
	public int readUByte() {
50
	@Override
51
    public int readUByte() {
50
		byte buf[] = new byte[1];
52
		byte buf[] = new byte[1];
51
		try {
53
		try {
52
			checkEOF(read(buf), 1);
54
			checkEOF(read(buf), 1);
Lines 56-66 Link Here
56
		return LittleEndian.getUByte(buf);
58
		return LittleEndian.getUByte(buf);
57
	}
59
	}
58
	
60
	
59
	public double readDouble() {
61
	@Override
62
    public double readDouble() {
60
		return Double.longBitsToDouble(readLong());
63
		return Double.longBitsToDouble(readLong());
61
	}
64
	}
62
	
65
	
63
	public int readInt() {
66
	@Override
67
    public int readInt() {
64
	    byte buf[] = new byte[LittleEndianConsts.INT_SIZE];
68
	    byte buf[] = new byte[LittleEndianConsts.INT_SIZE];
65
		try {
69
		try {
66
		    checkEOF(read(buf), buf.length);
70
		    checkEOF(read(buf), buf.length);
Lines 82-88 Link Here
82
       return retNum & 0x00FFFFFFFFL;
86
       return retNum & 0x00FFFFFFFFL;
83
    }
87
    }
84
	
88
	
85
	public long readLong() {
89
	@Override
90
    public long readLong() {
86
		byte buf[] = new byte[LittleEndianConsts.LONG_SIZE];
91
		byte buf[] = new byte[LittleEndianConsts.LONG_SIZE];
87
		try {
92
		try {
88
		    checkEOF(read(buf), LittleEndianConsts.LONG_SIZE);
93
		    checkEOF(read(buf), LittleEndianConsts.LONG_SIZE);
Lines 92-102 Link Here
92
		return LittleEndian.getLong(buf);
97
		return LittleEndian.getLong(buf);
93
	}
98
	}
94
	
99
	
95
	public short readShort() {
100
	@Override
101
    public short readShort() {
96
		return (short)readUShort();
102
		return (short)readUShort();
97
	}
103
	}
98
	
104
	
99
	public int readUShort() {
105
	@Override
106
    public int readUShort() {
100
		byte buf[] = new byte[LittleEndianConsts.SHORT_SIZE];
107
		byte buf[] = new byte[LittleEndianConsts.SHORT_SIZE];
101
		try {
108
		try {
102
		    checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE);
109
		    checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE);
Lines 112-122 Link Here
112
		}
119
		}
113
	}
120
	}
114
121
115
	public void readFully(byte[] buf) {
122
	@Override
123
    public void readFully(byte[] buf) {
116
		readFully(buf, 0, buf.length);
124
		readFully(buf, 0, buf.length);
117
	}
125
	}
118
126
119
	public void readFully(byte[] buf, int off, int len) {
127
	@Override
128
    public void readFully(byte[] buf, int off, int len) {
120
	    try {
129
	    try {
121
	        checkEOF(read(buf, off, len), len);
130
	        checkEOF(read(buf, off, len), len);
122
	    } catch (IOException e) {
131
	    } catch (IOException e) {
(-)src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java (-7 / +19 lines)
Lines 41-46 Link Here
41
import org.apache.poi.poifs.storage.HeaderBlockConstants;
41
import org.apache.poi.poifs.storage.HeaderBlockConstants;
42
import org.apache.poi.util.IOUtils;
42
import org.apache.poi.util.IOUtils;
43
import org.apache.poi.util.LittleEndian;
43
import org.apache.poi.util.LittleEndian;
44
import org.apache.poi.util.Removal;
44
45
45
public final class ZipHelper {
46
public final class ZipHelper {
46
    /**
47
    /**
Lines 53-59 Link Here
53
     * Buffer to read data from file. Use big buffer to improve performaces. the
54
     * Buffer to read data from file. Use big buffer to improve performaces. the
54
     * InputStream class is reading only 8192 bytes per read call (default value
55
     * InputStream class is reading only 8192 bytes per read call (default value
55
     * set by sun)
56
     * set by sun)
57
     * 
58
     * @deprecated in POI 3.15-beta3, not used anymore
56
     */
59
     */
60
    @Deprecated
61
    @Removal(version="3.17")
57
    public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192;
62
    public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192;
58
63
59
    /**
64
    /**
Lines 73-80 Link Here
73
        PackageRelationship corePropsRel = pkg.getRelationshipsByType(
78
        PackageRelationship corePropsRel = pkg.getRelationshipsByType(
74
                PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0);
79
                PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0);
75
80
76
        if (corePropsRel == null)
81
        if (corePropsRel == null) {
77
            return null;
82
            return null;
83
        }
78
84
79
        return new ZipEntry(corePropsRel.getTargetURI().getPath());
85
        return new ZipEntry(corePropsRel.getTargetURI().getPath());
80
    }
86
    }
Lines 90-97 Link Here
90
        while (entries.hasMoreElements()) {
96
        while (entries.hasMoreElements()) {
91
            ZipEntry entry = entries.nextElement();
97
            ZipEntry entry = entries.nextElement();
92
            if (entry.getName().equals(
98
            if (entry.getName().equals(
93
                    ContentTypeManager.CONTENT_TYPES_PART_NAME))
99
                    ContentTypeManager.CONTENT_TYPES_PART_NAME)) {
94
                return entry;
100
                return entry;
101
            }
95
        }
102
        }
96
        return null;
103
        return null;
97
    }
104
    }
Lines 105-112 Link Here
105
     * @return An OPC compliant name.
112
     * @return An OPC compliant name.
106
     */
113
     */
107
    public static String getOPCNameFromZipItemName(String zipItemName) {
114
    public static String getOPCNameFromZipItemName(String zipItemName) {
108
        if (zipItemName == null)
115
        if (zipItemName == null) {
109
            throw new IllegalArgumentException("zipItemName");
116
            throw new IllegalArgumentException("zipItemName");
117
        }
110
        if (zipItemName.startsWith(FORWARD_SLASH)) {
118
        if (zipItemName.startsWith(FORWARD_SLASH)) {
111
            return zipItemName;
119
            return zipItemName;
112
        }
120
        }
Lines 122-133 Link Here
122
     * @return A zip item name without any leading slashes.
130
     * @return A zip item name without any leading slashes.
123
     */
131
     */
124
    public static String getZipItemNameFromOPCName(String opcItemName) {
132
    public static String getZipItemNameFromOPCName(String opcItemName) {
125
        if (opcItemName == null)
133
        if (opcItemName == null) {
126
            throw new IllegalArgumentException("opcItemName");
134
            throw new IllegalArgumentException("opcItemName");
135
        }
127
136
128
        String retVal = opcItemName;
137
        String retVal = opcItemName;
129
        while (retVal.startsWith(FORWARD_SLASH))
138
        while (retVal.startsWith(FORWARD_SLASH)) {
130
            retVal = retVal.substring(1);
139
            retVal = retVal.substring(1);
140
        }
131
        return retVal;
141
        return retVal;
132
    }
142
    }
133
143
Lines 140-151 Link Here
140
     * @return A zip URI without any leading slashes.
150
     * @return A zip URI without any leading slashes.
141
     */
151
     */
142
    public static URI getZipURIFromOPCName(String opcItemName) {
152
    public static URI getZipURIFromOPCName(String opcItemName) {
143
        if (opcItemName == null)
153
        if (opcItemName == null) {
144
            throw new IllegalArgumentException("opcItemName");
154
            throw new IllegalArgumentException("opcItemName");
155
        }
145
156
146
        String retVal = opcItemName;
157
        String retVal = opcItemName;
147
        while (retVal.startsWith(FORWARD_SLASH))
158
        while (retVal.startsWith(FORWARD_SLASH)) {
148
            retVal = retVal.substring(1);
159
            retVal = retVal.substring(1);
160
        }
149
        try {
161
        try {
150
            return new URI(retVal);
162
            return new URI(retVal);
151
        } catch (URISyntaxException e) {
163
        } catch (URISyntaxException e) {
(-)src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java (-14 / +7 lines)
Lines 36-41 Link Here
36
import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
36
import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
37
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
37
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
38
import org.apache.poi.util.DocumentHelper;
38
import org.apache.poi.util.DocumentHelper;
39
import org.apache.poi.util.IOUtils;
39
import org.apache.poi.util.POILogFactory;
40
import org.apache.poi.util.POILogFactory;
40
import org.apache.poi.util.POILogger;
41
import org.apache.poi.util.POILogger;
41
import org.apache.poi.xssf.usermodel.XSSFRelation;
42
import org.apache.poi.xssf.usermodel.XSSFRelation;
Lines 44-51 Link Here
44
45
45
/**
46
/**
46
 * Zip part marshaller. This marshaller is use to save any part in a zip stream.
47
 * Zip part marshaller. This marshaller is use to save any part in a zip stream.
47
 *
48
 * @author Julien Chable
49
 */
48
 */
50
public final class ZipPartMarshaller implements PartMarshaller {
49
public final class ZipPartMarshaller implements PartMarshaller {
51
	private static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class);
50
	private static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class);
Lines 56-62 Link Here
56
	 * @throws OpenXML4JException
55
	 * @throws OpenXML4JException
57
	 *             Throws if an internal exception is thrown.
56
	 *             Throws if an internal exception is thrown.
58
	 */
57
	 */
59
	public boolean marshall(PackagePart part, OutputStream os)
58
	@Override
59
    public boolean marshall(PackagePart part, OutputStream os)
60
			throws OpenXML4JException {
60
			throws OpenXML4JException {
61
		if (!(os instanceof ZipOutputStream)) {
61
		if (!(os instanceof ZipOutputStream)) {
62
			logger.log(POILogger.ERROR,"Unexpected class " + os.getClass().getName());
62
			logger.log(POILogger.ERROR,"Unexpected class " + os.getClass().getName());
Lines 81-99 Link Here
81
81
82
			// Saving data in the ZIP file
82
			// Saving data in the ZIP file
83
			InputStream ins = part.getInputStream();
83
			InputStream ins = part.getInputStream();
84
			byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE];
84
			IOUtils.copy(ins, zos);
85
			while (ins.available() > 0) {
85
			ins.close();
86
				int resultRead = ins.read(buff);
86
87
				if (resultRead == -1) {
88
					// End of file reached
89
					break;
90
				}
91
				zos.write(buff, 0, resultRead);
92
			}
93
			zos.closeEntry();
87
			zos.closeEntry();
94
		} catch (IOException ioe) {
88
		} catch (IOException ioe) {
95
			logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP",
89
			logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP", ioe);
96
					ioe);
97
			return false;
90
			return false;
98
		}
91
		}
99
92
(-)src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java (-7 / +28 lines)
Lines 160-175 Link Here
160
     * @throws IOException if an I/O error has occurred
160
     * @throws IOException if an I/O error has occurred
161
     * @throws IllegalStateException if the zip file has been closed
161
     * @throws IllegalStateException if the zip file has been closed
162
     */
162
     */
163
    @Override
163
    @SuppressWarnings("resource")
164
    @SuppressWarnings("resource")
164
    public InputStream getInputStream(ZipEntry entry) throws IOException {
165
    public InputStream getInputStream(ZipEntry entry) throws IOException {
165
        InputStream zipIS = super.getInputStream(entry);
166
        InputStream zipIS = super.getInputStream(entry);
166
        return addThreshold(zipIS);
167
        return addThreshold(zipIS);
167
    }
168
    }
168
169
170
    @SuppressWarnings("resource")
169
    public static ThresholdInputStream addThreshold(final InputStream zipIS) throws IOException {
171
    public static ThresholdInputStream addThreshold(final InputStream zipIS) throws IOException {
170
        ThresholdInputStream newInner;
172
        ThresholdInputStream newInner;
171
        if (zipIS instanceof InflaterInputStream) {
173
        if (zipIS instanceof InflaterInputStream) {
172
            newInner = AccessController.doPrivileged(new PrivilegedAction<ThresholdInputStream>() {
174
            newInner = AccessController.doPrivileged(new PrivilegedAction<ThresholdInputStream>() {
175
                @Override
173
                @SuppressForbidden("TODO: Fix this to not use reflection (it will break in Java 9)! " +
176
                @SuppressForbidden("TODO: Fix this to not use reflection (it will break in Java 9)! " +
174
                        "Better would be to wrap *before* instead of tyring to insert wrapper afterwards.")
177
                        "Better would be to wrap *before* instead of tyring to insert wrapper afterwards.")
175
                public ThresholdInputStream run() {
178
                public ThresholdInputStream run() {
Lines 177-185 Link Here
177
                        Field f = FilterInputStream.class.getDeclaredField("in");
180
                        Field f = FilterInputStream.class.getDeclaredField("in");
178
                        f.setAccessible(true);
181
                        f.setAccessible(true);
179
                        InputStream oldInner = (InputStream)f.get(zipIS);
182
                        InputStream oldInner = (InputStream)f.get(zipIS);
180
                        ThresholdInputStream newInner = new ThresholdInputStream(oldInner, null);
183
                        ThresholdInputStream newInner2 = new ThresholdInputStream(oldInner, null);
181
                        f.set(zipIS, newInner);
184
                        f.set(zipIS, newInner2);
182
                        return newInner;
185
                        return newInner2;
183
                    } catch (Exception ex) {
186
                    } catch (Exception ex) {
184
                        logger.log(POILogger.WARN, "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream", ex);
187
                        logger.log(POILogger.WARN, "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream", ex);
185
                    }
188
                    }
Lines 203-226 Link Here
203
            this.cis = cis;
206
            this.cis = cis;
204
        }
207
        }
205
208
209
        @Override
206
        public int read() throws IOException {
210
        public int read() throws IOException {
207
            int b = in.read();
211
            int b = in.read();
208
            if (b > -1) advance(1);
212
            if (b > -1) {
213
                advance(1);
214
            }
209
            return b;
215
            return b;
210
        }
216
        }
211
217
218
        @Override
212
        public int read(byte b[], int off, int len) throws IOException {
219
        public int read(byte b[], int off, int len) throws IOException {
213
            int cnt = in.read(b, off, len);
220
            int cnt = in.read(b, off, len);
214
            if (cnt > -1) advance(cnt);
221
            if (cnt > -1) {
222
                advance(cnt);
223
            }
215
            return cnt;
224
            return cnt;
216
225
217
        }
226
        }
218
227
228
        @Override
219
        public long skip(long n) throws IOException {
229
        public long skip(long n) throws IOException {
220
            counter = 0;
230
            counter = 0;
221
            return in.skip(n);
231
            return in.skip(n);
222
        }
232
        }
223
233
234
        @Override
224
        public synchronized void reset() throws IOException {
235
        public synchronized void reset() throws IOException {
225
            counter = 0;
236
            counter = 0;
226
            in.reset();
237
            in.reset();
Lines 277-307 Link Here
277
            ((ZipInputStream)in).closeEntry();
288
            ((ZipInputStream)in).closeEntry();
278
        }
289
        }
279
290
291
        @Override
280
        public void unread(int b) throws IOException {
292
        public void unread(int b) throws IOException {
281
            if (!(in instanceof PushbackInputStream)) {
293
            if (!(in instanceof PushbackInputStream)) {
282
                throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
294
                throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
283
            }
295
            }
284
            if (--counter < 0) counter = 0;
296
            if (--counter < 0) {
297
                counter = 0;
298
            }
285
            ((PushbackInputStream)in).unread(b);
299
            ((PushbackInputStream)in).unread(b);
286
        }
300
        }
287
301
302
        @Override
288
        public void unread(byte[] b, int off, int len) throws IOException {
303
        public void unread(byte[] b, int off, int len) throws IOException {
289
            if (!(in instanceof PushbackInputStream)) {
304
            if (!(in instanceof PushbackInputStream)) {
290
                throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
305
                throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
291
            }
306
            }
292
            counter -= len;
307
            counter -= len;
293
            if (--counter < 0) counter = 0;
308
            if (--counter < 0) {
309
                counter = 0;
310
            }
294
            ((PushbackInputStream)in).unread(b, off, len);
311
            ((PushbackInputStream)in).unread(b, off, len);
295
        }
312
        }
296
313
314
        @Override
315
        @SuppressForbidden("just delegating")
297
        public int available() throws IOException {
316
        public int available() throws IOException {
298
            return in.available();
317
            return in.available();
299
        }
318
        }
300
319
320
        @Override
301
        public boolean markSupported() {
321
        public boolean markSupported() {
302
            return in.markSupported();
322
            return in.markSupported();
303
        }
323
        }
304
324
325
        @Override
305
        public synchronized void mark(int readlimit) {
326
        public synchronized void mark(int readlimit) {
306
            in.mark(readlimit);
327
            in.mark(readlimit);
307
        }
328
        }
(-)src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java (-2 / +3 lines)
Lines 30-35 Link Here
30
30
31
import org.apache.poi.POIXMLProperties.CoreProperties;
31
import org.apache.poi.POIXMLProperties.CoreProperties;
32
import org.apache.poi.openxml4j.util.Nullable;
32
import org.apache.poi.openxml4j.util.Nullable;
33
import org.apache.poi.util.IOUtils;
33
import org.apache.poi.util.LocaleUtil;
34
import org.apache.poi.util.LocaleUtil;
34
import org.apache.poi.xssf.XSSFTestDataSamples;
35
import org.apache.poi.xssf.XSSFTestDataSamples;
35
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
36
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
Lines 249-261 Link Here
249
        assertNotNull(noThumbProps.getThumbnailPart());
250
        assertNotNull(noThumbProps.getThumbnailPart());
250
        assertEquals("Testing.png", noThumbProps.getThumbnailFilename());
251
        assertEquals("Testing.png", noThumbProps.getThumbnailFilename());
251
        assertNotNull(noThumbProps.getThumbnailImage());
252
        assertNotNull(noThumbProps.getThumbnailImage());
252
        assertEquals(1, noThumbProps.getThumbnailImage().available());
253
        assertEquals(1, IOUtils.toByteArray(noThumbProps.getThumbnailImage()).length);
253
254
254
        noThumbProps.setThumbnail("Testing2.png", new ByteArrayInputStream(new byte[2]));
255
        noThumbProps.setThumbnail("Testing2.png", new ByteArrayInputStream(new byte[2]));
255
        assertNotNull(noThumbProps.getThumbnailPart());
256
        assertNotNull(noThumbProps.getThumbnailPart());
256
        assertEquals("Testing.png", noThumbProps.getThumbnailFilename());
257
        assertEquals("Testing.png", noThumbProps.getThumbnailFilename());
257
        assertNotNull(noThumbProps.getThumbnailImage());
258
        assertNotNull(noThumbProps.getThumbnailImage());
258
        assertEquals(2, noThumbProps.getThumbnailImage().available());
259
        assertEquals(2, IOUtils.toByteArray(noThumbProps.getThumbnailImage()).length);
259
    }
260
    }
260
261
261
    private static String zeroPad(long i) {
262
    private static String zeroPad(long i) {
(-)src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java (-12 / +21 lines)
Lines 37-46 Link Here
37
import org.apache.poi.xssf.XSSFTestDataSamples;
37
import org.apache.poi.xssf.XSSFTestDataSamples;
38
import org.junit.Test;
38
import org.junit.Test;
39
39
40
/**
41
 *  @author Maxim Valyanskiy
42
 *  @author Gary King
43
 */
44
public class TestDecryptor {
40
public class TestDecryptor {
45
    @Test
41
    @Test
46
    public void passwordVerification() throws IOException, GeneralSecurityException {
42
    public void passwordVerification() throws IOException, GeneralSecurityException {
Lines 51-56 Link Here
51
        Decryptor d = Decryptor.getInstance(info);
47
        Decryptor d = Decryptor.getInstance(info);
52
48
53
        assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
49
        assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
50
        
51
        fs.close();
54
    }
52
    }
55
53
56
    @Test
54
    @Test
Lines 64-69 Link Here
64
        d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
62
        d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
65
63
66
        zipOk(fs.getRoot(), d);
64
        zipOk(fs.getRoot(), d);
65
        
66
        fs.close();
67
    }
67
    }
68
68
69
    @Test
69
    @Test
Lines 79-84 Link Here
79
        assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
79
        assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
80
80
81
        zipOk(fs.getRoot(), d);
81
        zipOk(fs.getRoot(), d);
82
        fs.close();
82
    }
83
    }
83
84
84
    private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
85
    private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
Lines 86-99 Link Here
86
87
87
        while (true) {
88
        while (true) {
88
            ZipEntry entry = zin.getNextEntry();
89
            ZipEntry entry = zin.getNextEntry();
89
            if (entry==null) break;
90
            if (entry==null) {
91
                break;
92
            }
90
            // crc32 is checked within zip-stream
93
            // crc32 is checked within zip-stream
91
            if (entry.isDirectory()) continue;
94
            if (entry.isDirectory()) {
92
            zin.skip(entry.getSize());
95
                continue;
96
            }
97
            zin.skip(entry.getSize()-1);
93
            byte buf[] = new byte[10];
98
            byte buf[] = new byte[10];
94
            int readBytes = zin.read(buf);
99
            int readBytes = zin.read(buf);
95
            // zin.available() doesn't work for entries
100
            // zin.available() doesn't work for entries
96
            assertEquals("size failed for "+entry.getName(), -1, readBytes);
101
            assertEquals("size failed for "+entry.getName(), 1, readBytes);
97
        }
102
        }
98
        
103
        
99
        zin.close();
104
        zin.close();
Lines 126-135 Link Here
126
                break;
131
                break;
127
            }
132
            }
128
133
129
            while (zin.available()>0) {
134
            IOUtils.toByteArray(zin);
130
                zin.skip(zin.available());
131
            }
132
        }
135
        }
136
        
137
        is.close();
138
        fs.close();
133
    }
139
    }
134
140
135
    @Test
141
    @Test
Lines 156-165 Link Here
156
162
157
    @Test
163
    @Test
158
    public void test58616() throws IOException, GeneralSecurityException {
164
    public void test58616() throws IOException, GeneralSecurityException {
159
        POIFSFileSystem pfs = new POIFSFileSystem(new FileInputStream(XSSFTestDataSamples.getSampleFile("58616.xlsx")));                
165
        FileInputStream fis = new FileInputStream(XSSFTestDataSamples.getSampleFile("58616.xlsx"));
166
        POIFSFileSystem pfs = new POIFSFileSystem(fis);
160
        EncryptionInfo info = new EncryptionInfo(pfs);             
167
        EncryptionInfo info = new EncryptionInfo(pfs);             
161
        Decryptor dec = Decryptor.getInstance(info);   
168
        Decryptor dec = Decryptor.getInstance(info);   
162
        //dec.verifyPassword(null);
169
        //dec.verifyPassword(null);
163
        dec.getDataStream(pfs);
170
        dec.getDataStream(pfs);
171
        pfs.close();
172
        fis.close();
164
    }
173
    }
165
}
174
}
(-)src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java (-9 / +17 lines)
Lines 42-51 Link Here
42
import org.apache.poi.poifs.filesystem.Entry;
42
import org.apache.poi.poifs.filesystem.Entry;
43
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
43
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
44
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
44
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
45
import org.apache.poi.util.BoundedInputStream;
46
import org.apache.poi.util.IOUtils;
45
import org.apache.poi.util.IOUtils;
47
import org.apache.poi.util.TempFile;
46
import org.apache.poi.util.TempFile;
48
import org.apache.poi.xwpf.usermodel.XWPFDocument;
47
import org.apache.poi.xwpf.usermodel.XWPFDocument;
48
import org.bouncycastle.util.Arrays;
49
import org.junit.Assume;
49
import org.junit.Assume;
50
import org.junit.Ignore;
50
import org.junit.Ignore;
51
import org.junit.Test;
51
import org.junit.Test;
Lines 112-120 Link Here
112
        assertEquals(decPackLenExpected, payloadExpected.length);
112
        assertEquals(decPackLenExpected, payloadExpected.length);
113
113
114
        is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY);
114
        is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY);
115
        is = new BoundedInputStream(is, is.available()-16); // ignore padding block
116
        byte encPackExpected[] = IOUtils.toByteArray(is);
115
        byte encPackExpected[] = IOUtils.toByteArray(is);
117
        is.close();
116
        is.close();
117
        // ignore padding block
118
        encPackExpected = Arrays.copyOf(encPackExpected, encPackExpected.length-16);
118
        
119
        
119
        // listDir(nfs.getRoot(), "orig", "");
120
        // listDir(nfs.getRoot(), "orig", "");
120
        
121
        
Lines 149-154 Link Here
149
150
150
        ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
151
        ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
151
        fs.writeFilesystem(bos);
152
        fs.writeFilesystem(bos);
153
        fs.close();
152
        
154
        
153
        nfs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
155
        nfs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
154
        infoActual = new EncryptionInfo(nfs.getRoot());
156
        infoActual = new EncryptionInfo(nfs.getRoot());
Lines 164-171 Link Here
164
        long decPackLenActual = decActual.getLength();
166
        long decPackLenActual = decActual.getLength();
165
        
167
        
166
        is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY);
168
        is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY);
167
        is = new BoundedInputStream(is, is.available()-16); // ignore padding block
168
        byte encPackActual[] = IOUtils.toByteArray(is);
169
        byte encPackActual[] = IOUtils.toByteArray(is);
170
        // ignore padding block
171
        encPackActual = Arrays.copyOf(encPackActual, encPackActual.length-16);
169
        is.close();
172
        is.close();
170
        
173
        
171
        // listDir(nfs.getRoot(), "copy", "");
174
        // listDir(nfs.getRoot(), "copy", "");
Lines 245-258 Link Here
245
        
248
        
246
        bos.reset();
249
        bos.reset();
247
        fs.writeFilesystem(bos);
250
        fs.writeFilesystem(bos);
251
        fs.close();
248
252
249
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
253
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
250
        
254
        
251
        // FileOutputStream fos = new FileOutputStream("encrypted.docx");
252
        // IOUtils.copy(bis, fos);
253
        // fos.close();
254
        // bis.reset();
255
        
256
        nfs = new NPOIFSFileSystem(bis);
255
        nfs = new NPOIFSFileSystem(bis);
257
        infoExpected = new EncryptionInfo(nfs);
256
        infoExpected = new EncryptionInfo(nfs);
258
        d = Decryptor.getInstance(infoExpected);
257
        d = Decryptor.getInstance(infoExpected);
Lines 279-284 Link Here
279
    public void encryptPackageWithoutCoreProperties() throws Exception {
278
    public void encryptPackageWithoutCoreProperties() throws Exception {
280
        // Open our file without core properties
279
        // Open our file without core properties
281
        File inp = POIDataSamples.getOpenXML4JInstance().getFile("OPCCompliance_NoCoreProperties.xlsx");
280
        File inp = POIDataSamples.getOpenXML4JInstance().getFile("OPCCompliance_NoCoreProperties.xlsx");
281
        @SuppressWarnings("resource")
282
        OPCPackage pkg = OPCPackage.open(inp.getPath());
282
        OPCPackage pkg = OPCPackage.open(inp.getPath());
283
        
283
        
284
        // It doesn't have any core properties yet
284
        // It doesn't have any core properties yet
Lines 295-305 Link Here
295
        enc.confirmPassword("password");
295
        enc.confirmPassword("password");
296
        OutputStream os = enc.getDataStream(fs);
296
        OutputStream os = enc.getDataStream(fs);
297
        pkg.save(os);
297
        pkg.save(os);
298
        os.close();
298
        pkg.revert();
299
        pkg.revert();
299
        
300
        
300
        // Save the resulting OLE2 document, and re-open it
301
        // Save the resulting OLE2 document, and re-open it
301
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
302
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
302
        fs.writeFilesystem(baos);
303
        fs.writeFilesystem(baos);
304
        fs.close();
303
        
305
        
304
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
306
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
305
        NPOIFSFileSystem inpFS = new NPOIFSFileSystem(bais);
307
        NPOIFSFileSystem inpFS = new NPOIFSFileSystem(bais);
Lines 316-321 Link Here
316
        assertNotNull(inpPkg.getPackageProperties());
318
        assertNotNull(inpPkg.getPackageProperties());
317
        assertNotNull(inpPkg.getPackageProperties().getLanguageProperty());
319
        assertNotNull(inpPkg.getPackageProperties().getLanguageProperty());
318
        assertNull(inpPkg.getPackageProperties().getLanguageProperty().getValue());
320
        assertNull(inpPkg.getPackageProperties().getLanguageProperty().getValue());
321
        
322
        inpPkg.close();
323
        inpFS.close();
319
    }
324
    }
320
    
325
    
321
    @Test
326
    @Test
Lines 338-344 Link Here
338
        assertTrue(b);
343
        assertTrue(b);
339
344
340
        // do some strange things with it ;)
345
        // do some strange things with it ;)
341
        XWPFDocument docx = new XWPFDocument(d.getDataStream(fs));
346
        InputStream docIS = d.getDataStream(fs);
347
        XWPFDocument docx = new XWPFDocument(docIS);
342
        docx.getParagraphArray(0).insertNewRun(0).setText("POI was here! All your base are belong to us!");
348
        docx.getParagraphArray(0).insertNewRun(0).setText("POI was here! All your base are belong to us!");
343
        docx.getParagraphArray(0).insertNewRun(1).addBreak();
349
        docx.getParagraphArray(0).insertNewRun(1).addBreak();
344
350
Lines 346-351 Link Here
346
        Encryptor e = encInfo.getEncryptor();
352
        Encryptor e = encInfo.getEncryptor();
347
        e.confirmPassword("AYBABTU");
353
        e.confirmPassword("AYBABTU");
348
        docx.write(e.getDataStream(fs));
354
        docx.write(e.getDataStream(fs));
355
        docx.close();
356
        docIS.close();
349
        
357
        
350
        fs.close();
358
        fs.close();
351
    }
359
    }
(-)src/resources/devtools/forbidden-signatures.txt (+3 lines)
Lines 109-111 Link Here
109
109
110
@defaultMessage Don't interrupt threads use FutureUtils#cancel(Future<T>) instead
110
@defaultMessage Don't interrupt threads use FutureUtils#cancel(Future<T>) instead
111
java.util.concurrent.Future#cancel(boolean)
111
java.util.concurrent.Future#cancel(boolean)
112
113
@defaultMessage Don't use ...InputStream.available() as it gives wrong result for certain streams - use IOUtils.toByteArray to read the stream fully and then count the available bytes 
114
java.io.InputStream#available() 
(-)src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java (-33 / +43 lines)
Lines 53-92 Link Here
53
        placeableHeader = HwmfPlaceableHeader.readHeader(leis);
53
        placeableHeader = HwmfPlaceableHeader.readHeader(leis);
54
        header = new HwmfHeader(leis);
54
        header = new HwmfHeader(leis);
55
        
55
        
56
        for (;;) {
56
        try {
57
            if (leis.available() < 6) {
57
            for (;;) {
58
                logger.log(POILogger.ERROR, "unexpected eof - wmf file was truncated");
58
                long recordSize;
59
                break;
59
                int recordFunction;
60
            }
60
                try {
61
            // recordSize in DWORDs
61
                    // recordSize in DWORDs
62
            long recordSize = leis.readUInt()*2;
62
                    recordSize = leis.readUInt()*2;
63
            int recordFunction = leis.readShort();
63
                    recordFunction = leis.readShort();
64
            // 4 bytes (recordSize) + 2 bytes (recordFunction)
64
                } catch (Exception e) {
65
            int consumedSize = 6;
65
                    logger.log(POILogger.ERROR, "unexpected eof - wmf file was truncated");
66
            HwmfRecordType wrt = HwmfRecordType.getById(recordFunction);
66
                    break;
67
            if (wrt == null) {
67
                }
68
                throw new IOException("unexpected record type: "+recordFunction);
68
                // 4 bytes (recordSize) + 2 bytes (recordFunction)
69
            }
69
                int consumedSize = 6;
70
            if (wrt == HwmfRecordType.eof) break;
70
                HwmfRecordType wrt = HwmfRecordType.getById(recordFunction);
71
            if (wrt.clazz == null) {
71
                if (wrt == null) {
72
                throw new IOException("unsupported record type: "+recordFunction);
72
                    throw new IOException("unexpected record type: "+recordFunction);
73
            }
73
                }
74
            
74
                if (wrt == HwmfRecordType.eof) {
75
            HwmfRecord wr;
75
                    break;
76
            try {
76
                }
77
                wr = wrt.clazz.newInstance();
77
                if (wrt.clazz == null) {
78
                records.add(wr);
78
                    throw new IOException("unsupported record type: "+recordFunction);
79
            } catch (Exception e) {
79
                }
80
                throw (IOException)new IOException("can't create wmf record").initCause(e);
80
                
81
            }
81
                HwmfRecord wr;
82
            
82
                try {
83
            consumedSize += wr.init(leis, recordSize, recordFunction);
83
                    wr = wrt.clazz.newInstance();
84
            int remainingSize = (int)(recordSize - consumedSize);
84
                    records.add(wr);
85
            assert(remainingSize >= 0);
85
                } catch (Exception e) {
86
            if (remainingSize > 0) {
86
                    throw (IOException)new IOException("can't create wmf record").initCause(e);
87
            	// skip size in loops, because not always all bytes are skipped in one call 
87
                }
88
                for (int i=remainingSize; i>0; i-=leis.skip(i));
88
                
89
                consumedSize += wr.init(leis, recordSize, recordFunction);
90
                int remainingSize = (int)(recordSize - consumedSize);
91
                assert(remainingSize >= 0);
92
                if (remainingSize > 0) {
93
                	// skip size in loops, because not always all bytes are skipped in one call 
94
                    for (int i=remainingSize; i>0; i-=leis.skip(i));
95
                }
89
            }
96
            }
97
        } finally {
98
            leis.close();
99
            bis.close();
90
        }
100
        }
91
    }
101
    }
92
102
(-)src/testcases/org/apache/poi/hssf/record/TestObjRecord.java (-7 / +11 lines)
Lines 18-38 Link Here
18
package org.apache.poi.hssf.record;
18
package org.apache.poi.hssf.record;
19
19
20
import static org.junit.Assert.assertArrayEquals;
20
import static org.junit.Assert.assertArrayEquals;
21
import static org.junit.Assert.assertEquals;
22
import static org.junit.Assert.assertTrue;
23
import static org.junit.Assert.fail;
21
24
22
import java.util.List;
25
import java.util.List;
23
26
24
import junit.framework.AssertionFailedError;
25
import junit.framework.TestCase;
26
27
import org.apache.poi.util.HexRead;
27
import org.apache.poi.util.HexRead;
28
import org.junit.Test;
28
29
29
/**
30
/**
30
 * Tests the serialization and deserialization of the ObjRecord class works correctly.
31
 * Tests the serialization and deserialization of the ObjRecord class works correctly.
31
 * Test data taken directly from a real Excel file.
32
 * Test data taken directly from a real Excel file.
32
 *
33
 * @author Yegor Kozlov
34
 */
33
 */
35
public final class TestObjRecord extends TestCase {
34
public final class TestObjRecord {
36
    /**
35
    /**
37
     * OBJ record data containing two sub-records.
36
     * OBJ record data containing two sub-records.
38
     * The data taken directly from a real Excel file.
37
     * The data taken directly from a real Excel file.
Lines 58-63 Link Here
58
            + "15 00 12 00 00 00 01 00 11 60 00 00 00 00 38 6F CC 03 00 00 00 00 06 00 02 00 00 00 00 00 00 00"
57
            + "15 00 12 00 00 00 01 00 11 60 00 00 00 00 38 6F CC 03 00 00 00 00 06 00 02 00 00 00 00 00 00 00"
59
    );
58
    );
60
59
60
    @Test
61
    public void testLoad() {
61
    public void testLoad() {
62
        ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata));
62
        ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata));
63
63
Lines 70-75 Link Here
70
70
71
    }
71
    }
72
72
73
    @Test
73
    public void testStore() {
74
    public void testStore() {
74
        ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata));
75
        ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata));
75
76
Lines 80-85 Link Here
80
        assertArrayEquals(recdata, subData);
81
        assertArrayEquals(recdata, subData);
81
    }
82
    }
82
83
84
    @Test
83
    public void testConstruct() {
85
    public void testConstruct() {
84
        ObjRecord record = new ObjRecord();
86
        ObjRecord record = new ObjRecord();
85
        CommonObjectDataSubRecord ftCmo = new CommonObjectDataSubRecord();
87
        CommonObjectDataSubRecord ftCmo = new CommonObjectDataSubRecord();
Lines 106-116 Link Here
106
        assertTrue( subrecords.get(1) instanceof EndSubRecord );
108
        assertTrue( subrecords.get(1) instanceof EndSubRecord );
107
    }
109
    }
108
    
110
    
111
    @Test
109
    public void testReadWriteWithPadding_bug45133() {
112
    public void testReadWriteWithPadding_bug45133() {
110
        ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(recdataNeedingPadding));
113
        ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(recdataNeedingPadding));
111
        
114
        
112
        if (record.getRecordSize() == 34) {
115
        if (record.getRecordSize() == 34) {
113
            throw new AssertionFailedError("Identified bug 45133");
116
            fail("Identified bug 45133");
114
        }
117
        }
115
118
116
        assertEquals(36, record.getRecordSize());
119
        assertEquals(36, record.getRecordSize());
Lines 126-131 Link Here
126
     * Check that ObjRecord tolerates and preserves padding to a 4-byte boundary
129
     * Check that ObjRecord tolerates and preserves padding to a 4-byte boundary
127
     * (normally padding is to a 2-byte boundary).
130
     * (normally padding is to a 2-byte boundary).
128
     */
131
     */
132
    @Test
129
    public void test4BytePadding() {
133
    public void test4BytePadding() {
130
        // actual data from file saved by Excel 2007
134
        // actual data from file saved by Excel 2007
131
        byte[] data = HexRead.readFromString(""
135
        byte[] data = HexRead.readFromString(""
(-)src/testcases/org/apache/poi/poifs/filesystem/ReaderWriter.java (-8 / +12 lines)
Lines 29-34 Link Here
29
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
29
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
30
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
30
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
31
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
31
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
32
import org.apache.poi.util.IOUtils;
32
33
33
/**
34
/**
34
 * Test (Proof of concept) program that employs the
35
 * Test (Proof of concept) program that employs the
Lines 40-50 Link Here
40
public class ReaderWriter
41
public class ReaderWriter
41
    implements POIFSReaderListener, POIFSWriterListener
42
    implements POIFSReaderListener, POIFSWriterListener
42
{
43
{
43
    private POIFSFileSystem filesystem;
44
    private final POIFSFileSystem filesystem;
44
    private DirectoryEntry  root;
45
    private final DirectoryEntry  root;
45
46
46
    // keys are DocumentDescriptors, values are byte[]s
47
    // keys are DocumentDescriptors, values are byte[]s
47
    private Map<DocumentDescriptor, byte[]>             dataMap;
48
    private final Map<DocumentDescriptor, byte[]>             dataMap;
48
49
49
    /**
50
    /**
50
     * Constructor ReaderWriter
51
     * Constructor ReaderWriter
Lines 93-98 Link Here
93
94
94
            filesystem.writeFilesystem(ostream);
95
            filesystem.writeFilesystem(ostream);
95
            ostream.close();
96
            ostream.close();
97
            
98
            filesystem.close();
96
        }
99
        }
97
    }
100
    }
98
101
Lines 105-122 Link Here
105
     * @param event the POIFSReaderEvent
108
     * @param event the POIFSReaderEvent
106
     */
109
     */
107
110
111
    @Override
108
    public void processPOIFSReaderEvent(final POIFSReaderEvent event)
112
    public void processPOIFSReaderEvent(final POIFSReaderEvent event)
109
    {
113
    {
114
        @SuppressWarnings("resource")
110
        DocumentInputStream istream = event.getStream();
115
        DocumentInputStream istream = event.getStream();
111
        POIFSDocumentPath   path    = event.getPath();
116
        POIFSDocumentPath   path    = event.getPath();
112
        String              name    = event.getName();
117
        String              name    = event.getName();
113
118
114
        try
119
        try {
115
        {
120
            byte[] data = IOUtils.toByteArray(istream);
116
            int    size = istream.available();
121
            int    size = data.length;
117
            byte[] data = new byte[ istream.available() ];
118
122
119
            istream.read(data);
120
            DocumentDescriptor descriptor = new DocumentDescriptor(path,
123
            DocumentDescriptor descriptor = new DocumentDescriptor(path,
121
                                                name);
124
                                                name);
122
125
Lines 167-172 Link Here
167
     * @param event the POIFSWriterEvent
170
     * @param event the POIFSWriterEvent
168
     */
171
     */
169
172
173
    @Override
170
    public void processPOIFSWriterEvent(final POIFSWriterEvent event)
174
    public void processPOIFSWriterEvent(final POIFSWriterEvent event)
171
    {
175
    {
172
        try
176
        try
(-)src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java (-42 / +61 lines)
Lines 17-38 Link Here
17
17
18
package org.apache.poi.poifs.filesystem;
18
package org.apache.poi.poifs.filesystem;
19
19
20
import static org.junit.Assert.assertEquals;
21
import static org.junit.Assert.assertTrue;
22
import static org.junit.Assert.fail;
23
20
import java.io.ByteArrayInputStream;
24
import java.io.ByteArrayInputStream;
21
import java.io.File;
25
import java.io.File;
22
import java.io.FileInputStream;
26
import java.io.FileInputStream;
23
import java.io.IOException;
27
import java.io.IOException;
28
import java.io.InputStream;
24
import java.util.Arrays;
29
import java.util.Arrays;
25
30
26
import junit.framework.TestCase;
27
28
import org.apache.poi.POIDataSamples;
31
import org.apache.poi.POIDataSamples;
29
import org.apache.poi.poifs.property.DirectoryProperty;
32
import org.apache.poi.poifs.property.DirectoryProperty;
30
import org.apache.poi.poifs.storage.RawDataBlock;
33
import org.apache.poi.poifs.storage.RawDataBlock;
34
import org.apache.poi.util.SuppressForbidden;
35
import org.junit.Before;
36
import org.junit.Test;
31
37
32
/**
38
/**
33
 * Class to test DocumentInputStream functionality
39
 * Class to test DocumentInputStream functionality
34
 */
40
 */
35
public final class TestDocumentInputStream extends TestCase {
41
public final class TestDocumentInputStream {
36
   private DocumentNode     _workbook_n;
42
   private DocumentNode     _workbook_n;
37
   private DocumentNode     _workbook_o;
43
   private DocumentNode     _workbook_o;
38
   private byte[]           _workbook_data;
44
   private byte[]           _workbook_data;
Lines 42-48 Link Here
42
   // any block size
48
   // any block size
43
   private static final int _buffer_size   = 6;
49
   private static final int _buffer_size   = 6;
44
50
45
	protected void setUp() throws Exception {
51
   @Before
52
   public void setUp() throws Exception {
46
        int blocks = (_workbook_size + 511) / 512;
53
        int blocks = (_workbook_size + 511) / 512;
47
54
48
        _workbook_data = new byte[ 512 * blocks ];
55
        _workbook_data = new byte[ 512 * blocks ];
Lines 91-96 Link Here
91
	/**
98
	/**
92
     * test constructor
99
     * test constructor
93
     */
100
     */
101
    @Test
94
    public void testConstructor() throws IOException {
102
    public void testConstructor() throws IOException {
95
        DocumentInputStream ostream = new ODocumentInputStream(_workbook_o);
103
        DocumentInputStream ostream = new ODocumentInputStream(_workbook_o);
96
        DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
104
        DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
Lines 98-105 Link Here
98
        assertEquals(_workbook_size, _workbook_o.getSize());
106
        assertEquals(_workbook_size, _workbook_o.getSize());
99
        assertEquals(_workbook_size, _workbook_n.getSize());
107
        assertEquals(_workbook_size, _workbook_n.getSize());
100
108
101
        assertEquals(_workbook_size, ostream.available());
109
        assertEquals(_workbook_size, available(ostream));
102
        assertEquals(_workbook_size, nstream.available());
110
        assertEquals(_workbook_size, available(nstream));
103
        
111
        
104
        ostream.close();
112
        ostream.close();
105
        nstream.close();
113
        nstream.close();
Lines 108-130 Link Here
108
    /**
116
    /**
109
     * test available() behavior
117
     * test available() behavior
110
     */
118
     */
119
    @Test
111
    public void testAvailable() throws IOException {
120
    public void testAvailable() throws IOException {
112
        DocumentInputStream ostream = new DocumentInputStream(_workbook_o);
121
        DocumentInputStream ostream = new DocumentInputStream(_workbook_o);
113
        DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
122
        DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
114
123
115
        assertEquals(_workbook_size, ostream.available());
124
        assertEquals(_workbook_size, available(ostream));
116
        assertEquals(_workbook_size, nstream.available());
125
        assertEquals(_workbook_size, available(nstream));
117
        ostream.close();
126
        ostream.close();
118
        nstream.close();
127
        nstream.close();
119
        
128
        
120
        try {
129
        try {
121
           ostream.available();
130
           available(ostream);
122
           fail("Should have caught IOException");
131
           fail("Should have caught IOException");
123
        } catch (IllegalStateException ignored) {
132
        } catch (IllegalStateException ignored) {
124
           // as expected
133
           // as expected
125
        }
134
        }
126
        try {
135
        try {
127
           nstream.available();
136
           available(nstream);
128
           fail("Should have caught IOException");
137
           fail("Should have caught IOException");
129
       } catch (IllegalStateException ignored) {
138
       } catch (IllegalStateException ignored) {
130
           // as expected
139
           // as expected
Lines 134-139 Link Here
134
    /**
143
    /**
135
     * test mark/reset/markSupported.
144
     * test mark/reset/markSupported.
136
     */
145
     */
146
    @Test
137
    public void testMarkFunctions() throws IOException {
147
    public void testMarkFunctions() throws IOException {
138
        byte[] buffer = new byte[ _workbook_size / 5 ];
148
        byte[] buffer = new byte[ _workbook_size / 5 ];
139
        byte[] small_buffer = new byte[212];
149
        byte[] small_buffer = new byte[212];
Lines 151-162 Link Here
151
                    _workbook_data[ j ], buffer[ j ]
161
                    _workbook_data[ j ], buffer[ j ]
152
              );
162
              );
153
           }
163
           }
154
           assertEquals(_workbook_size - buffer.length, stream.available());
164
           assertEquals(_workbook_size - buffer.length, available(stream));
155
           
165
           
156
           // Reset, and check the available goes back to being the
166
           // Reset, and check the available goes back to being the
157
           //  whole of the stream
167
           //  whole of the stream
158
           stream.reset();
168
           stream.reset();
159
           assertEquals(_workbook_size, stream.available());
169
           assertEquals(_workbook_size, available(stream));
160
           
170
           
161
           
171
           
162
           // Read part of a block
172
           // Read part of a block
Lines 167-173 Link Here
167
                    _workbook_data[ j ], small_buffer[ j ]
177
                    _workbook_data[ j ], small_buffer[ j ]
168
              );
178
              );
169
           }
179
           }
170
           assertEquals(_workbook_size - small_buffer.length, stream.available());
180
           assertEquals(_workbook_size - small_buffer.length, available(stream));
171
           stream.mark(0);
181
           stream.mark(0);
172
           
182
           
173
           // Read the next part
183
           // Read the next part
Lines 178-188 Link Here
178
                    _workbook_data[ j+small_buffer.length ], small_buffer[ j ]
188
                    _workbook_data[ j+small_buffer.length ], small_buffer[ j ]
179
              );
189
              );
180
           }
190
           }
181
           assertEquals(_workbook_size - 2*small_buffer.length, stream.available());
191
           assertEquals(_workbook_size - 2*small_buffer.length, available(stream));
182
           
192
           
183
           // Reset, check it goes back to where it was
193
           // Reset, check it goes back to where it was
184
           stream.reset();
194
           stream.reset();
185
           assertEquals(_workbook_size - small_buffer.length, stream.available());
195
           assertEquals(_workbook_size - small_buffer.length, available(stream));
186
           
196
           
187
           // Read 
197
           // Read 
188
           stream.read(small_buffer);
198
           stream.read(small_buffer);
Lines 192-198 Link Here
192
                    _workbook_data[ j+small_buffer.length ], small_buffer[ j ]
202
                    _workbook_data[ j+small_buffer.length ], small_buffer[ j ]
193
              );
203
              );
194
           }
204
           }
195
           assertEquals(_workbook_size - 2*small_buffer.length, stream.available());
205
           assertEquals(_workbook_size - 2*small_buffer.length, available(stream));
196
           
206
           
197
           
207
           
198
           // Now read at various points
208
           // Now read at various points
Lines 235-245 Link Here
235
                    _workbook_data[ j ], buffer[ j ]
245
                    _workbook_data[ j ], buffer[ j ]
236
              );
246
              );
237
           }
247
           }
238
           assertEquals(_workbook_size - buffer.length, stream.available());
248
           assertEquals(_workbook_size - buffer.length, available(stream));
239
           
249
           
240
           // Read all of it again, check it began at the start again
250
           // Read all of it again, check it began at the start again
241
           stream.reset();
251
           stream.reset();
242
           assertEquals(_workbook_size, stream.available());
252
           assertEquals(_workbook_size, available(stream));
243
           
253
           
244
           stream.read(buffer);
254
           stream.read(buffer);
245
           for (int j = 0; j < buffer.length; j++) {
255
           for (int j = 0; j < buffer.length; j++) {
Lines 253-259 Link Here
253
           stream.mark(12);
263
           stream.mark(12);
254
           stream.read(buffer);
264
           stream.read(buffer);
255
           assertEquals(_workbook_size - (2 * buffer.length),
265
           assertEquals(_workbook_size - (2 * buffer.length),
256
                 stream.available());
266
                 available(stream));
257
           for (int j = buffer.length; j < (2 * buffer.length); j++)
267
           for (int j = buffer.length; j < (2 * buffer.length); j++)
258
           {
268
           {
259
              assertEquals("checking byte " + j, _workbook_data[ j ],
269
              assertEquals("checking byte " + j, _workbook_data[ j ],
Lines 262-273 Link Here
262
           
272
           
263
           // Reset, should go back to only one buffer full read
273
           // Reset, should go back to only one buffer full read
264
           stream.reset();
274
           stream.reset();
265
           assertEquals(_workbook_size - buffer.length, stream.available());
275
           assertEquals(_workbook_size - buffer.length, available(stream));
266
           
276
           
267
           // Read the buffer again
277
           // Read the buffer again
268
           stream.read(buffer);
278
           stream.read(buffer);
269
           assertEquals(_workbook_size - (2 * buffer.length),
279
           assertEquals(_workbook_size - (2 * buffer.length),
270
                 stream.available());
280
                 available(stream));
271
           for (int j = buffer.length; j < (2 * buffer.length); j++)
281
           for (int j = buffer.length; j < (2 * buffer.length); j++)
272
           {
282
           {
273
              assertEquals("checking byte " + j, _workbook_data[ j ],
283
              assertEquals("checking byte " + j, _workbook_data[ j ],
Lines 280-285 Link Here
280
    /**
290
    /**
281
     * test simple read method
291
     * test simple read method
282
     */
292
     */
293
    @Test
283
    public void testReadSingleByte() throws IOException {
294
    public void testReadSingleByte() throws IOException {
284
       DocumentInputStream[] streams = new DocumentInputStream[] {
295
       DocumentInputStream[] streams = new DocumentInputStream[] {
285
             new DocumentInputStream(_workbook_o),
296
             new DocumentInputStream(_workbook_o),
Lines 296-302 Link Here
296
                   ( byte ) b);
307
                   ( byte ) b);
297
             remaining--;
308
             remaining--;
298
             assertEquals("checking remaining after reading byte " + j,
309
             assertEquals("checking remaining after reading byte " + j,
299
                   remaining, stream.available());
310
                   remaining, available(stream));
300
          }
311
          }
301
          
312
          
302
          // Ensure we fell off the end
313
          // Ensure we fell off the end
Lines 316-321 Link Here
316
    /**
327
    /**
317
     * Test buffered read
328
     * Test buffered read
318
     */
329
     */
330
    @Test
319
    public void testBufferRead() throws IOException {
331
    public void testBufferRead() throws IOException {
320
       DocumentInputStream[] streams = new DocumentInputStream[] {
332
       DocumentInputStream[] streams = new DocumentInputStream[] {
321
             new DocumentInputStream(_workbook_o),
333
             new DocumentInputStream(_workbook_o),
Lines 332-354 Link Here
332
344
333
          // test reading zero length buffer
345
          // test reading zero length buffer
334
          assertEquals(0, stream.read(new byte[ 0 ]));
346
          assertEquals(0, stream.read(new byte[ 0 ]));
335
          assertEquals(_workbook_size, stream.available());
347
          assertEquals(_workbook_size, available(stream));
336
          byte[] buffer = new byte[ _buffer_size ];
348
          byte[] buffer = new byte[ _buffer_size ];
337
          int    offset = 0;
349
          int    offset = 0;
338
350
339
          while (stream.available() >= buffer.length)
351
          while (available(stream) >= buffer.length)
340
          {
352
          {
341
             assertEquals(_buffer_size, stream.read(buffer));
353
             assertEquals(_buffer_size, stream.read(buffer));
342
             for (int j = 0; j < buffer.length; j++)
354
             for (byte element : buffer) {
343
             {
344
                assertEquals("in main loop, byte " + offset,
355
                assertEquals("in main loop, byte " + offset,
345
                      _workbook_data[ offset ], buffer[ j ]);
356
                      _workbook_data[ offset ], element);
346
                offset++;
357
                offset++;
347
             }
358
             }
348
             assertEquals("offset " + offset, _workbook_size - offset,
359
             assertEquals("offset " + offset, _workbook_size - offset,
349
                   stream.available());
360
                   available(stream));
350
          }
361
          }
351
          assertEquals(_workbook_size % _buffer_size, stream.available());
362
          assertEquals(_workbook_size % _buffer_size, available(stream));
352
          Arrays.fill(buffer, ( byte ) 0);
363
          Arrays.fill(buffer, ( byte ) 0);
353
          int count = stream.read(buffer);
364
          int count = stream.read(buffer);
354
365
Lines 378-383 Link Here
378
    /**
389
    /**
379
     * Test complex buffered read
390
     * Test complex buffered read
380
     */
391
     */
392
    @Test
381
    public void testComplexBufferRead() throws IOException {
393
    public void testComplexBufferRead() throws IOException {
382
       DocumentInputStream[] streams = new DocumentInputStream[] {
394
       DocumentInputStream[] streams = new DocumentInputStream[] {
383
             new DocumentInputStream(_workbook_o),
395
             new DocumentInputStream(_workbook_o),
Lines 413-423 Link Here
413
425
414
          // test reading zero
426
          // test reading zero
415
          assertEquals(0, stream.read(new byte[ 5 ], 0, 0));
427
          assertEquals(0, stream.read(new byte[ 5 ], 0, 0));
416
          assertEquals(_workbook_size, stream.available());
428
          assertEquals(_workbook_size, available(stream));
417
          byte[] buffer = new byte[ _workbook_size ];
429
          byte[] buffer = new byte[ _workbook_size ];
418
          int    offset = 0;
430
          int    offset = 0;
419
431
420
          while (stream.available() >= _buffer_size)
432
          while (available(stream) >= _buffer_size)
421
          {
433
          {
422
             Arrays.fill(buffer, ( byte ) 0);
434
             Arrays.fill(buffer, ( byte ) 0);
423
             assertEquals(_buffer_size,
435
             assertEquals(_buffer_size,
Lines 437-445 Link Here
437
             }
449
             }
438
             offset += _buffer_size;
450
             offset += _buffer_size;
439
             assertEquals("offset " + offset, _workbook_size - offset,
451
             assertEquals("offset " + offset, _workbook_size - offset,
440
                   stream.available());
452
                   available(stream));
441
          }
453
          }
442
          assertEquals(_workbook_size % _buffer_size, stream.available());
454
          assertEquals(_workbook_size % _buffer_size, available(stream));
443
          Arrays.fill(buffer, ( byte ) 0);
455
          Arrays.fill(buffer, ( byte ) 0);
444
          int count = stream.read(buffer, offset,
456
          int count = stream.read(buffer, offset,
445
                _workbook_size % _buffer_size);
457
                _workbook_size % _buffer_size);
Lines 474-511 Link Here
474
    /**
486
    /**
475
     * Tests that we can skip within the stream
487
     * Tests that we can skip within the stream
476
     */
488
     */
489
    @Test
477
    public void testSkip() throws IOException {
490
    public void testSkip() throws IOException {
478
       DocumentInputStream[] streams = new DocumentInputStream[] {
491
       DocumentInputStream[] streams = new DocumentInputStream[] {
479
             new DocumentInputStream(_workbook_o),
492
             new DocumentInputStream(_workbook_o),
480
             new NDocumentInputStream(_workbook_n)
493
             new NDocumentInputStream(_workbook_n)
481
       };
494
       };
482
       for(DocumentInputStream stream : streams) {
495
       for(DocumentInputStream stream : streams) {
483
          assertEquals(_workbook_size, stream.available());
496
          assertEquals(_workbook_size, available(stream));
484
          int count = stream.available();
497
          int count = available(stream);
485
498
486
          while (stream.available() >= _buffer_size) {
499
          while (available(stream) >= _buffer_size) {
487
             assertEquals(_buffer_size, stream.skip(_buffer_size));
500
             assertEquals(_buffer_size, stream.skip(_buffer_size));
488
             count -= _buffer_size;
501
             count -= _buffer_size;
489
             assertEquals(count, stream.available());
502
             assertEquals(count, available(stream));
490
          }
503
          }
491
          assertEquals(_workbook_size % _buffer_size,
504
          assertEquals(_workbook_size % _buffer_size,
492
                stream.skip(_buffer_size));
505
                stream.skip(_buffer_size));
493
          assertEquals(0, stream.available());
506
          assertEquals(0, available(stream));
494
          stream.reset();
507
          stream.reset();
495
          assertEquals(_workbook_size, stream.available());
508
          assertEquals(_workbook_size, available(stream));
496
          assertEquals(_workbook_size, stream.skip(_workbook_size * 2));
509
          assertEquals(_workbook_size, stream.skip(_workbook_size * 2));
497
          assertEquals(0, stream.available());
510
          assertEquals(0, available(stream));
498
          stream.reset();
511
          stream.reset();
499
          assertEquals(_workbook_size, stream.available());
512
          assertEquals(_workbook_size, available(stream));
500
          assertEquals(_workbook_size,
513
          assertEquals(_workbook_size,
501
                stream.skip(2 + ( long ) Integer.MAX_VALUE));
514
                stream.skip(2 + ( long ) Integer.MAX_VALUE));
502
          assertEquals(0, stream.available());
515
          assertEquals(0, available(stream));
503
       }
516
       }
504
    }
517
    }
505
    
518
    
506
    /**
519
    /**
507
     * Test that we can read files at multiple levels down the tree
520
     * Test that we can read files at multiple levels down the tree
508
     */
521
     */
522
    @Test
509
    public void testReadMultipleTreeLevels() throws Exception {
523
    public void testReadMultipleTreeLevels() throws Exception {
510
       final POIDataSamples _samples = POIDataSamples.getPublisherInstance();
524
       final POIDataSamples _samples = POIDataSamples.getPublisherInstance();
511
       File sample = _samples.getFile("Sample.pub");
525
       File sample = _samples.getFile("Sample.pub");
Lines 551-554 Link Here
551
           npoifs.close();
565
           npoifs.close();
552
       }
566
       }
553
    }
567
    }
568
569
    @SuppressForbidden("just for testing")
570
    private static int available(InputStream is) throws IOException {
571
        return is.available();
572
    }
554
}
573
}
(-)src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java (-11 / +13 lines)
Lines 23-30 Link Here
23
import java.io.InputStream;
23
import java.io.InputStream;
24
import java.nio.ByteBuffer;
24
import java.nio.ByteBuffer;
25
25
26
import junit.framework.TestCase;
27
28
import org.apache.poi.POIDataSamples;
26
import org.apache.poi.POIDataSamples;
29
import org.apache.poi.hssf.HSSFTestDataSamples;
27
import org.apache.poi.hssf.HSSFTestDataSamples;
30
import org.apache.poi.poifs.common.POIFSBigBlockSize;
28
import org.apache.poi.poifs.common.POIFSBigBlockSize;
Lines 33-44 Link Here
33
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
31
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
34
import org.apache.poi.poifs.storage.HeaderBlock;
32
import org.apache.poi.poifs.storage.HeaderBlock;
35
import org.apache.poi.poifs.storage.RawDataBlockList;
33
import org.apache.poi.poifs.storage.RawDataBlockList;
34
import org.apache.poi.util.IOUtils;
35
36
import junit.framework.TestCase;
36
37
37
/**
38
/**
38
 * Tests for the older OPOIFS-based POIFSFileSystem
39
 * Tests for the older OPOIFS-based POIFSFileSystem
39
 */
40
 */
40
public final class TestPOIFSFileSystem extends TestCase {
41
public final class TestPOIFSFileSystem extends TestCase {
41
   private POIDataSamples _samples = POIDataSamples.getPOIFSInstance();
42
   private final POIDataSamples _samples = POIDataSamples.getPOIFSInstance();
42
43
43
	/**
44
	/**
44
	 * Mock exception used to ensure correct error handling
45
	 * Mock exception used to ensure correct error handling
Lines 66-79 Link Here
66
			_isClosed = false;
67
			_isClosed = false;
67
		}
68
		}
68
69
69
		public int read() throws IOException {
70
		@Override
71
        public int read() throws IOException {
70
			int result = _is.read();
72
			int result = _is.read();
71
			if(result >=0) {
73
			if(result >=0) {
72
				checkRead(1);
74
				checkRead(1);
73
			}
75
			}
74
			return result;
76
			return result;
75
		}
77
		}
76
		public int read(byte[] b, int off, int len) throws IOException {
78
		@Override
79
        public int read(byte[] b, int off, int len) throws IOException {
77
			int result = _is.read(b, off, len);
80
			int result = _is.read(b, off, len);
78
			checkRead(result);
81
			checkRead(result);
79
			return result;
82
			return result;
Lines 85-91 Link Here
85
				throw new MyEx();
88
				throw new MyEx();
86
			}
89
			}
87
		}
90
		}
88
		public void close() throws IOException {
91
		@Override
92
        public void close() throws IOException {
89
			_isClosed = true;
93
			_isClosed = true;
90
			_is.close();
94
			_is.close();
91
		}
95
		}
Lines 139-148 Link Here
139
			"ShortLastBlock.qwp", "ShortLastBlock.wps"
143
			"ShortLastBlock.qwp", "ShortLastBlock.wps"
140
		};
144
		};
141
145
142
		for(int i=0; i<files.length; i++) {
146
		for (String file : files) {
143
			// Open the file up
147
			// Open the file up
144
			OPOIFSFileSystem fs = new OPOIFSFileSystem(
148
			OPOIFSFileSystem fs = new OPOIFSFileSystem(
145
			    _samples.openResourceAsStream(files[i])
149
			    _samples.openResourceAsStream(file)
146
			);
150
			);
147
151
148
			// Write it into a temp output array
152
			// Write it into a temp output array
Lines 284-292 Link Here
284
	         DocumentNode doc = (DocumentNode) entry;
288
	         DocumentNode doc = (DocumentNode) entry;
285
	         DocumentInputStream dis = new DocumentInputStream(doc);
289
	         DocumentInputStream dis = new DocumentInputStream(doc);
286
	         try {
290
	         try {
287
    	         int numBytes = dis.available();
291
    	         IOUtils.toByteArray(dis);
288
    	         byte[] data = new byte [numBytes];
289
                dis.read(data);
290
	         } finally {
292
	         } finally {
291
	             dis.close();
293
	             dis.close();
292
	         }
294
	         }
(-)src/testcases/org/apache/poi/util/TestLittleEndian.java (-36 / +64 lines)
Lines 17-41 Link Here
17
17
18
package org.apache.poi.util;
18
package org.apache.poi.util;
19
19
20
import junit.framework.TestCase;
20
import static org.junit.Assert.assertEquals;
21
import org.apache.poi.util.LittleEndian.BufferUnderrunException;
21
import static org.junit.Assert.assertTrue;
22
import static org.junit.Assert.fail;
22
23
23
import java.io.ByteArrayInputStream;
24
import java.io.ByteArrayInputStream;
24
import java.io.IOException;
25
import java.io.IOException;
25
import java.io.InputStream;
26
import java.io.InputStream;
26
27
28
import org.apache.poi.util.LittleEndian.BufferUnderrunException;
29
import org.junit.Test;
30
27
/**
31
/**
28
 * Class to test LittleEndian functionality
32
 * Class to test LittleEndian functionality
29
 *
30
 * @author Marc Johnson
31
 */
33
 */
32
public final class TestLittleEndian extends TestCase {
34
public final class TestLittleEndian {
33
35
34
    /**
36
    /**
35
     * test the getShort() method
37
     * test the getShort() method
36
     */
38
     */
39
    @Test
37
    public void testGetShort() {
40
    public void testGetShort() {
38
        byte[] testdata = new byte[ LittleEndian.SHORT_SIZE + 1 ];
41
        byte[] testdata = new byte[ LittleEndianConsts.SHORT_SIZE + 1 ];
39
42
40
        testdata[0] = 0x01;
43
        testdata[0] = 0x01;
41
        testdata[1] = (byte) 0xFF;
44
        testdata[1] = (byte) 0xFF;
Lines 48-53 Link Here
48
        assertEquals(expected[1], LittleEndian.getShort(testdata, 1));
51
        assertEquals(expected[1], LittleEndian.getShort(testdata, 1));
49
    }
52
    }
50
53
54
    @Test
51
    public void testGetUShort() {
55
    public void testGetUShort() {
52
        byte[] testdata = {
56
        byte[] testdata = {
53
            (byte) 0x01,
57
            (byte) 0x01,
Lines 69-75 Link Here
69
        assertEquals(expected2, LittleEndian.getUShort(testdata2));
73
        assertEquals(expected2, LittleEndian.getUShort(testdata2));
70
        assertEquals(expected3, LittleEndian.getUShort(testdata2, 1));
74
        assertEquals(expected3, LittleEndian.getUShort(testdata2, 1));
71
75
72
        byte[] testdata3 = new byte[ LittleEndian.SHORT_SIZE + 1 ];
76
        byte[] testdata3 = new byte[ LittleEndianConsts.SHORT_SIZE + 1 ];
73
        LittleEndian.putUShort(testdata3, 0, expected2);
77
        LittleEndian.putUShort(testdata3, 0, expected2);
74
        LittleEndian.putUShort(testdata3, 1, expected3);
78
        LittleEndian.putUShort(testdata3, 1, expected3);
75
        assertEquals(testdata3[0], 0x0D);
79
        assertEquals(testdata3[0], 0x0D);
Lines 94-102 Link Here
94
    /**
98
    /**
95
     * test the getDouble() method
99
     * test the getDouble() method
96
     */
100
     */
101
    @Test
97
    public void testGetDouble() {
102
    public void testGetDouble() {
98
        assertEquals(_doubles[0], LittleEndian.getDouble(_double_array, 0), 0.000001 );
103
        assertEquals(_doubles[0], LittleEndian.getDouble(_double_array, 0), 0.000001 );
99
        assertEquals(_doubles[1], LittleEndian.getDouble( _double_array, LittleEndian.DOUBLE_SIZE), 0.000001);
104
        assertEquals(_doubles[1], LittleEndian.getDouble( _double_array, LittleEndianConsts.DOUBLE_SIZE), 0.000001);
100
        assertTrue(Double.isNaN(LittleEndian.getDouble(_nan_double_array, 0)));
105
        assertTrue(Double.isNaN(LittleEndian.getDouble(_nan_double_array, 0)));
101
106
102
        double nan = LittleEndian.getDouble(_nan_double_array, 0);
107
        double nan = LittleEndian.getDouble(_nan_double_array, 0);
Lines 110-115 Link Here
110
    /**
115
    /**
111
     * test the getInt() method
116
     * test the getInt() method
112
     */
117
     */
118
    @Test
113
    public void testGetInt() {
119
    public void testGetInt() {
114
        // reading 4 byte data from a 5 byte buffer
120
        // reading 4 byte data from a 5 byte buffer
115
        byte[] testdata = {
121
        byte[] testdata = {
Lines 127-132 Link Here
127
    /**
133
    /**
128
     * test the getLong method
134
     * test the getLong method
129
     */
135
     */
136
    @Test
130
    public void testGetLong() {
137
    public void testGetLong() {
131
138
132
        // reading 8 byte values from a 9 byte buffer
139
        // reading 8 byte values from a 9 byte buffer
Lines 149-174 Link Here
149
    /**
156
    /**
150
     * test the PutShort method
157
     * test the PutShort method
151
     */
158
     */
159
    @Test
152
    public void testPutShort() {
160
    public void testPutShort() {
153
        byte[] expected = new byte[ LittleEndian.SHORT_SIZE + 1 ];
161
        byte[] expected = new byte[ LittleEndianConsts.SHORT_SIZE + 1 ];
154
162
155
        expected[0] = 0x01;
163
        expected[0] = 0x01;
156
        expected[1] = (byte) 0xFF;
164
        expected[1] = (byte) 0xFF;
157
        expected[2] = 0x02;
165
        expected[2] = 0x02;
158
        byte[] received   = new byte[ LittleEndian.SHORT_SIZE + 1 ];
166
        byte[] received   = new byte[ LittleEndianConsts.SHORT_SIZE + 1 ];
159
        short  testdata[] = new short[2];
167
        short  testdata[] = new short[2];
160
168
161
        testdata[0] = ( short ) 0xFF01;
169
        testdata[0] = ( short ) 0xFF01;
162
        testdata[1] = 0x02FF;
170
        testdata[1] = 0x02FF;
163
        LittleEndian.putShort(received, 0, testdata[0]);
171
        LittleEndian.putShort(received, 0, testdata[0]);
164
        assertTrue(compareByteArrays(received, expected, 0, LittleEndian.SHORT_SIZE));
172
        assertTrue(compareByteArrays(received, expected, 0, LittleEndianConsts.SHORT_SIZE));
165
        LittleEndian.putShort(received, 1, testdata[1]);
173
        LittleEndian.putShort(received, 1, testdata[1]);
166
        assertTrue(compareByteArrays(received, expected, 1, LittleEndian.SHORT_SIZE));
174
        assertTrue(compareByteArrays(received, expected, 1, LittleEndianConsts.SHORT_SIZE));
167
    }
175
    }
168
176
169
    /**
177
    /**
170
     * test the putInt method
178
     * test the putInt method
171
     */
179
     */
180
    @Test
172
    public void testPutInt() {
181
    public void testPutInt() {
173
        // writing 4 byte data to a 5 byte buffer
182
        // writing 4 byte data to a 5 byte buffer
174
        byte[] expected = {
183
        byte[] expected = {
Lines 178-210 Link Here
178
                (byte) 0xFF,
187
                (byte) 0xFF,
179
                (byte) 0x02,
188
                (byte) 0x02,
180
        };
189
        };
181
        byte[] received = new byte[ LittleEndian.INT_SIZE + 1 ];
190
        byte[] received = new byte[ LittleEndianConsts.INT_SIZE + 1 ];
182
191
183
        LittleEndian.putInt(received, 0, 0xFFFFFF01);
192
        LittleEndian.putInt(received, 0, 0xFFFFFF01);
184
        assertTrue(compareByteArrays(received, expected, 0, LittleEndian.INT_SIZE));
193
        assertTrue(compareByteArrays(received, expected, 0, LittleEndianConsts.INT_SIZE));
185
        LittleEndian.putInt(received, 1, 0x02FFFFFF);
194
        LittleEndian.putInt(received, 1, 0x02FFFFFF);
186
        assertTrue(compareByteArrays(received, expected, 1, LittleEndian.INT_SIZE));
195
        assertTrue(compareByteArrays(received, expected, 1, LittleEndianConsts.INT_SIZE));
187
    }
196
    }
188
197
189
    /**
198
    /**
190
     * test the putDouble methods
199
     * test the putDouble methods
191
     */
200
     */
201
    @Test
192
    public void testPutDouble() {
202
    public void testPutDouble() {
193
        byte[] received = new byte[ LittleEndian.DOUBLE_SIZE + 1 ];
203
        byte[] received = new byte[ LittleEndianConsts.DOUBLE_SIZE + 1 ];
194
204
195
        LittleEndian.putDouble(received, 0, _doubles[0]);
205
        LittleEndian.putDouble(received, 0, _doubles[0]);
196
        assertTrue(compareByteArrays(received, _double_array, 0, LittleEndian.DOUBLE_SIZE));
206
        assertTrue(compareByteArrays(received, _double_array, 0, LittleEndianConsts.DOUBLE_SIZE));
197
        LittleEndian.putDouble(received, 1, _doubles[1]);
207
        LittleEndian.putDouble(received, 1, _doubles[1]);
198
        byte[] expected = new byte[ LittleEndian.DOUBLE_SIZE + 1 ];
208
        byte[] expected = new byte[ LittleEndianConsts.DOUBLE_SIZE + 1 ];
199
209
200
        System.arraycopy(_double_array, LittleEndian.DOUBLE_SIZE, expected,
210
        System.arraycopy(_double_array, LittleEndianConsts.DOUBLE_SIZE, expected,
201
                         1, LittleEndian.DOUBLE_SIZE);
211
                         1, LittleEndianConsts.DOUBLE_SIZE);
202
        assertTrue(compareByteArrays(received, expected, 1, LittleEndian.DOUBLE_SIZE));
212
        assertTrue(compareByteArrays(received, expected, 1, LittleEndianConsts.DOUBLE_SIZE));
203
    }
213
    }
204
214
205
    /**
215
    /**
206
     * test the putLong method
216
     * test the putLong method
207
     */
217
     */
218
    @Test
208
    public void testPutLong() {
219
    public void testPutLong() {
209
        // writing 8 byte values to a 9 byte buffer
220
        // writing 8 byte values to a 9 byte buffer
210
        byte[] expected = {
221
        byte[] expected = {
Lines 218-231 Link Here
218
            (byte) 0xFF,
229
            (byte) 0xFF,
219
            (byte) 0x02,
230
            (byte) 0x02,
220
        };
231
        };
221
        byte[] received   = new byte[ LittleEndian.LONG_SIZE + 1 ];
232
        byte[] received   = new byte[ LittleEndianConsts.LONG_SIZE + 1 ];
222
233
223
        long testdata0 = 0xFFFFFFFFFFFFFF01L;
234
        long testdata0 = 0xFFFFFFFFFFFFFF01L;
224
        long testdata1 = 0x02FFFFFFFFFFFFFFL;
235
        long testdata1 = 0x02FFFFFFFFFFFFFFL;
225
        LittleEndian.putLong(received, 0, testdata0);
236
        LittleEndian.putLong(received, 0, testdata0);
226
        assertTrue(compareByteArrays(received, expected, 0, LittleEndian.LONG_SIZE));
237
        assertTrue(compareByteArrays(received, expected, 0, LittleEndianConsts.LONG_SIZE));
227
        LittleEndian.putLong(received, 1, testdata1);
238
        LittleEndian.putLong(received, 1, testdata1);
228
        assertTrue(compareByteArrays(received, expected, 1, LittleEndian.LONG_SIZE));
239
        assertTrue(compareByteArrays(received, expected, 1, LittleEndianConsts.LONG_SIZE));
229
    }
240
    }
230
241
231
    private static byte[] _good_array = {
242
    private static byte[] _good_array = {
Lines 241-255 Link Here
241
    /**
252
    /**
242
     * test the readShort method
253
     * test the readShort method
243
     */
254
     */
255
    @Test
244
    public void testReadShort() throws IOException {
256
    public void testReadShort() throws IOException {
245
        short       expected_value = 0x0201;
257
        short       expected_value = 0x0201;
246
        InputStream stream         = new ByteArrayInputStream(_good_array);
258
        InputStream stream         = new ByteArrayInputStream(_good_array);
247
        int         count          = 0;
259
        int         count          = 0;
248
260
249
        while (stream.available() > 0) {
261
        while (true) {
250
            short value = LittleEndian.readShort(stream);
262
            try {
251
            assertEquals(value, expected_value);
263
                short value = LittleEndian.readShort(stream);
252
            count++;
264
                assertEquals(value, expected_value);
265
                count++;
266
            } catch (BufferUnderrunException e) {
267
                break;
268
            }
253
        }
269
        }
254
        assertEquals(count,
270
        assertEquals(count,
255
                     _good_array.length / LittleEndianConsts.SHORT_SIZE);
271
                     _good_array.length / LittleEndianConsts.SHORT_SIZE);
Lines 265-279 Link Here
265
    /**
281
    /**
266
     * test the readInt method
282
     * test the readInt method
267
     */
283
     */
284
    @Test
268
    public void testReadInt() throws IOException {
285
    public void testReadInt() throws IOException {
269
        int         expected_value = 0x02010201;
286
        int         expected_value = 0x02010201;
270
        InputStream stream         = new ByteArrayInputStream(_good_array);
287
        InputStream stream         = new ByteArrayInputStream(_good_array);
271
        int         count          = 0;
288
        int         count          = 0;
272
289
273
        while (stream.available() > 0) {
290
        while (true) {
274
            int value = LittleEndian.readInt(stream);
291
            try {
275
            assertEquals(value, expected_value);
292
                int value = LittleEndian.readInt(stream);
276
            count++;
293
                assertEquals(value, expected_value);
294
                count++;
295
            } catch (BufferUnderrunException e) {
296
                break;
297
            }
277
        }
298
        }
278
        assertEquals(count, _good_array.length / LittleEndianConsts.INT_SIZE);
299
        assertEquals(count, _good_array.length / LittleEndianConsts.INT_SIZE);
279
        stream = new ByteArrayInputStream(_bad_array);
300
        stream = new ByteArrayInputStream(_bad_array);
Lines 289-303 Link Here
289
    /**
310
    /**
290
     * test the readLong method
311
     * test the readLong method
291
     */
312
     */
313
    @Test
292
    public void testReadLong() throws IOException {
314
    public void testReadLong() throws IOException {
293
        long        expected_value = 0x0201020102010201L;
315
        long        expected_value = 0x0201020102010201L;
294
        InputStream stream         = new ByteArrayInputStream(_good_array);
316
        InputStream stream         = new ByteArrayInputStream(_good_array);
295
        int         count          = 0;
317
        int         count          = 0;
296
318
297
        while (stream.available() > 0) {
319
        while (true) {
298
            long value = LittleEndian.readLong(stream);
320
            try {
299
            assertEquals(value, expected_value);
321
                long value = LittleEndian.readLong(stream);
300
            count++;
322
                assertEquals(value, expected_value);
323
                count++;
324
            } catch (BufferUnderrunException e) {
325
                break;
326
            }
301
        }
327
        }
302
        assertEquals(count,
328
        assertEquals(count,
303
                     _good_array.length / LittleEndianConsts.LONG_SIZE);
329
                     _good_array.length / LittleEndianConsts.LONG_SIZE);
Lines 326-331 Link Here
326
//        }
352
//        }
327
//    }
353
//    }
328
354
355
    @Test
329
    public void testUnsignedByteToInt() {
356
    public void testUnsignedByteToInt() {
330
        assertEquals(255, LittleEndian.ubyteToInt((byte)255));
357
        assertEquals(255, LittleEndian.ubyteToInt((byte)255));
331
    }
358
    }
Lines 342-347 Link Here
342
        return true;
369
        return true;
343
    }
370
    }
344
371
372
    @Test
345
    public void testUnsignedShort() {
373
    public void testUnsignedShort() {
346
        assertEquals(0xffff, LittleEndian.getUShort(new byte[] { (byte)0xff, (byte)0xff }, 0));
374
        assertEquals(0xffff, LittleEndian.getUShort(new byte[] { (byte)0xff, (byte)0xff }, 0));
347
    }
375
    }

Return to bug 59893