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

(-)a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/PropertiesChunk.java (+62 lines)
Lines 391-396 public abstract class PropertiesChunk extends Chunk { Link Here
391
        return variableLengthProperties;
391
        return variableLengthProperties;
392
    }
392
    }
393
393
394
    /**
395
     * Writes the manually pre-calculated(have header and data written manually) properties.
396
     *
397
     * @param out
398
     *          The {@code OutputStream}.
399
     * @return The variable-length properties that need to be written in another
400
     *         node.
401
     * @throws IOException
402
     *           If an I/O error occurs.
403
     */
404
    protected List<PropertyValue> writePreCalculatedProperties(OutputStream out) throws IOException {
405
        List<PropertyValue> variableLengthProperties = new ArrayList<>();
406
        for (Entry<MAPIProperty, PropertyValue> entry : properties.entrySet()) {
407
            MAPIProperty property = entry.getKey();
408
            PropertyValue value = entry.getValue();
409
            if (value == null) {
410
                continue;
411
            }
412
            if (property.id < 0) {
413
                continue;
414
            }
415
            // generic header
416
            // page 23, point 2.4.2
417
            // tag is the property id and its type
418
            long tag = Long.parseLong(getActualTypeTag(property, value.getActualType()), 16);
419
            LittleEndian.putUInt(tag, out);
420
            LittleEndian.putUInt(value.getFlags(), out); // readable + writable
421
422
            MAPIType type = value.getActualType();
423
            if (type.isFixedLength()) {
424
                // page 11, point 2.1.2
425
                writeFixedLengthValueHeader(out, property, type, value);
426
            } else {
427
                // page 12, point 2.1.3
428
                writeVariableLengthPreCalculatedValue(out, value);
429
                variableLengthProperties.add(value);
430
            }
431
        }
432
        return variableLengthProperties;
433
    }
434
394
    private void writeFixedLengthValueHeader(OutputStream out, MAPIProperty property, MAPIType type, PropertyValue value) throws IOException {
435
    private void writeFixedLengthValueHeader(OutputStream out, MAPIProperty property, MAPIType type, PropertyValue value) throws IOException {
395
        // fixed type header
436
        // fixed type header
396
        // page 24, point 2.4.2.1.1
437
        // page 24, point 2.4.2.1.1
Lines 402-407 public abstract class PropertiesChunk extends Chunk { Link Here
402
        out.write(new byte[8 - length]);
443
        out.write(new byte[8 - length]);
403
    }
444
    }
404
445
446
    /**
447
     * Writes out pre-calculated raw values which assume any variable length property `data`
448
     *  field to already have size, reserved and manually written header
449
     * @param out
450
     * @throws IOException
451
     */
452
    private void writeVariableLengthPreCalculatedValue(OutputStream out, PropertyValue value) throws IOException {
453
        // variable length header
454
        // page 24, point 2.4.2.2
455
        byte[] bytes = value.getRawValue();
456
        out.write(bytes);
457
    }
458
405
    private void writeVariableLengthValueHeader(OutputStream out, MAPIProperty propertyEx, MAPIType type,
459
    private void writeVariableLengthValueHeader(OutputStream out, MAPIProperty propertyEx, MAPIType type,
406
        PropertyValue value) throws IOException {
460
        PropertyValue value) throws IOException {
407
        // variable length header
461
        // variable length header
Lines 419-424 public abstract class PropertiesChunk extends Chunk { Link Here
419
        LittleEndian.putUInt(0, out);
473
        LittleEndian.putUInt(0, out);
420
    }
474
    }
421
475
476
    private String getActualTypeTag(MAPIProperty property, MAPIType actualType) {
477
        String str = Integer.toHexString(property.id).toUpperCase(Locale.ROOT);
478
        while (str.length() < 4) {
479
            str = "0" + str;
480
        }
481
        return str + actualType.asFileEnding();
482
    }
483
422
    private String getFileName(MAPIProperty property, MAPIType actualType) {
484
    private String getFileName(MAPIProperty property, MAPIType actualType) {
423
        StringBuilder str = new StringBuilder(Integer.toHexString(property.id).toUpperCase(Locale.ROOT));
485
        StringBuilder str = new StringBuilder(Integer.toHexString(property.id).toUpperCase(Locale.ROOT));
424
        int need0count = 4 - str.length();
486
        int need0count = 4 - str.length();
(-)a/poi-scratchpad/src/main/java/org/apache/poi/hsmf/datatypes/StoragePropertiesChunk.java (+14 lines)
Lines 49-52 public class StoragePropertiesChunk extends PropertiesChunk { Link Here
49
        // Now properties
49
        // Now properties
50
        writeProperties(out);
50
        writeProperties(out);
51
    }
51
    }
52
53
    /**
54
     * Writes out pre-calculated header values which assume any variable length property `data`
55
     *  field to already have Size and Reserved
56
     * @param out
57
     * @throws IOException
58
     */
59
    public void writePreCalculatedValue(OutputStream out) throws IOException {
60
        // 8 bytes of reserved zeros
61
        out.write(new byte[8]);
62
63
        // Now properties
64
        writePreCalculatedProperties(out);
65
    }
52
}
66
}
(-)a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/datatypes/TestChunkData.java (+15 lines)
Lines 19-24 package org.apache.poi.hsmf.datatypes; Link Here
19
19
20
import static org.junit.jupiter.api.Assertions.assertEquals;
20
import static org.junit.jupiter.api.Assertions.assertEquals;
21
21
22
import java.io.ByteArrayOutputStream;
23
import java.io.IOException;
24
import java.util.List;
22
import org.junit.jupiter.api.Test;
25
import org.junit.jupiter.api.Test;
23
26
24
/**
27
/**
Lines 87-90 public final class TestChunkData { Link Here
87
      assertEquals(chunk.getChunkId(), MAPIProperty.SUBJECT.id);
90
      assertEquals(chunk.getChunkId(), MAPIProperty.SUBJECT.id);
88
    }
91
    }
89
92
93
    @Test
94
    void testWritePreCalculatedProperties() throws IOException {
95
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
96
        StoragePropertiesChunk storagePropertiesChunk = new StoragePropertiesChunk(null);
97
        PropertyValue.LongPropertyValue attachSize = new PropertyValue.LongPropertyValue(MAPIProperty.ATTACH_SIZE, 6L,  new byte[0]);
98
        PropertyValue currentValue = new PropertyValue(MAPIProperty.DISPLAY_BCC, 6L, new byte[0]);
99
        attachSize.setValue(3934266);
100
        storagePropertiesChunk.setProperty(attachSize);
101
        storagePropertiesChunk.setProperty(currentValue);
102
        List<PropertyValue> propertyValue= storagePropertiesChunk.writePreCalculatedProperties(stream);
103
        assertEquals(propertyValue.size(),1);
104
    }
90
}
105
}

Return to bug 66301