diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..a0cbe33
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..42ac320
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ java-libpst
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/PropertyNames.txt b/PropertyNames.txt
index 572a87f..16e6278 100644
--- a/PropertyNames.txt
+++ b/PropertyNames.txt
@@ -135,6 +135,7 @@
3FDE=PidTagInternetCodepage
3FF1=PidTagMessageLocaleId
3FFD=PidTagMessageCodepage
+3ff9=PidTagCreatorName
4019=PidTagSenderFlags
401A=PidTagSentRepresentingFlags
401B=PidTagReceivedByFlags
@@ -170,6 +171,8 @@
7FFD=PidTagAttachmentFlags
7FFE=PidTagAttachmentHidden
7FFF=PidTagAttachmentContactPhoto
+3FFA=PidTagLastModifiedName_W
+3FFB=PidTagLastModifierEntryId
00000001=PidLidAttendeeCriticalChange
00000002=PidLidWhere
00000003=PidLidGlobalObjectId
diff --git a/com/pff/LZFu.java b/com/pff/LZFu.java
deleted file mode 100644
index c5a573b..0000000
--- a/com/pff/LZFu.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2010 Richard Johnson & Orin Eman
- *
- * Licensed 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.
- *
- * ---
- *
- * This file is part of java-libpst.
- *
- * java-libpst is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * java-libpst is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with java-libpst. If not, see .
- *
- */
-
-package com.pff;
-
-import java.io.UnsupportedEncodingException;
-
-/**
- * An implementation of the LZFu algorithm to decompress RTF content
- * @author Richard Johnson
- */
-public class LZFu {
-
- public static final String LZFU_HEADER = "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscript \\fdecor MS Sans SerifSymbolArialTimes New RomanCourier{\\colortbl\\red0\\green0\\blue0\n\r\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab\\tx";
-
- public static String decode(byte[] data)
- throws PSTException
- {
-
- @SuppressWarnings("unused")
- int compressedSize = (int)PSTObject.convertLittleEndianBytesToLong(data, 0, 4);
- int uncompressedSize = (int)PSTObject.convertLittleEndianBytesToLong(data, 4, 8);
- int compressionSig = (int)PSTObject.convertLittleEndianBytesToLong(data, 8, 12);
- @SuppressWarnings("unused")
- int compressedCRC = (int)PSTObject.convertLittleEndianBytesToLong(data, 12, 16);
-
- if (compressionSig == 0x75465a4c) {
- // we are compressed...
- byte[] output = new byte[uncompressedSize];
- int outputPosition = 0;
- byte[] lzBuffer = new byte[4096];
- // preload our buffer.
- try {
- byte[] bytes = LZFU_HEADER.getBytes("US-ASCII");
- System.arraycopy(bytes, 0, lzBuffer, 0, LZFU_HEADER.length());
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- int bufferPosition = LZFU_HEADER.length();
- int currentDataPosition = 16;
-
- // next byte is the flags,
- while (currentDataPosition < data.length - 2 && outputPosition < output.length) {
- int flags = data[currentDataPosition++] & 0xFF;
- for (int x = 0; x < 8 && outputPosition < output.length; x++) {
- boolean isRef = ((flags & 1) == 1);
- flags >>= 1;
- if (isRef) {
- // get the starting point for the buffer and the
- // length to read
- int refOffsetOrig = data[currentDataPosition++] & 0xFF;
- int refSizeOrig = data[currentDataPosition++] & 0xFF;
- int refOffset = (refOffsetOrig << 4) | (refSizeOrig >>> 4);
- int refSize = (refSizeOrig & 0xF) + 2;
- //refOffset &= 0xFFF;
- try {
- // copy the data from the buffer
- int index = refOffset;
- for (int y = 0; y < refSize && outputPosition < output.length; y++) {
- output[outputPosition++] = lzBuffer[index];
- lzBuffer[bufferPosition] = lzBuffer[index];
- bufferPosition++;
- bufferPosition %= 4096;
- ++index;
- index %= 4096;
- }
- } catch ( Exception e ) {
- e.printStackTrace();
- }
-
- } else {
- // copy the byte over
- lzBuffer[bufferPosition] = data[currentDataPosition];
- bufferPosition++;
- bufferPosition %= 4096;
- output[outputPosition++] = data[currentDataPosition++];
- }
- }
- }
-
- if ( outputPosition != uncompressedSize ) {
- throw new PSTException(String.format("Error decompressing RTF! Expected %d bytes, got %d bytes\n", uncompressedSize, outputPosition));
- }
- return new String(output).trim();
-
- } else if (compressionSig == 0x414c454d) {
- // we are not compressed!
- // just return the rest of the contents as a string
- byte[] output = new byte[data.length-16];
- System.arraycopy(data, 16, output, 0, data.length-16);
- return new String(output).trim();
- }
-
- return "";
- }
-}
diff --git a/com/pff/PSTUtils.java b/com/pff/PSTUtils.java
new file mode 100644
index 0000000..402b223
--- /dev/null
+++ b/com/pff/PSTUtils.java
@@ -0,0 +1,376 @@
+package com.pff;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Calendar;
+import java.util.Date;
+
+import com.pff.exceptions.PSTException;
+import com.pff.objects.sub.PSTTimeZone;
+
+public abstract class PSTUtils {
+
+ public static final String LZFU_HEADER = "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscript \\fdecor MS Sans SerifSymbolArialTimes New RomanCourier{\\colortbl\\red0\\green0\\blue0\n\r\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab\\tx";
+
+
+ // substitution table for the compressible encryption type.
+ static int[] compEnc = {
+ 0x47, 0xf1, 0xb4, 0xe6, 0x0b, 0x6a, 0x72, 0x48, 0x85, 0x4e, 0x9e, 0xeb, 0xe2, 0xf8, 0x94, 0x53,
+ 0xe0, 0xbb, 0xa0, 0x02, 0xe8, 0x5a, 0x09, 0xab, 0xdb, 0xe3, 0xba, 0xc6, 0x7c, 0xc3, 0x10, 0xdd,
+ 0x39, 0x05, 0x96, 0x30, 0xf5, 0x37, 0x60, 0x82, 0x8c, 0xc9, 0x13, 0x4a, 0x6b, 0x1d, 0xf3, 0xfb,
+ 0x8f, 0x26, 0x97, 0xca, 0x91, 0x17, 0x01, 0xc4, 0x32, 0x2d, 0x6e, 0x31, 0x95, 0xff, 0xd9, 0x23,
+ 0xd1, 0x00, 0x5e, 0x79, 0xdc, 0x44, 0x3b, 0x1a, 0x28, 0xc5, 0x61, 0x57, 0x20, 0x90, 0x3d, 0x83,
+ 0xb9, 0x43, 0xbe, 0x67, 0xd2, 0x46, 0x42, 0x76, 0xc0, 0x6d, 0x5b, 0x7e, 0xb2, 0x0f, 0x16, 0x29,
+ 0x3c, 0xa9, 0x03, 0x54, 0x0d, 0xda, 0x5d, 0xdf, 0xf6, 0xb7, 0xc7, 0x62, 0xcd, 0x8d, 0x06, 0xd3,
+ 0x69, 0x5c, 0x86, 0xd6, 0x14, 0xf7, 0xa5, 0x66, 0x75, 0xac, 0xb1, 0xe9, 0x45, 0x21, 0x70, 0x0c,
+ 0x87, 0x9f, 0x74, 0xa4, 0x22, 0x4c, 0x6f, 0xbf, 0x1f, 0x56, 0xaa, 0x2e, 0xb3, 0x78, 0x33, 0x50,
+ 0xb0, 0xa3, 0x92, 0xbc, 0xcf, 0x19, 0x1c, 0xa7, 0x63, 0xcb, 0x1e, 0x4d, 0x3e, 0x4b, 0x1b, 0x9b,
+ 0x4f, 0xe7, 0xf0, 0xee, 0xad, 0x3a, 0xb5, 0x59, 0x04, 0xea, 0x40, 0x55, 0x25, 0x51, 0xe5, 0x7a,
+ 0x89, 0x38, 0x68, 0x52, 0x7b, 0xfc, 0x27, 0xae, 0xd7, 0xbd, 0xfa, 0x07, 0xf4, 0xcc, 0x8e, 0x5f,
+ 0xef, 0x35, 0x9c, 0x84, 0x2b, 0x15, 0xd5, 0x77, 0x34, 0x49, 0xb6, 0x12, 0x0a, 0x7f, 0x71, 0x88,
+ 0xfd, 0x9d, 0x18, 0x41, 0x7d, 0x93, 0xd8, 0x58, 0x2c, 0xce, 0xfe, 0x24, 0xaf, 0xde, 0xb8, 0x36,
+ 0xc8, 0xa1, 0x80, 0xa6, 0x99, 0x98, 0xa8, 0x2f, 0x0e, 0x81, 0x65, 0x73, 0xe4, 0xc2, 0xa2, 0x8a,
+ 0xd4, 0xe1, 0x11, 0xd0, 0x08, 0x8b, 0x2a, 0xf2, 0xed, 0x9a, 0x64, 0x3f, 0xc1, 0x6c, 0xf9, 0xec
+ };
+
+ /**
+ * Output a dump of data in hex format in the order it was read in
+ * @param data
+ * @param pretty
+ */
+ public static void printHexFormatted(byte[] data, boolean pretty) {
+ printHexFormatted(data,pretty, new int[0]);
+ }
+ protected static void printHexFormatted(byte[] data, boolean pretty, int[] indexes) {
+ // groups of two
+ if (pretty) { System.out.println("---"); }
+ long tmpLongValue;
+ String line = "";
+ int nextIndex = 0;
+ int indexIndex = 0;
+ if (indexes.length > 0) {
+ nextIndex = indexes[0];
+ indexIndex++;
+ }
+ for (int x = 0; x < data.length; x++) {
+ tmpLongValue = (long)data[x] & 0xff;
+
+ if (indexes.length > 0 &&
+ x == nextIndex &&
+ nextIndex < data.length)
+ {
+ System.out.print("+");
+ line += "+";
+ while (indexIndex < indexes.length-1 && indexes[indexIndex] <= nextIndex)
+ {
+ indexIndex++;
+ }
+ nextIndex = indexes[indexIndex];
+ //indexIndex++;
+ }
+
+ if (Character.isLetterOrDigit((char)tmpLongValue)) {
+ line += (char)tmpLongValue;
+ }
+ else
+ {
+ line += ".";
+ }
+
+ if (Long.toHexString(tmpLongValue).length() < 2) {
+ System.out.print("0");
+ }
+ System.out.print(Long.toHexString(tmpLongValue));
+ if (x % 2 == 1 && pretty) {
+ System.out.print(" ");
+ }
+ if (x % 16 == 15 && pretty) {
+ System.out.print(" "+line);
+ System.out.println("");
+ line = "";
+ }
+ }
+ if (pretty) { System.out.println(" "+line); System.out.println("---"); System.out.println(data.length); } else { }
+ }
+
+
+
+ /**
+ * decode a lump of data that has been encrypted with the compressible encryption
+ * @param data
+ * @return decoded data
+ */
+ public static byte[] decode(byte[] data) {
+ int temp;
+ for (int x = 0; x < data.length; x++) {
+ temp = data[x] & 0xff;
+ data[x] = (byte)compEnc[temp];
+ }
+ return data;
+ }
+
+
+ public static byte[] encode(byte[] data) {
+ // create the encoding array...
+ int[] enc = new int[compEnc.length];
+ for (int x = 0; x < enc.length; x++) {
+ enc[compEnc[x]] = x;
+ }
+
+ // now it's just the same as decode...
+ int temp;
+ for (int x = 0; x < data.length; x++) {
+ temp = data[x] & 0xff;
+ data[x] = (byte)enc[temp];
+ }
+ return data;
+ }
+
+
+ /**
+ * Utility function for converting little endian bytes into a usable java long
+ * @param data
+ * @return long version of the data
+ */
+ public static long convertLittleEndianBytesToLong(byte[] data) {
+ return convertLittleEndianBytesToLong(data, 0, data.length);
+ }
+ /**
+ * Utility function for converting little endian bytes into a usable java long
+ * @param data
+ * @param start
+ * @param end
+ * @return long version of the data
+ */
+ public static long convertLittleEndianBytesToLong(byte[] data, int start, int end) {
+
+ long offset = data[end-1] & 0xff;
+ long tmpLongValue;
+ for (int x = end-2; x >= start; x--) {
+ offset = offset << 8;
+ tmpLongValue = (long)data[x] & 0xff;
+ offset |= tmpLongValue;
+ }
+
+ return offset;
+ }
+
+ /**
+ * Utility function for converting big endian bytes into a usable java long
+ * @param data
+ * @param start
+ * @param end
+ * @return long version of the data
+ */
+ public static long convertBigEndianBytesToLong(byte[] data, int start, int end) {
+
+ long offset = 0;
+ for ( int x = start; x < end; ++x ) {
+ offset = offset << 8;
+ offset |= ((long)data[x] & 0xFFL);
+ }
+
+ return offset;
+ }
+/*
+ protected static boolean isPSTArray(byte[] data) {
+ return (data[0] == 1 && data[1] == 1);
+ }
+/**/
+/*
+ protected static int[] getBlockOffsets(RandomAccessFile in, byte[] data)
+ throws IOException, PSTException
+ {
+ // is the data an array?
+ if (!(data[0] == 1 && data[1] == 1))
+ {
+ throw new PSTException("Unable to process array, does not appear to be one!");
+ }
+
+ // we are an array!
+ // get the array items and merge them together
+ int numberOfEntries = (int)PSTObject.convertLittleEndianBytesToLong(data, 2, 4);
+ int[] output = new int[numberOfEntries];
+ int tableOffset = 8;
+ int blockOffset = 0;
+ for (int y = 0; y < numberOfEntries; y++) {
+ // get the offset identifier
+ long tableOffsetIdentifierIndex = PSTObject.convertLittleEndianBytesToLong(data, tableOffset, tableOffset+8);
+ // clear the last bit of the identifier. Why so hard?
+ tableOffsetIdentifierIndex = (tableOffsetIdentifierIndex & 0xfffffffe);
+ OffsetIndexItem tableOffsetIdentifier = PSTObject.getOffsetIndexNode(in, tableOffsetIdentifierIndex);
+ blockOffset += tableOffsetIdentifier.size;
+ output[y] = blockOffset;
+ tableOffset += 8;
+ }
+
+ // replace the item data with the stuff from the array...
+ return output;
+ }
+/**/
+
+
+
+
+
+ /**
+ * the code below was taken from a random apache project
+ * http://www.koders.com/java/fidA9D4930E7443F69F32571905DD4CA01E4D46908C.aspx
+ * my bit-shifting isn't that 1337
+ */
+
+ /**
+ *
The difference between the Windows epoch (1601-01-01
+ * 00:00:00) and the Unix epoch (1970-01-01 00:00:00) in
+ * milliseconds: 11644473600000L. (Use your favorite spreadsheet
+ * program to verify the correctness of this value. By the way,
+ * did you notice that you can tell from the epochs which
+ * operating system is the modern one? :-))
+ */
+ private static final long EPOCH_DIFF = 11644473600000L;
+
+ /**
+ * Converts a Windows FILETIME into a {@link Date}. The Windows
+ * FILETIME structure holds a date and time associated with a
+ * file. The structure identifies a 64-bit integer specifying the
+ * number of 100-nanosecond intervals which have passed since
+ * January 1, 1601. This 64-bit value is split into the two double
+ * words stored in the structure.
+ *
+ * @param high The higher double word of the FILETIME structure.
+ * @param low The lower double word of the FILETIME structure.
+ * @return The Windows FILETIME as a {@link Date}.
+ */
+ public static Date filetimeToDate(final int high, final int low) {
+ final long filetime = ((long) high) << 32 | (low & 0xffffffffL);
+ //System.out.printf("0x%X\n", filetime);
+ final long ms_since_16010101 = filetime / (1000 * 10);
+ final long ms_since_19700101 = ms_since_16010101 - EPOCH_DIFF;
+ return new Date(ms_since_19700101);
+ }
+
+ public static Calendar apptTimeToCalendar(int minutes) {
+ final long ms_since_16010101 = minutes * (60*1000L);
+ final long ms_since_19700101 = ms_since_16010101 - EPOCH_DIFF;
+ Calendar c = Calendar.getInstance(PSTTimeZone.utcTimeZone);
+ c.setTimeInMillis(ms_since_19700101);
+ return c;
+ }
+
+ public static Calendar apptTimeToUTC(int minutes, PSTTimeZone tz) {
+ // Must convert minutes since 1/1/1601 in local time to UTC
+ // There's got to be a better way of doing this...
+ // First get a UTC calendar object that contains _local time_
+ Calendar cUTC = apptTimeToCalendar(minutes);
+ if ( tz != null ) {
+ // Create an empty Calendar object with the required time zone
+ Calendar cLocal = Calendar.getInstance(tz.getSimpleTimeZone());
+ cLocal.clear();
+
+ // Now transfer the local date/time from the UTC calendar object
+ // to the object that knows about the time zone...
+ cLocal.set(cUTC.get(Calendar.YEAR),
+ cUTC.get(Calendar.MONTH),
+ cUTC.get(Calendar.DATE),
+ cUTC.get(Calendar.HOUR_OF_DAY),
+ cUTC.get(Calendar.MINUTE),
+ cUTC.get(Calendar.SECOND));
+
+ // Get the true UTC from the local time calendar object.
+ // Drop any milliseconds, they won't be printed anyway!
+ long utcs = cLocal.getTimeInMillis() / 1000;
+
+ // Finally, set the true UTC in the UTC calendar object
+ cUTC.setTimeInMillis(utcs * 1000);
+ } // else hope for the best!
+
+ return cUTC;
+ }
+
+
+
+
+ public static int getCompEnc(int value) {
+ return compEnc[value];
+ }
+
+
+ public static String decodeLZFU(byte[] data) throws PSTException {
+
+ @SuppressWarnings("unused")
+ int compressedSize = (int)PSTUtils.convertLittleEndianBytesToLong(data, 0, 4);
+ int uncompressedSize = (int)PSTUtils.convertLittleEndianBytesToLong(data, 4, 8);
+ int compressionSig = (int)PSTUtils.convertLittleEndianBytesToLong(data, 8, 12);
+ @SuppressWarnings("unused")
+ int compressedCRC = (int)PSTUtils.convertLittleEndianBytesToLong(data, 12, 16);
+
+ if (compressionSig == 0x75465a4c) {
+ // we are compressed...
+ byte[] output = new byte[uncompressedSize];
+ int outputPosition = 0;
+ byte[] lzBuffer = new byte[4096];
+ // preload our buffer.
+ try {
+ byte[] bytes = LZFU_HEADER.getBytes("US-ASCII");
+ System.arraycopy(bytes, 0, lzBuffer, 0, LZFU_HEADER.length());
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ int bufferPosition = LZFU_HEADER.length();
+ int currentDataPosition = 16;
+
+ // next byte is the flags,
+ while (currentDataPosition < data.length - 2 && outputPosition < output.length) {
+ int flags = data[currentDataPosition++] & 0xFF;
+ for (int x = 0; x < 8 && outputPosition < output.length; x++) {
+ boolean isRef = ((flags & 1) == 1);
+ flags >>= 1;
+ if (isRef) {
+ // get the starting point for the buffer and the
+ // length to read
+ int refOffsetOrig = data[currentDataPosition++] & 0xFF;
+ int refSizeOrig = data[currentDataPosition++] & 0xFF;
+ int refOffset = (refOffsetOrig << 4) | (refSizeOrig >>> 4);
+ int refSize = (refSizeOrig & 0xF) + 2;
+ //refOffset &= 0xFFF;
+ try {
+ // copy the data from the buffer
+ int index = refOffset;
+ for (int y = 0; y < refSize && outputPosition < output.length; y++) {
+ output[outputPosition++] = lzBuffer[index];
+ lzBuffer[bufferPosition] = lzBuffer[index];
+ bufferPosition++;
+ bufferPosition %= 4096;
+ ++index;
+ index %= 4096;
+ }
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ }
+
+ } else {
+ // copy the byte over
+ lzBuffer[bufferPosition] = data[currentDataPosition];
+ bufferPosition++;
+ bufferPosition %= 4096;
+ output[outputPosition++] = data[currentDataPosition++];
+ }
+ }
+ }
+
+ if ( outputPosition != uncompressedSize ) {
+ throw new PSTException(String.format("Error decompressing RTF! Expected %d bytes, got %d bytes\n", uncompressedSize, outputPosition));
+ }
+ return new String(output).trim();
+
+ } else if (compressionSig == 0x414c454d) {
+ // we are not compressed!
+ // just return the rest of the contents as a string
+ byte[] output = new byte[data.length-16];
+ System.arraycopy(data, 16, output, 0, data.length-16);
+ return new String(output).trim();
+ }
+
+ return "";
+ }
+
+}
diff --git a/com/pff/PSTAppointmentException.java b/com/pff/exceptions/PSTAppointmentException.java
similarity index 60%
rename from com/pff/PSTAppointmentException.java
rename to com/pff/exceptions/PSTAppointmentException.java
index 9230070..8e88ba1 100644
--- a/com/pff/PSTAppointmentException.java
+++ b/com/pff/exceptions/PSTAppointmentException.java
@@ -32,12 +32,16 @@
*
*/
-package com.pff;
+package com.pff.exceptions;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
+import com.pff.PSTUtils;
+import com.pff.objects.PSTAppointment;
+import com.pff.objects.sub.PSTTimeZone;
+
/**
* Class containing information on exceptions to a recurring appointment
* @author Orin Eman
@@ -49,9 +53,9 @@ public class PSTAppointmentException {
// Access methods - return the value from the exception if
// OverrideFlags say it's present, otherwise the value from the appointment.
public String getSubject() {
- if ( (OverrideFlags & 0x0001) != 0 ) {
+ if ( (overrideFlags & 0x0001) != 0 ) {
try {
- return new String(WideCharSubject, "UTF-16LE");
+ return new String(wideCharSubject, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
@@ -63,8 +67,8 @@ public String getSubject() {
public int getMeetingType()
{
- if ( (OverrideFlags & 0x0002) != 0 ) {
- return MeetingType;
+ if ( (overrideFlags & 0x0002) != 0 ) {
+ return meetingType;
}
return appt.getMeetingStatus();
@@ -72,7 +76,7 @@ public int getMeetingType()
public int getReminderDelta() {
- if ( (OverrideFlags & 0x0004) != 0 ) {
+ if ( (overrideFlags & 0x0004) != 0 ) {
return ReminderDelta;
}
@@ -81,7 +85,7 @@ public int getReminderDelta() {
public boolean getReminderSet() {
- if ( (OverrideFlags & 0x0008) != 0 ) {
+ if ( (overrideFlags & 0x0008) != 0 ) {
return ReminderSet;
}
@@ -90,9 +94,9 @@ public boolean getReminderSet() {
public String getLocation() {
- if ( (OverrideFlags & 0x0010) != 0 ) {
+ if ( (overrideFlags & 0x0010) != 0 ) {
try {
- return new String(WideCharLocation, "UTF-16LE");
+ return new String(wideCharLocation, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
@@ -103,8 +107,8 @@ public String getLocation() {
public int getBusyStatus() {
- if ( (OverrideFlags & 0x0020) != 0 ) {
- return BusyStatus;
+ if ( (overrideFlags & 0x0020) != 0 ) {
+ return busyStatus;
}
return appt.getBusyStatus();
@@ -112,8 +116,8 @@ public int getBusyStatus() {
public boolean getSubType() {
- if ( (OverrideFlags & 0x0080) != 0 ) {
- return SubType;
+ if ( (overrideFlags & 0x0080) != 0 ) {
+ return subType;
}
return appt.getSubType();
@@ -144,15 +148,15 @@ public Date getDTStamp() {
}
public int getStartDateTime() {
- return StartDateTime;
+ return startDateTime;
}
public int getEndDateTime() {
- return EndDateTime;
+ return endDateTime;
}
public int getOriginalStartDate() {
- return OriginalStartDate;
+ return originalStartDate;
}
public int getAppointmentSequence(int def) {
@@ -170,28 +174,23 @@ public int getImportance(int def) {
}
public byte[] getSubjectBytes() {
- if ( (OverrideFlags & 0x0010) != 0 ) {
+ if ( (overrideFlags & 0x0010) != 0 ) {
return Subject;
}
-
return null;
}
public byte[] getLocationBytes() {
- if ( (OverrideFlags & 0x0010) != 0 ) {
- return Location;
+ if ( (overrideFlags & 0x0010) != 0 ) {
+ return location;
}
-
return null;
}
public boolean attachmentsPresent() {
- if ( (OverrideFlags & 0x0040) != 0 &&
- Attachment == 0x00000001 )
- {
+ if ( (overrideFlags & 0x0040) != 0 && attachment == 0x00000001 ) {
return true;
}
-
return false;
}
@@ -207,109 +206,106 @@ public PSTAppointment getEmbeddedMessage() {
return embeddedMessage;
}
- PSTAppointmentException(byte[] recurrencePattern,
- int offset,
- int writerVersion2,
- PSTAppointment appt) {
+ public PSTAppointmentException(byte[] recurrencePattern, int offset, int writerVersion2, PSTAppointment appt) {
this.writerVersion2 = writerVersion2;
int initialOffset = offset;
this.appt = appt;
embeddedMessage = null;
- StartDateTime = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ startDateTime = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- EndDateTime = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ endDateTime = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- OriginalStartDate = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ originalStartDate = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- OverrideFlags = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
+ overrideFlags = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
- if ( (OverrideFlags & ARO_SUBJECT) != 0 ) {
+ if ( (overrideFlags & ARO_SUBJECT) != 0 ) {
//@SuppressWarnings("unused")
//short SubjectLength = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
- short SubjectLength2 = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
+ short SubjectLength2 = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
Subject = new byte[SubjectLength2];
System.arraycopy(recurrencePattern, offset, Subject, 0, SubjectLength2);
offset += SubjectLength2;
}
- if ( (OverrideFlags & ARO_MEETINGTYPE) != 0 ) {
- MeetingType = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ if ( (overrideFlags & ARO_MEETINGTYPE) != 0 ) {
+ meetingType = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
}
- if ( (OverrideFlags & ARO_REMINDERDELTA) != 0 ) {
- ReminderDelta = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ if ( (overrideFlags & ARO_REMINDERDELTA) != 0 ) {
+ ReminderDelta = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
}
- if ( (OverrideFlags & ARO_REMINDER) != 0 ) {
- ReminderSet = ((int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4) != 0);
+ if ( (overrideFlags & ARO_REMINDER) != 0 ) {
+ ReminderSet = ((int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4) != 0);
offset += 4;
}
- if ( (OverrideFlags & ARO_LOCATION) != 0 ) {
+ if ( (overrideFlags & ARO_LOCATION) != 0 ) {
//@SuppressWarnings("unused")
//short LocationLength = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
- short LocationLength2 = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
+ short LocationLength2 = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
- Location = new byte[LocationLength2];
- System.arraycopy(recurrencePattern, offset, Location, 0, LocationLength2);
+ location = new byte[LocationLength2];
+ System.arraycopy(recurrencePattern, offset, location, 0, LocationLength2);
offset += LocationLength2;
}
- if ( (OverrideFlags & ARO_BUSYSTATUS) != 0 ) {
- BusyStatus = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ if ( (overrideFlags & ARO_BUSYSTATUS) != 0 ) {
+ busyStatus = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
}
- if ( (OverrideFlags & ARO_ATTACHMENT) != 0 ) {
- Attachment = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ if ( (overrideFlags & ARO_ATTACHMENT) != 0 ) {
+ attachment = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
}
- if ( (OverrideFlags & ARO_SUBTYPE) != 0 ) {
- SubType = ((int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4) != 0);
+ if ( (overrideFlags & ARO_SUBTYPE) != 0 ) {
+ subType = ((int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4) != 0);
offset += 4;
}
length = offset - initialOffset;
}
- void ExtendedException(byte[] recurrencePattern, int offset) {
+ public void buildExtendedException(byte[] recurrencePattern, int offset) {
int initialOffset = offset;
if ( writerVersion2 >= 0x00003009 ) {
- int ChangeHighlightSize = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ int ChangeHighlightSize = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- ChangeHighlightValue = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ changeHighlightValue = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += ChangeHighlightSize;
}
- int ReservedBlockEESize = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ int ReservedBlockEESize = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4 + ReservedBlockEESize;
// See http://msdn.microsoft.com/en-us/library/cc979209(office.12).aspx
- if ( (OverrideFlags & (ARO_SUBJECT|ARO_LOCATION)) != 0 ) {
+ if ( (overrideFlags & (ARO_SUBJECT|ARO_LOCATION)) != 0 ) {
// Same as regular Exception structure?
- StartDateTime = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ startDateTime = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- EndDateTime = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ endDateTime = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- OriginalStartDate = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ originalStartDate = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
}
- if ( (OverrideFlags & ARO_SUBJECT) != 0 ) {
- WideCharSubjectLength = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
+ if ( (overrideFlags & ARO_SUBJECT) != 0 ) {
+ wideCharSubjectLength = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
- WideCharSubject = new byte[WideCharSubjectLength * 2];
- System.arraycopy(recurrencePattern, offset, WideCharSubject, 0, WideCharSubject.length);
- offset += WideCharSubject.length;
+ wideCharSubject = new byte[wideCharSubjectLength * 2];
+ System.arraycopy(recurrencePattern, offset, wideCharSubject, 0, wideCharSubject.length);
+ offset += wideCharSubject.length;
/*
try {
String subject = new String(WideCharSubject, "UTF-16LE");
@@ -320,47 +316,47 @@ void ExtendedException(byte[] recurrencePattern, int offset) {
/**/
}
- if ( (OverrideFlags & ARO_LOCATION) != 0 ) {
- WideCharLocationLength = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
+ if ( (overrideFlags & ARO_LOCATION) != 0 ) {
+ wideCharLocationLength = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
- WideCharLocation = new byte[WideCharLocationLength*2];
- System.arraycopy(recurrencePattern, offset, WideCharLocation, 0, WideCharLocation.length);
- offset += WideCharLocation.length;
+ wideCharLocation = new byte[wideCharLocationLength*2];
+ System.arraycopy(recurrencePattern, offset, wideCharLocation, 0, wideCharLocation.length);
+ offset += wideCharLocation.length;
}
// See http://msdn.microsoft.com/en-us/library/cc979209(office.12).aspx
- if ( (OverrideFlags & (ARO_SUBJECT|ARO_LOCATION)) != 0 ) {
- ReservedBlockEESize = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ if ( (overrideFlags & (ARO_SUBJECT|ARO_LOCATION)) != 0 ) {
+ ReservedBlockEESize = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4 + ReservedBlockEESize;
}
extendedLength = offset - initialOffset;
}
- void setEmbeddedMessage(PSTAppointment embeddedMessage) {
+ public void setEmbeddedMessage(PSTAppointment embeddedMessage) {
this.embeddedMessage = embeddedMessage;
}
private int writerVersion2;
- private int StartDateTime;
- private int EndDateTime;
- private int OriginalStartDate;
- private short OverrideFlags;
+ private int startDateTime;
+ private int endDateTime;
+ private int originalStartDate;
+ private short overrideFlags;
private byte[] Subject = null;
- private int MeetingType;
+ private int meetingType;
private int ReminderDelta;
private boolean ReminderSet;
- private byte[] Location = null;
- private int BusyStatus;
- private int Attachment;
- private boolean SubType;
+ private byte[] location = null;
+ private int busyStatus;
+ private int attachment;
+ private boolean subType;
// private int AppointmentColor; // Reserved - don't read from the PST file
@SuppressWarnings("unused")
- private int ChangeHighlightValue;
- private int WideCharSubjectLength = 0;
- private byte[] WideCharSubject = null;
- private int WideCharLocationLength = 0;
- private byte[] WideCharLocation = null;
+ private int changeHighlightValue;
+ private int wideCharSubjectLength = 0;
+ private byte[] wideCharSubject = null;
+ private int wideCharLocationLength = 0;
+ private byte[] wideCharLocation = null;
private PSTAppointment embeddedMessage = null;
private PSTAppointment appt;
private int length;
@@ -368,12 +364,12 @@ void setEmbeddedMessage(PSTAppointment embeddedMessage) {
// Length of this ExceptionInfo structure in the PST file
- int getLength() {
+ public int getLength() {
return length;
}
// Length of this ExtendedException structure in the PST file
- int getExtendedLength() {
+ public int getExtendedLength() {
return extendedLength;
}
diff --git a/com/pff/PSTException.java b/com/pff/exceptions/PSTException.java
similarity index 93%
rename from com/pff/PSTException.java
rename to com/pff/exceptions/PSTException.java
index 36d570e..b573ced 100644
--- a/com/pff/PSTException.java
+++ b/com/pff/exceptions/PSTException.java
@@ -31,7 +31,7 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.exceptions;
/**
* Simple exception for PST File related errors
@@ -44,10 +44,10 @@ public class PSTException extends Exception
*/
private static final long serialVersionUID = 4284698344354718143L;
- PSTException(String error) {
+ public PSTException(String error) {
super(error);
}
- PSTException(String error, Exception orig) {
+ public PSTException(String error, Exception orig) {
super(error, orig);
}
}
diff --git a/com/pff/PSTActivity.java b/com/pff/objects/PSTActivity.java
similarity index 80%
rename from com/pff/PSTActivity.java
rename to com/pff/objects/PSTActivity.java
index d4cae3d..460bf2a 100644
--- a/com/pff/PSTActivity.java
+++ b/com/pff/objects/PSTActivity.java
@@ -31,11 +31,17 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.IOException;
-import java.util.HashMap;
import java.util.Date;
+import java.util.HashMap;
+
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.source.PSTSource;
/**
* PSTActivity represents Journal entries
@@ -49,7 +55,7 @@ public class PSTActivity extends PSTMessage {
* @throws PSTException
* @throws IOException
*/
- public PSTActivity(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ public PSTActivity(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException {
super(theFile, descriptorIndexNode);
}
@@ -60,7 +66,7 @@ public PSTActivity(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
* @param table
* @param localDescriptorItems
*/
- public PSTActivity(PSTFile theFile, DescriptorIndexNode folderIndexNode,
+ public PSTActivity(PSTSource theFile, DescriptorIndexNode folderIndexNode,
PSTTableBC table,
HashMap localDescriptorItems) {
super(theFile, folderIndexNode, table, localDescriptorItems);
@@ -70,61 +76,61 @@ public PSTActivity(PSTFile theFile, DescriptorIndexNode folderIndexNode,
* Type
*/
public String getLogType() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008700, PSTFile.PSETID_Log));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008700, PSTSource.PSETID_Log));
}
/**
* Start
*/
public Date getLogStart() {
- return getDateItem(pstFile.getNameToIdMapItem(0x00008706, PSTFile.PSETID_Log));
+ return getDateItem(pstFile.getNameToIdMapItem(0x00008706, PSTSource.PSETID_Log));
}
/**
* Duration
*/
public int getLogDuration() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008707, PSTFile.PSETID_Log));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008707, PSTSource.PSETID_Log));
}
/**
* End
*/
public Date getLogEnd() {
- return getDateItem(pstFile.getNameToIdMapItem(0x00008708, PSTFile.PSETID_Log));
+ return getDateItem(pstFile.getNameToIdMapItem(0x00008708, PSTSource.PSETID_Log));
}
/**
* LogFlags
*/
public int getLogFlags() {
- return getIntItem(pstFile.getNameToIdMapItem(0x0000870c, PSTFile.PSETID_Log));
+ return getIntItem(pstFile.getNameToIdMapItem(0x0000870c, PSTSource.PSETID_Log));
}
/**
* DocPrinted
*/
public boolean isDocumentPrinted() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x0000870e, PSTFile.PSETID_Log)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x0000870e, PSTSource.PSETID_Log)));
}
/**
* DocSaved
*/
public boolean isDocumentSaved() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x0000870f, PSTFile.PSETID_Log)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x0000870f, PSTSource.PSETID_Log)));
}
/**
* DocRouted
*/
public boolean isDocumentRouted() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008710, PSTFile.PSETID_Log)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008710, PSTSource.PSETID_Log)));
}
/**
* DocPosted
*/
public boolean isDocumentPosted() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008711, PSTFile.PSETID_Log)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008711, PSTSource.PSETID_Log)));
}
/**
* Type Description
*/
public String getLogTypeDesc() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008712, PSTFile.PSETID_Log));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008712, PSTSource.PSETID_Log));
}
public String toString() {
diff --git a/com/pff/PSTAppointment.java b/com/pff/objects/PSTAppointment.java
similarity index 62%
rename from com/pff/PSTAppointment.java
rename to com/pff/objects/PSTAppointment.java
index b82216e..df69cce 100644
--- a/com/pff/PSTAppointment.java
+++ b/com/pff/objects/PSTAppointment.java
@@ -31,59 +31,67 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
+import com.pff.exceptions.PSTException;
+import com.pff.objects.sub.PSTGlobalObjectId;
+import com.pff.objects.sub.PSTTimeZone;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.source.PSTSource;
+
/**
* PSTAppointment is for Calendar items
* @author Richard Johnson
*/
public class PSTAppointment extends PSTMessage {
- PSTAppointment(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ public PSTAppointment(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException
{
super(theFile, descriptorIndexNode);
}
- PSTAppointment(PSTFile theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems)
+ public PSTAppointment(PSTSource theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems)
{
super(theFile, folderIndexNode, table, localDescriptorItems);
}
public boolean getSendAsICAL() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008200, PSTFile.PSETID_Appointment)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008200, PSTSource.PSETID_Appointment)));
}
public int getBusyStatus()
{
- return getIntItem(pstFile.getNameToIdMapItem(0x00008205, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008205, PSTSource.PSETID_Appointment));
}
public boolean getShowAsBusy() {
return getBusyStatus() == 2;
}
public String getLocation() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008208, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008208, PSTSource.PSETID_Appointment));
}
public Date getStartTime() {
- return getDateItem(pstFile.getNameToIdMapItem(0x0000820d, PSTFile.PSETID_Appointment));
+ return getDateItem(pstFile.getNameToIdMapItem(0x0000820d, PSTSource.PSETID_Appointment));
}
public PSTTimeZone getStartTimeZone() {
- return getTimeZoneItem(pstFile.getNameToIdMapItem(0x0000825e, PSTFile.PSETID_Appointment));
+ return getTimeZoneItem(pstFile.getNameToIdMapItem(0x0000825e, PSTSource.PSETID_Appointment));
}
public Date getEndTime() {
- return getDateItem(pstFile.getNameToIdMapItem(0x0000820e, PSTFile.PSETID_Appointment));
+ return getDateItem(pstFile.getNameToIdMapItem(0x0000820e, PSTSource.PSETID_Appointment));
}
public PSTTimeZone getEndTimeZone() {
- return getTimeZoneItem(pstFile.getNameToIdMapItem(0x0000825f, PSTFile.PSETID_Appointment));
+ return getTimeZoneItem(pstFile.getNameToIdMapItem(0x0000825f, PSTSource.PSETID_Appointment));
}
public PSTTimeZone getRecurrenceTimeZone() {
- String desc = getStringItem(pstFile.getNameToIdMapItem(0x00008234, PSTFile.PSETID_Appointment));
+ String desc = getStringItem(pstFile.getNameToIdMapItem(0x00008234, PSTSource.PSETID_Appointment));
if ( desc!= null && desc.length() != 0 ) {
- byte[] tzData = getBinaryItem(pstFile.getNameToIdMapItem(0x00008233, PSTFile.PSETID_Appointment));
+ byte[] tzData = getBinaryItem(pstFile.getNameToIdMapItem(0x00008233, PSTSource.PSETID_Appointment));
if ( tzData != null && tzData.length != 0 ) {
return new PSTTimeZone(desc, tzData);
}
@@ -91,103 +99,110 @@ public PSTTimeZone getRecurrenceTimeZone() {
return null;
}
public int getDuration() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008213, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008213, PSTSource.PSETID_Appointment));
}
public int getColor() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008214, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008214, PSTSource.PSETID_Appointment));
}
public boolean getSubType() {
- return (getIntItem(pstFile.getNameToIdMapItem(0x00008215, PSTFile.PSETID_Appointment)) != 0);
+ return (getIntItem(pstFile.getNameToIdMapItem(0x00008215, PSTSource.PSETID_Appointment)) != 0);
}
public int getMeetingStatus() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008217, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008217, PSTSource.PSETID_Appointment));
}
public int getResponseStatus() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008218, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008218, PSTSource.PSETID_Appointment));
}
public boolean isRecurring() {
- return getBooleanItem(pstFile.getNameToIdMapItem(0x00008223, PSTFile.PSETID_Appointment));
+ return getBooleanItem(pstFile.getNameToIdMapItem(0x00008223, PSTSource.PSETID_Appointment));
}
public Date getRecurrenceBase() {
- return getDateItem(pstFile.getNameToIdMapItem(0x00008228, PSTFile.PSETID_Appointment));
+ return getDateItem(pstFile.getNameToIdMapItem(0x00008228, PSTSource.PSETID_Appointment));
}
public int getRecurrenceType() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008231, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008231, PSTSource.PSETID_Appointment));
}
public String getRecurrencePattern() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008232, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008232, PSTSource.PSETID_Appointment));
}
public byte[] getRecurrenceStructure() {
- return getBinaryItem(pstFile.getNameToIdMapItem(0x00008216, PSTFile.PSETID_Appointment));
+ return getBinaryItem(pstFile.getNameToIdMapItem(0x00008216, PSTSource.PSETID_Appointment));
}
public byte[] getTimezone() {
- return getBinaryItem(pstFile.getNameToIdMapItem(0x00008233, PSTFile.PSETID_Appointment));
+ return getBinaryItem(pstFile.getNameToIdMapItem(0x00008233, PSTSource.PSETID_Appointment));
}
public String getAllAttendees() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008238, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008238, PSTSource.PSETID_Appointment));
}
public String getToAttendees() {
- return getStringItem(pstFile.getNameToIdMapItem(0x0000823b, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x0000823b, PSTSource.PSETID_Appointment));
}
public String getCCAttendees() {
- return getStringItem(pstFile.getNameToIdMapItem(0x0000823c, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x0000823c, PSTSource.PSETID_Appointment));
}
public int getAppointmentSequence() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008201, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008201, PSTSource.PSETID_Appointment));
}
// online meeting properties
public boolean isOnlineMeeting() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008240, PSTFile.PSETID_Appointment)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008240, PSTSource.PSETID_Appointment)));
}
public int getNetMeetingType() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008241, PSTFile.PSETID_Appointment));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008241, PSTSource.PSETID_Appointment));
}
public String getNetMeetingServer() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008242, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008242, PSTSource.PSETID_Appointment));
}
public String getNetMeetingOrganizerAlias() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008243, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008243, PSTSource.PSETID_Appointment));
}
public boolean getNetMeetingAutostart() {
- return (getIntItem(pstFile.getNameToIdMapItem(0x00008245, PSTFile.PSETID_Appointment)) != 0);
+ return (getIntItem(pstFile.getNameToIdMapItem(0x00008245, PSTSource.PSETID_Appointment)) != 0);
}
public boolean getConferenceServerAllowExternal() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008246, PSTFile.PSETID_Appointment)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008246, PSTSource.PSETID_Appointment)));
}
public String getNetMeetingDocumentPathName() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008247, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008247, PSTSource.PSETID_Appointment));
}
public String getNetShowURL() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008248, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008248, PSTSource.PSETID_Appointment));
}
public Date getAttendeeCriticalChange() {
- return getDateItem(pstFile.getNameToIdMapItem(0x00000001, PSTFile.PSETID_Meeting));
+ return getDateItem(pstFile.getNameToIdMapItem(0x00000001, PSTSource.PSETID_Meeting));
}
public Date getOwnerCriticalChange() {
- return getDateItem(pstFile.getNameToIdMapItem(0x0000001a, PSTFile.PSETID_Meeting));
+ return getDateItem(pstFile.getNameToIdMapItem(0x0000001a, PSTSource.PSETID_Meeting));
}
public String getConferenceServerPassword() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008249, PSTFile.PSETID_Appointment));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008249, PSTSource.PSETID_Appointment));
}
public boolean getAppointmentCounterProposal() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008257, PSTFile.PSETID_Appointment)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x00008257, PSTSource.PSETID_Appointment)));
}
public boolean isSilent() {
- return (getBooleanItem(pstFile.getNameToIdMapItem(0x00000004, PSTFile.PSETID_Meeting)));
+ return (getBooleanItem(pstFile.getNameToIdMapItem(0x00000004, PSTSource.PSETID_Meeting)));
}
public String getRequiredAttendees() {
- return getStringItem(this.pstFile.getNameToIdMapItem(0x00000006, PSTFile.PSETID_Meeting));
+ return getStringItem(this.pstFile.getNameToIdMapItem(0x00000006, PSTSource.PSETID_Meeting));
}
public int getLocaleId() {
return getIntItem(0x3ff1);
}
- public byte[] getGlobalObjectId() {
- return getBinaryItem(pstFile.getNameToIdMapItem(0x00000003, PSTFile.PSETID_Meeting));
+ /*public byte[] getGlobalObjectId() {
+ return getBinaryItem(pstFile.getNameToIdMapItem(0x00000003, PSTSource.PSETID_Meeting));
+ }*/
+ public PSTGlobalObjectId getGlobalObjectId() {
+ return new PSTGlobalObjectId(getBinaryItem(pstFile.getNameToIdMapItem(0x00000003, PSTSource.PSETID_Meeting)));
+ }
+
+ public PSTGlobalObjectId getCleanGlobalObjectId() {
+ return new PSTGlobalObjectId(getBinaryItem(pstFile.getNameToIdMapItem(0x00000023, PSTSource.PSETID_Meeting)));
}
}
diff --git a/com/pff/PSTAttachment.java b/com/pff/objects/PSTAttachment.java
similarity index 92%
rename from com/pff/PSTAttachment.java
rename to com/pff/objects/PSTAttachment.java
index 2b2f1db..3e03643 100644
--- a/com/pff/PSTAttachment.java
+++ b/com/pff/objects/PSTAttachment.java
@@ -31,11 +31,19 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.*;
import java.util.*;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.parsing.tables.PSTTableBCItem;
+import com.pff.source.PSTSource;
+
/**
* Class containing attachment information
@@ -43,7 +51,7 @@
*/
public class PSTAttachment extends PSTObject {
- PSTAttachment(PSTFile theFile, PSTTableBC table, HashMap localDescriptorItems) {
+ PSTAttachment(PSTSource theFile, PSTTableBC table, HashMap localDescriptorItems) {
super(theFile, null, table, localDescriptorItems);
}
@@ -74,11 +82,11 @@ public PSTMessage getEmbeddedPSTMessage()
throw new PSTException("External reference in getEmbeddedPSTMessage()!\n");
}
} else if ( item.entryValueType == 0x000D ) {
- int descriptorItem = (int)PSTObject.convertLittleEndianBytesToLong(item.data, 0, 4);
+ int descriptorItem = (int)PSTUtils.convertLittleEndianBytesToLong(item.data, 0, 4);
//PSTObject.printHexFormatted(item.data, true);
PSTDescriptorItem descriptorItemNested = this.localDescriptorItems.get(descriptorItem);
in = new PSTNodeInputStream(this.pstFile, descriptorItemNested);
- this.localDescriptorItems.putAll(pstFile.getPSTDescriptorItems(descriptorItemNested.subNodeOffsetIndexIdentifier));
+ this.localDescriptorItems.putAll(pstFile.getPSTDescriptorItems(descriptorItemNested.getSubNodeOffsetIndexIdentifier()));
/*
if ( descriptorItemNested != null ) {
try {
diff --git a/com/pff/PSTContact.java b/com/pff/objects/PSTContact.java
similarity index 96%
rename from com/pff/PSTContact.java
rename to com/pff/objects/PSTContact.java
index 7a1bd10..a3170cd 100644
--- a/com/pff/PSTContact.java
+++ b/com/pff/objects/PSTContact.java
@@ -31,12 +31,18 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.source.PSTSource;
+
/**
* Class for Contacts
@@ -50,7 +56,7 @@ public class PSTContact extends PSTMessage {
* @throws PSTException
* @throws IOException
*/
- public PSTContact(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ public PSTContact(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException {
super(theFile, descriptorIndexNode);
}
@@ -61,7 +67,7 @@ public PSTContact(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
* @param table
* @param localDescriptorItems
*/
- public PSTContact(PSTFile theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems) {
+ public PSTContact(PSTSource theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems) {
super(theFile, folderIndexNode, table, localDescriptorItems);
}
@@ -416,7 +422,7 @@ public String getNote() {
}
String getNamedStringItem(int key) {
- int id = pstFile.getNameToIdMapItem(key, PSTFile.PSETID_Address);
+ int id = pstFile.getNameToIdMapItem(key, PSTSource.PSETID_Address);
if ( id != -1 ) {
return getStringItem(id);
}
@@ -548,7 +554,7 @@ public String getOtherAddress() {
* Selected Mailing Address
*/
public int getPostalAddressId() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008022, PSTFile.PSETID_Address));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008022, PSTSource.PSETID_Address));
}
/**
diff --git a/com/pff/PSTFolder.java b/com/pff/objects/PSTFolder.java
similarity index 92%
rename from com/pff/PSTFolder.java
rename to com/pff/objects/PSTFolder.java
index d3fc0a4..68d00ff 100644
--- a/com/pff/PSTFolder.java
+++ b/com/pff/objects/PSTFolder.java
@@ -31,9 +31,24 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
-import java.io.*;
-import java.util.*;
+package com.pff.objects;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+import com.pff.parsing.tables.PSTTable7C;
+import com.pff.parsing.tables.PSTTable7CItem;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.source.PSTSource;
/**
@@ -51,7 +66,7 @@ public class PSTFolder extends PSTObject {
* @throws PSTException
* @throws IOException
*/
- PSTFolder(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ public PSTFolder(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException
{
super(theFile, descriptorIndexNode);
@@ -64,7 +79,7 @@ public class PSTFolder extends PSTObject {
* @param folderIndexNode
* @param table
*/
- PSTFolder(PSTFile theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems) {
+ PSTFolder(PSTSource theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems) {
super(theFile, folderIndexNode, table, localDescriptorItems);
}
@@ -75,11 +90,11 @@ public class PSTFolder extends PSTObject {
* @throws PSTException
* @throws IOException
*/
- public Vector getSubFolders()
+ public ArrayList getSubFolders()
throws PSTException, IOException
{
initSubfoldersTable();
- Vector output = new Vector();
+ ArrayList output = new ArrayList();
if (this.hasSubfolders()) {
try {
List> itemMapSet = subfoldersTable.getItems();
@@ -126,7 +141,7 @@ private void initSubfoldersTable()
* internal vars for the tracking of things..
*/
private int currentEmailIndex = 0;
- private LinkedHashSet otherItems = null;
+ //private LinkedHashSet otherItems = null;
private PSTTable7C emailsTable = null;
private LinkedList fallbackEmailsTable = null;
@@ -198,12 +213,12 @@ private void initEmailsTable()
* @throws PSTException
* @throws IOException
*/
- public Vector getChildren(int numberToReturn)
+ public ArrayList getChildren(int numberToReturn)
throws PSTException, IOException
{
initEmailsTable();
- Vector output = new Vector();
+ ArrayList output = new ArrayList();
if (emailsTable != null) {
List> rows = this.emailsTable.getItems(currentEmailIndex, numberToReturn);
diff --git a/com/pff/PSTMessage.java b/com/pff/objects/PSTMessage.java
similarity index 91%
rename from com/pff/PSTMessage.java
rename to com/pff/objects/PSTMessage.java
index 2644276..4cf58e9 100644
--- a/com/pff/PSTMessage.java
+++ b/com/pff/objects/PSTMessage.java
@@ -31,12 +31,25 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.objects.sub.PSTConversationIndex;
+import com.pff.objects.sub.PSTRecipient;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+import com.pff.parsing.tables.PSTTable7C;
+import com.pff.parsing.tables.PSTTable7CItem;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.parsing.tables.PSTTableBCItem;
+import com.pff.source.PSTSource;
+
/**
* PST Message contains functions that are common across most MAPI objects.
* Note that many of these functions may not be applicable for the item in question,
@@ -51,13 +64,13 @@ public class PSTMessage extends PSTObject {
public static final int IMPORTANCE_NORMAL = 1;
public static final int IMPORTANCE_HIGH = 2;
- PSTMessage(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ PSTMessage(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException
{
super(theFile, descriptorIndexNode);
}
- PSTMessage(PSTFile theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems)
+ PSTMessage(PSTSource theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems)
{
super(theFile, folderIndexNode, table, localDescriptorItems);
}
@@ -71,12 +84,12 @@ public String getRTFBody()
// is it a reference?
PSTTableBCItem item = this.items.get(0x1009);
if (item.data.length > 0) {
- return (LZFu.decode(item.data));
+ return (PSTUtils.decodeLZFU(item.data));
}
int ref = item.entryValueReference;
PSTDescriptorItem descItem = this.localDescriptorItems.get(ref);
if ( descItem != null ) {
- return LZFu.decode(descItem.getData());
+ return PSTUtils.decodeLZFU(descItem.getData());
}
}
@@ -317,8 +330,8 @@ public boolean getMessageCcMe () {
/**
* Message addressed to me ASCII or Unicode string
*/
- public String getMessageRecipMe () {
- return this.getStringItem(0x0059);
+ public boolean getMessageRecipMe () {
+ return this.getIntItem(0x0059) != 0;
}
/**
* Response requested Boolean
@@ -585,6 +598,10 @@ public Date getMessageDeliveryTime() {
// return (this.getIntItem(0x0e17) & 0x2000) != 0;
// }
+ public int getNativeBodyType() {
+ return this.getIntItem(0x1016);
+ }
+
/**
* Message content properties
*/
@@ -599,7 +616,7 @@ public String getBody() {
cpItem = this.items.get(0x3FDE); // PidTagInternetCodepage
}
if (cpItem != null) {
- cp = PSTFile.getInternetCodePageCharset(cpItem.entryValueReference);
+ cp = PSTSource.getInternetCodePageCharset(cpItem.entryValueReference);
}
return this.getStringItem(0x1000, 0, cp);
}
@@ -649,7 +666,7 @@ public String getBodyHTML() {
cpItem = this.items.get(0x3FFD); // PidTagMessageCodepage
}
if (cpItem != null) {
- cp = PSTFile.getInternetCodePageCharset(cpItem.entryValueReference);
+ cp = PSTSource.getInternetCodePageCharset(cpItem.entryValueReference);
}
return this.getStringItem(0x1013, 0, cp);
}
@@ -759,8 +776,8 @@ private void processRecipients()
{
PSTDescriptorItem item = this.localDescriptorItems.get(recipientTableKey);
HashMap descriptorItems = null;
- if (item.subNodeOffsetIndexIdentifier > 0) {
- descriptorItems =pstFile.getPSTDescriptorItems(item.subNodeOffsetIndexIdentifier);
+ if (item.getSubNodeOffsetIndexIdentifier() > 0) {
+ descriptorItems =pstFile.getPSTDescriptorItems(item.getSubNodeOffsetIndexIdentifier());
}
recipientTable = new PSTTable7C(new PSTNodeInputStream(pstFile, item), descriptorItems);
}
@@ -811,8 +828,8 @@ private void processAttachments()
{
PSTDescriptorItem item = this.localDescriptorItems.get(attachmentTableKey);
HashMap descriptorItems = null;
- if (item.subNodeOffsetIndexIdentifier > 0) {
- descriptorItems =pstFile.getPSTDescriptorItems(item.subNodeOffsetIndexIdentifier);
+ if (item.getSubNodeOffsetIndexIdentifier() > 0) {
+ descriptorItems =pstFile.getPSTDescriptorItems(item.getSubNodeOffsetIndexIdentifier());
}
attachmentTable = new PSTTable7C(new PSTNodeInputStream(pstFile, item), descriptorItems);
}
@@ -822,13 +839,13 @@ private void processAttachments()
* Start date Filetime
*/
public Date getTaskStartDate() {
- return getDateItem(pstFile.getNameToIdMapItem(0x00008104, PSTFile.PSETID_Task));
+ return getDateItem(pstFile.getNameToIdMapItem(0x00008104, PSTSource.PSETID_Task));
}
/**
* Due date Filetime
*/
public Date getTaskDueDate() {
- return getDateItem(pstFile.getNameToIdMapItem(0x00008105, PSTFile.PSETID_Task));
+ return getDateItem(pstFile.getNameToIdMapItem(0x00008105, PSTSource.PSETID_Task));
}
/**
@@ -836,11 +853,11 @@ public Date getTaskDueDate() {
* @return
*/
public boolean getReminderSet() {
- return getBooleanItem(pstFile.getNameToIdMapItem(0x00008503, PSTFile.PSETID_Common));
+ return getBooleanItem(pstFile.getNameToIdMapItem(0x00008503, PSTSource.PSETID_Common));
}
public int getReminderDelta() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008501, PSTFile.PSETID_Common));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008501, PSTSource.PSETID_Common));
}
/**
@@ -871,7 +888,7 @@ public String[] getColorCategories()
categories = new String[categoryCount];
int[] offsets = new int[categoryCount];
for (int x = 0; x < categoryCount; x++) {
- offsets[x] = (int)PSTObject.convertBigEndianBytesToLong(item.data, (x*4)+1, (x+1)*4+1);
+ offsets[x] = (int)PSTUtils.convertBigEndianBytesToLong(item.data, (x*4)+1, (x+1)*4+1);
}
for (int x = 0; x < offsets.length -1; x++) {
int start = offsets[x];
@@ -958,8 +975,8 @@ public PSTAttachment getAttachment(int attachmentNumber)
// note that all the information that was in the c7 table is repeated in the eb table in attachment data.
// so no need to pass it...
HashMap attachmentDescriptorItems = new HashMap();
- if (descriptorItem.subNodeOffsetIndexIdentifier > 0) {
- attachmentDescriptorItems = pstFile.getPSTDescriptorItems(descriptorItem.subNodeOffsetIndexIdentifier);
+ if (descriptorItem.getSubNodeOffsetIndexIdentifier() > 0) {
+ attachmentDescriptorItems = pstFile.getPSTDescriptorItems(descriptorItem.getSubNodeOffsetIndexIdentifier());
}
return new PSTAttachment(this.pstFile, attachmentDetailsTable, attachmentDescriptorItems);
}
@@ -1014,4 +1031,16 @@ public String toString() {
this.localDescriptorItems;
}
+
+ public byte[] getConversationId() {
+ return getBinaryItem(0x3013);
+ }
+
+ public PSTConversationIndex getConversationIndex() {
+ return new PSTConversationIndex(getBinaryItem(0x0071));
+ }
+
+ public boolean isConversationIndexTracking() {
+ return getBooleanItem(0x3016, false);
+ }
}
diff --git a/com/pff/PSTMessageStore.java b/com/pff/objects/PSTMessageStore.java
similarity index 79%
rename from com/pff/PSTMessageStore.java
rename to com/pff/objects/PSTMessageStore.java
index 553593f..b231aab 100644
--- a/com/pff/PSTMessageStore.java
+++ b/com/pff/objects/PSTMessageStore.java
@@ -31,11 +31,17 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.*;
import java.util.*;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.tables.PSTTableBCItem;
+import com.pff.source.PSTSource;
+
/**
* Object that represents the message store.
@@ -44,7 +50,7 @@
*/
public class PSTMessageStore extends PSTObject {
- PSTMessageStore(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ public PSTMessageStore(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException
{
super(theFile, descriptorIndexNode);
@@ -60,10 +66,10 @@ public UUID getTagRecordKeyAsUUID() {
PSTTableBCItem item = this.items.get(guidEntryType);
int offset = 0;
byte[] bytes = item.data;
- long mostSigBits = (PSTObject.convertLittleEndianBytesToLong(bytes, offset, offset+4) << 32) |
- (PSTObject.convertLittleEndianBytesToLong(bytes, offset+4, offset+6) << 16) |
- PSTObject.convertLittleEndianBytesToLong(bytes, offset+6, offset+8);
- long leastSigBits = PSTObject.convertBigEndianBytesToLong(bytes, offset+8, offset+16);
+ long mostSigBits = (PSTUtils.convertLittleEndianBytesToLong(bytes, offset, offset+4) << 32) |
+ (PSTUtils.convertLittleEndianBytesToLong(bytes, offset+4, offset+6) << 16) |
+ PSTUtils.convertLittleEndianBytesToLong(bytes, offset+6, offset+8);
+ long leastSigBits = PSTUtils.convertBigEndianBytesToLong(bytes, offset+8, offset+16);
return new UUID(mostSigBits, leastSigBits);
}
return null;
diff --git a/com/pff/PSTObject.java b/com/pff/objects/PSTObject.java
similarity index 60%
rename from com/pff/PSTObject.java
rename to com/pff/objects/PSTObject.java
index c89aa48..aab6c34 100644
--- a/com/pff/PSTObject.java
+++ b/com/pff/objects/PSTObject.java
@@ -31,11 +31,21 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.IOException;
import java.util.*;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.objects.sub.PSTTimeZone;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.parsing.tables.PSTTableBCItem;
+import com.pff.source.PSTSource;
+
/**
* PST Object is the root class of all PST Items.
* It also provides a number of static utility functions. The most important of which is the
@@ -71,7 +81,7 @@ public String getItemsString() {
return items.toString();
}
- protected PSTFile pstFile;
+ protected PSTSource pstFile;
protected byte[] data;
protected DescriptorIndexNode descriptorIndexNode;
protected HashMap items;
@@ -79,7 +89,7 @@ public String getItemsString() {
protected LinkedHashMap> children;
- protected PSTObject(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ protected PSTObject(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException
{
this.pstFile = theFile;
@@ -104,7 +114,7 @@ protected PSTObject(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
* @param folderIndexNode
* @param table
*/
- protected PSTObject(PSTFile theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems) {
+ protected PSTObject(PSTSource theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems) {
this.pstFile = theFile;
this.descriptorIndexNode = folderIndexNode;
this.items = table.getItems();
@@ -129,7 +139,11 @@ public DescriptorIndexNode getDescriptorNode() {
* @return item's descriptor node identifier
*/
public long getDescriptorNodeId() {
- return this.descriptorIndexNode.descriptorIdentifier;
+ //return this.descriptorIndexNode.descriptorIdentifier;
+ if (this.descriptorIndexNode != null) { // Prevent null pointer exceptions for embedded messages
+ return this.descriptorIndexNode.descriptorIdentifier;
+ }
+ return 0;
}
public int getNodeType() {
@@ -168,7 +182,7 @@ protected double getDoubleItem(int identifier) {
protected double getDoubleItem(int identifier, double defaultValue) {
if (this.items.containsKey(identifier)) {
PSTTableBCItem item = this.items.get(identifier);
- long longVersion = PSTObject.convertLittleEndianBytesToLong(item.data);
+ long longVersion = PSTUtils.convertLittleEndianBytesToLong(item.data);
return Double.longBitsToDouble(longVersion);
}
return defaultValue;
@@ -187,7 +201,7 @@ protected long getLongItem(int identifier, long defaultValue) {
} else if ( item.entryValueType == 0x0014 ){
// we are a long
if ( item.data != null && item.data.length == 8 ) {
- return PSTObject.convertLittleEndianBytesToLong(item.data, 0, 8);
+ return PSTUtils.convertLittleEndianBytesToLong(item.data, 0, 8);
} else {
System.err.printf("Invalid data length for long id 0x%04X\n", identifier);
// Return the default value for now...
@@ -237,7 +251,7 @@ protected String getStringItem(int identifier, int stringType, String codepage)
} catch (Exception e) {
System.err.printf("Exception %s decoding string %s: %s\n",
e.toString(),
- PSTFile.getPropertyDescription(identifier, stringType), data != null ? data.toString() : "null");
+ PSTSource.getPropertyDescription(identifier, stringType), data != null ? data.toString() : "null");
return "";
}
//System.out.printf("PSTObject.getStringItem - item isn't a string: 0x%08X\n", identifier);
@@ -292,7 +306,7 @@ private String getStringCodepage() {
cpItem = this.items.get(0x3FDE); // PidTagInternetCodepage
}
if (cpItem != null) {
- return PSTFile.getInternetCodePageCharset(cpItem.entryValueReference);
+ return PSTSource.getInternetCodePageCharset(cpItem.entryValueReference);
}
return null;
}
@@ -303,10 +317,10 @@ public Date getDateItem(int identifier) {
if (item.data.length == 0 ) {
return new Date(0);
}
- int high = (int)PSTObject.convertLittleEndianBytesToLong(item.data, 4, 8);
- int low = (int)PSTObject.convertLittleEndianBytesToLong(item.data, 0, 4);
+ int high = (int)PSTUtils.convertLittleEndianBytesToLong(item.data, 4, 8);
+ int low = (int)PSTUtils.convertLittleEndianBytesToLong(item.data, 0, 4);
- return PSTObject.filetimeToDate(high, low);
+ return PSTUtils.filetimeToDate(high, low);
}
return null;
}
@@ -398,209 +412,7 @@ public Date getLastModificationTime() {
}
- /**
- * Static stuff below
- * ------------------
- */
-
- // substitution table for the compressible encryption type.
- static int[] compEnc = {
- 0x47, 0xf1, 0xb4, 0xe6, 0x0b, 0x6a, 0x72, 0x48, 0x85, 0x4e, 0x9e, 0xeb, 0xe2, 0xf8, 0x94, 0x53,
- 0xe0, 0xbb, 0xa0, 0x02, 0xe8, 0x5a, 0x09, 0xab, 0xdb, 0xe3, 0xba, 0xc6, 0x7c, 0xc3, 0x10, 0xdd,
- 0x39, 0x05, 0x96, 0x30, 0xf5, 0x37, 0x60, 0x82, 0x8c, 0xc9, 0x13, 0x4a, 0x6b, 0x1d, 0xf3, 0xfb,
- 0x8f, 0x26, 0x97, 0xca, 0x91, 0x17, 0x01, 0xc4, 0x32, 0x2d, 0x6e, 0x31, 0x95, 0xff, 0xd9, 0x23,
- 0xd1, 0x00, 0x5e, 0x79, 0xdc, 0x44, 0x3b, 0x1a, 0x28, 0xc5, 0x61, 0x57, 0x20, 0x90, 0x3d, 0x83,
- 0xb9, 0x43, 0xbe, 0x67, 0xd2, 0x46, 0x42, 0x76, 0xc0, 0x6d, 0x5b, 0x7e, 0xb2, 0x0f, 0x16, 0x29,
- 0x3c, 0xa9, 0x03, 0x54, 0x0d, 0xda, 0x5d, 0xdf, 0xf6, 0xb7, 0xc7, 0x62, 0xcd, 0x8d, 0x06, 0xd3,
- 0x69, 0x5c, 0x86, 0xd6, 0x14, 0xf7, 0xa5, 0x66, 0x75, 0xac, 0xb1, 0xe9, 0x45, 0x21, 0x70, 0x0c,
- 0x87, 0x9f, 0x74, 0xa4, 0x22, 0x4c, 0x6f, 0xbf, 0x1f, 0x56, 0xaa, 0x2e, 0xb3, 0x78, 0x33, 0x50,
- 0xb0, 0xa3, 0x92, 0xbc, 0xcf, 0x19, 0x1c, 0xa7, 0x63, 0xcb, 0x1e, 0x4d, 0x3e, 0x4b, 0x1b, 0x9b,
- 0x4f, 0xe7, 0xf0, 0xee, 0xad, 0x3a, 0xb5, 0x59, 0x04, 0xea, 0x40, 0x55, 0x25, 0x51, 0xe5, 0x7a,
- 0x89, 0x38, 0x68, 0x52, 0x7b, 0xfc, 0x27, 0xae, 0xd7, 0xbd, 0xfa, 0x07, 0xf4, 0xcc, 0x8e, 0x5f,
- 0xef, 0x35, 0x9c, 0x84, 0x2b, 0x15, 0xd5, 0x77, 0x34, 0x49, 0xb6, 0x12, 0x0a, 0x7f, 0x71, 0x88,
- 0xfd, 0x9d, 0x18, 0x41, 0x7d, 0x93, 0xd8, 0x58, 0x2c, 0xce, 0xfe, 0x24, 0xaf, 0xde, 0xb8, 0x36,
- 0xc8, 0xa1, 0x80, 0xa6, 0x99, 0x98, 0xa8, 0x2f, 0x0e, 0x81, 0x65, 0x73, 0xe4, 0xc2, 0xa2, 0x8a,
- 0xd4, 0xe1, 0x11, 0xd0, 0x08, 0x8b, 0x2a, 0xf2, 0xed, 0x9a, 0x64, 0x3f, 0xc1, 0x6c, 0xf9, 0xec
- };
-
- /**
- * Output a dump of data in hex format in the order it was read in
- * @param data
- * @param pretty
- */
- public static void printHexFormatted(byte[] data, boolean pretty) {
- printHexFormatted(data,pretty, new int[0]);
- }
- protected static void printHexFormatted(byte[] data, boolean pretty, int[] indexes) {
- // groups of two
- if (pretty) { System.out.println("---"); }
- long tmpLongValue;
- String line = "";
- int nextIndex = 0;
- int indexIndex = 0;
- if (indexes.length > 0) {
- nextIndex = indexes[0];
- indexIndex++;
- }
- for (int x = 0; x < data.length; x++) {
- tmpLongValue = (long)data[x] & 0xff;
-
- if (indexes.length > 0 &&
- x == nextIndex &&
- nextIndex < data.length)
- {
- System.out.print("+");
- line += "+";
- while (indexIndex < indexes.length-1 && indexes[indexIndex] <= nextIndex)
- {
- indexIndex++;
- }
- nextIndex = indexes[indexIndex];
- //indexIndex++;
- }
-
- if (Character.isLetterOrDigit((char)tmpLongValue)) {
- line += (char)tmpLongValue;
- }
- else
- {
- line += ".";
- }
-
- if (Long.toHexString(tmpLongValue).length() < 2) {
- System.out.print("0");
- }
- System.out.print(Long.toHexString(tmpLongValue));
- if (x % 2 == 1 && pretty) {
- System.out.print(" ");
- }
- if (x % 16 == 15 && pretty) {
- System.out.print(" "+line);
- System.out.println("");
- line = "";
- }
- }
- if (pretty) { System.out.println(" "+line); System.out.println("---"); System.out.println(data.length); } else { }
- }
-
-
-
- /**
- * decode a lump of data that has been encrypted with the compressible encryption
- * @param data
- * @return decoded data
- */
- protected static byte[] decode(byte[] data) {
- int temp;
- for (int x = 0; x < data.length; x++) {
- temp = data[x] & 0xff;
- data[x] = (byte)compEnc[temp];
- }
-
- return data;
- }
-
-
- protected static byte[] encode(byte[] data) {
- // create the encoding array...
- int[] enc = new int[compEnc.length];
- for (int x = 0; x < enc.length; x++) {
- enc[compEnc[x]] = x;
- }
-
- // now it's just the same as decode...
- int temp;
- for (int x = 0; x < data.length; x++) {
- temp = data[x] & 0xff;
- data[x] = (byte)enc[temp];
- }
-
- return data;
- }
-
- /**
- * Utility function for converting little endian bytes into a usable java long
- * @param data
- * @return long version of the data
- */
- public static long convertLittleEndianBytesToLong(byte[] data) {
- return convertLittleEndianBytesToLong(data, 0, data.length);
- }
- /**
- * Utility function for converting little endian bytes into a usable java long
- * @param data
- * @param start
- * @param end
- * @return long version of the data
- */
- public static long convertLittleEndianBytesToLong(byte[] data, int start, int end) {
-
- long offset = data[end-1] & 0xff;
- long tmpLongValue;
- for (int x = end-2; x >= start; x--) {
- offset = offset << 8;
- tmpLongValue = (long)data[x] & 0xff;
- offset |= tmpLongValue;
- }
-
- return offset;
- }
-
- /**
- * Utility function for converting big endian bytes into a usable java long
- * @param data
- * @param start
- * @param end
- * @return long version of the data
- */
- public static long convertBigEndianBytesToLong(byte[] data, int start, int end) {
-
- long offset = 0;
- for ( int x = start; x < end; ++x ) {
- offset = offset << 8;
- offset |= ((long)data[x] & 0xFFL);
- }
-
- return offset;
- }
-/*
- protected static boolean isPSTArray(byte[] data) {
- return (data[0] == 1 && data[1] == 1);
- }
-/**/
-/*
- protected static int[] getBlockOffsets(RandomAccessFile in, byte[] data)
- throws IOException, PSTException
- {
- // is the data an array?
- if (!(data[0] == 1 && data[1] == 1))
- {
- throw new PSTException("Unable to process array, does not appear to be one!");
- }
-
- // we are an array!
- // get the array items and merge them together
- int numberOfEntries = (int)PSTObject.convertLittleEndianBytesToLong(data, 2, 4);
- int[] output = new int[numberOfEntries];
- int tableOffset = 8;
- int blockOffset = 0;
- for (int y = 0; y < numberOfEntries; y++) {
- // get the offset identifier
- long tableOffsetIdentifierIndex = PSTObject.convertLittleEndianBytesToLong(data, tableOffset, tableOffset+8);
- // clear the last bit of the identifier. Why so hard?
- tableOffsetIdentifierIndex = (tableOffsetIdentifierIndex & 0xfffffffe);
- OffsetIndexItem tableOffsetIdentifier = PSTObject.getOffsetIndexNode(in, tableOffsetIdentifierIndex);
- blockOffset += tableOffsetIdentifier.size;
- output[y] = blockOffset;
- tableOffset += 8;
- }
-
- // replace the item data with the stuff from the array...
- return output;
- }
-/**/
-
/**
* Detect and load a PST Object from a file with the specified descriptor index
* @param theFile
@@ -609,10 +421,10 @@ protected static int[] getBlockOffsets(RandomAccessFile in, byte[] data)
* @throws IOException
* @throws PSTException
*/
- public static PSTObject detectAndLoadPSTObject(PSTFile theFile, long descriptorIndex)
+ public static PSTObject detectAndLoadPSTObject(PSTSource theFile, long descriptorIndex)
throws IOException, PSTException
{
- return PSTObject.detectAndLoadPSTObject(theFile, theFile.getDescriptorIndexNode(descriptorIndex));
+ return detectAndLoadPSTObject(theFile, theFile.getDescriptorIndexNode(descriptorIndex));
}
/**
@@ -623,7 +435,7 @@ public static PSTObject detectAndLoadPSTObject(PSTFile theFile, long descriptorI
* @throws IOException
* @throws PSTException
*/
- static PSTObject detectAndLoadPSTObject(PSTFile theFile, DescriptorIndexNode folderIndexNode)
+ public static PSTObject detectAndLoadPSTObject(PSTSource theFile, DescriptorIndexNode folderIndexNode)
throws IOException, PSTException
{
int nidType = (folderIndexNode.descriptorIdentifier & 0x1F);
@@ -639,7 +451,7 @@ static PSTObject detectAndLoadPSTObject(PSTFile theFile, DescriptorIndexNode fol
if ( nidType == 0x02 || nidType == 0x03 ) {
return new PSTFolder(theFile, folderIndexNode, table, localDescriptorItems);
} else {
- return PSTObject.createAppropriatePSTMessageObject(theFile, folderIndexNode, table, localDescriptorItems);
+ return createAppropriatePSTMessageObject(theFile, folderIndexNode, table, localDescriptorItems);
}
}
else
@@ -647,8 +459,10 @@ static PSTObject detectAndLoadPSTObject(PSTFile theFile, DescriptorIndexNode fol
throw new PSTException("Unknown child type with offset id: "+folderIndexNode.localDescriptorsOffsetIndexIdentifier);
}
}
-
- static PSTMessage createAppropriatePSTMessageObject(PSTFile theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems)
+
+
+
+ static PSTMessage createAppropriatePSTMessageObject(PSTSource theFile, DescriptorIndexNode folderIndexNode, PSTTableBC table, HashMap localDescriptorItems)
{
PSTTableBCItem item = table.getItems().get(0x001a);
@@ -679,7 +493,8 @@ static PSTMessage createAppropriatePSTMessageObject(PSTFile theFile, DescriptorI
return new PSTMessage(theFile, folderIndexNode, table, localDescriptorItems);
}
- static String guessPSTObjectType(PSTFile theFile, DescriptorIndexNode folderIndexNode)
+
+ public static String guessPSTObjectType(PSTSource theFile, DescriptorIndexNode folderIndexNode)
throws IOException, PSTException
{
@@ -734,79 +549,5 @@ else if (key.intValue() >= 0x3c00 &&
}
return "Unknown";
}
-
- /**
- * the code below was taken from a random apache project
- * http://www.koders.com/java/fidA9D4930E7443F69F32571905DD4CA01E4D46908C.aspx
- * my bit-shifting isn't that 1337
- */
-
- /**
- * The difference between the Windows epoch (1601-01-01
- * 00:00:00) and the Unix epoch (1970-01-01 00:00:00) in
- * milliseconds: 11644473600000L. (Use your favorite spreadsheet
- * program to verify the correctness of this value. By the way,
- * did you notice that you can tell from the epochs which
- * operating system is the modern one? :-))
- */
- private static final long EPOCH_DIFF = 11644473600000L;
-
- /**
- * Converts a Windows FILETIME into a {@link Date}. The Windows
- * FILETIME structure holds a date and time associated with a
- * file. The structure identifies a 64-bit integer specifying the
- * number of 100-nanosecond intervals which have passed since
- * January 1, 1601. This 64-bit value is split into the two double
- * words stored in the structure.
- *
- * @param high The higher double word of the FILETIME structure.
- * @param low The lower double word of the FILETIME structure.
- * @return The Windows FILETIME as a {@link Date}.
- */
- protected static Date filetimeToDate(final int high, final int low)
- {
- final long filetime = ((long) high) << 32 | (low & 0xffffffffL);
- //System.out.printf("0x%X\n", filetime);
- final long ms_since_16010101 = filetime / (1000 * 10);
- final long ms_since_19700101 = ms_since_16010101 - EPOCH_DIFF;
- return new Date(ms_since_19700101);
- }
- public static Calendar apptTimeToCalendar(int minutes) {
- final long ms_since_16010101 = minutes * (60*1000L);
- final long ms_since_19700101 = ms_since_16010101 - EPOCH_DIFF;
- Calendar c = Calendar.getInstance(PSTTimeZone.utcTimeZone);
- c.setTimeInMillis(ms_since_19700101);
- return c;
- }
-
- public static Calendar apptTimeToUTC(int minutes, PSTTimeZone tz) {
- // Must convert minutes since 1/1/1601 in local time to UTC
- // There's got to be a better way of doing this...
- // First get a UTC calendar object that contains _local time_
- Calendar cUTC = PSTObject.apptTimeToCalendar(minutes);
- if ( tz != null ) {
- // Create an empty Calendar object with the required time zone
- Calendar cLocal = Calendar.getInstance(tz.getSimpleTimeZone());
- cLocal.clear();
-
- // Now transfer the local date/time from the UTC calendar object
- // to the object that knows about the time zone...
- cLocal.set(cUTC.get(Calendar.YEAR),
- cUTC.get(Calendar.MONTH),
- cUTC.get(Calendar.DATE),
- cUTC.get(Calendar.HOUR_OF_DAY),
- cUTC.get(Calendar.MINUTE),
- cUTC.get(Calendar.SECOND));
-
- // Get the true UTC from the local time calendar object.
- // Drop any milliseconds, they won't be printed anyway!
- long utcs = cLocal.getTimeInMillis() / 1000;
-
- // Finally, set the true UTC in the UTC calendar object
- cUTC.setTimeInMillis(utcs * 1000);
- } // else hope for the best!
-
- return cUTC;
- }
}
diff --git a/com/pff/PSTRss.java b/com/pff/objects/PSTRss.java
similarity index 84%
rename from com/pff/PSTRss.java
rename to com/pff/objects/PSTRss.java
index 85c830c..bec2e93 100644
--- a/com/pff/PSTRss.java
+++ b/com/pff/objects/PSTRss.java
@@ -31,11 +31,17 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.IOException;
import java.util.HashMap;
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.source.PSTSource;
+
/**
* Object that represents a RSS item
* @author Richard Johnson
@@ -48,7 +54,7 @@ public class PSTRss extends PSTMessage {
* @throws PSTException
* @throws IOException
*/
- public PSTRss(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ public PSTRss(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException {
super(theFile, descriptorIndexNode);
}
@@ -59,7 +65,7 @@ public PSTRss(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
* @param table
* @param localDescriptorItems
*/
- public PSTRss(PSTFile theFile, DescriptorIndexNode folderIndexNode,
+ public PSTRss(PSTSource theFile, DescriptorIndexNode folderIndexNode,
PSTTableBC table,
HashMap localDescriptorItems) {
super(theFile, folderIndexNode, table, localDescriptorItems);
@@ -69,43 +75,43 @@ public PSTRss(PSTFile theFile, DescriptorIndexNode folderIndexNode,
* Channel
*/
public String getPostRssChannelLink() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008900, PSTFile.PSETID_PostRss));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008900, PSTSource.PSETID_PostRss));
}
/**
* Item link
*/
public String getPostRssItemLink() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008901, PSTFile.PSETID_PostRss));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008901, PSTSource.PSETID_PostRss));
}
/**
* Item hash Integer 32-bit signed
*/
public int getPostRssItemHash() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008902, PSTFile.PSETID_PostRss));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008902, PSTSource.PSETID_PostRss));
}
/**
* Item GUID
*/
public String getPostRssItemGuid() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008903, PSTFile.PSETID_PostRss));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008903, PSTSource.PSETID_PostRss));
}
/**
* Channel GUID
*/
public String getPostRssChannel() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008904, PSTFile.PSETID_PostRss));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008904, PSTSource.PSETID_PostRss));
}
/**
* Item XML
*/
public String getPostRssItemXml() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008905, PSTFile.PSETID_PostRss));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008905, PSTSource.PSETID_PostRss));
}
/**
* Subscription
*/
public String getPostRssSubscription() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008906, PSTFile.PSETID_PostRss));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008906, PSTSource.PSETID_PostRss));
}
public String toString() {
diff --git a/com/pff/PSTTask.java b/com/pff/objects/PSTTask.java
similarity index 81%
rename from com/pff/PSTTask.java
rename to com/pff/objects/PSTTask.java
index c58888b..1477aec 100644
--- a/com/pff/PSTTask.java
+++ b/com/pff/objects/PSTTask.java
@@ -31,11 +31,17 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects;
import java.io.IOException;
-import java.util.HashMap;
import java.util.Date;
+import java.util.HashMap;
+
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.source.PSTSource;
/**
* Object that represents Task items
@@ -49,7 +55,7 @@ public class PSTTask extends PSTMessage {
* @throws PSTException
* @throws IOException
*/
- public PSTTask(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
+ public PSTTask(PSTSource theFile, DescriptorIndexNode descriptorIndexNode)
throws PSTException, IOException {
super(theFile, descriptorIndexNode);
}
@@ -60,7 +66,7 @@ public PSTTask(PSTFile theFile, DescriptorIndexNode descriptorIndexNode)
* @param table
* @param localDescriptorItems
*/
- public PSTTask(PSTFile theFile, DescriptorIndexNode folderIndexNode,
+ public PSTTask(PSTSource theFile, DescriptorIndexNode folderIndexNode,
PSTTableBC table,
HashMap localDescriptorItems) {
super(theFile, folderIndexNode, table, localDescriptorItems);
@@ -70,98 +76,98 @@ public PSTTask(PSTFile theFile, DescriptorIndexNode folderIndexNode,
* Status Integer 32-bit signed 0x0 => Not started
*/
public int getTaskStatus() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008101, PSTFile.PSETID_Task));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008101, PSTSource.PSETID_Task));
}
/**
* Percent Complete Floating point double precision (64-bit)
*/
public double getPercentComplete() {
- return getDoubleItem(pstFile.getNameToIdMapItem(0x00008102, PSTFile.PSETID_Task));
+ return getDoubleItem(pstFile.getNameToIdMapItem(0x00008102, PSTSource.PSETID_Task));
}
/**
* Is team task Boolean
*/
public boolean isTeamTask() {
- return getBooleanItem(pstFile.getNameToIdMapItem(0x00008103, PSTFile.PSETID_Task));
+ return getBooleanItem(pstFile.getNameToIdMapItem(0x00008103, PSTSource.PSETID_Task));
}
/**
* Date completed Filetime
*/
public Date getTaskDateCompleted() {
- return getDateItem(pstFile.getNameToIdMapItem(0x0000810f, PSTFile.PSETID_Task));
+ return getDateItem(pstFile.getNameToIdMapItem(0x0000810f, PSTSource.PSETID_Task));
}
/**
* Actual effort in minutes Integer 32-bit signed
*/
public int getTaskActualEffort() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008110, PSTFile.PSETID_Task));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008110, PSTSource.PSETID_Task));
}
/**
* Total effort in minutes Integer 32-bit signed
*/
public int getTaskEstimatedEffort() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008111, PSTFile.PSETID_Task));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008111, PSTSource.PSETID_Task));
}
/**
* Task version Integer 32-bit signed FTK: Access count
*/
public int getTaskVersion() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008112, PSTFile.PSETID_Task));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008112, PSTSource.PSETID_Task));
}
/**
* Complete Boolean
*/
public boolean isTaskComplete() {
- return getBooleanItem(pstFile.getNameToIdMapItem(0x0000811c, PSTFile.PSETID_Task));
+ return getBooleanItem(pstFile.getNameToIdMapItem(0x0000811c, PSTSource.PSETID_Task));
}
/**
* Owner ASCII or Unicode string
*/
public String getTaskOwner() {
- return getStringItem(pstFile.getNameToIdMapItem(0x0000811f, PSTFile.PSETID_Task));
+ return getStringItem(pstFile.getNameToIdMapItem(0x0000811f, PSTSource.PSETID_Task));
}
/**
* Delegator ASCII or Unicode string
*/
public String getTaskAssigner() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008121, PSTFile.PSETID_Task));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008121, PSTSource.PSETID_Task));
}
/**
* Unknown ASCII or Unicode string
*/
public String getTaskLastUser() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008122, PSTFile.PSETID_Task));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008122, PSTSource.PSETID_Task));
}
/**
* Ordinal Integer 32-bit signed
*/
public int getTaskOrdinal() {
- return this.getIntItem(pstFile.getNameToIdMapItem(0x00008123, PSTFile.PSETID_Task));
+ return this.getIntItem(pstFile.getNameToIdMapItem(0x00008123, PSTSource.PSETID_Task));
}
/**
* Is recurring Boolean
*/
public boolean isTaskFRecurring() {
- return getBooleanItem(pstFile.getNameToIdMapItem(0x00008126, PSTFile.PSETID_Task));
+ return getBooleanItem(pstFile.getNameToIdMapItem(0x00008126, PSTSource.PSETID_Task));
}
/**
* Role ASCII or Unicode string
*/
public String getTaskRole() {
- return getStringItem(pstFile.getNameToIdMapItem(0x00008127, PSTFile.PSETID_Task));
+ return getStringItem(pstFile.getNameToIdMapItem(0x00008127, PSTSource.PSETID_Task));
}
/**
* Ownership Integer 32-bit signed
*/
public int getTaskOwnership() {
- return getIntItem(pstFile.getNameToIdMapItem(0x00008129, PSTFile.PSETID_Task));
+ return getIntItem(pstFile.getNameToIdMapItem(0x00008129, PSTSource.PSETID_Task));
}
/**
* Delegation State
*/
public int getAcceptanceState() {
- return getIntItem(pstFile.getNameToIdMapItem(0x0000812a, PSTFile.PSETID_Task));
+ return getIntItem(pstFile.getNameToIdMapItem(0x0000812a, PSTSource.PSETID_Task));
}
public String toString() {
diff --git a/com/pff/PSTAppointmentRecurrence.java b/com/pff/objects/sub/PSTAppointmentRecurrence.java
similarity index 76%
rename from com/pff/PSTAppointmentRecurrence.java
rename to com/pff/objects/sub/PSTAppointmentRecurrence.java
index 4d06c3d..f78f138 100644
--- a/com/pff/PSTAppointmentRecurrence.java
+++ b/com/pff/objects/sub/PSTAppointmentRecurrence.java
@@ -31,7 +31,7 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects.sub;
/*
import java.text.SimpleDateFormat;
@@ -41,6 +41,12 @@
import java.util.Date;
import java.util.SimpleTimeZone;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTAppointmentException;
+import com.pff.objects.PSTAppointment;
+import com.pff.objects.PSTAttachment;
+import com.pff.objects.PSTMessage;
+
/**
* Class containing recurrence information for a recurring appointment
* @author Orin Eman
@@ -52,6 +58,14 @@ public class PSTAppointmentRecurrence {
// Access methods
+ public Calendar[] getDeletedInstanceDates() {
+ return DeletedInstanceDates;
+ }
+
+ public Calendar[] getModifiedInstanceDates() {
+ return ModifiedInstanceDates;
+ }
+
public short getExceptionCount() {
return ExceptionCount;
}
@@ -132,34 +146,34 @@ public PSTAppointmentRecurrence(byte[] recurrencePattern, PSTAppointment appt, P
SimpleTimeZone stz = RecurrenceTimeZone.getSimpleTimeZone();
// Read the structure
- RecurFrequency = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, 4, 6);
- PatternType = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, 6, 8);
- CalendarType = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, 8, 10);
- FirstDateTime = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, 10, 14);
- Period = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, 14, 18);
- SlidingFlag = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, 18, 22);
+ RecurFrequency = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, 4, 6);
+ PatternType = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, 6, 8);
+ CalendarType = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, 8, 10);
+ FirstDateTime = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, 10, 14);
+ Period = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, 14, 18);
+ SlidingFlag = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, 18, 22);
int offset = 22;
if ( PatternType != 0 ) {
- PatternSpecific = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ PatternSpecific = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
if ( PatternType == 0x0003 || PatternType == 0x000B ) {
- PatternSpecificNth = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ PatternSpecificNth = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
}
}
- EndType = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ EndType = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- OccurrenceCount = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ OccurrenceCount = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- FirstDOW = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ FirstDOW = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- DeletedInstanceCount = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ DeletedInstanceCount = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
DeletedInstanceDates = new Calendar[DeletedInstanceCount];
for ( int i = 0; i < DeletedInstanceCount; ++i ) {
- DeletedInstanceDates[i] = PSTObject.apptTimeToUTC(
- (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4),
+ DeletedInstanceDates[i] = PSTUtils.apptTimeToUTC(
+ (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4),
RecurrenceTimeZone);
offset += 4;
/*
@@ -169,12 +183,12 @@ public PSTAppointmentRecurrence(byte[] recurrencePattern, PSTAppointment appt, P
/**/
}
- ModifiedInstanceCount = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ ModifiedInstanceCount = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
ModifiedInstanceDates = new Calendar[ModifiedInstanceCount];
for ( int i = 0; i < ModifiedInstanceCount; ++i ) {
- ModifiedInstanceDates[i] = PSTObject.apptTimeToUTC(
- (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4),
+ ModifiedInstanceDates[i] = PSTUtils.apptTimeToUTC(
+ (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4),
RecurrenceTimeZone);
offset += 4;
/*
@@ -184,19 +198,19 @@ public PSTAppointmentRecurrence(byte[] recurrencePattern, PSTAppointment appt, P
/**/
}
- StartDate = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ StartDate = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- EndDate = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ EndDate = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4 + 4; // Skip ReaderVersion2
- writerVersion2 = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ writerVersion2 = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- StartTimeOffset = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ StartTimeOffset = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- EndTimeOffset = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ EndTimeOffset = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4;
- ExceptionCount = (short)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
+ ExceptionCount = (short)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+2);
offset += 2;
// Read exceptions
@@ -207,13 +221,13 @@ public PSTAppointmentRecurrence(byte[] recurrencePattern, PSTAppointment appt, P
}
if ( (offset + 4) <= recurrencePattern.length ) {
- int ReservedBlock1Size = (int)PSTObject.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
+ int ReservedBlock1Size = (int)PSTUtils.convertLittleEndianBytesToLong(recurrencePattern, offset, offset+4);
offset += 4 + (ReservedBlock1Size * 4);
}
// Read extended exception info
for ( int i = 0; i < ExceptionCount; ++i ) {
- Exceptions[i].ExtendedException(recurrencePattern, offset);
+ Exceptions[i].buildExtendedException(recurrencePattern, offset);
offset += Exceptions[i].getExtendedLength();
/*
Calendar c = PSTObject.apptTimeToUTC(Exceptions[i].getStartDateTime(), RecurrenceTimeZone);
diff --git a/com/pff/PSTRecipient.java b/com/pff/objects/sub/PSTRecipient.java
similarity index 96%
rename from com/pff/PSTRecipient.java
rename to com/pff/objects/sub/PSTRecipient.java
index 5d9bc8e..4e7ebe3 100644
--- a/com/pff/PSTRecipient.java
+++ b/com/pff/objects/sub/PSTRecipient.java
@@ -31,11 +31,13 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects.sub;
//import java.util.Date;
import java.util.HashMap;
+import com.pff.parsing.tables.PSTTable7CItem;
+
/**
* Class containing recipient information
* @author Orin Eman
@@ -50,8 +52,7 @@ public class PSTRecipient {
public static final int MAPI_CC = 2;
public static final int MAPI_BCC = 3;
- PSTRecipient(HashMap recipientDetails)
- {
+ public PSTRecipient(HashMap recipientDetails) {
details = recipientDetails;
}
diff --git a/com/pff/PSTTimeZone.java b/com/pff/objects/sub/PSTTimeZone.java
similarity index 77%
rename from com/pff/PSTTimeZone.java
rename to com/pff/objects/sub/PSTTimeZone.java
index 063d2ca..152a424 100644
--- a/com/pff/PSTTimeZone.java
+++ b/com/pff/objects/sub/PSTTimeZone.java
@@ -31,11 +31,13 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.objects.sub;
import java.util.Calendar;
import java.util.SimpleTimeZone;
+import com.pff.PSTUtils;
+
/**
* Class containing time zone information
* @author Orin Eman
@@ -44,21 +46,23 @@
*/
public class PSTTimeZone {
- PSTTimeZone(byte [] timeZoneData) {
+
+
+ public PSTTimeZone(byte [] timeZoneData) {
this.rule = null;
name = "";
try {
- int headerLen = (int)PSTObject.convertLittleEndianBytesToLong(timeZoneData, 2, 4);
- int nameLen = 2*(int)PSTObject.convertLittleEndianBytesToLong(timeZoneData, 6, 8);
+ int headerLen = (int)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, 2, 4);
+ int nameLen = 2*(int)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, 6, 8);
name = new String(timeZoneData, 8, nameLen, "UTF-16LE");
int ruleOffset = 8+nameLen;
- int nRules = (int)PSTObject.convertLittleEndianBytesToLong(timeZoneData, ruleOffset, ruleOffset+2);
+ int nRules = (int)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, ruleOffset, ruleOffset+2);
ruleOffset = 4 + headerLen;
for ( int rule = 0; rule < nRules; ++rule ) {
// Is this rule the effective rule?
- int flags = (int)PSTObject.convertLittleEndianBytesToLong(timeZoneData, ruleOffset+4, ruleOffset+6);
+ int flags = (int)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, ruleOffset+4, ruleOffset+6);
if ( (flags & 0x0002) != 0 ) {
this.rule = new TZRule(timeZoneData, ruleOffset+6);
break;
@@ -74,7 +78,7 @@ public class PSTTimeZone {
}
}
- PSTTimeZone(String name, byte[] timeZoneData) {
+ public PSTTimeZone(String name, byte[] timeZoneData) {
this.name = name;
this.rule = null;
@@ -181,14 +185,14 @@ public class SYSTEMTIME {
}
SYSTEMTIME(byte[] timeZoneData, int offset) {
- wYear = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset, offset+2)&0x7FFF);
- wMonth = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+2, offset+4)&0x7FFF);
- wDayOfWeek = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+4, offset+6)&0x7FFF);
- wDay = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+6, offset+8)&0x7FFF);
- wHour = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+8, offset+10)&0x7FFF);
- wMinute = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+10, offset+12)&0x7FFF);
- wSecond = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+12, offset+14)&0x7FFF);
- wMilliseconds = (short)(PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+14, offset+16)&0x7FFF);
+ wYear = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset, offset+2)&0x7FFF);
+ wMonth = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+2, offset+4)&0x7FFF);
+ wDayOfWeek = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+4, offset+6)&0x7FFF);
+ wDay = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+6, offset+8)&0x7FFF);
+ wHour = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+8, offset+10)&0x7FFF);
+ wMinute = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+10, offset+12)&0x7FFF);
+ wSecond = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+12, offset+14)&0x7FFF);
+ wMilliseconds = (short)(PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+14, offset+16)&0x7FFF);
}
boolean isEqual(SYSTEMTIME rhs) {
@@ -223,10 +227,10 @@ private class TZRule {
this.dtStart = dtStart;
InitBiases(timeZoneData, offset);
@SuppressWarnings("unused")
- short wStandardYear = (short)PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+12, offset+14);
+ short wStandardYear = (short)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+12, offset+14);
startStandard = new SYSTEMTIME(timeZoneData, offset+14);
@SuppressWarnings("unused")
- short wDaylightYear = (short)PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+30, offset+32);
+ short wDaylightYear = (short)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+30, offset+32);
startDaylight = new SYSTEMTIME(timeZoneData, offset+32);
}
@@ -238,9 +242,9 @@ private class TZRule {
}
private void InitBiases(byte[] timeZoneData, int offset) {
- lBias = (int)PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset, offset+4);
- lStandardBias = (int)PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+4, offset+8);
- lDaylightBias = (int)PSTObject.convertLittleEndianBytesToLong(timeZoneData, offset+8, offset+12);
+ lBias = (int)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset, offset+4);
+ lStandardBias = (int)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+4, offset+8);
+ lDaylightBias = (int)PSTUtils.convertLittleEndianBytesToLong(timeZoneData, offset+8, offset+12);
}
boolean isEqual(TZRule rhs) {
diff --git a/com/pff/DescriptorIndexNode.java b/com/pff/parsing/DescriptorIndexNode.java
similarity index 72%
rename from com/pff/DescriptorIndexNode.java
rename to com/pff/parsing/DescriptorIndexNode.java
index 8e97b76..6b13daf 100644
--- a/com/pff/DescriptorIndexNode.java
+++ b/com/pff/parsing/DescriptorIndexNode.java
@@ -31,10 +31,14 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing;
import java.io.IOException;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.source.PSTSource;
+
/**
* DescriptorIndexNode is a leaf item from the Descriptor index b-tree
* It is like a pointer to an element in the PST file, everything has one...
@@ -53,21 +57,21 @@ public class DescriptorIndexNode {
* parse the data out into something meaningful
* @param data
*/
- DescriptorIndexNode(byte[] data, int pstFileType) {
+ public DescriptorIndexNode(byte[] data, int pstFileType) {
// parse it out
// first 4 bytes
- if (pstFileType == PSTFile.PST_TYPE_ANSI) {
- descriptorIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 0, 4);
- dataOffsetIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 4, 8);
- localDescriptorsOffsetIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 8, 12);
- parentDescriptorIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 12, 16);
+ if (pstFileType == PSTSource.PST_TYPE_ANSI) {
+ descriptorIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 0, 4);
+ dataOffsetIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 4, 8);
+ localDescriptorsOffsetIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 8, 12);
+ parentDescriptorIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 12, 16);
//itemType = (int)PSTObject.convertLittleEndianBytesToLong(data, 28, 32);
} else {
- descriptorIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 0, 4);
- dataOffsetIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 8, 16);
- localDescriptorsOffsetIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 16, 24);
- parentDescriptorIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, 24, 28);
- itemType = (int)PSTObject.convertLittleEndianBytesToLong(data, 28, 32);
+ descriptorIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 0, 4);
+ dataOffsetIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 8, 16);
+ localDescriptorsOffsetIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 16, 24);
+ parentDescriptorIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, 24, 28);
+ itemType = (int)PSTUtils.convertLittleEndianBytesToLong(data, 28, 32);
}
}
@@ -82,7 +86,7 @@ void readData(PSTFile file)
*
*/
- PSTNodeInputStream getNodeInputStream(PSTFile pstFile)
+ PSTNodeInputStream getNodeInputStream(PSTSource pstFile)
throws IOException, PSTException
{
return new PSTNodeInputStream(pstFile,pstFile.getOffsetIndexNode(dataOffsetIndexIdentifier));
diff --git a/com/pff/OffsetIndexItem.java b/com/pff/parsing/OffsetIndexItem.java
similarity index 67%
rename from com/pff/OffsetIndexItem.java
rename to com/pff/parsing/OffsetIndexItem.java
index 76f1808..6e7635c 100644
--- a/com/pff/OffsetIndexItem.java
+++ b/com/pff/parsing/OffsetIndexItem.java
@@ -31,34 +31,38 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing;
+
+import com.pff.PSTUtils;
+import com.pff.source.PSTSource;
/**
* OffsetIndexItem is a leaf item from the Offset index b-tree
* Only really used internally to get the file offset for items
* @author Richard Johnson
*/
-class OffsetIndexItem {
+public class OffsetIndexItem {
long indexIdentifier;
long fileOffset;
int size;
long cRef;
- OffsetIndexItem(byte[] data, int pstFileType) {
- if (pstFileType == PSTFile.PST_TYPE_ANSI) {
- indexIdentifier = PSTObject.convertLittleEndianBytesToLong(data, 0, 4);
- fileOffset = PSTObject.convertLittleEndianBytesToLong(data, 4, 8);
- size = (int)PSTObject.convertLittleEndianBytesToLong(data, 8, 10);
- cRef = (int)PSTObject.convertLittleEndianBytesToLong(data, 10, 12);
+ public OffsetIndexItem(byte[] data, int pstFileType) {
+ if (pstFileType == PSTSource.PST_TYPE_ANSI) {
+ indexIdentifier = PSTUtils.convertLittleEndianBytesToLong(data, 0, 4);
+ fileOffset = PSTUtils.convertLittleEndianBytesToLong(data, 4, 8);
+ size = (int)PSTUtils.convertLittleEndianBytesToLong(data, 8, 10);
+ cRef = (int)PSTUtils.convertLittleEndianBytesToLong(data, 10, 12);
} else {
- indexIdentifier = PSTObject.convertLittleEndianBytesToLong(data, 0, 8);
- fileOffset = PSTObject.convertLittleEndianBytesToLong(data, 8, 16);
- size = (int)PSTObject.convertLittleEndianBytesToLong(data, 16, 18);
- cRef = (int)PSTObject.convertLittleEndianBytesToLong(data, 16, 18);
+ indexIdentifier = PSTUtils.convertLittleEndianBytesToLong(data, 0, 8);
+ fileOffset = PSTUtils.convertLittleEndianBytesToLong(data, 8, 16);
+ size = (int)PSTUtils.convertLittleEndianBytesToLong(data, 16, 18);
+ cRef = (int)PSTUtils.convertLittleEndianBytesToLong(data, 16, 18);
}
//System.out.println("Data size: "+data.length);
}
+
@Override
public String toString() {
@@ -68,4 +72,23 @@ public String toString() {
"cRef: "+cRef+" (0x"+Long.toHexString(cRef)+" bin:"+Long.toBinaryString(cRef)+")\n"+
"Size: "+size+" (0x"+Long.toHexString(size)+")";
}
+
+
+ public long getIndexIdentifier() {
+ return indexIdentifier;
+ }
+
+
+ public long getFileOffset() {
+ return fileOffset;
+ }
+
+
+ public int getSize() {
+ return size;
+ }
+
+
+
+
}
diff --git a/com/pff/PSTDescriptorItem.java b/com/pff/parsing/PSTDescriptorItem.java
similarity index 69%
rename from com/pff/PSTDescriptorItem.java
rename to com/pff/parsing/PSTDescriptorItem.java
index 3d67dc7..96a861d 100644
--- a/com/pff/PSTDescriptorItem.java
+++ b/com/pff/parsing/PSTDescriptorItem.java
@@ -31,40 +31,41 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing;
import java.io.IOException;
-import java.util.*;
+
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.source.PSTSource;
+
/**
* The descriptor items contain information that describes a PST object.
* This is like extended table entries, usually when the data cannot fit in a traditional table item.
* @author Richard Johnson
*/
-class PSTDescriptorItem
+public class PSTDescriptorItem
{
- PSTDescriptorItem(byte[] data, int offset, PSTFile pstFile)
- {
+ public PSTDescriptorItem(byte[] data, int offset, PSTSource pstFile) {
this.pstFile = pstFile;
- if (pstFile.getPSTFileType() == PSTFile.PST_TYPE_ANSI) {
- descriptorIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, offset, offset+4);
- offsetIndexIdentifier = ((int)PSTObject.convertLittleEndianBytesToLong(data, offset+4, offset+8))
+ if (pstFile.getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
+ descriptorIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, offset, offset+4);
+ offsetIndexIdentifier = ((int)PSTUtils.convertLittleEndianBytesToLong(data, offset+4, offset+8))
& 0xfffffffe;
- subNodeOffsetIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, offset+8, offset+12)
+ subNodeOffsetIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, offset+8, offset+12)
& 0xfffffffe;
} else {
- descriptorIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, offset, offset+4);
- offsetIndexIdentifier = ((int)PSTObject.convertLittleEndianBytesToLong(data, offset+8, offset+16))
+ descriptorIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, offset, offset+4);
+ offsetIndexIdentifier = ((int)PSTUtils.convertLittleEndianBytesToLong(data, offset+8, offset+16))
& 0xfffffffe;
- subNodeOffsetIndexIdentifier = (int)PSTObject.convertLittleEndianBytesToLong(data, offset+16, offset+24)
+ subNodeOffsetIndexIdentifier = (int)PSTUtils.convertLittleEndianBytesToLong(data, offset+16, offset+24)
& 0xfffffffe;
}
}
- public byte[] getData()
- throws IOException, PSTException
- {
+ public byte[] getData() throws IOException, PSTException {
if ( dataBlockData != null ) {
return dataBlockData;
}
@@ -76,11 +77,8 @@ public byte[] getData()
return dataBlockData;
}
- public int[] getBlockOffsets()
- throws IOException, PSTException
- {
+ public int[] getBlockOffsets() throws IOException, PSTException {
if ( dataBlockOffsets != null ) {
-
return dataBlockOffsets;
}
Long[] offsets = pstFile.readLeaf(offsetIndexIdentifier).getBlockOffsets();
@@ -91,14 +89,14 @@ public int[] getBlockOffsets()
return offsetsOut;
}
- public int getDataSize()
- throws IOException, PSTException
- {
+ public int getDataSize() throws IOException, PSTException {
return pstFile.getLeafSize(offsetIndexIdentifier);
}
// Public data
int descriptorIdentifier;
+
+
int offsetIndexIdentifier;
int subNodeOffsetIndexIdentifier;
@@ -106,7 +104,7 @@ public int getDataSize()
//private PSTFile.PSTFileBlock dataBlock = null;
byte[] dataBlockData = null;
int[] dataBlockOffsets = null;
- private PSTFile pstFile;
+ private PSTSource pstFile;
@Override
public String toString() {
@@ -118,5 +116,17 @@ public String toString() {
}
+
+
+ public int getDescriptorIdentifier() {
+ return descriptorIdentifier;
+ }
+
+ public int getSubNodeOffsetIndexIdentifier() {
+ return subNodeOffsetIndexIdentifier;
+ }
+
+
+
}
diff --git a/com/pff/PSTNodeInputStream.java b/com/pff/parsing/PSTNodeInputStream.java
similarity index 80%
rename from com/pff/PSTNodeInputStream.java
rename to com/pff/parsing/PSTNodeInputStream.java
index 3c36218..707126f 100644
--- a/com/pff/PSTNodeInputStream.java
+++ b/com/pff/parsing/PSTNodeInputStream.java
@@ -32,10 +32,15 @@
*
*/
-package com.pff;
+package com.pff.parsing;
-import java.io.*;
-import java.util.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedList;
+
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.source.PSTSource;
/**
* this input stream basically "maps" an input stream on top of the random access file
@@ -43,8 +48,8 @@
*/
public class PSTNodeInputStream extends InputStream {
- private RandomAccessFile in;
- private PSTFile pstFile;
+ //private _RandomAccessPSTSource in;
+ private PSTSource pstFile;
private LinkedList skipPoints = new LinkedList();
private LinkedList indexItems = new LinkedList();
private int currentBlock = 0;
@@ -56,14 +61,14 @@ public class PSTNodeInputStream extends InputStream {
private boolean encrypted = false;
- PSTNodeInputStream(PSTFile pstFile, byte[] attachmentData) {
+ public PSTNodeInputStream(PSTSource pstFile, byte[] attachmentData) {
this.allData = attachmentData;
this.length = this.allData.length;
- encrypted = pstFile.getEncryptionType() == PSTFile.ENCRYPTION_TYPE_COMPRESSIBLE;
+ encrypted = pstFile.getEncryptionType() == PSTSource.ENCRYPTION_TYPE_COMPRESSIBLE;
this.currentBlock = 0;
this.currentLocation = 0;
}
- PSTNodeInputStream(PSTFile pstFile, byte[] attachmentData, boolean encrypted) {
+ public PSTNodeInputStream(PSTSource pstFile, byte[] attachmentData, boolean encrypted) {
this.allData = attachmentData;
this.encrypted = encrypted;
this.length = this.allData.length;
@@ -71,12 +76,12 @@ public class PSTNodeInputStream extends InputStream {
this.currentLocation = 0;
}
- PSTNodeInputStream(PSTFile pstFile, PSTDescriptorItem descriptorItem)
+ public PSTNodeInputStream(PSTSource pstFile, PSTDescriptorItem descriptorItem)
throws IOException, PSTException
{
- this.in = pstFile.getFileHandle();
+ //this.in = pstFile.getFileHandle();
this.pstFile = pstFile;
- this.encrypted = pstFile.getEncryptionType() == PSTFile.ENCRYPTION_TYPE_COMPRESSIBLE;
+ this.encrypted = pstFile.getEncryptionType() == PSTSource.ENCRYPTION_TYPE_COMPRESSIBLE;
// we want to get the first block of data and see what we are dealing with
OffsetIndexItem offsetItem = pstFile.getOffsetIndexNode(descriptorItem.offsetIndexIdentifier);
@@ -86,12 +91,12 @@ public class PSTNodeInputStream extends InputStream {
}
- PSTNodeInputStream(PSTFile pstFile, OffsetIndexItem offsetItem)
+ public PSTNodeInputStream(PSTSource pstFile, OffsetIndexItem offsetItem)
throws IOException, PSTException
{
- this.in = pstFile.getFileHandle();
+ //this.in = pstFile.getFileHandle();
this.pstFile = pstFile;
- this.encrypted = pstFile.getEncryptionType() == PSTFile.ENCRYPTION_TYPE_COMPRESSIBLE;
+ this.encrypted = pstFile.getEncryptionType() == PSTSource.ENCRYPTION_TYPE_COMPRESSIBLE;
loadFromOffsetItem(offsetItem);
this.currentBlock = 0;
this.currentLocation = 0;
@@ -102,9 +107,11 @@ private void loadFromOffsetItem(OffsetIndexItem offsetItem)
{
boolean bInternal = (offsetItem.indexIdentifier & 0x02) != 0;
- in.seek(offsetItem.fileOffset);
+ //System.out.println("PSTNodeInputStream - loadFromOffsetItem 0 => seek "+ offsetItem.fileOffset);
+
+ pstFile.getRASource().seek(offsetItem.fileOffset);
byte[] data = new byte[offsetItem.size];
- in.read(data);
+ pstFile.getRASource().read(data);
if ( bInternal ) {
// All internal blocks are at least 8 bytes long...
@@ -116,7 +123,7 @@ private void loadFromOffsetItem(OffsetIndexItem offsetItem)
{
bInternal = false;
// we are a block, or xxblock
- length = PSTObject.convertLittleEndianBytesToLong(data, 4, 8);
+ length = PSTUtils.convertLittleEndianBytesToLong(data, 4, 8);
// go through all of the blocks and create skip points.
this.getBlockSkipPoints(data);
return;
@@ -143,23 +150,25 @@ private void getBlockSkipPoints(byte[] data)
throw new PSTException("Unable to process XBlock, incorrect identifier");
}
- int numberOfEntries = (int)PSTObject.convertLittleEndianBytesToLong(data, 2, 4);
+ int numberOfEntries = (int)PSTUtils.convertLittleEndianBytesToLong(data, 2, 4);
int arraySize = 8;
- if (this.pstFile.getPSTFileType() == PSTFile.PST_TYPE_ANSI) {
+ if (this.pstFile.getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
arraySize = 4;
}
if (data[1] == 0x2) {
// XXBlock
int offset = 8;
for (int x = 0; x < numberOfEntries; x++) {
- long bid = PSTObject.convertLittleEndianBytesToLong(data, offset, offset+arraySize);
+ long bid = PSTUtils.convertLittleEndianBytesToLong(data, offset, offset+arraySize);
bid &= 0xfffffffe;
// get the details in this block and
OffsetIndexItem offsetItem = this.pstFile.getOffsetIndexNode(bid);
- in.seek(offsetItem.fileOffset);
+ //System.out.println("PSTNodeInputStream - getBlockSkipPoints 0 => seek "+ offsetItem.fileOffset);
+
+ pstFile.getRASource().seek(offsetItem.fileOffset);
byte[] blockData = new byte[offsetItem.size];
- in.read(blockData);
+ pstFile.getRASource().read(blockData);
this.getBlockSkipPoints(blockData);
offset += arraySize;
}
@@ -167,7 +176,7 @@ private void getBlockSkipPoints(byte[] data)
// normal XBlock
int offset = 8;
for (int x = 0; x < numberOfEntries; x++) {
- long bid = PSTObject.convertLittleEndianBytesToLong(data, offset, offset+arraySize);
+ long bid = PSTUtils.convertLittleEndianBytesToLong(data, offset, offset+arraySize);
bid &= 0xfffffffe;
// get the details in this block and add it to the list
OffsetIndexItem offsetItem = pstFile.getOffsetIndexNode(bid);
@@ -197,7 +206,7 @@ public int read()
int value = this.allData[(int)this.currentLocation] & 0xFF;
this.currentLocation++;
if (this.encrypted) {
- value = PSTObject.compEnc[value];
+ value = PSTUtils.getCompEnc(value);
}
return value;
}
@@ -218,16 +227,16 @@ public int read()
// get the next byte.
long pos = (item.fileOffset + (this.currentLocation - skipPoint));
- if (in.getFilePointer() != pos) {
- in.seek(pos);
+ if (pstFile.getRASource().position() != pos) {
+ pstFile.getRASource().seek(pos);
}
- int output = in.read();
+ int output = pstFile.getRASource().read();
if (output < 0) {
return -1;
}
if (this.encrypted) {
- output = PSTObject.compEnc[output];
+ output = PSTUtils.getCompEnc(output);
}
this.currentLocation++;
@@ -235,7 +244,7 @@ public int read()
return output;
}
- private int totalLoopCount = 0;
+ //private int totalLoopCount = 0;
/**
* Read a block from the input stream.
@@ -263,14 +272,14 @@ public int read(byte[] output)
if (output.length >= bytesRemaining) {
System.arraycopy(this.allData, (int)this.currentLocation, output, 0, bytesRemaining);
if (this.encrypted) {
- PSTObject.decode(output);
+ PSTUtils.decode(output);
}
this.currentLocation += bytesRemaining; // should be = to this.length
return bytesRemaining;
} else {
System.arraycopy(this.allData, (int)this.currentLocation, output, 0, output.length);
if (this.encrypted) {
- PSTObject.decode(output);
+ PSTUtils.decode(output);
}
this.currentLocation += output.length;
return output.length;
@@ -287,7 +296,10 @@ public int read(byte[] output)
OffsetIndexItem offset = this.indexItems.get(this.currentBlock);
long skipPoint = this.skipPoints.get(currentBlock);
int currentPosInBlock = (int)(this.currentLocation - skipPoint);
- in.seek(offset.fileOffset + currentPosInBlock);
+
+ //System.out.println("PSTNodeInputStream - read 0 => seek "+ (offset.fileOffset + currentPosInBlock));
+
+ pstFile.getRASource().seek(offset.fileOffset + currentPosInBlock);
long nextSkipPoint = skipPoint + offset.size;
int bytesRemaining = (output.length - totalBytesFilled);
@@ -300,7 +312,7 @@ public int read(byte[] output)
if (nextSkipPoint >= this.currentLocation + bytesRemaining) {
// we can fill the output with the rest of our current block!
byte[] chunk = new byte[bytesRemaining];
- in.read(chunk);
+ pstFile.getRASource().read(chunk);
System.arraycopy(chunk, 0, output, totalBytesFilled, bytesRemaining);
totalBytesFilled += bytesRemaining;
@@ -311,18 +323,18 @@ public int read(byte[] output)
// we need to read out a whole chunk and keep going
int bytesToRead = offset.size - currentPosInBlock;
byte[] chunk = new byte[bytesToRead];
- in.read(chunk);
+ pstFile.getRASource().read(chunk);
System.arraycopy(chunk, 0, output, totalBytesFilled, bytesToRead);
totalBytesFilled += bytesToRead;
this.currentBlock++;
this.currentLocation += bytesToRead;
}
- totalLoopCount++;
+ //totalLoopCount++;
}
// decode the array if required
if (this.encrypted) {
- PSTObject.decode(output);
+ PSTUtils.decode(output);
}
// fill up our chunk
@@ -430,7 +442,9 @@ public void seek(long location)
blockStart = this.indexItems.get(currentBlock).fileOffset;
}
long newFilePos = blockStart + (location - skipPoint);
- this.in.seek(newFilePos);
+
+ //System.out.println("PSTNodeInputStream - seek 0 => seek "+ newFilePos);
+ pstFile.getRASource().seek(newFilePos);
}
@@ -440,10 +454,10 @@ public long seekAndReadLong(long location, int bytes)
this.seek(location);
byte[] buffer = new byte[bytes];
this.read(buffer);
- return PSTObject.convertLittleEndianBytesToLong(buffer);
+ return PSTUtils.convertLittleEndianBytesToLong(buffer);
}
- public PSTFile getPSTFile() {
+ public PSTSource getPSTFile() {
return this.pstFile;
}
diff --git a/com/pff/PSTTable.java b/com/pff/parsing/tables/PSTTable.java
similarity index 96%
rename from com/pff/PSTTable.java
rename to com/pff/parsing/tables/PSTTable.java
index 1e27667..6892703 100644
--- a/com/pff/PSTTable.java
+++ b/com/pff/parsing/tables/PSTTable.java
@@ -31,11 +31,16 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing.tables;
import java.io.IOException;
import java.util.HashMap;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+
/**
* The PST Table is the workhorse of the whole system.
@@ -81,8 +86,8 @@ protected PSTTable(PSTNodeInputStream in, HashMap su
in.read(headdata);
if ((int)headdata[2] != 0xffffffec) {
//System.out.println(in.isEncrypted());
- PSTObject.decode(headdata);
- PSTObject.printHexFormatted(headdata, true);
+ PSTUtils.decode(headdata);
+ PSTUtils.printHexFormatted(headdata, true);
throw new PSTException("Unable to parse table, bad table type...");
}
@@ -131,7 +136,7 @@ protected PSTTable(PSTNodeInputStream in, HashMap su
headerNodeInfo.in.seek(headerNodeInfo.startOffset);
byte[] tmp = new byte[1024];
headerNodeInfo.in.read(tmp);
- PSTObject.printHexFormatted(tmp, true);
+ PSTUtils.printHexFormatted(tmp, true);
//System.out.println(PSTObject.compEnc[headerByte]);
throw new PSTException("Unable to parse table, can't find BTHHEADER header information: "+headerByte);
}
diff --git a/com/pff/PSTTable7C.java b/com/pff/parsing/tables/PSTTable7C.java
similarity index 94%
rename from com/pff/PSTTable7C.java
rename to com/pff/parsing/tables/PSTTable7C.java
index e092ebf..883dd16 100644
--- a/com/pff/PSTTable7C.java
+++ b/com/pff/parsing/tables/PSTTable7C.java
@@ -31,20 +31,27 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing.tables;
/*
import java.io.UnsupportedEncodingException;
/**/
-import java.util.*;
-import java.io.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+import com.pff.source.PSTSource;
/**
* Specific functions for the 7c table type ("Table Context").
* This is used for attachments.
* @author Richard Johnson
*/
-class PSTTable7C extends PSTTable {
+public class PSTTable7C extends PSTTable {
private final int BLOCK_SIZE = 8176;
@@ -56,12 +63,12 @@ class PSTTable7C extends PSTTable {
private int TCI_1b = 0;
private int overrideCol = -1;
- protected PSTTable7C(PSTNodeInputStream in, HashMap subNodeDescriptorItems)
+ public PSTTable7C(PSTNodeInputStream in, HashMap subNodeDescriptorItems)
throws PSTException, java.io.IOException
{
this(in, subNodeDescriptorItems, -1);
}
- protected PSTTable7C(PSTNodeInputStream in, HashMap subNodeDescriptorItems, int entityToExtract)
+ public PSTTable7C(PSTNodeInputStream in, HashMap subNodeDescriptorItems, int entityToExtract)
throws PSTException, java.io.IOException
{
super(in, subNodeDescriptorItems);
@@ -154,16 +161,15 @@ protected PSTTable7C(PSTNodeInputStream in, HashMap
* get all the items parsed out of this table.
* @return
*/
- List> getItems()
- throws PSTException, IOException
- {
+ public List> getItems() throws PSTException, IOException {
if ( items == null ) {
items = getItems(-1, -1);
}
return items;
}
+
- List> getItems(int startAtRecord, int numberOfRecordsToReturn)
+ public List> getItems(int startAtRecord, int numberOfRecordsToReturn)
throws PSTException, IOException
{
List> itemList = new ArrayList>();
@@ -194,7 +200,7 @@ List> getItems(int startAtRecord, int numberOfR
{
HashMap currentItem = new HashMap();
// add on some padding for block boundries?
- if (rowNodeInfo.in.getPSTFile().getPSTFileType() == PSTFile.PST_TYPE_ANSI) {
+ if (rowNodeInfo.in.getPSTFile().getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
if (currentValueArrayStart >= BLOCK_SIZE) {
currentValueArrayStart = currentValueArrayStart + (4) * (currentValueArrayStart / BLOCK_SIZE);
}
diff --git a/com/pff/PSTTable7CItem.java b/com/pff/parsing/tables/PSTTable7CItem.java
similarity index 94%
rename from com/pff/PSTTable7CItem.java
rename to com/pff/parsing/tables/PSTTable7CItem.java
index 16b9877..0d0fec3 100644
--- a/com/pff/PSTTable7CItem.java
+++ b/com/pff/parsing/tables/PSTTable7CItem.java
@@ -31,13 +31,13 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing.tables;
/**
* Items found in the 7c tables
* @author Richard Johnson
*/
-class PSTTable7CItem extends PSTTableItem
+public class PSTTable7CItem extends PSTTableItem
{
public String toString() {
diff --git a/com/pff/PSTTableBC.java b/com/pff/parsing/tables/PSTTableBC.java
similarity index 90%
rename from com/pff/PSTTableBC.java
rename to com/pff/parsing/tables/PSTTableBC.java
index f681248..22a56aa 100644
--- a/com/pff/PSTTableBC.java
+++ b/com/pff/parsing/tables/PSTTableBC.java
@@ -31,26 +31,29 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing.tables;
import java.util.HashMap;
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+
/**
* The BC Table type. (Property Context)
* Used by pretty much everything.
* @author Richard Johnson
*/
-class PSTTableBC extends PSTTable {
+public class PSTTableBC extends PSTTable {
private HashMap items = new HashMap();
private StringBuilder descBuffer = new StringBuilder();
private boolean isDescNotYetInitiated = false;
- PSTTableBC(PSTNodeInputStream in)
- throws PSTException, java.io.IOException
- {
+ public PSTTableBC(PSTNodeInputStream in) throws PSTException, java.io.IOException {
super(in, new HashMap());
//data = null; // No direct access to data!
@@ -81,11 +84,11 @@ class PSTTableBC extends PSTTable {
PSTTableBCItem item = new PSTTableBCItem();
item.itemIndex = x;
- item.entryType =(int)PSTObject.convertLittleEndianBytesToLong(keyTableInfo, offset+0, offset+2);
+ item.entryType =(int)PSTUtils.convertLittleEndianBytesToLong(keyTableInfo, offset+0, offset+2);
//item.entryType =(int)in.seekAndReadLong(offset, 2);
- item.entryValueType = (int)PSTObject.convertLittleEndianBytesToLong(keyTableInfo, offset+2, offset+4);
+ item.entryValueType = (int)PSTUtils.convertLittleEndianBytesToLong(keyTableInfo, offset+2, offset+4);
//item.entryValueType = (int)in.seekAndReadLong(offset+2, 2);
- item.entryValueReference = (int)PSTObject.convertLittleEndianBytesToLong(keyTableInfo, offset+4, offset+8);
+ item.entryValueReference = (int)PSTUtils.convertLittleEndianBytesToLong(keyTableInfo, offset+4, offset+8);
//item.entryValueReference = (int)in.seekAndReadLong(offset+4, 4);
// Data is in entryValueReference for all types <= 4 bytes long
diff --git a/com/pff/PSTTableBCItem.java b/com/pff/parsing/tables/PSTTableBCItem.java
similarity index 94%
rename from com/pff/PSTTableBCItem.java
rename to com/pff/parsing/tables/PSTTableBCItem.java
index 4f7b330..bf33aa0 100644
--- a/com/pff/PSTTableBCItem.java
+++ b/com/pff/parsing/tables/PSTTableBCItem.java
@@ -31,13 +31,13 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing.tables;
/**
* Items within the BC Table
* @author Richard Johnson
*/
-class PSTTableBCItem extends PSTTableItem
+public class PSTTableBCItem extends PSTTableItem
{
public String toString() {
diff --git a/com/pff/PSTTableItem.java b/com/pff/parsing/tables/PSTTableItem.java
similarity index 91%
rename from com/pff/PSTTableItem.java
rename to com/pff/parsing/tables/PSTTableItem.java
index fe5fd1a..f660413 100644
--- a/com/pff/PSTTableItem.java
+++ b/com/pff/parsing/tables/PSTTableItem.java
@@ -31,7 +31,7 @@
* along with java-libpst. If not, see .
*
*/
-package com.pff;
+package com.pff.parsing.tables;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
@@ -39,12 +39,15 @@
import java.util.Date;
import java.util.SimpleTimeZone;
+import com.pff.PSTUtils;
+import com.pff.source.PSTSource;
+
/**
* Generic table item.
* Provides some basic string functions
* @author Richard Johnson
*/
-class PSTTableItem {
+public class PSTTableItem {
public static final int VALUE_TYPE_PT_UNICODE = 0x1f;
public static final int VALUE_TYPE_PT_STRING8 = 0x1e;
@@ -59,7 +62,7 @@ class PSTTableItem {
public long getLongValue() {
if ( this.data.length > 0 ) {
- return PSTObject.convertLittleEndianBytesToLong(data);
+ return PSTUtils.convertLittleEndianBytesToLong(data);
}
return -1;
}
@@ -134,7 +137,7 @@ public String getStringValue(int stringType) {
}
public String toString() {
- String ret = PSTFile.getPropertyDescription(entryType, entryValueType);
+ String ret = PSTSource.getPropertyDescription(entryType, entryValueType);
if ( entryValueType == 0x000B )
{
@@ -153,7 +156,7 @@ public String toString() {
return ret + "no data";
}
if ( data.length == 8 ) {
- long l = PSTObject.convertLittleEndianBytesToLong(data, 0, 8);
+ long l = PSTUtils.convertLittleEndianBytesToLong(data, 0, 8);
return String.format("%s0x%016X (%d)", ret, l, l);
} else {
return String.format("%s invalid data length: %d", ret, data.length);
@@ -162,10 +165,10 @@ public String toString() {
if ( entryValueType == 0x0040 ) {
// It's a date...
- int high = (int)PSTObject.convertLittleEndianBytesToLong(data, 4, 8);
- int low = (int)PSTObject.convertLittleEndianBytesToLong(data, 0, 4);
+ int high = (int)PSTUtils.convertLittleEndianBytesToLong(data, 4, 8);
+ int low = (int)PSTUtils.convertLittleEndianBytesToLong(data, 0, 4);
- Date d = PSTObject.filetimeToDate(high, low);
+ Date d = PSTUtils.filetimeToDate(high, low);
dateFormatter.setTimeZone(utcTimeZone);
return ret + dateFormatter.format(d);
}
diff --git a/com/pff/source/PSTRandomAccessFile.java b/com/pff/source/PSTRandomAccessFile.java
new file mode 100644
index 0000000..fe4cc9f
--- /dev/null
+++ b/com/pff/source/PSTRandomAccessFile.java
@@ -0,0 +1,57 @@
+package com.pff.source;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+public class PSTRandomAccessFile implements _RandomAccessPSTSource {
+
+ RandomAccessFile raf;
+
+ public PSTRandomAccessFile(File f) throws FileNotFoundException {
+ this.raf = new RandomAccessFile(f, "r");
+ }
+
+
+ public PSTRandomAccessFile(String filename) throws FileNotFoundException {
+ this.raf = new RandomAccessFile(filename, "r");
+ }
+
+
+
+ @Override
+ public void close() throws IOException {
+ this.raf.close();
+ }
+
+
+ @Override
+ public void seek(long pos) throws IOException {
+ this.raf.seek(pos);
+ }
+
+
+ @Override
+ public int read() throws IOException {
+ return this.raf.read();
+ }
+
+
+ @Override
+ public int read(byte[] buffer, int offset, int length) throws IOException {
+ return this.raf.read(buffer, offset, length);
+ }
+
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return this.raf.read(b);
+ }
+
+
+ @Override
+ public long position() throws IOException {
+ return this.raf.getFilePointer();
+ }
+}
diff --git a/com/pff/source/PSTSource.java b/com/pff/source/PSTSource.java
new file mode 100644
index 0000000..94b28a1
--- /dev/null
+++ b/com/pff/source/PSTSource.java
@@ -0,0 +1,918 @@
+/**
+ * Copyright 2010 Richard Johnson & Orin Eman
+ *
+ * Licensed 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.
+ *
+ * ---
+ *
+ * This file is part of java-libpst.
+ *
+ * java-libpst is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * java-libpst is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with java-libpst. If not, see .
+ *
+ */
+package com.pff.source;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Properties;
+import java.util.UUID;
+
+import com.pff.PSTUtils;
+import com.pff.exceptions.PSTException;
+import com.pff.objects.PSTFolder;
+import com.pff.objects.PSTMessageStore;
+import com.pff.parsing.DescriptorIndexNode;
+import com.pff.parsing.OffsetIndexItem;
+import com.pff.parsing.PSTDescriptorItem;
+import com.pff.parsing.PSTNodeInputStream;
+import com.pff.parsing.tables.PSTTableBC;
+import com.pff.parsing.tables.PSTTableBCItem;
+import com.pff.parsing.tables.PSTTableItem;
+
+/**
+ * PSTFile is the containing class that allows you to access items within a .pst file.
+ * Start here, get the root of the folders and work your way down through your items.
+ * @author Richard Johnson
+ */
+public class PSTSource {
+
+ public static final int ENCRYPTION_TYPE_NONE = 0;
+ public static final int ENCRYPTION_TYPE_COMPRESSIBLE = 1;
+
+ private static final int MESSAGE_STORE_DESCRIPTOR_IDENTIFIER = 33;
+ private static final int ROOT_FOLDER_DESCRIPTOR_IDENTIFIER = 290;
+
+ public static final int PST_TYPE_ANSI = 14;
+ protected static final int PST_TYPE_ANSI_2 = 15;
+ public static final int PST_TYPE_UNICODE = 23;
+
+ // Known GUIDs
+ // Local IDs first
+ public static final int PS_PUBLIC_STRINGS = 0;
+ public static final int PSETID_Common = 1;
+ public static final int PSETID_Address = 2;
+ public static final int PS_INTERNET_HEADERS = 3;
+ public static final int PSETID_Appointment = 4;
+ public static final int PSETID_Meeting = 5;
+ public static final int PSETID_Log = 6;
+ public static final int PSETID_Messaging = 7;
+ public static final int PSETID_Note = 8;
+ public static final int PSETID_PostRss = 9;
+ public static final int PSETID_Task = 10;
+ public static final int PSETID_UnifiedMessaging = 11;
+ public static final int PS_MAPI = 12;
+ public static final int PSETID_AirSync = 13;
+ public static final int PSETID_Sharing = 14;
+
+ // Now the string guids
+ private static final String guidStrings[] =
+ { "00020329-0000-0000-C000-000000000046",
+ "00062008-0000-0000-C000-000000000046",
+ "00062004-0000-0000-C000-000000000046",
+ "00020386-0000-0000-C000-000000000046",
+ "00062002-0000-0000-C000-000000000046",
+ "6ED8DA90-450B-101B-98DA-00AA003F1305",
+ "0006200A-0000-0000-C000-000000000046",
+ "41F28F13-83F4-4114-A584-EEDB5A6B0BFF",
+ "0006200E-0000-0000-C000-000000000046",
+ "00062041-0000-0000-C000-000000000046",
+ "00062003-0000-0000-C000-000000000046",
+ "4442858E-A9E3-4E80-B900-317A210CC15B",
+ "00020328-0000-0000-C000-000000000046",
+ "71035549-0739-4DCB-9163-00F0580DBBDF",
+ "00062040-0000-0000-C000-000000000046" };
+
+ private HashMap guidMap = new HashMap();
+
+ // the type of encryption the files uses.
+ private int encryptionType = 0;
+
+ // our all important tree.
+ private LinkedHashMap> childrenDescriptorTree = null;
+
+ private HashMap nameToId = new HashMap();
+ private HashMap stringToId = new HashMap();
+ private static HashMap idToName = new HashMap();
+ private HashMap idToString = new HashMap();
+ private byte[] guids = null;
+
+ _RandomAccessPSTSource in;
+
+ int itemCount=0;
+
+ /**
+ * constructor
+ * @param fileName
+ * @throws FileNotFoundException
+ * @throws PSTException
+ * @throws IOException
+ */
+ public PSTSource(_RandomAccessPSTSource in)
+ throws FileNotFoundException, PSTException, IOException
+ {
+ // attempt to open the file.
+ this.in = in;
+
+ // get the first 4 bytes, should be !BDN
+ try {
+ byte[] temp = new byte[4];
+ in.read(temp);
+ String strValue = new String(temp);
+ if (!strValue.equals("!BDN")) {
+ throw new PSTException("Invalid file header: "+strValue+", expected: !BDN");
+ }
+
+ // make sure we are using a supported version of a PST...
+ byte[] fileTypeBytes = new byte[2];
+ in.seek(10); //seekStream(in, 10); //
+ in.read(fileTypeBytes);
+ // ANSI file types can be 14 or 15:
+ if (fileTypeBytes[0] == PSTSource.PST_TYPE_ANSI_2) {
+ fileTypeBytes[0] = PSTSource.PST_TYPE_ANSI;
+ }
+ if (fileTypeBytes[0] != PSTSource.PST_TYPE_ANSI &&
+ fileTypeBytes[0] != PSTSource.PST_TYPE_UNICODE)
+ {
+ throw new PSTException("Unrecognised PST File version: "+fileTypeBytes[0]);
+ }
+ this.pstFileType = fileTypeBytes[0];
+
+ // make sure encryption is turned off at this stage...
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ in.seek(461);
+ } else {
+ in.seek(513);
+ }
+ encryptionType = in.read();
+ if (encryptionType == 0x02) {
+ throw new PSTException("Only unencrypted and compressable PST files are supported at this time");
+ }
+
+ // build out name to id map.
+ processNameToIdMap(in);
+
+ } catch (IOException err) {
+ throw new PSTException("Unable to read PST Sig", err);
+ }
+
+ }
+
+ private int pstFileType = 0;
+ public int getPSTFileType() {
+ return pstFileType;
+ }
+
+ /**
+ * read the name-to-id map from the file and load it in
+ * @param in
+ * @throws IOException
+ * @throws PSTException
+ */
+ private void processNameToIdMap(_RandomAccessPSTSource in)
+ throws IOException, PSTException
+ {
+
+ // Create our guid map
+ for ( int i = 0; i < guidStrings.length; ++i ) {
+ UUID uuid = UUID.fromString(guidStrings[i]);
+ guidMap.put(uuid, i);
+/*
+ System.out.printf("guidMap[{%s}] = %d\n", uuid.toString(), i);
+/**/
+ }
+
+ // process the name to id map
+ DescriptorIndexNode nameToIdMapDescriptorNode = (getDescriptorIndexNode(97));
+ //nameToIdMapDescriptorNode.readData(this);
+
+ // get the descriptors if we have them
+ HashMap localDescriptorItems = null;
+ if (nameToIdMapDescriptorNode.localDescriptorsOffsetIndexIdentifier != 0) {
+ //PSTDescriptor descriptor = new PSTDescriptor(this, nameToIdMapDescriptorNode.localDescriptorsOffsetIndexIdentifier);
+ //localDescriptorItems = descriptor.getChildren();
+ localDescriptorItems = this.getPSTDescriptorItems(nameToIdMapDescriptorNode.localDescriptorsOffsetIndexIdentifier);
+ }
+
+ // process the map
+ //PSTTableBC bcTable = new PSTTableBC(nameToIdMapDescriptorNode.dataBlock.data, nameToIdMapDescriptorNode.dataBlock.blockOffsets);
+ OffsetIndexItem off = this.getOffsetIndexNode(nameToIdMapDescriptorNode.dataOffsetIndexIdentifier);
+ PSTNodeInputStream nodein = new PSTNodeInputStream(this, off);
+ byte[] tmp = new byte[1024];
+ nodein.read(tmp);
+ PSTTableBC bcTable = new PSTTableBC(nodein);
+
+ HashMap tableItems = (bcTable.getItems());
+ // Get the guids
+ PSTTableBCItem guidEntry = tableItems.get(2); // PidTagNameidStreamGuid
+ guids = getData(guidEntry, localDescriptorItems);
+ int nGuids = guids.length / 16;
+ UUID[] uuidArray = new UUID[nGuids];
+ int[] uuidIndexes = new int[nGuids];
+ int offset = 0;
+ for ( int i = 0; i < nGuids; ++i ) {
+ long mostSigBits = (PSTUtils.convertLittleEndianBytesToLong(guids, offset, offset+4) << 32) |
+ (PSTUtils.convertLittleEndianBytesToLong(guids, offset+4, offset+6) << 16) |
+ PSTUtils.convertLittleEndianBytesToLong(guids, offset+6, offset+8);
+ long leastSigBits = PSTUtils.convertBigEndianBytesToLong(guids, offset+8, offset+16);
+ uuidArray[i] = new UUID(mostSigBits, leastSigBits);
+ if ( guidMap.containsKey(uuidArray[i]) ) {
+ uuidIndexes[i] = guidMap.get(uuidArray[i]);
+ } else {
+ uuidIndexes[i] = -1; // We don't know this guid
+ }
+/*
+ System.out.printf("uuidArray[%d] = {%s},%d\n", i, uuidArray[i].toString(), uuidIndexes[i]);
+/**/
+ offset += 16;
+ }
+
+ // if we have a reference to an internal descriptor
+ PSTTableBCItem mapEntries = tableItems.get(3); //
+ byte[] nameToIdByte = getData(mapEntries, localDescriptorItems);
+
+ PSTTableBCItem stringMapEntries = tableItems.get(4); //
+ byte[] stringNameToIdByte = getData(stringMapEntries, localDescriptorItems);
+
+ // process the entries
+ for (int x = 0; x+8 < nameToIdByte.length; x += 8) {
+ int dwPropertyId = (int)PSTUtils.convertLittleEndianBytesToLong(nameToIdByte, x, x+4);
+ int wGuid = (int)PSTUtils.convertLittleEndianBytesToLong(nameToIdByte, x+4, x+6);
+ int wPropIdx = ((int)PSTUtils.convertLittleEndianBytesToLong(nameToIdByte, x+6, x+8));
+
+ if ( (wGuid & 0x0001) == 0 ) {
+ wPropIdx += 0x8000;
+ wGuid >>= 1;
+ int guidIndex;
+ if ( wGuid == 1 ) {
+ guidIndex = PS_MAPI;
+ } else if ( wGuid == 2 ) {
+ guidIndex = PS_PUBLIC_STRINGS;
+ } else {
+ guidIndex = uuidIndexes[wGuid-3];
+ }
+ nameToId.put((long)dwPropertyId | ((long)guidIndex << 32), wPropIdx);
+ idToName.put(wPropIdx, (long)dwPropertyId);
+/*
+ System.out.printf("0x%08X:%04X, 0x%08X\n", dwPropertyId, guidIndex, wPropIdx);
+/**/
+ } else {
+ // else the identifier is a string
+ // dwPropertyId becomes thHke byte offset into the String stream in which the string name of the property is stored.
+ int len = (int)PSTUtils.convertLittleEndianBytesToLong(
+ stringNameToIdByte,
+ dwPropertyId,
+ dwPropertyId+4
+ );
+ byte[] keyByteValue = new byte[len];
+ System.arraycopy(stringNameToIdByte, dwPropertyId+4, keyByteValue, 0, keyByteValue.length);
+ wPropIdx += 0x8000;
+ String key = new String(keyByteValue, "UTF-16LE");
+ stringToId.put(key, wPropIdx);
+ idToString.put(wPropIdx, key);
+ /*
+ if (wPropIdx == 32784) {
+ System.out.println("here!" + dwPropertyId);
+ System.out.println(key);
+ //System.out.println(32784 - 0x8000);
+ }
+ */
+ }
+ }
+ }
+
+
+ private byte [] getData(PSTTableItem item, HashMap localDescriptorItems)
+ throws IOException, PSTException
+ {
+ if ( item.data.length != 0 ) {
+ return item.data;
+ }
+
+ if ( localDescriptorItems == null ) {
+ throw new PSTException("External reference but no localDescriptorItems in PSTFile.getData()");
+ }
+
+ if ( item.entryValueType != 0x0102 ) {
+ throw new PSTException("Attempting to get non-binary data in PSTFile.getData()");
+ }
+
+ PSTDescriptorItem mapDescriptorItem = localDescriptorItems.get(item.entryValueReference);
+ if (mapDescriptorItem == null) {
+ throw new PSTException ("not here "+item.entryValueReference + "\n"+localDescriptorItems.keySet());
+ }
+ return mapDescriptorItem.getData();
+ }
+
+ public int getNameToIdMapItem(int key, int propertySetIndex)
+ {
+ long lKey = ((long)propertySetIndex << 32) | (long)key;
+ Integer i = nameToId.get(lKey);
+ if ( i == null )
+ {
+ return -1;
+ }
+ return i;
+ }
+ public int getPublicStringToIdMapItem(String key)
+ {
+ Integer i = this.stringToId.get(key);
+ if (i == null) {
+ return -1;
+ }
+ return i;
+ }
+
+
+ static long getNameToIdMapKey(int id)
+ //throws PSTException
+ {
+ Long i = idToName.get(id);
+ if ( i == null )
+ {
+ //throw new PSTException("Name to Id mapping not found");
+ return -1;
+ }
+ return i;
+ }
+
+
+
+ static private Properties propertyInternetCodePages = null;
+ static private boolean bCPFirstTime = true;
+ public static String getInternetCodePageCharset(int propertyId) {
+ if ( bCPFirstTime ) {
+ bCPFirstTime = false;
+ propertyInternetCodePages = new Properties();
+ try {
+ InputStream propertyStream = PSTSource.class.getResourceAsStream("/InternetCodepages.txt");
+ if ( propertyStream != null ) {
+ propertyInternetCodePages.load(propertyStream);
+ } else {
+ propertyInternetCodePages = null;
+ }
+ } catch (FileNotFoundException e) {
+ propertyInternetCodePages = null;
+ e.printStackTrace();
+ } catch (IOException e) {
+ propertyInternetCodePages = null;
+ e.printStackTrace();
+ }
+ }
+ if ( propertyInternetCodePages != null ) {
+ return propertyInternetCodePages.getProperty(propertyId+"");
+ }
+ return null;
+ }
+
+
+ static private Properties propertyNames = null;
+ static private boolean bFirstTime = true;
+
+ static String getPropertyName(int propertyId, boolean bNamed) {
+ if ( bFirstTime ) {
+ bFirstTime = false;
+ propertyNames = new Properties();
+ try {
+ InputStream propertyStream = PSTSource.class.getResourceAsStream("/PropertyNames.txt");
+ if ( propertyStream != null ) {
+ propertyNames.load(propertyStream);
+ } else {
+ propertyNames = null;
+ }
+ } catch (FileNotFoundException e) {
+ propertyNames = null;
+ e.printStackTrace();
+ } catch (IOException e) {
+ propertyNames = null;
+ e.printStackTrace();
+ }
+ }
+
+ if ( propertyNames != null ) {
+ String key = String.format((bNamed ? "%08X" : "%04X"), propertyId);
+ return propertyNames.getProperty(key);
+ }
+
+ return null;
+ }
+
+
+
+ public static String getPropertyDescription(int entryType, int entryValueType) {
+ String ret = "";
+ if ( entryType < 0x8000 ) {
+ String name = PSTSource.getPropertyName(entryType, false);
+ if ( name != null ) {
+ ret = String.format("%s:%04X: ", name, entryValueType);
+ } else {
+ ret = String.format("0x%04X:%04X: ", entryType, entryValueType);
+ }
+ } else {
+ long type = PSTSource.getNameToIdMapKey(entryType);
+ if ( type == -1 ) {
+ ret = String.format("0xFFFF(%04X):%04X: ", entryType, entryValueType);
+ } else {
+ String name = PSTSource.getPropertyName((int)type, true);
+ if ( name != null ) {
+ ret = String.format("%s(%04X):%04X: ", name, entryType, entryValueType);
+ } else {
+ ret = String.format("0x%04X(%04X):%04X: ", type, entryType, entryValueType);
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * destructor just closes the file handle...
+ */
+ @Override
+ protected void finalize() throws IOException {
+ in.close();
+ }
+
+ /**
+ * get the type of encryption the file uses
+ * @return encryption type used in the PST File
+ */
+ public int getEncryptionType() {
+ return this.encryptionType;
+ }
+
+ /**
+ * get the handle to the file we are currently accessing
+ */
+ /*public RandomAccessFile getFileHandle() {
+ return this.in;
+ }*/
+
+
+ /**
+ * get the message store of the PST file.
+ * Note that this doesn't really have much information, better to look under the root folder
+ * @throws PSTException
+ * @throws IOException
+ */
+ public PSTMessageStore getMessageStore() throws PSTException, IOException {
+ DescriptorIndexNode messageStoreDescriptor = getDescriptorIndexNode(MESSAGE_STORE_DESCRIPTOR_IDENTIFIER);
+ return new PSTMessageStore(this, messageStoreDescriptor);
+ }
+
+ /**
+ * get the root folder for the PST file.
+ * You should find all of your data under here...
+ * @throws PSTException
+ * @throws IOException
+ */
+ public PSTFolder getRootFolder() throws PSTException, IOException {
+ DescriptorIndexNode rootFolderDescriptor = getDescriptorIndexNode(ROOT_FOLDER_DESCRIPTOR_IDENTIFIER);
+ PSTFolder output = new PSTFolder(this, rootFolderDescriptor);
+ return output;
+ }
+
+
+
+ public PSTNodeInputStream readLeaf(long bid) throws IOException, PSTException {
+ //PSTFileBlock ret = null;
+ //PSTNodeInputStream ret = null;
+
+ // get the index node for the descriptor index
+ OffsetIndexItem offsetItem = getOffsetIndexNode(bid);
+ return new PSTNodeInputStream(this, offsetItem);
+
+ }
+
+
+ public int getLeafSize(long bid) throws IOException, PSTException {
+ OffsetIndexItem offsetItem = getOffsetIndexNode(bid);
+
+ // Internal block?
+ if ( (offsetItem.getIndexIdentifier() & 0x02) == 0 ) {
+ // No, return the raw size
+ return offsetItem.getSize();
+ }
+
+ // we only need the first 8 bytes
+ byte[] data = new byte[8];
+ in.seek(offsetItem.getFileOffset());
+ in.read(data);
+
+ // we are an array, get the sum of the sizes...
+ return (int)PSTUtils.convertLittleEndianBytesToLong(data, 4, 8);
+ }
+
+ /**
+ * Read a file offset from the file
+ * PST Files have this tendency to store file offsets (pointers) in 8 little endian bytes.
+ * Convert this to a long for seeking to.
+ * @param in handle for PST file
+ * @param startOffset where to read the 8 bytes from
+ * @return long representing the read location
+ * @throws IOException
+ */
+ protected long extractLEFileOffset(long startOffset)
+ throws IOException
+ {
+ long offset = 0;
+ if (this.getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
+ in.seek(startOffset);
+ byte[] temp = new byte[4];
+ in.read(temp);
+ offset |= temp[3] & 0xff;
+ offset <<= 8;
+ offset |= temp[2] & 0xff;
+ offset <<= 8;
+ offset |= temp[1] & 0xff;
+ offset <<= 8;
+ offset |= temp[0] & 0xff;
+ } else {
+ in.seek(startOffset);
+ byte[] temp = new byte[8];
+ in.read(temp);
+ offset = temp[7] & 0xff;
+ long tmpLongValue;
+ for (int x = 6; x >= 0; x--) {
+ offset = offset << 8;
+ tmpLongValue = (long)temp[x] & 0xff;
+ offset |= tmpLongValue;
+ }
+ }
+
+ return offset;
+ }
+
+ /**
+ * Generic function used by getOffsetIndexNode and getDescriptorIndexNode for navigating the PST B-Trees
+ * @param in
+ * @param index
+ * @param descTree
+ * @return
+ * @throws IOException
+ * @throws PSTException
+ */
+ private byte[] findBtreeItem(_RandomAccessPSTSource in, long index, boolean descTree)
+ throws IOException, PSTException
+ {
+
+ long btreeStartOffset;
+ // first find the starting point for the offset index
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ btreeStartOffset = this.extractLEFileOffset(196);
+ if (descTree) {
+ btreeStartOffset = this.extractLEFileOffset(188);
+ }
+ } else {
+ btreeStartOffset = this.extractLEFileOffset(240);
+ if (descTree) {
+ btreeStartOffset = this.extractLEFileOffset(224);
+ }
+ }
+
+ // okay, what we want to do is navigate the tree until you reach the bottom....
+ // try and read the index b-tree
+ byte[] temp = new byte[2];
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ in.seek(btreeStartOffset+500);
+ } else {
+ in.seek(btreeStartOffset+496);
+ }
+ in.read(temp);
+ while ((temp[0] == 0xffffff80 && temp[1] == 0xffffff80 && !descTree) ||
+ (temp[0] == 0xffffff81 && temp[1] == 0xffffff81 && descTree))
+ {
+
+ // get the rest of the data....
+ byte[] branchNodeItems;
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ branchNodeItems = new byte[496];
+ } else {
+ branchNodeItems = new byte[488];
+ }
+ in.seek(btreeStartOffset);
+ in.read(branchNodeItems);
+
+ int numberOfItems = in.read();
+ in.read(); // maxNumberOfItems
+ in.read(); // itemSize
+ int levelsToLeaf = in.read();
+
+ if (levelsToLeaf > 0) {
+ boolean found = false;
+ for (int x = 0; x < numberOfItems; x++) {
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ long indexIdOfFirstChildNode = extractLEFileOffset(btreeStartOffset + (x * 12));
+ if (indexIdOfFirstChildNode > index) {
+ // get the address for the child first node in this group
+ btreeStartOffset = extractLEFileOffset(btreeStartOffset+((x-1) * 12)+8);
+ in.seek(btreeStartOffset+500);
+ in.read(temp);
+ found = true;
+ break;
+ }
+ } else {
+ long indexIdOfFirstChildNode = extractLEFileOffset(btreeStartOffset + (x * 24));
+ if (indexIdOfFirstChildNode > index) {
+ // get the address for the child first node in this group
+ btreeStartOffset = extractLEFileOffset(btreeStartOffset+((x-1) * 24)+16);
+ in.seek(btreeStartOffset+496);
+ in.read(temp);
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ // it must be in the very last branch...
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ btreeStartOffset = extractLEFileOffset(btreeStartOffset+((numberOfItems-1) * 12)+8);
+ in.seek(btreeStartOffset+500);
+ in.read(temp);
+ } else {
+ btreeStartOffset = extractLEFileOffset(btreeStartOffset+((numberOfItems-1) * 24)+16);
+ in.seek(btreeStartOffset+496);
+ in.read(temp);
+ }
+ }
+ }
+ else
+ {
+ // we are at the bottom of the tree...
+ // we want to get our file offset!
+ for (int x = 0; x < numberOfItems; x++) {
+
+ if (this.getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
+ if (descTree)
+ {
+ // The 32-bit descriptor index b-tree leaf node item
+ in.seek(btreeStartOffset + (x * 16));
+ temp = new byte[4];
+ in.read(temp);
+ if (PSTUtils.convertLittleEndianBytesToLong(temp) == index) {
+ // give me the offset index please!
+ in.seek(btreeStartOffset + (x * 16));
+ temp = new byte[16];
+ in.read(temp);
+ return temp;
+ }
+ }
+ else
+ {
+ // The 32-bit (file) offset index item
+ long indexIdOfFirstChildNode = extractLEFileOffset(btreeStartOffset + (x * 12));
+
+ if (indexIdOfFirstChildNode == index) {
+ // we found it!!!! OMG
+ //System.out.println("item found as item #"+x);
+ in.seek(btreeStartOffset + (x * 12));
+
+ temp = new byte[12];
+ in.read(temp);
+ return temp;
+ }
+ }
+ } else {
+ if (descTree)
+ {
+ // The 64-bit descriptor index b-tree leaf node item
+ in.seek(btreeStartOffset + (x * 32));
+
+ temp = new byte[4];
+ in.read(temp);
+ if (PSTUtils.convertLittleEndianBytesToLong(temp) == index) {
+ // give me the offset index please!
+ in.seek(btreeStartOffset + (x * 32));
+ temp = new byte[32];
+ in.read(temp);
+ return temp;
+ }
+ }
+ else
+ {
+ // The 64-bit (file) offset index item
+ long indexIdOfFirstChildNode = extractLEFileOffset(btreeStartOffset + (x * 24));
+
+ if (indexIdOfFirstChildNode == index) {
+ // we found it!!!! OMG
+ //System.out.println("item found as item #"+x);
+ in.seek(btreeStartOffset + (x * 24));
+
+ temp = new byte[24];
+ in.read(temp);
+ return temp;
+ }
+ }
+ }
+ }
+ throw new PSTException("Unable to find "+index);
+ }
+ }
+
+ throw new PSTException("Unable to find node: "+index);
+ }
+
+ /**
+ * navigate the internal descriptor B-Tree and find a specific item
+ * @param in
+ * @param identifier
+ * @return the descriptor node for the item
+ * @throws IOException
+ * @throws PSTException
+ */
+ public DescriptorIndexNode getDescriptorIndexNode(long identifier)
+ throws IOException, PSTException
+ {
+ return new DescriptorIndexNode(findBtreeItem(in, identifier, true), this.getPSTFileType());
+ }
+
+ /**
+ * navigate the internal index B-Tree and find a specific item
+ * @param in
+ * @param identifier
+ * @return the offset index item
+ * @throws IOException
+ * @throws PSTException
+ */
+ public OffsetIndexItem getOffsetIndexNode(long identifier) throws IOException, PSTException {
+ return new OffsetIndexItem(findBtreeItem(in, identifier, false), this.getPSTFileType());
+ }
+
+
+ /**
+ * parse a PSTDescriptor and get all of its items
+ */
+ public HashMap getPSTDescriptorItems(long localDescriptorsOffsetIndexIdentifier)
+ throws PSTException, IOException
+ {
+ return this.getPSTDescriptorItems(this.readLeaf(localDescriptorsOffsetIndexIdentifier));
+ }
+ HashMap getPSTDescriptorItems(PSTNodeInputStream in)
+ throws PSTException, IOException
+ {
+ // make sure the signature is correct
+ in.seek(0);
+ int sig = in.read();
+ if (sig != 0x2) {
+ throw new PSTException("Unable to process descriptor node, bad signature: "+sig);
+ }
+
+ HashMap output = new HashMap();
+ int numberOfItems = (int)in.seekAndReadLong(2, 2);
+ int offset;
+ if (this.getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
+ offset = 4;
+ } else {
+ offset = 8;
+ }
+
+ byte[] data = new byte[(int)in.length()];
+ in.seek(0);
+ in.read(data);
+
+ for (int x = 0; x < numberOfItems; x++) {
+ PSTDescriptorItem item = new PSTDescriptorItem(data, offset, this);
+ output.put(item.getDescriptorIdentifier(), item);
+ if (this.getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
+ offset += 12;
+ } else {
+ offset += 24;
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Build the children descriptor tree
+ * This goes through the entire descriptor B-Tree and adds every item to the childrenDescriptorTree.
+ * This is used as fallback when the nodes that list file contents are broken.
+ * @param in
+ * @throws IOException
+ * @throws PSTException
+ */
+ public LinkedHashMap> getChildDescriptorTree()
+ throws IOException, PSTException
+ {
+ if (this.childrenDescriptorTree == null) {
+ long btreeStartOffset = 0;
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ btreeStartOffset = this.extractLEFileOffset(188);
+ } else {
+ btreeStartOffset = this.extractLEFileOffset(224);
+ }
+ this.childrenDescriptorTree = new LinkedHashMap>();
+ processDescriptorBTree(btreeStartOffset);
+ }
+ return this.childrenDescriptorTree;
+ }
+
+ /**
+ * Recursive function for building the descriptor tree, used by buildDescriptorTree
+ * @param in
+ * @param btreeStartOffset
+ * @throws IOException
+ * @throws PSTException
+ */
+ private void processDescriptorBTree(long btreeStartOffset)
+ throws IOException, PSTException
+ {
+ byte[] temp = new byte[2];
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ in.seek(btreeStartOffset+500);
+ } else {
+ in.seek(btreeStartOffset+496);
+ }
+ in.read(temp);
+
+ if ((temp[0] == 0xffffff81 && temp[1] == 0xffffff81)) {
+
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ in.seek(btreeStartOffset+496);
+ } else {
+ in.seek(btreeStartOffset+488);
+ }
+
+ int numberOfItems = in.read();
+ in.read(); // maxNumberOfItems
+ in.read(); // itemSize
+ int levelsToLeaf = in.read();
+
+ if (levelsToLeaf > 0) {
+ for (int x = 0; x < numberOfItems; x++) {
+ if (this.getPSTFileType() == PST_TYPE_ANSI) {
+ long branchNodeItemStartIndex = (btreeStartOffset + (12*x));
+ long nextLevelStartsAt = this.extractLEFileOffset(branchNodeItemStartIndex+8);
+ processDescriptorBTree(nextLevelStartsAt);
+ } else {
+ long branchNodeItemStartIndex = (btreeStartOffset + (24*x));
+ long nextLevelStartsAt = this.extractLEFileOffset(branchNodeItemStartIndex+16);
+ processDescriptorBTree(nextLevelStartsAt);
+ }
+ }
+ } else {
+ for (int x = 0; x < numberOfItems; x++) {
+ // The 64-bit descriptor index b-tree leaf node item give me the offset index please!
+ if (this.getPSTFileType() == PSTSource.PST_TYPE_ANSI) {
+ in.seek(btreeStartOffset + (x * 16));
+ temp = new byte[16];
+ in.read(temp);
+ } else {
+ in.seek(btreeStartOffset + (x * 32));
+ temp = new byte[32];
+ in.read(temp);
+ }
+
+ DescriptorIndexNode tempNode = new DescriptorIndexNode(temp, this.getPSTFileType());
+
+ // we don't want to be children of ourselves...
+ if (tempNode.parentDescriptorIndexIdentifier == tempNode.descriptorIdentifier) {
+ // skip!
+ } else if (childrenDescriptorTree.containsKey(tempNode.parentDescriptorIndexIdentifier)) {
+ // add this entry to the existing list of children
+ LinkedList children = childrenDescriptorTree.get(tempNode.parentDescriptorIndexIdentifier);
+ children.add(tempNode);
+ } else {
+ // create a new entry and add this one to that
+ LinkedList children = new LinkedList();
+ children.add(tempNode);
+ childrenDescriptorTree.put(tempNode.parentDescriptorIndexIdentifier, children);
+ }
+ this.itemCount++;
+ }
+ }
+ } else {
+ PSTUtils.printHexFormatted(temp, true);
+ throw new PSTException("Unable to read descriptor node, is not a descriptor");
+ }
+ }
+
+
+ public _RandomAccessPSTSource getRASource() {
+ return this.in;
+ }
+
+
+}
diff --git a/com/pff/source/_RandomAccessPSTSource.java b/com/pff/source/_RandomAccessPSTSource.java
new file mode 100644
index 0000000..8fa11d1
--- /dev/null
+++ b/com/pff/source/_RandomAccessPSTSource.java
@@ -0,0 +1,22 @@
+package com.pff.source;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+public interface _RandomAccessPSTSource extends Closeable {
+
+
+ public void seek(long pos) throws IOException;
+
+ public int read() throws IOException;
+
+ public int read(byte[] buffer, int offset, int length) throws IOException;
+
+ public int read( byte[] b ) throws IOException;
+
+ public long position() throws IOException;
+
+
+
+
+}
diff --git a/deprecated/LZFu.java b/deprecated/LZFu.java
new file mode 100644
index 0000000..48f387e
--- /dev/null
+++ b/deprecated/LZFu.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010 Richard Johnson & Orin Eman
+ *
+ * Licensed 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.
+ *
+ * ---
+ *
+ * This file is part of java-libpst.
+ *
+ * java-libpst is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * java-libpst is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with java-libpst. If not, see .
+ *
+ */
+
+package com.pff;
+
+import java.io.UnsupportedEncodingException;
+
+import com.pff.exceptions.PSTException;
+
+/**
+ * An implementation of the LZFu algorithm to decompress RTF content
+ * @author Richard Johnson
+ */
+public class LZFu {
+
+
+
+}
diff --git a/com/pff/PSTFile.java b/deprecated/PSTFile.java
similarity index 93%
rename from com/pff/PSTFile.java
rename to deprecated/PSTFile.java
index 64e396e..596e5f6 100644
--- a/com/pff/PSTFile.java
+++ b/deprecated/PSTFile.java
@@ -135,7 +135,8 @@ public PSTFile(File fileName)
// make sure we are using a supported version of a PST...
byte[] fileTypeBytes = new byte[2];
- in.seek(10);
+ //in.seek(10);
+ seek(10);
in.read(fileTypeBytes);
// ANSI file types can be 14 or 15:
if (fileTypeBytes[0] == PSTFile.PST_TYPE_ANSI_2) {
@@ -150,9 +151,11 @@ public PSTFile(File fileName)
// make sure encryption is turned off at this stage...
if (this.getPSTFileType() == PST_TYPE_ANSI) {
- in.seek(461);
+ //in.seek(461);
+ seek(461);
} else {
- in.seek(513);
+ //in.seek(513);
+ seek(513);
}
encryptionType = in.readByte();
if (encryptionType == 0x02) {
@@ -407,6 +410,7 @@ static String getPropertyName(int propertyId, boolean bNamed) {
return null;
}
+
static String getPropertyDescription(int entryType, int entryValueType) {
String ret = "";
if ( entryType < 0x8000 ) {
@@ -492,7 +496,7 @@ PSTNodeInputStream readLeaf(long bid)
throws IOException, PSTException
{
//PSTFileBlock ret = null;
- PSTNodeInputStream ret = null;
+ //PSTNodeInputStream ret = null;
// get the index node for the descriptor index
OffsetIndexItem offsetItem = getOffsetIndexNode(bid);
@@ -514,7 +518,8 @@ public int getLeafSize(long bid)
// we only need the first 8 bytes
byte[] data = new byte[8];
- in.seek(offsetItem.fileOffset);
+ //in.seek(offsetItem.fileOffset);
+ seek(offsetItem.fileOffset);
in.read(data);
// we are an array, get the sum of the sizes...
@@ -535,7 +540,8 @@ protected long extractLEFileOffset(long startOffset)
{
long offset = 0;
if (this.getPSTFileType() == PSTFile.PST_TYPE_ANSI) {
- in.seek(startOffset);
+ //in.seek(startOffset);
+ seek(startOffset);
byte[] temp = new byte[4];
in.read(temp);
offset |= temp[3] & 0xff;
@@ -546,7 +552,8 @@ protected long extractLEFileOffset(long startOffset)
offset <<= 8;
offset |= temp[0] & 0xff;
} else {
- in.seek(startOffset);
+ //in.seek(startOffset);
+ seek(startOffset);
byte[] temp = new byte[8];
in.read(temp);
offset = temp[7] & 0xff;
@@ -570,7 +577,7 @@ protected long extractLEFileOffset(long startOffset)
* @throws IOException
* @throws PSTException
*/
- private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
+ private byte[] findBtreeItem(/*RandomAccessFile in, */long index, boolean descTree)
throws IOException, PSTException
{
@@ -592,9 +599,11 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
// try and read the index b-tree
byte[] temp = new byte[2];
if (this.getPSTFileType() == PST_TYPE_ANSI) {
- in.seek(btreeStartOffset+500);
+ //in.seek(btreeStartOffset+500);
+ seek(btreeStartOffset+500);
} else {
- in.seek(btreeStartOffset+496);
+ //in.seek(btreeStartOffset+496);
+ seek(btreeStartOffset+496);
}
in.read(temp);
while ((temp[0] == 0xffffff80 && temp[1] == 0xffffff80 && !descTree) ||
@@ -608,7 +617,8 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
} else {
branchNodeItems = new byte[488];
}
- in.seek(btreeStartOffset);
+ //in.seek(btreeStartOffset);
+ seek(btreeStartOffset);
in.read(branchNodeItems);
int numberOfItems = in.read();
@@ -624,7 +634,8 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
if (indexIdOfFirstChildNode > index) {
// get the address for the child first node in this group
btreeStartOffset = extractLEFileOffset(btreeStartOffset+((x-1) * 12)+8);
- in.seek(btreeStartOffset+500);
+ //in.seek(btreeStartOffset+500);
+ seek(btreeStartOffset+500);
in.read(temp);
found = true;
break;
@@ -634,7 +645,8 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
if (indexIdOfFirstChildNode > index) {
// get the address for the child first node in this group
btreeStartOffset = extractLEFileOffset(btreeStartOffset+((x-1) * 24)+16);
- in.seek(btreeStartOffset+496);
+ //in.seek(btreeStartOffset+496);
+ seek(btreeStartOffset+496);
in.read(temp);
found = true;
break;
@@ -645,11 +657,13 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
// it must be in the very last branch...
if (this.getPSTFileType() == PST_TYPE_ANSI) {
btreeStartOffset = extractLEFileOffset(btreeStartOffset+((numberOfItems-1) * 12)+8);
- in.seek(btreeStartOffset+500);
+ //in.seek(btreeStartOffset+500);
+ seek(btreeStartOffset+500);
in.read(temp);
} else {
btreeStartOffset = extractLEFileOffset(btreeStartOffset+((numberOfItems-1) * 24)+16);
- in.seek(btreeStartOffset+496);
+ //in.seek(btreeStartOffset+496);
+ seek(btreeStartOffset+496);
in.read(temp);
}
}
@@ -664,12 +678,14 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
if (descTree)
{
// The 32-bit descriptor index b-tree leaf node item
- in.seek(btreeStartOffset + (x * 16));
+ //in.seek(btreeStartOffset + (x * 16));
+ seek(btreeStartOffset + (x * 16));
temp = new byte[4];
in.read(temp);
if (PSTObject.convertLittleEndianBytesToLong(temp) == index) {
// give me the offset index please!
- in.seek(btreeStartOffset + (x * 16));
+ //in.seek(btreeStartOffset + (x * 16));
+ seek(btreeStartOffset + (x * 16));
temp = new byte[16];
in.read(temp);
return temp;
@@ -683,7 +699,8 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
if (indexIdOfFirstChildNode == index) {
// we found it!!!! OMG
//System.out.println("item found as item #"+x);
- in.seek(btreeStartOffset + (x * 12));
+ //in.seek(btreeStartOffset + (x * 12));
+ seek(btreeStartOffset + (x * 12));
temp = new byte[12];
in.read(temp);
@@ -694,13 +711,15 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
if (descTree)
{
// The 64-bit descriptor index b-tree leaf node item
- in.seek(btreeStartOffset + (x * 32));
+ //in.seek(btreeStartOffset + (x * 32));
+ seek(btreeStartOffset + (x * 32));
temp = new byte[4];
in.read(temp);
if (PSTObject.convertLittleEndianBytesToLong(temp) == index) {
// give me the offset index please!
- in.seek(btreeStartOffset + (x * 32));
+ //in.seek(btreeStartOffset + (x * 32));
+ seek(btreeStartOffset + (x * 32));
temp = new byte[32];
in.read(temp);
return temp;
@@ -714,7 +733,8 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
if (indexIdOfFirstChildNode == index) {
// we found it!!!! OMG
//System.out.println("item found as item #"+x);
- in.seek(btreeStartOffset + (x * 24));
+ //in.seek(btreeStartOffset + (x * 24));
+ seek(btreeStartOffset + (x * 24));
temp = new byte[24];
in.read(temp);
@@ -741,7 +761,7 @@ private byte[] findBtreeItem(RandomAccessFile in, long index, boolean descTree)
DescriptorIndexNode getDescriptorIndexNode(long identifier)
throws IOException, PSTException
{
- return new DescriptorIndexNode(findBtreeItem(in, identifier, true), this.getPSTFileType());
+ return new DescriptorIndexNode(findBtreeItem(/*in,*/ identifier, true), this.getPSTFileType());
}
/**
@@ -755,7 +775,7 @@ DescriptorIndexNode getDescriptorIndexNode(long identifier)
OffsetIndexItem getOffsetIndexNode(long identifier)
throws IOException, PSTException
{
- return new OffsetIndexItem(findBtreeItem(in, identifier, false), this.getPSTFileType());
+ return new OffsetIndexItem(findBtreeItem(/*in,*/ identifier, false), this.getPSTFileType());
}
@@ -909,4 +929,10 @@ private void processDescriptorBTree(long btreeStartOffset)
}
+
+
+ private void seek(long pos) throws IOException {
+ System.out.println("seeking file => "+pos);
+ this.in.seek(pos);
+ }
}
diff --git a/example/Test.java b/example/Test.java
index b95d13b..112540d 100644
--- a/example/Test.java
+++ b/example/Test.java
@@ -1,16 +1,23 @@
package example;
-import com.pff.*;
-import java.util.*;
+import java.util.ArrayList;
+
+import com.pff.exceptions.PSTException;
+import com.pff.objects.PSTFolder;
+import com.pff.objects.PSTMessage;
+import com.pff.source.PSTRandomAccessFile;
+import com.pff.source.PSTSource;
+import com.pff.source._RandomAccessPSTSource;
public class Test {
- public static void main(String[] args)
- {
+
+ public static void main(String[] args) {
new Test(args[0]);
}
public Test(String filename) {
try {
- PSTFile pstFile = new PSTFile(filename);
+ _RandomAccessPSTSource raSrc = new PSTRandomAccessFile(filename);
+ PSTSource pstFile = new PSTSource(raSrc);
System.out.println(pstFile.getMessageStore().getDisplayName());
processFolder(pstFile.getRootFolder());
} catch (Exception err) {
@@ -19,9 +26,7 @@ public Test(String filename) {
}
int depth = -1;
- public void processFolder(PSTFolder folder)
- throws PSTException, java.io.IOException
- {
+ public void processFolder(PSTFolder folder) throws PSTException, java.io.IOException {
depth++;
// the root folder doesn't have a display name
if (depth > 0) {
@@ -31,7 +36,7 @@ public void processFolder(PSTFolder folder)
// go through the folders...
if (folder.hasSubfolders()) {
- Vector childFolders = folder.getSubFolders();
+ ArrayList childFolders = folder.getSubFolders();
for (PSTFolder childFolder : childFolders) {
processFolder(childFolder);
}
diff --git a/example/TestGui.java b/example/TestGui.java
index 6672855..a945dbb 100644
--- a/example/TestGui.java
+++ b/example/TestGui.java
@@ -4,26 +4,62 @@
package example;
-import java.awt.*;
-import java.awt.event.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-import javax.swing.table.AbstractTableModel;
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
-import java.io.*;
-import javax.swing.tree.*;
-
-import com.pff.*;
-
-import java.util.*;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.JTextPane;
+import javax.swing.JTree;
+import javax.swing.ListSelectionModel;
+import javax.swing.WindowConstants;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import com.pff.exceptions.PSTException;
+import com.pff.objects.PSTActivity;
+import com.pff.objects.PSTAttachment;
+import com.pff.objects.PSTContact;
+import com.pff.objects.PSTFolder;
+import com.pff.objects.PSTMessage;
+import com.pff.objects.PSTMessageStore;
+import com.pff.objects.PSTObject;
+import com.pff.objects.PSTRss;
+import com.pff.objects.PSTTask;
+import com.pff.source.PSTRandomAccessFile;
+import com.pff.source.PSTSource;
/**
* @author toweruser
*
*/
public class TestGui implements ActionListener {
- private PSTFile pstFile;
+ private PSTSource pstFile;
private EmailTableModel emailTableModel;
private JTextPane emailText;
private JPanel emailPanel;
@@ -40,7 +76,7 @@ public TestGui() throws PSTException, IOException {
// attempt to open the pst file
try {
- /*
+
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(f) == JFileChooser.APPROVE_OPTION) {
} else {
@@ -48,13 +84,12 @@ public TestGui() throws PSTException, IOException {
}
String filename = chooser.getSelectedFile().getCanonicalPath();
- */
- String filename = "Outlook-new.pst";
- filename = "G:\\From old Tower\\pff\\java\\Old Email.pst";
+
+ /*String filename = "Outlook-new.pst";
+ filename = "G:\\From old Tower\\pff\\java\\Old Email.pst";*/
//filename = "RichardJohnson@sumac.uk.com - exchange.ost";
//String filename = "Outlook 32bit.pst";
- //String russian = "Узеи́р Абду́л-Гусе́йн оглы́ Гаджибе́ков (азерб. Üzeyir bəy Əbdülhüseyn oğlu Hacıbəyov; 18 сентября 1885, Агджабеди, Шушинский уезд, Елизаветпольская губерния, Российская империя — 23 ноября 1948, Баку, Азербайджанская ССР, СССР) — азербайджанский композитор, дирижёр, публицист, фельетонист, драматург и педагог, народный артист СССР (1938), дважды лауреат Сталинских премий (1941, 1946). Действительный член АН Азербайджана (1945), профессор (1940), ректор Азербайджанской государственной ";
-
+
//System.out.println(java.nio.charset.Charset.availableCharsets());
//byte[] russianBytes = russian.getBytes("UTF-8");
@@ -62,7 +97,8 @@ public TestGui() throws PSTException, IOException {
//String filename = "Outlook 32bit.pst";
//filename = "RichardJohnson@sumac.uk.com - exchange.ost";
- pstFile = new PSTFile(filename);
+ PSTRandomAccessFile pstRaF = new PSTRandomAccessFile(filename);
+ pstFile = new PSTSource(pstRaF);
//pstFile = new PSTFile("RichardJohnson@sumac.uk.com - exchange.ost");
@@ -175,7 +211,9 @@ public TestGui() throws PSTException, IOException {
}
final JTree folderTree = new JTree(top){
- public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+ private static final long serialVersionUID = 1L;
+
+ public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
DefaultMutableTreeNode nodeValue = (DefaultMutableTreeNode)value;
if (nodeValue.getUserObject() instanceof PSTFolder) {
PSTFolder folderValue = (PSTFolder)nodeValue.getUserObject();
@@ -293,14 +331,14 @@ public void valueChanged(ListSelectionEvent e) {
// Set the visibility as true, thereby displaying it
f.setVisible(true);
// f.setSize(800, 600);
- f.setExtendedState(f.getExtendedState() | f.MAXIMIZED_BOTH);
+ f.setExtendedState(f.getExtendedState() | JFrame.MAXIMIZED_BOTH);
}
private void buildTree(DefaultMutableTreeNode top, PSTFolder theFolder) {
// this is recursive, try and keep up.
try {
- Vector children = theFolder.getSubFolders();
- Iterator childrenIterator = children.iterator();
+ ArrayList children = theFolder.getSubFolders();
+ Iterator childrenIterator = children.iterator();
while (childrenIterator.hasNext()) {
PSTFolder folder = (PSTFolder)childrenIterator.next();
@@ -429,13 +467,14 @@ public static void main(String[] args) throws PSTException, IOException {
}
class EmailTableModel extends AbstractTableModel {
+ private static final long serialVersionUID = 6414607674310021030L;
PSTFolder theFolder = null;
- PSTFile theFile = null;
+ PSTSource theFile = null;
- HashMap cache = new HashMap();
+ HashMap cache = new HashMap();
- public EmailTableModel(PSTFolder theFolder, PSTFile theFile) {
+ public EmailTableModel(PSTFolder theFolder, PSTSource theFile) {
super();
this.theFolder = theFolder;
@@ -527,7 +566,7 @@ public void setFolder(PSTFolder theFolder)
{
theFolder.moveChildCursorTo(0);
this.theFolder = theFolder;
- cache = new HashMap();
+ cache = new HashMap();
this.fireTableDataChanged();
}
diff --git a/example/TestRandomAccess.java b/example/TestRandomAccess.java
new file mode 100644
index 0000000..d0fdc97
--- /dev/null
+++ b/example/TestRandomAccess.java
@@ -0,0 +1,15 @@
+package example;
+
+public class TestRandomAccess {
+
+ public TestRandomAccess() {
+
+ }
+
+
+ public static void main(String[] args) {
+
+
+ }
+
+}