2 // XmlMtomDictionaryWriter.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2009 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Net.Mime;
35 internal class XmlMtomDictionaryWriter : XmlDictionaryWriter
37 public XmlMtomDictionaryWriter (Stream stream, Encoding encoding, int maxSizeInBytes, string startInfo, string boundary, string startUri, bool writeMessageHeaders, bool ownsStream)
39 writer = new StreamWriter (stream, encoding);
40 max_bytes = maxSizeInBytes;
41 write_headers = writeMessageHeaders;
42 owns_stream = ownsStream;
44 var settings = new XmlWriterSettings ();
45 settings.Encoding = encoding;
46 settings.OmitXmlDeclaration = true;
47 settings.ConformanceLevel = ConformanceLevel.Fragment;
48 settings.NewLineChars = "\r\n";
49 xml_writer_settings = settings;
51 // FIXME: actually it does not likely use ContentType.ToString() but writes those header items by own.
52 // (so that it could generate "start" header dynamically)
53 var c = new ContentType ("multipart/related");
54 c.Parameters ["type"] = "application/xop+xml";
55 c.Boundary = boundary;
56 c.Parameters ["start"] = "<" + startUri + ">";
57 c.Parameters ["start-info"] = startInfo;
61 // constructor arguments
63 XmlWriterSettings xml_writer_settings;
68 ContentType content_type;
75 XmlWriter CreateWriter ()
77 return XmlWriter.Create (writer, xml_writer_settings);
80 public override void Close ()
87 public override void Flush ()
92 public override string LookupPrefix (string namespaceUri)
94 return w.LookupPrefix (namespaceUri);
97 public override void WriteBase64 (byte [] bytes, int start, int length)
100 w.WriteBase64 (bytes, start, length);
103 public override void WriteCData (string text)
109 public override void WriteCharEntity (char c)
112 w.WriteCharEntity (c);
115 public override void WriteChars (char [] buffer, int index, int count)
118 w.WriteChars (buffer, index, count);
121 public override void WriteComment (string comment)
124 w.WriteComment (comment);
127 public override void WriteDocType (string name, string pubid, string sysid, string intSubset)
129 throw new NotSupportedException (); // indeed
132 public override void WriteEndAttribute ()
134 w.WriteEndAttribute ();
137 public override void WriteEndDocument ()
139 // We don't call w.WriteEndElement() because that causes state error
140 // (which is correct; MTOM writer just does not expect it).
143 public override void WriteEndElement ()
145 w.WriteEndElement ();
147 WriteEndOfMimeSection ();
150 public override void WriteEntityRef (string name)
152 w.WriteEntityRef (name);
155 public override void WriteFullEndElement ()
157 w.WriteFullEndElement ();
159 WriteEndOfMimeSection ();
162 public override void WriteProcessingInstruction (string name, string data)
164 throw new NotSupportedException ();
167 public override void WriteRaw (string raw)
173 public override void WriteRaw (char [] chars, int index, int count)
176 w.WriteRaw (chars, index, count);
179 public override void WriteStartAttribute (string prefix, string localName, string namespaceURI)
182 w.WriteStartAttribute (prefix, localName, namespaceURI);
185 public override void WriteStartDocument ()
188 // We don't call w.WriteStartDocument() because that causes state error
189 // (which is correct; MTOM writer just does not expect it).
192 public override void WriteStartDocument (bool standalone)
195 // We don't call w.WriteStartDocument() because that causes state error
196 // (which is correct; MTOM writer just does not expect it).
199 public override void WriteStartElement (string prefix, string localName, string namespaceURI)
204 WriteStartOfMimeSection ();
206 w.WriteStartElement (prefix, localName, namespaceURI);
210 public override WriteState WriteState {
211 get { return w.WriteState; }
214 static readonly char [] eol_chars = "\r\n".ToCharArray ();
216 public override void WriteString (string text)
222 i1 = text.IndexOfAny (eol_chars, i2);
224 w.WriteString (text.Substring (i2, i1 - i2));
225 if (text [i1] == '\r')
226 w.WriteCharEntity ('\r');
231 w.WriteString (text.Substring (i2));
237 public override void WriteSurrogateCharEntity (char low, char high)
240 w.WriteSurrogateCharEntity (low, high);
243 public override void WriteWhitespace (string text)
246 w.WriteWhitespace (text);
249 public override string XmlLang {
250 get { return w.XmlLang; }
253 public override XmlSpace XmlSpace {
254 get { return w.XmlSpace; }
259 if (w == null && write_headers)
262 if (w == null || w.WriteState == WriteState.Closed || w.WriteState == WriteState.Error)
266 void WriteMimeHeaders ()
269 writer.Write ("MIME-Version: 1.0\r\n");
270 writer.Write ("Content-Type: ");
271 writer.Write (content_type.ToString ());
272 writer.Write ("\r\n\r\n\r\n");
275 void WriteStartOfMimeSection ()
279 // I'm not sure what's the expected behavior of this
280 // strange XmlWriter, but so far - it outputs only one
282 if (section_count > 1)
285 writer.Write ("\r\n");
287 writer.Write (content_type.Boundary);
288 writer.Write ("\r\n");
289 writer.Write ("Content-ID: ");
290 writer.Write (content_type.Parameters ["start"]);
291 writer.Write ("\r\n");
292 writer.Write ("Content-Transfer-Encoding: 8bit\r\n");
293 writer.Write ("Content-Type: application/xop+xml;charset=");
294 writer.Write (xml_writer_settings.Encoding.HeaderName);
295 writer.Write (";type=\"");
296 writer.Write (content_type.Parameters ["start-info"].Replace ("\"", "\\\""));
297 writer.Write ("\"\r\n\r\n");
300 void WriteEndOfMimeSection ()
302 // I'm not sure what's the expected behavior of this
303 // strange XmlWriter, but so far - it outputs only one
305 if (section_count > 1)
309 writer.Write ("\r\n");
311 writer.Write (content_type.Boundary);
312 writer.Write ("--\r\n");