use of org.apache.poi.hsmf.datatypes.Types.MAPIType in project poi by apache.
the class POIFSChunkParser method process.
/**
* Creates a chunk, and gives it to its parent group
*/
protected static void process(Entry entry, ChunkGroup grouping) {
String entryName = entry.getName();
Chunk chunk = null;
// Is it a properties chunk? (They have special names)
if (entryName.equals(PropertiesChunk.NAME)) {
if (grouping instanceof Chunks) {
// These should be the properties for the message itself
chunk = new MessagePropertiesChunk(grouping);
} else {
// Will be properties on an attachment or recipient
chunk = new StoragePropertiesChunk(grouping);
}
} else {
// Check it's a regular chunk
if (entryName.length() < 9) {
// Name in the wrong format
return;
}
if (!entryName.contains("_")) {
// Name in the wrong format
return;
}
// Split it into its parts
int splitAt = entryName.lastIndexOf('_');
String namePrefix = entryName.substring(0, splitAt + 1);
String ids = entryName.substring(splitAt + 1);
// the form __<name>_<id><type>
if (namePrefix.equals("Olk10SideProps") || namePrefix.equals("Olk10SideProps_")) {
// This is some odd Outlook 2002 thing, skip
return;
} else if (splitAt <= entryName.length() - 8) {
// In the right form for a normal chunk
// We'll process this further in a little bit
} else {
// Underscores not the right place, something's wrong
throw new IllegalArgumentException("Invalid chunk name " + entryName);
}
// Now try to turn it into id + type
try {
int chunkId = Integer.parseInt(ids.substring(0, 4), 16);
int typeId = Integer.parseInt(ids.substring(4, 8), 16);
MAPIType type = Types.getById(typeId);
if (type == null) {
type = Types.createCustom(typeId);
}
// Special cases based on the ID
if (chunkId == MAPIProperty.MESSAGE_SUBMISSION_ID.id) {
chunk = new MessageSubmissionChunk(namePrefix, chunkId, type);
} else {
// So, do the usual thing which is by type
if (type == Types.BINARY) {
chunk = new ByteChunk(namePrefix, chunkId, type);
} else if (type == Types.DIRECTORY) {
if (entry instanceof DirectoryNode) {
chunk = new DirectoryChunk((DirectoryNode) entry, namePrefix, chunkId, type);
}
} else if (type == Types.ASCII_STRING || type == Types.UNICODE_STRING) {
chunk = new StringChunk(namePrefix, chunkId, type);
} else {
// Type of an unsupported type! Skipping...
}
}
} catch (NumberFormatException e) {
// Name in the wrong format
return;
}
}
if (chunk != null) {
if (entry instanceof DocumentNode) {
DocumentInputStream inp = null;
try {
inp = new DocumentInputStream((DocumentNode) entry);
chunk.readValue(inp);
grouping.record(chunk);
} catch (IOException e) {
logger.log(POILogger.ERROR, "Error reading from part " + entry.getName() + " - " + e);
} finally {
if (inp != null)
inp.close();
}
} else {
grouping.record(chunk);
}
}
}
use of org.apache.poi.hsmf.datatypes.Types.MAPIType in project poi by apache.
the class PropertiesChunk method readProperties.
protected void readProperties(InputStream value) throws IOException {
boolean going = true;
while (going) {
try {
// Read in the header
int typeID = LittleEndian.readUShort(value);
int id = LittleEndian.readUShort(value);
long flags = LittleEndian.readUInt(value);
// Turn the Type and ID into helper objects
MAPIType type = Types.getById(typeID);
MAPIProperty prop = MAPIProperty.get(id);
// Wrap properties we don't know about as custom ones
if (prop == MAPIProperty.UNKNOWN) {
prop = MAPIProperty.createCustom(id, type, "Unknown " + id);
}
if (type == null) {
logger.log(POILogger.WARN, "Invalid type found, expected ", prop.usualType, " but got ", typeID, " for property ", prop);
going = false;
break;
}
// Sanity check the property's type against the value's type
if (prop.usualType != type) {
// Is it an allowed substitution?
if (type == Types.ASCII_STRING && prop.usualType == Types.UNICODE_STRING || type == Types.UNICODE_STRING && prop.usualType == Types.ASCII_STRING) {
// It's fine to go with the specified instead of the
// normal
} else if (prop.usualType == Types.UNKNOWN) {
// We don't know what this property normally is, but it
// has come
// through with a valid type, so use that
logger.log(POILogger.INFO, "Property definition for ", prop, " is missing a type definition, found a value with type ", type);
} else {
// Oh dear, something has gone wrong...
logger.log(POILogger.WARN, "Type mismatch, expected ", prop.usualType, " but got ", type, " for property ", prop);
going = false;
break;
}
}
// TODO Detect if it is multi-valued, since if it is
// then even fixed-length strings store their multiple
// values in another chunk (much as variable length ones)
// Work out how long the "data" is
// This might be the actual data, or just a pointer
// to another chunk which holds the data itself
boolean isPointer = false;
int length = type.getLength();
if (!type.isFixedLength()) {
isPointer = true;
length = 8;
}
// Grab the data block
byte[] data = new byte[length];
IOUtils.readFully(value, data);
// Skip over any padding
if (length < 8) {
byte[] padding = new byte[8 - length];
IOUtils.readFully(value, padding);
}
// Wrap and store
PropertyValue propVal = null;
if (isPointer) {
// We'll match up the chunk later
propVal = new ChunkBasedPropertyValue(prop, flags, data);
} else if (type == Types.NULL) {
propVal = new NullPropertyValue(prop, flags, data);
} else if (type == Types.BOOLEAN) {
propVal = new BooleanPropertyValue(prop, flags, data);
} else if (type == Types.SHORT) {
propVal = new ShortPropertyValue(prop, flags, data);
} else if (type == Types.LONG) {
propVal = new LongPropertyValue(prop, flags, data);
} else if (type == Types.LONG_LONG) {
propVal = new LongLongPropertyValue(prop, flags, data);
} else if (type == Types.FLOAT) {
propVal = new FloatPropertyValue(prop, flags, data);
} else if (type == Types.DOUBLE) {
propVal = new DoublePropertyValue(prop, flags, data);
} else if (type == Types.CURRENCY) {
propVal = new CurrencyPropertyValue(prop, flags, data);
} else if (type == Types.TIME) {
propVal = new TimePropertyValue(prop, flags, data);
} else // TODO Add in the rest of the types
{
propVal = new PropertyValue(prop, flags, data);
}
if (properties.get(prop) != null) {
logger.log(POILogger.WARN, "Duplicate values found for " + prop);
}
properties.put(prop, propVal);
} catch (BufferUnderrunException e) {
// Invalid property, ended short
going = false;
}
}
}
use of org.apache.poi.hsmf.datatypes.Types.MAPIType in project poi by apache.
the class MAPIAttribute method create.
/**
* Parses a MAPI Properties TNEF Attribute, and returns
* the list of MAPI Attributes contained within it
*/
public static List<MAPIAttribute> create(TNEFAttribute parent) throws IOException {
if (parent.getProperty() == TNEFProperty.ID_MAPIPROPERTIES) {
// Regular MAPI Properties, normally on the message
} else if (parent.getProperty() == TNEFProperty.ID_ATTACHMENT) {
// MAPI Properties for an attachment
} else {
// Something else, oh dear...
throw new IllegalArgumentException("Can only create from a MAPIProperty attribute, " + "instead received a " + parent.getProperty() + " one");
}
ByteArrayInputStream inp = new ByteArrayInputStream(parent.getData());
// First up, get the number of attributes
int count = LittleEndian.readInt(inp);
List<MAPIAttribute> attrs = new ArrayList<MAPIAttribute>();
// Now, read each one in in turn
for (int i = 0; i < count; i++) {
int typeAndMV = LittleEndian.readUShort(inp);
int id = LittleEndian.readUShort(inp);
// Is it either Multi-Valued or Variable-Length?
boolean isMV = false;
boolean isVL = false;
int typeId = typeAndMV;
if ((typeAndMV & Types.MULTIVALUED_FLAG) != 0) {
isMV = true;
typeId -= Types.MULTIVALUED_FLAG;
}
if (typeId == Types.ASCII_STRING.getId() || typeId == Types.UNICODE_STRING.getId() || typeId == Types.BINARY.getId() || typeId == Types.DIRECTORY.getId()) {
isVL = true;
}
// Turn the type ID into a strongly typed thing
MAPIType type = Types.getById(typeId);
if (type == null) {
type = Types.createCustom(typeId);
}
// If it's a named property, rather than a standard
// MAPI property, grab the details of it
MAPIProperty prop = MAPIProperty.get(id);
if (id >= 0x8000 && id <= 0xFFFF) {
byte[] guid = new byte[16];
IOUtils.readFully(inp, guid);
int mptype = LittleEndian.readInt(inp);
// Get the name of it
String name;
if (mptype == 0) {
// It's based on a normal one
int mpid = LittleEndian.readInt(inp);
MAPIProperty base = MAPIProperty.get(mpid);
name = base.name;
} else {
// Custom name was stored
int mplen = LittleEndian.readInt(inp);
byte[] mpdata = new byte[mplen];
IOUtils.readFully(inp, mpdata);
name = StringUtil.getFromUnicodeLE(mpdata, 0, (mplen / 2) - 1);
skipToBoundary(mplen, inp);
}
// Now create
prop = MAPIProperty.createCustom(id, type, name);
}
if (prop == MAPIProperty.UNKNOWN) {
prop = MAPIProperty.createCustom(id, type, "(unknown " + Integer.toHexString(id) + ")");
}
// Now read in the value(s)
int values = 1;
if (isMV || isVL) {
values = LittleEndian.readInt(inp);
}
for (int j = 0; j < values; j++) {
int len = getLength(type, inp);
byte[] data = new byte[len];
IOUtils.readFully(inp, data);
skipToBoundary(len, inp);
// Create
MAPIAttribute attr;
if (type == Types.UNICODE_STRING || type == Types.ASCII_STRING) {
attr = new MAPIStringAttribute(prop, typeId, data);
} else if (type == Types.APP_TIME || type == Types.TIME) {
attr = new MAPIDateAttribute(prop, typeId, data);
} else if (id == MAPIProperty.RTF_COMPRESSED.id) {
attr = new MAPIRtfAttribute(prop, typeId, data);
} else {
attr = new MAPIAttribute(prop, typeId, data);
}
attrs.add(attr);
}
}
// All done
return attrs;
}
Aggregations