3c1f479b9d
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
317 lines
7.9 KiB
C#
317 lines
7.9 KiB
C#
//
|
|
// XmlMtomDictionaryWriter.cs
|
|
//
|
|
// Author:
|
|
// Atsushi Enomoto <atsushi@ximian.com>
|
|
//
|
|
// Copyright (C) 2009 Novell, Inc. http://www.novell.com
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
using System;
|
|
using System.IO;
|
|
using System.Net.Mime;
|
|
using System.Text;
|
|
|
|
namespace System.Xml
|
|
{
|
|
internal class XmlMtomDictionaryWriter : XmlDictionaryWriter
|
|
{
|
|
public XmlMtomDictionaryWriter (Stream stream, Encoding encoding, int maxSizeInBytes, string startInfo, string boundary, string startUri, bool writeMessageHeaders, bool ownsStream)
|
|
{
|
|
writer = new StreamWriter (stream, encoding);
|
|
max_bytes = maxSizeInBytes;
|
|
write_headers = writeMessageHeaders;
|
|
owns_stream = ownsStream;
|
|
|
|
var settings = new XmlWriterSettings ();
|
|
settings.Encoding = encoding;
|
|
settings.OmitXmlDeclaration = true;
|
|
settings.ConformanceLevel = ConformanceLevel.Fragment;
|
|
settings.NewLineChars = "\r\n";
|
|
xml_writer_settings = settings;
|
|
|
|
// FIXME: actually it does not likely use ContentType.ToString() but writes those header items by own.
|
|
// (so that it could generate "start" header dynamically)
|
|
var c = new ContentType ("multipart/related");
|
|
c.Parameters ["type"] = "application/xop+xml";
|
|
c.Boundary = boundary;
|
|
c.Parameters ["start"] = "<" + startUri + ">";
|
|
c.Parameters ["start-info"] = startInfo;
|
|
content_type = c;
|
|
}
|
|
|
|
// constructor arguments
|
|
TextWriter writer;
|
|
XmlWriterSettings xml_writer_settings;
|
|
Encoding encoding;
|
|
int max_bytes;
|
|
bool write_headers;
|
|
bool owns_stream;
|
|
ContentType content_type;
|
|
|
|
// state
|
|
XmlWriter w;
|
|
int depth;
|
|
int section_count;
|
|
|
|
XmlWriter CreateWriter ()
|
|
{
|
|
return XmlWriter.Create (writer, xml_writer_settings);
|
|
}
|
|
|
|
public override void Close ()
|
|
{
|
|
w.Close ();
|
|
if (owns_stream)
|
|
writer.Close ();
|
|
}
|
|
|
|
public override void Flush ()
|
|
{
|
|
w.Flush ();
|
|
}
|
|
|
|
public override string LookupPrefix (string namespaceUri)
|
|
{
|
|
return w.LookupPrefix (namespaceUri);
|
|
}
|
|
|
|
public override void WriteBase64 (byte [] bytes, int start, int length)
|
|
{
|
|
CheckState ();
|
|
w.WriteBase64 (bytes, start, length);
|
|
}
|
|
|
|
public override void WriteCData (string text)
|
|
{
|
|
CheckState ();
|
|
w.WriteCData (text);
|
|
}
|
|
|
|
public override void WriteCharEntity (char c)
|
|
{
|
|
CheckState ();
|
|
w.WriteCharEntity (c);
|
|
}
|
|
|
|
public override void WriteChars (char [] buffer, int index, int count)
|
|
{
|
|
CheckState ();
|
|
w.WriteChars (buffer, index, count);
|
|
}
|
|
|
|
public override void WriteComment (string comment)
|
|
{
|
|
CheckState ();
|
|
w.WriteComment (comment);
|
|
}
|
|
|
|
public override void WriteDocType (string name, string pubid, string sysid, string intSubset)
|
|
{
|
|
throw new NotSupportedException (); // indeed
|
|
}
|
|
|
|
public override void WriteEndAttribute ()
|
|
{
|
|
w.WriteEndAttribute ();
|
|
}
|
|
|
|
public override void WriteEndDocument ()
|
|
{
|
|
// We don't call w.WriteEndElement() because that causes state error
|
|
// (which is correct; MTOM writer just does not expect it).
|
|
}
|
|
|
|
public override void WriteEndElement ()
|
|
{
|
|
w.WriteEndElement ();
|
|
if (--depth == 0)
|
|
WriteEndOfMimeSection ();
|
|
}
|
|
|
|
public override void WriteEntityRef (string name)
|
|
{
|
|
w.WriteEntityRef (name);
|
|
}
|
|
|
|
public override void WriteFullEndElement ()
|
|
{
|
|
w.WriteFullEndElement ();
|
|
if (--depth == 0)
|
|
WriteEndOfMimeSection ();
|
|
}
|
|
|
|
public override void WriteProcessingInstruction (string name, string data)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
public override void WriteRaw (string raw)
|
|
{
|
|
CheckState ();
|
|
w.WriteRaw (raw);
|
|
}
|
|
|
|
public override void WriteRaw (char [] chars, int index, int count)
|
|
{
|
|
CheckState ();
|
|
w.WriteRaw (chars, index, count);
|
|
}
|
|
|
|
public override void WriteStartAttribute (string prefix, string localName, string namespaceURI)
|
|
{
|
|
CheckState ();
|
|
w.WriteStartAttribute (prefix, localName, namespaceURI);
|
|
}
|
|
|
|
public override void WriteStartDocument ()
|
|
{
|
|
CheckState ();
|
|
// We don't call w.WriteStartDocument() because that causes state error
|
|
// (which is correct; MTOM writer just does not expect it).
|
|
}
|
|
|
|
public override void WriteStartDocument (bool standalone)
|
|
{
|
|
CheckState ();
|
|
// We don't call w.WriteStartDocument() because that causes state error
|
|
// (which is correct; MTOM writer just does not expect it).
|
|
}
|
|
|
|
public override void WriteStartElement (string prefix, string localName, string namespaceURI)
|
|
{
|
|
CheckState ();
|
|
|
|
if (depth == 0)
|
|
WriteStartOfMimeSection ();
|
|
|
|
w.WriteStartElement (prefix, localName, namespaceURI);
|
|
depth++;
|
|
}
|
|
|
|
public override WriteState WriteState {
|
|
get { return w.WriteState; }
|
|
}
|
|
|
|
static readonly char [] eol_chars = "\r\n".ToCharArray ();
|
|
|
|
public override void WriteString (string text)
|
|
{
|
|
CheckState ();
|
|
|
|
int i1, i2 = 0;
|
|
do {
|
|
i1 = text.IndexOfAny (eol_chars, i2);
|
|
if (i1 >= 0) {
|
|
w.WriteString (text.Substring (i2, i1 - i2));
|
|
if (text [i1] == '\r')
|
|
w.WriteCharEntity ('\r');
|
|
else
|
|
w.WriteRaw ("\r\n");
|
|
i2 = i1 + 1;
|
|
} else {
|
|
w.WriteString (text.Substring (i2));
|
|
break;
|
|
}
|
|
} while (true);
|
|
}
|
|
|
|
public override void WriteSurrogateCharEntity (char low, char high)
|
|
{
|
|
CheckState ();
|
|
w.WriteSurrogateCharEntity (low, high);
|
|
}
|
|
|
|
public override void WriteWhitespace (string text)
|
|
{
|
|
CheckState ();
|
|
w.WriteWhitespace (text);
|
|
}
|
|
|
|
public override string XmlLang {
|
|
get { return w.XmlLang; }
|
|
}
|
|
|
|
public override XmlSpace XmlSpace {
|
|
get { return w.XmlSpace; }
|
|
}
|
|
|
|
void CheckState ()
|
|
{
|
|
if (w == null && write_headers)
|
|
WriteMimeHeaders ();
|
|
|
|
if (w == null || w.WriteState == WriteState.Closed || w.WriteState == WriteState.Error)
|
|
w = CreateWriter ();
|
|
}
|
|
|
|
void WriteMimeHeaders ()
|
|
{
|
|
w.Flush ();
|
|
writer.Write ("MIME-Version: 1.0\r\n");
|
|
writer.Write ("Content-Type: ");
|
|
writer.Write (content_type.ToString ());
|
|
writer.Write ("\r\n\r\n\r\n");
|
|
}
|
|
|
|
void WriteStartOfMimeSection ()
|
|
{
|
|
section_count++;
|
|
|
|
// I'm not sure what's the expected behavior of this
|
|
// strange XmlWriter, but so far - it outputs only one
|
|
// section.
|
|
if (section_count > 1)
|
|
return;
|
|
|
|
writer.Write ("\r\n");
|
|
writer.Write ("--");
|
|
writer.Write (content_type.Boundary);
|
|
writer.Write ("\r\n");
|
|
writer.Write ("Content-ID: ");
|
|
writer.Write (content_type.Parameters ["start"]);
|
|
writer.Write ("\r\n");
|
|
writer.Write ("Content-Transfer-Encoding: 8bit\r\n");
|
|
writer.Write ("Content-Type: application/xop+xml;charset=");
|
|
writer.Write (xml_writer_settings.Encoding.HeaderName);
|
|
writer.Write (";type=\"");
|
|
writer.Write (content_type.Parameters ["start-info"].Replace ("\"", "\\\""));
|
|
writer.Write ("\"\r\n\r\n");
|
|
}
|
|
|
|
void WriteEndOfMimeSection ()
|
|
{
|
|
// I'm not sure what's the expected behavior of this
|
|
// strange XmlWriter, but so far - it outputs only one
|
|
// section.
|
|
if (section_count > 1)
|
|
return;
|
|
|
|
w.Flush ();
|
|
writer.Write ("\r\n");
|
|
writer.Write ("--");
|
|
writer.Write (content_type.Boundary);
|
|
writer.Write ("--\r\n");
|
|
}
|
|
}
|
|
}
|
|
|