You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Chunks.java 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hsmf.datatypes;
  16. import java.util.ArrayList;
  17. import java.util.Collections;
  18. import java.util.HashMap;
  19. import java.util.List;
  20. import java.util.Map;
  21. import org.apache.poi.util.POILogFactory;
  22. import org.apache.poi.util.POILogger;
  23. /**
  24. * Collection of convenience chunks for standard parts of the MSG file.
  25. *
  26. * Not all of these will be present in any given file.
  27. *
  28. * A partial list is available at:
  29. * http://msdn.microsoft.com/en-us/library/ms526356%28v=exchg.10%29.aspx
  30. *
  31. * TODO Deprecate the public Chunks in favour of Property Lookups
  32. */
  33. public final class Chunks implements ChunkGroupWithProperties {
  34. private static final POILogger LOG = POILogFactory.getLogger(Chunks.class);
  35. /**
  36. * Holds all the chunks that were found, indexed by their MAPIProperty.
  37. * Normally a property will have zero chunks (fixed sized) or one chunk
  38. * (variable size), but in some cases (eg Unknown) you may get more.
  39. */
  40. private Map<MAPIProperty, List<Chunk>> allChunks = new HashMap<>();
  41. /** Type of message that the MSG represents (ie. IPM.Note) */
  42. private StringChunk messageClass;
  43. /** BODY Chunk, for plain/text messages */
  44. private StringChunk textBodyChunk;
  45. /** BODY Html Chunk, for html messages */
  46. private StringChunk htmlBodyChunkString;
  47. private ByteChunk htmlBodyChunkBinary;
  48. /** BODY Rtf Chunk, for Rtf (Rich) messages */
  49. private ByteChunk rtfBodyChunk;
  50. /** Subject link chunk, in plain/text */
  51. private StringChunk subjectChunk;
  52. /**
  53. * Value that is in the TO field (not actually the addresses as they are
  54. * stored in recip directory nodes
  55. */
  56. private StringChunk displayToChunk;
  57. /** Value that is in the FROM field */
  58. private StringChunk displayFromChunk;
  59. /** value that shows in the CC field */
  60. private StringChunk displayCCChunk;
  61. /** Value that shows in the BCC field */
  62. private StringChunk displayBCCChunk;
  63. /** Sort of like the subject line, but without the RE: and FWD: parts. */
  64. private StringChunk conversationTopic;
  65. /** Type of server that the message originated from (SMTP, etc). */
  66. private StringChunk sentByServerType;
  67. /** The email headers */
  68. private StringChunk messageHeaders;
  69. /** TODO */
  70. private MessageSubmissionChunk submissionChunk;
  71. /** TODO */
  72. private StringChunk emailFromChunk;
  73. /** The message ID */
  74. private StringChunk messageId;
  75. /** The message properties */
  76. private MessagePropertiesChunk messageProperties;
  77. @Override
  78. public Map<MAPIProperty, List<PropertyValue>> getProperties() {
  79. if (messageProperties != null) {
  80. return messageProperties.getProperties();
  81. } else {
  82. return Collections.emptyMap();
  83. }
  84. }
  85. public Map<MAPIProperty, PropertyValue> getRawProperties() {
  86. if (messageProperties != null) {
  87. return messageProperties.getRawProperties();
  88. } else {
  89. return Collections.emptyMap();
  90. }
  91. }
  92. public Map<MAPIProperty, List<Chunk>> getAll() {
  93. return allChunks;
  94. }
  95. @Override
  96. public Chunk[] getChunks() {
  97. ArrayList<Chunk> chunks = new ArrayList<>(allChunks.size());
  98. for (List<Chunk> c : allChunks.values()) {
  99. chunks.addAll(c);
  100. }
  101. return chunks.toArray(new Chunk[chunks.size()]);
  102. }
  103. public StringChunk getMessageClass() {
  104. return messageClass;
  105. }
  106. public StringChunk getTextBodyChunk() {
  107. return textBodyChunk;
  108. }
  109. public StringChunk getHtmlBodyChunkString() {
  110. return htmlBodyChunkString;
  111. }
  112. public ByteChunk getHtmlBodyChunkBinary() {
  113. return htmlBodyChunkBinary;
  114. }
  115. public ByteChunk getRtfBodyChunk() {
  116. return rtfBodyChunk;
  117. }
  118. public StringChunk getSubjectChunk() {
  119. return subjectChunk;
  120. }
  121. public StringChunk getDisplayToChunk() {
  122. return displayToChunk;
  123. }
  124. public StringChunk getDisplayFromChunk() {
  125. return displayFromChunk;
  126. }
  127. public StringChunk getDisplayCCChunk() {
  128. return displayCCChunk;
  129. }
  130. public StringChunk getDisplayBCCChunk() {
  131. return displayBCCChunk;
  132. }
  133. public StringChunk getConversationTopic() {
  134. return conversationTopic;
  135. }
  136. public StringChunk getSentByServerType() {
  137. return sentByServerType;
  138. }
  139. public StringChunk getMessageHeaders() {
  140. return messageHeaders;
  141. }
  142. public MessageSubmissionChunk getSubmissionChunk() {
  143. return submissionChunk;
  144. }
  145. public StringChunk getEmailFromChunk() {
  146. return emailFromChunk;
  147. }
  148. public StringChunk getMessageId() {
  149. return messageId;
  150. }
  151. public MessagePropertiesChunk getMessageProperties() {
  152. return messageProperties;
  153. }
  154. /**
  155. * Called by the parser whenever a chunk is found.
  156. */
  157. @Override
  158. public void record(Chunk chunk) {
  159. // Work out what MAPIProperty this corresponds to
  160. MAPIProperty prop = MAPIProperty.get(chunk.getChunkId());
  161. // Assign it for easy lookup, as best we can
  162. if (prop == MAPIProperty.MESSAGE_CLASS) {
  163. messageClass = (StringChunk) chunk;
  164. } else if (prop == MAPIProperty.INTERNET_MESSAGE_ID) {
  165. messageId = (StringChunk) chunk;
  166. } else if (prop == MAPIProperty.MESSAGE_SUBMISSION_ID) {
  167. // TODO - parse
  168. submissionChunk = (MessageSubmissionChunk) chunk;
  169. } else if (prop == MAPIProperty.RECEIVED_BY_ADDRTYPE) {
  170. sentByServerType = (StringChunk) chunk;
  171. } else if (prop == MAPIProperty.TRANSPORT_MESSAGE_HEADERS) {
  172. messageHeaders = (StringChunk) chunk;
  173. }
  174. else if (prop == MAPIProperty.CONVERSATION_TOPIC) {
  175. conversationTopic = (StringChunk) chunk;
  176. } else if (prop == MAPIProperty.SUBJECT) {
  177. subjectChunk = (StringChunk) chunk;
  178. } /*else if (prop == MAPIProperty.ORIGINAL_SUBJECT) {
  179. // TODO
  180. }*/
  181. else if (prop == MAPIProperty.DISPLAY_TO) {
  182. displayToChunk = (StringChunk) chunk;
  183. } else if (prop == MAPIProperty.DISPLAY_CC) {
  184. displayCCChunk = (StringChunk) chunk;
  185. } else if (prop == MAPIProperty.DISPLAY_BCC) {
  186. displayBCCChunk = (StringChunk) chunk;
  187. }
  188. else if (prop == MAPIProperty.SENDER_EMAIL_ADDRESS) {
  189. emailFromChunk = (StringChunk) chunk;
  190. } else if (prop == MAPIProperty.SENDER_NAME) {
  191. displayFromChunk = (StringChunk) chunk;
  192. } else if (prop == MAPIProperty.BODY) {
  193. textBodyChunk = (StringChunk) chunk;
  194. } else if (prop == MAPIProperty.BODY_HTML) {
  195. if (chunk instanceof StringChunk) {
  196. htmlBodyChunkString = (StringChunk) chunk;
  197. }
  198. if (chunk instanceof ByteChunk) {
  199. htmlBodyChunkBinary = (ByteChunk) chunk;
  200. }
  201. } else if (prop == MAPIProperty.RTF_COMPRESSED) {
  202. rtfBodyChunk = (ByteChunk) chunk;
  203. } else if (chunk instanceof MessagePropertiesChunk) {
  204. messageProperties = (MessagePropertiesChunk) chunk;
  205. }
  206. // And add to the main list
  207. if (allChunks.get(prop) == null) {
  208. allChunks.put(prop, new ArrayList<>());
  209. }
  210. allChunks.get(prop).add(chunk);
  211. }
  212. @Override
  213. public void chunksComplete() {
  214. if (messageProperties != null) {
  215. messageProperties.matchVariableSizedPropertiesToChunks();
  216. } else {
  217. LOG.log(POILogger.WARN,
  218. "Message didn't contain a root list of properties!");
  219. }
  220. }
  221. }