| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.hmef.dev; |
| |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.List; |
| |
| import org.apache.poi.hmef.HMEFMessage; |
| import org.apache.poi.hmef.attribute.MAPIAttribute; |
| import org.apache.poi.hmef.attribute.TNEFAttribute; |
| import org.apache.poi.hmef.attribute.TNEFDateAttribute; |
| import org.apache.poi.hmef.attribute.TNEFProperty; |
| import org.apache.poi.hmef.attribute.TNEFStringAttribute; |
| import org.apache.poi.util.HexDump; |
| import org.apache.poi.util.IOUtils; |
| import org.apache.poi.util.LittleEndian; |
| |
| /** |
| * Developer focused raw dumper |
| */ |
| public final class HMEFDumper { |
| |
| //arbitrarily selected; may need to increase |
| private static final int MAX_RECORD_LENGTH = 1_000_000; |
| |
| public static void main(String[] args) throws Exception { |
| if(args.length < 1) { |
| throw new IllegalArgumentException("Filename must be given"); |
| } |
| |
| boolean truncatePropData = true; |
| for (String arg : args) { |
| if (arg.equalsIgnoreCase("--full")) { |
| truncatePropData = false; |
| continue; |
| } |
| |
| try (InputStream stream = new FileInputStream(arg)) { |
| HMEFDumper dumper = new HMEFDumper(stream); |
| dumper.setTruncatePropertyData(truncatePropData); |
| dumper.dump(); |
| } |
| } |
| } |
| |
| private InputStream inp; |
| private boolean truncatePropertyData; |
| |
| public HMEFDumper(InputStream inp) throws IOException { |
| this.inp = inp; |
| |
| // Check the signature matches |
| int sig = LittleEndian.readInt(inp); |
| if(sig != HMEFMessage.HEADER_SIGNATURE) { |
| throw new IllegalArgumentException( |
| "TNEF signature not detected in file, " + |
| "expected " + HMEFMessage.HEADER_SIGNATURE + |
| " but got " + sig |
| ); |
| } |
| |
| // Skip over the File ID |
| LittleEndian.readUShort(inp); |
| } |
| |
| public void setTruncatePropertyData(boolean truncate) { |
| truncatePropertyData = truncate; |
| } |
| |
| private void dump() throws IOException { |
| int level; |
| int attachments = 0; |
| |
| while(true) { |
| // Fetch the level |
| level = inp.read(); |
| if(level == TNEFProperty.LEVEL_END_OF_FILE) { |
| break; |
| } |
| |
| // Build the attribute |
| TNEFAttribute attr = TNEFAttribute.create(inp); |
| |
| // Is it a new attachment? |
| if(level == TNEFProperty.LEVEL_ATTACHMENT && |
| attr.getProperty() == TNEFProperty.ID_ATTACHRENDERDATA) { |
| attachments++; |
| System.out.println(); |
| System.out.println("Attachment # " + attachments); |
| System.out.println(); |
| } |
| |
| // Print the attribute into |
| System.out.println( |
| "Level " + level + " : Type " + attr.getType() + |
| " : ID " + attr.getProperty() |
| ); |
| |
| // Print the contents |
| String indent = " "; |
| |
| if(attr instanceof TNEFStringAttribute) { |
| System.out.println(indent + indent + indent + ((TNEFStringAttribute)attr).getString()); |
| } |
| if(attr instanceof TNEFDateAttribute) { |
| System.out.println(indent + indent + indent + ((TNEFDateAttribute)attr).getDate()); |
| } |
| |
| System.out.println(indent + "Data of length " + attr.getData().length); |
| if(attr.getData().length > 0) { |
| int len = attr.getData().length; |
| if(truncatePropertyData) { |
| len = Math.min( attr.getData().length, 48 ); |
| } |
| |
| int loops = len/16; |
| if(loops == 0) loops = 1; |
| |
| for(int i=0; i<loops; i++) { |
| int thisLen = 16; |
| int offset = i*16; |
| if(i == loops-1) { |
| thisLen = len - offset; |
| } |
| |
| byte[] data = IOUtils.safelyClone(attr.getData(), offset, thisLen, MAX_RECORD_LENGTH); |
| |
| System.out.print( |
| indent + HexDump.dump(data, 0, 0) |
| ); |
| } |
| } |
| System.out.println(); |
| |
| if(attr.getProperty() == TNEFProperty.ID_MAPIPROPERTIES || |
| attr.getProperty() == TNEFProperty.ID_ATTACHMENT) { |
| List<MAPIAttribute> attrs = MAPIAttribute.create(attr); |
| for(MAPIAttribute ma : attrs) { |
| System.out.println(indent + indent + ma); |
| } |
| System.out.println(); |
| } |
| } |
| } |
| } |