@@ -129,39 +129,56 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
129129 metadata .set (OneNote .RGB_PLACEHOLDER ,
130130 "0x" + Long .toHexString (oneNoteDocument .header .rgbPlaceholder ));
131131
132- Pair <Long , ExtendedGUID > roleAndContext = Pair .of (1L , ExtendedGUID .nil ());
133- OneNoteTreeWalker oneNoteTreeWalker =
134- new OneNoteTreeWalker (options , oneNoteDocument , oneNoteDirectFileResource ,
135- xhtml , metadata , context , roleAndContext );
132+ Exception structureFailure = oneNoteDocument .structureParseException ;
133+ boolean walked = false ;
134+ if (structureFailure == null ) {
135+ try {
136+ Pair <Long , ExtendedGUID > roleAndContext = Pair .of (1L , ExtendedGUID .nil ());
137+ OneNoteTreeWalker oneNoteTreeWalker =
138+ new OneNoteTreeWalker (options , oneNoteDocument ,
139+ oneNoteDirectFileResource , xhtml , metadata , context ,
140+ roleAndContext );
136141
137- oneNoteTreeWalker .walkTree ();
142+ oneNoteTreeWalker .walkTree ();
138143
139- if (!oneNoteTreeWalker .getAuthors ().isEmpty ()) {
140- metadata .set (TikaCoreProperties .CREATOR ,
141- sortedValues (oneNoteTreeWalker .getAuthors ()));
142- }
143- if (!oneNoteTreeWalker .getMostRecentAuthors ().isEmpty ()) {
144- metadata .set (OneNote .MOST_RECENT_AUTHORS ,
145- sortedValues (oneNoteTreeWalker .getMostRecentAuthors ()));
146- }
147- if (!oneNoteTreeWalker .getOriginalAuthors ().isEmpty ()) {
148- metadata .set (OneNote .ORIGINAL_AUTHORS ,
149- sortedValues (oneNoteTreeWalker .getOriginalAuthors ()));
150- }
151- if (!Instant .MAX .equals (
152- Instant .ofEpochMilli (oneNoteTreeWalker .getCreationTimestamp ()))) {
153- metadata .set (OneNote .CREATION_TIMESTAMP ,
154- String .valueOf (oneNoteTreeWalker .getCreationTimestamp ()));
155- }
156- if (!Instant .MIN .equals (oneNoteTreeWalker .getLastModifiedTimestamp ())) {
157- metadata .set (OneNote .LAST_MODIFIED_TIMESTAMP , String .valueOf (
158- oneNoteTreeWalker .getLastModifiedTimestamp ().toEpochMilli ()));
144+ if (!oneNoteTreeWalker .getAuthors ().isEmpty ()) {
145+ metadata .set (TikaCoreProperties .CREATOR ,
146+ sortedValues (oneNoteTreeWalker .getAuthors ()));
147+ }
148+ if (!oneNoteTreeWalker .getMostRecentAuthors ().isEmpty ()) {
149+ metadata .set (OneNote .MOST_RECENT_AUTHORS ,
150+ sortedValues (oneNoteTreeWalker .getMostRecentAuthors ()));
151+ }
152+ if (!oneNoteTreeWalker .getOriginalAuthors ().isEmpty ()) {
153+ metadata .set (OneNote .ORIGINAL_AUTHORS ,
154+ sortedValues (oneNoteTreeWalker .getOriginalAuthors ()));
155+ }
156+ if (!Instant .MAX .equals (
157+ Instant .ofEpochMilli (oneNoteTreeWalker .getCreationTimestamp ()))) {
158+ metadata .set (OneNote .CREATION_TIMESTAMP ,
159+ String .valueOf (oneNoteTreeWalker .getCreationTimestamp ()));
160+ }
161+ if (!Instant .MIN .equals (oneNoteTreeWalker .getLastModifiedTimestamp ())) {
162+ metadata .set (OneNote .LAST_MODIFIED_TIMESTAMP , String .valueOf (
163+ oneNoteTreeWalker .getLastModifiedTimestamp ().toEpochMilli ()));
164+ }
165+ if (oneNoteTreeWalker .getLastModified () > Long .MIN_VALUE ) {
166+ metadata .set (TikaCoreProperties .MODIFIED ,
167+ String .valueOf (oneNoteTreeWalker .getLastModified ()));
168+ }
169+ walked = true ;
170+ } catch (Exception e ) {
171+ rethrowIfLimitReached (e );
172+ structureFailure = e ;
173+ }
159174 }
160- if (oneNoteTreeWalker .getLastModified () > Long .MIN_VALUE ) {
161- metadata .set (TikaCoreProperties .MODIFIED ,
162- String .valueOf (oneNoteTreeWalker .getLastModified ()));
175+ if (!walked ) {
176+ legacyFallbackDump ("OneNote parse failed; falling back to legacy text dump: " +
177+ failureMessage (structureFailure ), structureFailure , metadata ,
178+ xhtml , oneNoteDirectFileResource );
163179 }
164180 } else if (header .isLegacyOrAlternativePackaging ()) {
181+ MSOneStorePackage pkg = null ;
165182 try {
166183 AlternativePackaging alternatePackageOneStoreFile = new AlternativePackaging ();
167184 byte [] bytes ;
@@ -172,27 +189,18 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
172189 alternatePackageOneStoreFile .doDeserializeFromByteArray (bytes , 0 );
173190
174191 MSOneStoreParser onenoteParser = new MSOneStoreParser ();
175- MSOneStorePackage pkg =
176- onenoteParser .parse (alternatePackageOneStoreFile .dataElementPackage );
192+ pkg = onenoteParser .parse (alternatePackageOneStoreFile .dataElementPackage );
177193
178194 pkg .walkTree (options , metadata , xhtml , context );
179195 } catch (Exception e ) {
180- WriteLimitReachedException .throwIfWriteLimitReached (e );
181- if (e instanceof EmbeddedLimitReachedException ) {
182- throw (EmbeddedLimitReachedException ) e ;
183- }
184- String failure = e .getMessage () == null ? e .getClass ().getSimpleName () :
185- e .getMessage ();
186- LOG .warn ("OneNote FSSHTTPB parse failed; falling back to legacy text dump: {}" ,
187- failure );
188- LOG .debug ("OneNote FSSHTTPB parse failure" , e );
189- metadata .add (TikaCoreProperties .TIKA_META_EXCEPTION_WARNING ,
196+ rethrowIfLimitReached (e );
197+ legacyFallbackDump (
190198 "OneNote FSSHTTPB parse failed; falling back to legacy text dump: " +
191- failure );
192- OneNoteLegacyDumpStrings dumpStrings =
193- new OneNoteLegacyDumpStrings (oneNoteDirectFileResource , xhtml );
194- dumpStrings .dump ();
199+ failureMessage (e ), e , metadata , xhtml ,
200+ oneNoteDirectFileResource );
201+ pkg = null ;
195202 }
203+ legacyFallbackIfNoContent (pkg , metadata , xhtml , oneNoteDirectFileResource );
196204 } else {
197205 throw new TikaException ("Invalid OneStore document - could not parse headers" );
198206 }
@@ -208,6 +216,42 @@ private static String[] sortedValues(Set<String> values) {
208216 return sorted ;
209217 }
210218
219+ private static void rethrowIfLimitReached (Exception e ) throws TikaException , SAXException {
220+ WriteLimitReachedException .throwIfWriteLimitReached (e );
221+ if (e instanceof EmbeddedLimitReachedException ) {
222+ throw (EmbeddedLimitReachedException ) e ;
223+ }
224+ }
225+
226+ private static String failureMessage (Exception e ) {
227+ return e .getMessage () == null ? e .getClass ().getSimpleName () : e .getMessage ();
228+ }
229+
230+ // the walk completed but every page dangled - without this a degraded
231+ // file would yield empty output where the dump still finds its text
232+ static void legacyFallbackIfNoContent (MSOneStorePackage pkg , Metadata metadata ,
233+ XHTMLContentHandler xhtml ,
234+ OneNoteDirectFileResource oneNoteDirectFileResource )
235+ throws TikaException , SAXException {
236+ if (pkg != null && !pkg .hasEmittedContent ()) {
237+ legacyFallbackDump ("OneNote FSSHTTPB parse produced no content; " +
238+ "falling back to legacy text dump" , null , metadata , xhtml ,
239+ oneNoteDirectFileResource );
240+ }
241+ }
242+
243+ private static void legacyFallbackDump (String warning , Exception cause , Metadata metadata ,
244+ XHTMLContentHandler xhtml ,
245+ OneNoteDirectFileResource oneNoteDirectFileResource )
246+ throws TikaException , SAXException {
247+ LOG .warn (warning );
248+ if (cause != null ) {
249+ LOG .debug ("OneNote parse failure" , cause );
250+ }
251+ metadata .add (TikaCoreProperties .TIKA_META_EXCEPTION_WARNING , warning );
252+ new OneNoteLegacyDumpStrings (oneNoteDirectFileResource , xhtml ).dump ();
253+ }
254+
211255 /**
212256 * Create a OneNoteDocument object.
213257 * <p>
@@ -241,7 +285,8 @@ private static String[] sortedValues(Set<String> values) {
241285 * content.
242286 * @return A parsed one note document. This document does not contain any of the binary data,
243287 * rather it just contains
244- * the data pointers and metadata.
288+ * the data pointers and metadata. A failure while parsing the root file node list is not
289+ * thrown; it is recorded in the returned document's {@code structureParseException}.
245290 * @throws IOException Will throw IOException in typical IO issue situations.
246291 */
247292 public OneNoteDocument createOneNoteDocumentFromDirectFileResource (
@@ -253,9 +298,15 @@ public OneNoteDocument createOneNoteDocumentFromDirectFileResource(
253298
254299 if (oneNoteDocument .header .isMsOneStoreFormat ()) {
255300 // Now that we parsed the header, the "root file node list"
256- oneNotePtr .reposition (oneNoteDocument .header .fcrFileNodeListRoot );
257- FileNodePtr curPath = new FileNodePtr ();
258- oneNotePtr .deserializeFileNodeList (oneNoteDocument .root , curPath );
301+ try {
302+ oneNotePtr .reposition (oneNoteDocument .header .fcrFileNodeListRoot );
303+ FileNodePtr curPath = new FileNodePtr ();
304+ oneNotePtr .deserializeFileNodeList (oneNoteDocument .root , curPath );
305+ } catch (TikaException | IOException | RuntimeException e ) {
306+ // a truncated or malformed root list is recorded, not thrown, so the
307+ // caller can fall back to the legacy string dump
308+ oneNoteDocument .structureParseException = e ;
309+ }
259310 }
260311 return oneNoteDocument ;
261312 }
0 commit comments