import java.util.Arrays;
import java.util.List;
-import org.apache.poi.util.POILogFactory;
-
-import org.apache.poi.util.POILogger;
-
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
import org.apache.poi.util.Internal;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
@Internal
public class BookmarksTables
int namesLength = fib.getLcbSttbfbkmk();
if ( namesStart != 0 && namesLength != 0 )
- this.names = new ArrayList<String>( Arrays.asList( SttbfUtils.read(
- tableStream, namesStart ) ) );
+ this.names = new ArrayList<String>( Arrays.asList( SttbUtils
+ .readSttbfBkmk( tableStream, namesStart ) ) );
int firstDescriptorsStart = fib.getFcPlcfbkf();
int firstDescriptorsLength = fib.getLcbPlcfbkf();
}
int start = tableStream.getOffset();
- SttbfUtils
- .write( tableStream, names.toArray( new String[names.size()] ) );
+ SttbUtils.writeSttbfBkmk( names.toArray( new String[names.size()] ),
+ tableStream );
int end = tableStream.getOffset();
fib.setFcSttbfbkmk( start );
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
/**
* String table containing the names of authors of revision marks, e-mails and
*/
@Internal
public final class RevisionMarkAuthorTable {
- /**
- * must be 0xFFFF
- */
- private short fExtend = (short) 0xFFFF;
-
- /**
- * the number of entries in the table
- */
- private short cData = 0;
-
- /**
- * must be 0
- */
- private short cbExtra = 0;
-
/**
* Array of entries.
*/
* @param offset the offset into the byte array.
* @param size the size of the table in the byte array.
*/
- public RevisionMarkAuthorTable(byte[] tableStream, int offset, int size) throws IOException {
- // Read fExtend - it isn't used
- fExtend = LittleEndian.getShort(tableStream, offset);
- if(fExtend != 0xFFFF) {
- //TODO: throw an exception here?
- }
- offset += 2;
-
- // Read the number of entries
- cData = LittleEndian.getShort(tableStream, offset);
- offset += 2;
-
- // Read cbExtra - it isn't used
- cbExtra = LittleEndian.getShort(tableStream, offset);
- if(cbExtra != 0) {
- //TODO: throw an exception here?
- }
- offset += 2;
-
- entries = new String[cData];
- for (int i = 0; i < cData; i++) {
- int len = LittleEndian.getShort(tableStream, offset);
- offset += 2;
-
- String name = StringUtil.getFromUnicodeLE(tableStream, offset, len);
- offset += len * 2;
-
- entries[i] = name;
- }
- }
+ public RevisionMarkAuthorTable( byte[] tableStream, int offset, int size )
+ throws IOException
+ {
+ entries = SttbUtils.readSttbfRMark( tableStream, offset );
+ }
/**
* Gets the entries. The returned list cannot be modified.
* @return the number of entries.
*/
public int getSize() {
- return cData;
+ return entries.length;
}
/**
* @param tableStream the table stream to write to.
* @throws IOException if an error occurs while writing.
*/
- public void writeTo(HWPFOutputStream tableStream) throws IOException {
- byte[] header = new byte[6];
- LittleEndian.putShort(header, 0, fExtend);
- LittleEndian.putShort(header, 2, cData);
- LittleEndian.putShort(header, 4, cbExtra);
- tableStream.write(header);
-
- for (String name : entries) {
- byte[] buf = new byte[name.length() * 2 + 2];
- LittleEndian.putShort(buf, 0, (short) name.length());
- StringUtil.putUnicodeLE(name, buf, 2);
- tableStream.write(buf);
- }
- }
+ public void writeTo( HWPFOutputStream tableStream ) throws IOException
+ {
+ SttbUtils.writeSttbfRMark( entries, tableStream );
+ }
}
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.hwpf.model;
import java.io.IOException;
import org.apache.poi.util.Internal;
/**
- * String table containing the history of the last few revisions ("saves") of the document.
- * Read-only for the time being.
- *
+ * String table containing the history of the last few revisions ("saves") of
+ * the document. Read-only for the time being.
+ *
* @author Daniel Noll
*/
@Internal
public final class SavedByTable
{
+ /**
+ * Array of entries.
+ */
+ private SavedByEntry[] entries;
- /**
- * Array of entries.
- */
- private SavedByEntry[] entries;
-
- /**
- * Constructor to read the table from the table stream.
- *
- * @param tableStream the table stream.
- * @param offset the offset into the byte array.
- * @param size the size of the table in the byte array.
- */
- public SavedByTable(byte[] tableStream, int offset, int size)
- {
-// // Read the value that I don't know what it does. :-)
-// unknownValue = LittleEndian.getShort(tableStream, offset);
-// offset += 2;
-//
-// // The stored int is the number of strings, and there are two strings per entry.
-// int numEntries = LittleEndian.getInt(tableStream, offset) / 2;
-// offset += 4;
-//
-// entries = new SavedByEntry[numEntries];
-// for (int i = 0; i < numEntries; i++)
-// {
-// int len = LittleEndian.getShort(tableStream, offset);
-// offset += 2;
-// String userName = StringUtil.getFromUnicodeLE(tableStream, offset, len);
-// offset += len * 2;
-// len = LittleEndian.getShort(tableStream, offset);
-// offset += 2;
-// String saveLocation = StringUtil.getFromUnicodeLE(tableStream, offset, len);
-// offset += len * 2;
-//
-// entries[i] = new SavedByEntry(userName, saveLocation);
-// }
-
- // first value is mark for extended STTBF ;) -- sergey
- String[] strings = SttbfUtils.read( tableStream, offset );
-
+ /**
+ * Constructor to read the table from the table stream.
+ *
+ * @param tableStream
+ * the table stream.
+ * @param offset
+ * the offset into the byte array.
+ * @param size
+ * the size of the table in the byte array.
+ */
+ public SavedByTable( byte[] tableStream, int offset, int size )
+ {
+ String[] strings = SttbUtils.readSttbSavedBy( tableStream, offset );
int numEntries = strings.length / 2;
entries = new SavedByEntry[numEntries];
for ( int i = 0; i < numEntries; i++ )
}
}
- /**
- * Gets the entries. The returned list cannot be modified.
- *
- * @return the list of entries.
- */
- public List<SavedByEntry> getEntries()
- {
- return Collections.unmodifiableList(Arrays.asList(entries));
- }
+ /**
+ * Gets the entries. The returned list cannot be modified.
+ *
+ * @return the list of entries.
+ */
+ public List<SavedByEntry> getEntries()
+ {
+ return Collections.unmodifiableList( Arrays.asList( entries ) );
+ }
/**
* Writes this table to the table stream.
toSave[counter++] = entry.getUserName();
toSave[counter++] = entry.getSaveLocation();
}
- SttbfUtils.write( tableStream, toSave );
+ SttbUtils.writeSttbSavedBy( toSave, tableStream );
}
}
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.hwpf.model;
+
+import java.io.IOException;
+
+import org.apache.poi.hwpf.model.io.HWPFOutputStream;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.StringUtil;
+
+/**
+ * Utils class for storing and reading "STring TaBle stored in File"
+ *
+ * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
+ */
+@Internal
+class SttbUtils
+{
+
+ static class Sttb
+ {
+ public int cbExtra;
+
+ public int cDataLength;
+
+ public String[] data;
+
+ public byte[][] extraData;
+ }
+
+ private static final int CBEXTRA_STTB_SAVED_BY = 0; // bytes
+
+ private static final int CBEXTRA_STTBF_BKMK = 0; // bytes
+
+ private static final int CBEXTRA_STTBF_R_MARK = 0; // bytes
+
+ private static final int CDATA_SIZE_STTB_SAVED_BY = 2; // bytes
+
+ private static final int CDATA_SIZE_STTBF_BKMK = 2; // bytes
+
+ private static final int CDATA_SIZE_STTBF_R_MARK = 2; // bytes
+
+ static Sttb read( int cDataLength, byte[] buffer, int startOffset )
+ {
+ short ffff = LittleEndian.getShort( buffer, startOffset );
+ int offset = startOffset + 2;
+
+ if ( ffff != (short) 0xffff )
+ {
+ // Non-extended character Pascal strings
+ throw new UnsupportedOperationException(
+ "Non-extended character Pascal strings are not supported right now. "
+ + "Please, contact POI developers for update." );
+ }
+ // strings are extended character strings
+
+ int cData = cDataLength == 2 ? LittleEndian.getUShort( buffer, offset )
+ : LittleEndian.getInt( buffer, offset );
+ offset += cDataLength;
+
+ Sttb sttb = new Sttb();
+ sttb.cDataLength = cDataLength;
+ sttb.cbExtra = LittleEndian.getUShort( buffer, offset );
+ offset += 2;
+
+ sttb.data = new String[cData];
+ sttb.extraData = new byte[cData][];
+
+ for ( int i = 0; i < cData; i++ )
+ {
+ int cchData = LittleEndian.getShort( buffer, offset );
+ offset += 2;
+
+ if ( cchData < 0 )
+ continue;
+
+ sttb.data[i] = StringUtil
+ .getFromUnicodeLE( buffer, offset, cchData );
+ offset += cchData * 2;
+
+ sttb.extraData[i] = LittleEndian.getByteArray( buffer, offset,
+ sttb.cbExtra );
+ offset += sttb.cbExtra;
+ }
+
+ return sttb;
+ }
+
+ static String[] readSttbfBkmk( byte[] buffer, int startOffset )
+ {
+ return read( CDATA_SIZE_STTBF_BKMK, buffer, startOffset ).data;
+ }
+
+ static String[] readSttbfRMark( byte[] buffer, int startOffset )
+ {
+ return read( CDATA_SIZE_STTBF_R_MARK, buffer, startOffset ).data;
+ }
+
+ static String[] readSttbSavedBy( byte[] buffer, int startOffset )
+ {
+ return read( CDATA_SIZE_STTB_SAVED_BY, buffer, startOffset ).data;
+ }
+
+ static void write( Sttb sttb, HWPFOutputStream tableStream )
+ throws IOException
+ {
+ final int headerSize = sttb.cDataLength == 2 ? 6 : 8;
+
+ byte[] header = new byte[headerSize];
+ LittleEndian.putShort( header, 0, (short) 0xffff );
+
+ if ( sttb.data == null || sttb.data.length == 0 )
+ {
+ if ( sttb.cDataLength == 4 )
+ {
+ LittleEndian.putInt( header, 2, 0 );
+ LittleEndian.putUShort( header, 6, sttb.cbExtra );
+ tableStream.write( header );
+ return;
+ }
+
+ LittleEndian.putUShort( header, 2, 0 );
+ LittleEndian.putUShort( header, 4, sttb.cbExtra );
+ tableStream.write( header );
+ return;
+ }
+
+ if ( sttb.cDataLength == 4 )
+ {
+ LittleEndian.putInt( header, 2, sttb.data.length );
+ LittleEndian.putUShort( header, 6, sttb.cbExtra );
+ tableStream.write( header );
+ }
+ else
+ {
+ LittleEndian.putUShort( header, 2, sttb.data.length );
+ LittleEndian.putUShort( header, 4, sttb.cbExtra );
+ tableStream.write( header );
+ }
+
+ for ( int i = 0; i < sttb.data.length; i++ )
+ {
+ String entry = sttb.data[i];
+ if ( entry == null )
+ {
+ // is it correct?
+ tableStream.write( new byte[] { -1, 0 } );
+ continue;
+ }
+
+ byte[] buf = new byte[entry.length() * 2 + sttb.cbExtra + 2];
+
+ LittleEndian.putShort( buf, 0, (short) entry.length() );
+ StringUtil.putUnicodeLE( entry, buf, 2 );
+
+ if ( sttb.extraData != null && i < sttb.extraData.length
+ && sttb.extraData[i] != null )
+ System.arraycopy( sttb.extraData[i], 0, buf,
+ entry.length() * 2,
+ Math.min( sttb.extraData[i].length, sttb.cbExtra ) );
+
+ tableStream.write( buf );
+ }
+ }
+
+ static void writeSttbfBkmk( String[] data, HWPFOutputStream tableStream )
+ throws IOException
+ {
+ Sttb sttb = new Sttb();
+ sttb.cDataLength = CDATA_SIZE_STTBF_BKMK;
+ sttb.data = data;
+ sttb.cbExtra = CBEXTRA_STTBF_BKMK;
+ write( sttb, tableStream );
+ }
+
+ static void writeSttbfRMark( String[] data, HWPFOutputStream tableStream )
+ throws IOException
+ {
+ Sttb sttb = new Sttb();
+ sttb.cDataLength = CDATA_SIZE_STTBF_R_MARK;
+ sttb.data = data;
+ sttb.cbExtra = CBEXTRA_STTBF_R_MARK;
+ write( sttb, tableStream );
+ }
+
+ static void writeSttbSavedBy( String[] data, HWPFOutputStream tableStream )
+ throws IOException
+ {
+ Sttb sttb = new Sttb();
+ sttb.cDataLength = CDATA_SIZE_STTB_SAVED_BY;
+ sttb.data = data;
+ sttb.cbExtra = CBEXTRA_STTB_SAVED_BY;
+ write( sttb, tableStream );
+ }
+
+}
+++ /dev/null
-/* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================== */
-package org.apache.poi.hwpf.model;
-
-import java.io.IOException;
-
-import org.apache.poi.hwpf.model.io.HWPFOutputStream;
-import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
-
-/**
- * Utils for storing and reading "STring TaBle stored in File"
- *
- * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
- */
-@Internal
-class SttbfUtils
-{
- public static String[] read( byte[] data, int startOffset )
- {
- short ffff = LittleEndian.getShort( data, startOffset );
-
- if ( ffff != (short) 0xffff )
- {
- // Non-extended character Pascal strings
- throw new UnsupportedOperationException(
- "Non-extended character Pascal strings are not supported right now. "
- + "Please, contact POI developers for update." );
- }
-
- // strings are extended character strings
- int offset = startOffset + 2;
- int numEntries = LittleEndian.getInt( data, offset );
- offset += 4;
-
- String[] entries = new String[numEntries];
- for ( int i = 0; i < numEntries; i++ )
- {
- int len = LittleEndian.getShort( data, offset );
- offset += 2;
- String value = StringUtil.getFromUnicodeLE( data, offset, len );
- offset += len * 2;
- entries[i] = value;
- }
- return entries;
- }
-
- public static int write( HWPFOutputStream tableStream, String[] entries )
- throws IOException
- {
- byte[] header = new byte[6];
- LittleEndian.putShort( header, 0, (short) 0xffff );
-
- if ( entries == null || entries.length == 0 )
- {
- LittleEndian.putInt( header, 2, 0 );
- tableStream.write( header );
- return 6;
- }
-
- LittleEndian.putInt( header, 2, entries.length );
- tableStream.write( header );
- int size = 6;
-
- for ( String entry : entries )
- {
- byte[] buf = new byte[entry.length() * 2 + 2];
- LittleEndian.putShort( buf, 0, (short) entry.length() );
- StringUtil.putUnicodeLE( entry, buf, 2 );
- tableStream.write( buf );
- size += buf.length;
- }
-
- return size;
- }
-
-}