- 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:
Rainer Klute 2004-08-31 20:47:09 +00:00
parent 8cb8e5f43d
commit ff53b56c07
2 changed files with 63 additions and 30 deletions

View File

@ -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. */

View File

@ -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;