diff --git a/Builder/IISMainHandler/build.txt b/Builder/IISMainHandler/build.txt index 3b2a35f..880a8fb 100644 --- a/Builder/IISMainHandler/build.txt +++ b/Builder/IISMainHandler/build.txt @@ -1 +1 @@ -1293 \ No newline at end of file +1305 \ No newline at end of file diff --git a/IISMainHandler/TemplateEngine.cs b/IISMainHandler/TemplateEngine.cs index f158470..f4e368c 100644 --- a/IISMainHandler/TemplateEngine.cs +++ b/IISMainHandler/TemplateEngine.cs @@ -6,10 +6,98 @@ using System.Xml; using System.Xml.Linq; using System.Xml.Xsl; using System.IO; +using System.Globalization; +using FLocal.Core; namespace FLocal.IISHandler { class TemplateEngine { + public static class EncodingInfo { + + public class XmlEncoderReplacementFallback : EncoderFallback { + + private readonly Encoding originalEncoding; + + public XmlEncoderReplacementFallback(Encoding encoding) { + this.originalEncoding = encoding; + } + + public override EncoderFallbackBuffer CreateFallbackBuffer() { + return new XmlEncoderReplacementFallbackBuffer(this.originalEncoding); + } + + public override int MaxCharCount { + get { + return 20; + } + } + + } + + private class XmlEncoderReplacementFallbackBuffer : EncoderFallbackBuffer { + + const int SurHighStart = 0xd800; + const int SurHighEnd = 0xdbff; + const int SurLowStart = 0xdc00; + const int SurLowEnd = 0xdfff; + + int fallbackIndex = -1; + string currentReplacement = ""; + + private readonly Encoding originalEncoding; + + public XmlEncoderReplacementFallbackBuffer(Encoding originalEncoding) { + this.originalEncoding = originalEncoding; + } + + private bool Fallback(int ch) { + this.currentReplacement = string.Format(CultureInfo.InvariantCulture, "&#x{0:X};", ch); + return this.currentReplacement.Length > 0; + } + + public override bool Fallback(char highChar, char lowChar, int index) { + if (!char.IsSurrogatePair(highChar, lowChar)) { + throw new CriticalException("Invalid surrogate pair: " + (int)lowChar + (int)highChar); + } + return this.Fallback(char.ConvertToUtf32(highChar, lowChar)); + } + + public override bool Fallback(char ch, int index) { + if (char.IsSurrogate(ch)) { + throw new FLocalException("Wrong char: " + (int)ch); + } + return this.Fallback(ch); + } + + public override char GetNextChar() { + this.fallbackIndex++; + return this.currentReplacement[this.fallbackIndex]; + } + + public override bool MovePrevious() { + if(this.fallbackIndex > 0) { + this.fallbackIndex--; + return true; + } else { + return false; + } + } + + public override int Remaining { + get { + return this.currentReplacement.Length - this.fallbackIndex - 1; + } + } + + public override void Reset() { + this.fallbackIndex = -1; + this.currentReplacement = ""; + base.Reset(); + } + } + + } + private class TemplateCacher { public static TemplateCacher instance = new TemplateCacher(); @@ -33,8 +121,9 @@ namespace FLocal.IISHandler { } - public static void WriteCompiled(string templateName, XDocument data, Encoding encoding, TextWriter outStream) { - using(XmlWriter writer = XmlWriter.Create(outStream, new XmlWriterSettings { Indent = false, Encoding = encoding })) { + public static void WriteCompiled(string templateName, XDocument data, TextWriter outStream) { + //var fallback = new EncodingInfo.XmlEncoderReplacementFallback(outStream.Encoding); + using(XmlWriter writer = XmlWriter.Create(outStream, new XmlWriterSettings { Indent = false })) { using(XmlReader reader = data.CreateReader()) { TemplateCacher.instance.getCompiledTransform(templateName).Transform(reader, writer); } diff --git a/IISMainHandler/WebContext.cs b/IISMainHandler/WebContext.cs index 2699d1b..81c7c86 100644 --- a/IISMainHandler/WebContext.cs +++ b/IISMainHandler/WebContext.cs @@ -141,7 +141,7 @@ namespace FLocal.IISHandler { public void WriteTransformResult(string templateName, System.Xml.Linq.XDocument data) { this.httpresponse.ContentType = this.design.ContentType; this.httpresponse.ContentEncoding = OutputEncoding; - TemplateEngine.WriteCompiled(this.design.GetFSName(templateName), data, OutputEncoding, this.httpresponse.Output); + TemplateEngine.WriteCompiled(this.design.GetFSName(templateName), data, this.httpresponse.Output); } public XElement exportSession() {