From 975fe00071b9a9797eaf3b39ac687c605399873a Mon Sep 17 00:00:00 2001 From: Vhati Date: Sat, 7 Sep 2013 04:26:37 -0400 Subject: [PATCH] Added rebuildXMLFile() to repair non-append xml in mods during patching --- .../vhati/modmanager/core/ModPatchThread.java | 19 ++++++++-- .../vhati/modmanager/core/ModUtilities.java | 37 ++++++++++++++++++- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/vhati/modmanager/core/ModPatchThread.java b/src/main/java/net/vhati/modmanager/core/ModPatchThread.java index bb9a3ed..d5cf5b0 100644 --- a/src/main/java/net/vhati/modmanager/core/ModPatchThread.java +++ b/src/main/java/net/vhati/modmanager/core/ModPatchThread.java @@ -237,7 +237,21 @@ public class ModPatchThread extends Thread { moddedItems.add( innerPath ); } } - else if ( fileName.endsWith( ".xml" ) || fileName.endsWith( ".txt" ) ) { + if ( fileName.endsWith( ".xml" ) ) { + innerPath = checkCase( innerPath, knownPaths, knownPathsLower ); + + InputStream fixedStream = ModUtilities.rebuildXMLFile( zis, "windows-1252", modFile.getName()+":"+parentPath+fileName ); + + if ( !moddedItems.contains(innerPath) ) + moddedItems.add( innerPath ); + else + log.warn( String.format( "Clobbering earlier mods: %s", innerPath ) ); + + if ( ftlP.contains( innerPath ) ) + ftlP.remove( innerPath ); + ftlP.add( innerPath, fixedStream ); + } + else if ( fileName.endsWith( ".txt" ) ) { innerPath = checkCase( innerPath, knownPaths, knownPathsLower ); // Normalize line endings for other text files to CR-LF. @@ -245,9 +259,6 @@ public class ModPatchThread extends Thread { String fixedText = ModUtilities.decodeText( zis, modFile.getName()+":"+parentPath+fileName ).text; fixedText = Pattern.compile("\n").matcher( fixedText ).replaceAll( "\r\n" ); - if ( fileName.endsWith( ".xml" ) ) - fixedText = fixedText.replaceAll( "<[?]xml [^>]*?[?]>\n*", "\n" ); - InputStream fixedStream = ModUtilities.encodeText( fixedText, "windows-1252", modFile.getName()+":"+parentPath+fileName+" (with new EOL)" ); if ( !moddedItems.contains(innerPath) ) diff --git a/src/main/java/net/vhati/modmanager/core/ModUtilities.java b/src/main/java/net/vhati/modmanager/core/ModUtilities.java index c1bb6f2..8d7b8e8 100644 --- a/src/main/java/net/vhati/modmanager/core/ModUtilities.java +++ b/src/main/java/net/vhati/modmanager/core/ModUtilities.java @@ -199,8 +199,8 @@ public class ModUtilities { * which doesn't need closing. * * The result will have CR-LF line endings and the desired encoding. - * FTL stubbornly assumes all XML is in windows-1252 encoding, even - * on Linux. + * Note: FTL stubbornly assumes all XML is in windows-1252 encoding, + * even on Linux. * * The description arguments identify the streams for log messages. * @@ -231,6 +231,39 @@ public class ModUtilities { return result; } + /** + * Decodes, parses, sloppy prints, and reencodes an XML stream. + * This effectively repairs any XML problems that the sloppy parser + * can tolerate. + * + * The returned stream is a ByteArrayInputStream + * which doesn't need closing. + * + * The result will have CR-LF line endings and the desired encoding. + * Note: FTL stubbornly assumes all XML is in windows-1252 encoding, + * even on Linux. + * + * The description argument identifies the stream for log messages. + * + * @see net.vhati.modmanager.core.XMLPatcher + * @see net.vhati.modmanager.core.SloppyXMLOutputProcessor + */ + public static InputStream rebuildXMLFile( InputStream srcStream, String encoding, String srcDescription ) throws IOException, JDOMException { + Pattern xmlDeclPtn = Pattern.compile( "<[?]xml [^>]*?[?]>\n*" ); + + String srcText = decodeText( srcStream, srcDescription ).text; + srcText = xmlDeclPtn.matcher(srcText).replaceFirst( "" ); + srcText = ""+ srcText +""; + Document doc = parseStrictOrSloppyXML( srcText, srcDescription+" (wrapped)" ); + + StringWriter writer = new StringWriter(); + SloppyXMLOutputProcessor.sloppyPrint( doc, writer, encoding ); + String resultString = writer.toString(); + + InputStream result = encodeText( resultString, encoding, srcDescription+" (cleaned)" ); + return result; + } + /** * Returns an XML Document, parsed strictly if possible, or sloppily.