mirror of https://github.com/apache/poi.git
- A section's size is a multiple of 4 now. The Windows explorer seems to be constrained to this requirement in order to display custom properties.
- Custom properties may be written in character encodings different from Unicode. git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353596 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8cb8e5f43d
commit
ff53b56c07
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
Copyright 2002-2004 Apache Software Foundation
|
Copyright 2002-2004 Apache Software Foundation
|
||||||
|
|
||||||
|
@ -22,6 +21,7 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
@ -223,7 +223,18 @@ public class MutablePropertySet extends PropertySet
|
||||||
throw new NoFormatIDException();
|
throw new NoFormatIDException();
|
||||||
length += TypeWriter.writeToStream(out, s.getFormatID());
|
length += TypeWriter.writeToStream(out, s.getFormatID());
|
||||||
length += TypeWriter.writeUIntToStream(out, offset);
|
length += TypeWriter.writeUIntToStream(out, offset);
|
||||||
offset += s.getSize();
|
try
|
||||||
|
{
|
||||||
|
offset += s.getSize();
|
||||||
|
}
|
||||||
|
catch (HPSFRuntimeException ex)
|
||||||
|
{
|
||||||
|
final Throwable cause = ex.getReason();
|
||||||
|
if (cause instanceof UnsupportedEncodingException)
|
||||||
|
throw new IllegalPropertySetDataException(cause);
|
||||||
|
else
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the sections themselves. */
|
/* Write the sections themselves. */
|
||||||
|
|
|
@ -302,7 +302,9 @@ public class MutableSection extends Section
|
||||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
write(out);
|
write(out);
|
||||||
out.close();
|
out.close();
|
||||||
sectionBytes = out.toByteArray();
|
/* Pad to multiple of 4 bytes so that even the Windows shell (explorer)
|
||||||
|
* shows custom properties. */
|
||||||
|
sectionBytes = Util.pad4(out.toByteArray());
|
||||||
return sectionBytes.length;
|
return sectionBytes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,6 +358,7 @@ public class MutableSection extends Section
|
||||||
/* Writing the section's dictionary it tricky. If there is a dictionary
|
/* Writing the section's dictionary it tricky. If there is a dictionary
|
||||||
* (property 0) the codepage property (property 1) has to be set, too.
|
* (property 0) the codepage property (property 1) has to be set, too.
|
||||||
* Since HPSF supports Unicode only, the codepage must be 1200. */
|
* Since HPSF supports Unicode only, the codepage must be 1200. */
|
||||||
|
int codepage = -1;
|
||||||
if (getProperty(PropertyIDMap.PID_DICTIONARY) != null)
|
if (getProperty(PropertyIDMap.PID_DICTIONARY) != null)
|
||||||
{
|
{
|
||||||
final Object p1 = getProperty(PropertyIDMap.PID_CODEPAGE);
|
final Object p1 = getProperty(PropertyIDMap.PID_CODEPAGE);
|
||||||
|
@ -365,14 +368,12 @@ public class MutableSection extends Section
|
||||||
throw new IllegalPropertySetDataException
|
throw new IllegalPropertySetDataException
|
||||||
("The codepage property (ID = 1) must be an " +
|
("The codepage property (ID = 1) must be an " +
|
||||||
"Integer object.");
|
"Integer object.");
|
||||||
else if (((Integer) p1).intValue() != Constants.CP_UNICODE)
|
|
||||||
throw new IllegalPropertySetDataException
|
|
||||||
("The codepage property (ID = 1) must be " +
|
|
||||||
"1200 (Unicode).");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new IllegalPropertySetDataException
|
throw new IllegalPropertySetDataException
|
||||||
("The codepage property (ID = 1) must be set.");
|
("The codepage property (ID = 1) must be set if the " +
|
||||||
|
"section contains a dictionary.");
|
||||||
|
codepage = getCodepage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sort the property list by their property IDs: */
|
/* Sort the property list by their property IDs: */
|
||||||
|
@ -412,11 +413,11 @@ public class MutableSection extends Section
|
||||||
position += p.write(propertyStream, getCodepage());
|
position += p.write(propertyStream, getCodepage());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
final int codepage = getCodepage();
|
|
||||||
if (codepage == -1)
|
if (codepage == -1)
|
||||||
throw new IllegalPropertySetDataException
|
throw new IllegalPropertySetDataException
|
||||||
("Codepage (property 1) is undefined.");
|
("Codepage (property 1) is undefined.");
|
||||||
position += writeDictionary(propertyStream, dictionary);
|
position += writeDictionary(propertyStream, dictionary,
|
||||||
|
codepage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyStream.close();
|
propertyStream.close();
|
||||||
|
@ -450,40 +451,61 @@ public class MutableSection extends Section
|
||||||
*
|
*
|
||||||
* @param out The output stream to write to.
|
* @param out The output stream to write to.
|
||||||
* @param dictionary The dictionary.
|
* @param dictionary The dictionary.
|
||||||
|
* @param codepage The codepage to be used to write the dictionary items.
|
||||||
* @return The number of bytes written
|
* @return The number of bytes written
|
||||||
* @exception IOException if an I/O exception occurs.
|
* @exception IOException if an I/O exception occurs.
|
||||||
*/
|
*/
|
||||||
private static int writeDictionary(final OutputStream out,
|
private static int writeDictionary(final OutputStream out,
|
||||||
final Map dictionary)
|
final Map dictionary, final int codepage)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
int length = 0;
|
int length = TypeWriter.writeUIntToStream(out, dictionary.size());
|
||||||
length += TypeWriter.writeUIntToStream(out, dictionary.size());
|
|
||||||
for (final Iterator i = dictionary.keySet().iterator(); i.hasNext();)
|
for (final Iterator i = dictionary.keySet().iterator(); i.hasNext();)
|
||||||
{
|
{
|
||||||
final Long key = (Long) i.next();
|
final Long key = (Long) i.next();
|
||||||
final String value = (String) dictionary.get(key);
|
final String value = (String) dictionary.get(key);
|
||||||
int sLength = value.length() + 1;
|
|
||||||
if (sLength % 2 == 1)
|
if (codepage == Constants.CP_UNICODE)
|
||||||
sLength++;
|
|
||||||
length += TypeWriter.writeUIntToStream(out, key.longValue());
|
|
||||||
length += TypeWriter.writeUIntToStream(out, sLength);
|
|
||||||
final char[] ca = value.toCharArray();
|
|
||||||
for (int j = 0; j < ca.length; j++)
|
|
||||||
{
|
{
|
||||||
int high = (ca[j] & 0x0ff00) >> 8;
|
/* Write the dictionary item in Unicode. */
|
||||||
int low = (ca[j] & 0x000ff);
|
int sLength = value.length() + 1;
|
||||||
out.write(low);
|
if (sLength % 2 == 1)
|
||||||
out.write(high);
|
sLength++;
|
||||||
length += 2;
|
length += TypeWriter.writeUIntToStream(out, key.longValue());
|
||||||
sLength--;
|
length += TypeWriter.writeUIntToStream(out, sLength);
|
||||||
|
final char[] ca = value.toCharArray();
|
||||||
|
for (int j = 0; j < ca.length; j++)
|
||||||
|
{
|
||||||
|
int high = (ca[j] & 0x0ff00) >> 8;
|
||||||
|
int low = (ca[j] & 0x000ff);
|
||||||
|
out.write(low);
|
||||||
|
out.write(high);
|
||||||
|
length += 2;
|
||||||
|
sLength--;
|
||||||
|
}
|
||||||
|
while (sLength > 0)
|
||||||
|
{
|
||||||
|
out.write(0x00);
|
||||||
|
out.write(0x00);
|
||||||
|
length += 2;
|
||||||
|
sLength--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (sLength > 0)
|
else
|
||||||
{
|
{
|
||||||
|
/* Write the dictionary item in another codepage than
|
||||||
|
* Unicode. */
|
||||||
|
length += TypeWriter.writeUIntToStream(out, key.longValue());
|
||||||
|
length += TypeWriter.writeUIntToStream(out, value.length() + 1);
|
||||||
|
final byte[] ba =
|
||||||
|
value.getBytes(VariantSupport.codepageToEncoding(codepage));
|
||||||
|
for (int j = 0; j < ba.length; j++)
|
||||||
|
{
|
||||||
|
out.write(ba[j]);
|
||||||
|
length++;
|
||||||
|
}
|
||||||
out.write(0x00);
|
out.write(0x00);
|
||||||
out.write(0x00);
|
length++;
|
||||||
length += 2;
|
|
||||||
sLength--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
|
|
Loading…
Reference in New Issue