[Mono-bugs] [Bug 43362][Maj] New - multipart form data bug
bugzilla-daemon@rocky.ximian.com
bugzilla-daemon@rocky.ximian.com
Tue, 20 May 2003 05:58:35 -0400 (EDT)
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by mark_kuschnir@yahoo.co.uk.
http://bugzilla.ximian.com/show_bug.cgi?id=43362
--- shadow/43362 Tue May 20 05:58:35 2003
+++ shadow/43362.tmp.16306 Tue May 20 05:58:35 2003
@@ -0,0 +1,340 @@
+Bug#: 43362
+Product: Mono/Class Libraries
+Version: unspecified
+OS:
+OS Details: Windows 2000 with all service packs
+Status: NEW
+Resolution:
+Severity:
+Priority: Major
+Component: System.Web
+AssignedTo: mono-bugs@ximian.com
+ReportedBy: Mark_Kuschnir@yahoo.co.uk
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: multipart form data bug
+
+Please fill in this template when reporting a bug, unless you know what
+you are doing.
+
+Description of Problem:
+The following complete program (InsertTest.cs) demonstrates the problem
+with Mono 0.24. Basically I'm building up a multipart form and sending it
+to a database (Tamino). The only trouble is that with Mono the data sent
+is incomplete. I was using HttpSniffer.pl (www.schmerg.com) on port 8000
+to demonstrate this. I'm sure you don't need a database to be able to see
+that the sent data is incomplete. I suspect that it only happens with
+messages of a particular size hence the nonsense document contained in the
+program.
+
+Steps:
+1. mcs -target:exe InsertTest.cs
+2. mono InsertTest.exe
+
+Actual Results:
+Incomplete message transmitted.
+
+Expected Results:
+In .NET the message is sent correctly.
+
+How often does this happen?
+Always.
+
+
+
+Additional Information:
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+using System.Collections.Specialized;
+
+/// <summary>
+/// Base HTTP request.
+/// </summary>
+
+internal class HttpRequest
+{
+ /// <summary>
+ /// HTTP request.
+ /// </summary>
+ protected HttpWebRequest m_req;
+
+ //=================================================================
+===
+ /// <summary>
+ /// Construct a request object tied to the specified url.
+ /// </summary>
+ /// <param name="url">url the request is for</param>
+ /// <param name="method">request method</param>
+
+ internal HttpRequest(string url, string method)
+ {
+ m_req = (HttpWebRequest) WebRequest.Create(url);
+ m_req.Method = method;
+ m_req.Headers["Accept-Charset"] = "utf-8";
+ m_req.UserAgent = "InsertTest";
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// Allow the HTTP header "Content-Type" to be specified.
+ /// </summary>
+
+ internal string ContentType
+ {
+ set { m_req.ContentType = value; }
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// Set header to specified value.
+ /// </summary>
+ /// <param name="name">header name</param>
+ /// <param name="val">header value</param>
+
+ internal void SetHeader(string name, string val)
+ {
+ m_req.Headers[name] = val;
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// Add the specified stream data to the request stream.
+ /// Attempt to reset the user's request stream (requires CanSeek).
+ /// </summary>
+ /// <param name="dataStream">stream to write</param>
+ /// <remarks>This is a single shot method!
+ /// Once used the request stream will be closed.</remarks>
+
+ internal void Write(Stream dataStream)
+ {
+ Stream reqStream = m_req.GetRequestStream();
+
+ // attempt to reset the stream for the user
+ if (dataStream.CanSeek) dataStream.Position = 0;
+
+ byte[] data = new byte[8192];
+ int len;
+
+ while ((len = dataStream.Read(data, 0, data.GetLength
+(0))) != 0)
+ {
+ reqStream.Write(data, 0, len);
+ }
+
+ reqStream.Flush();
+ reqStream.Close();
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// Get response.
+ /// </summary>
+
+ internal void Response()
+ {
+ HttpWebResponse res = (HttpWebResponse) m_req.GetResponse
+();
+ // res.Headers
+ // res.GetResponseStream()
+ Console.WriteLine("StatusCode: "+res.StatusCode.ToString
+());
+ }
+}
+
+/// <summary>
+/// Implement an HTTP POST request.
+/// </summary>
+
+internal class HttpPostRequest : HttpRequest
+{
+ /// <summary>
+ /// The boundary constant for the multipart/form-data HTTP
+requests.
+ /// </summary>
+ const string BOUNDARY = "---------------------------7d16151062e";
+
+ /// <summary>
+ /// The start boundary constant for the multipart/form-data HTTP
+requests.
+ /// </summary>
+ const string START_BOUNDARY = "--" + BOUNDARY;
+
+ /// <summary>
+ /// The end boundary constant for the multipart/form-data HTTP
+requests.
+ /// </summary>
+ const string END_BOUNDARY = START_BOUNDARY + "--";
+
+ /// <summary>
+ /// The line separator constant, which is for multipart/form-data
+CRLF.
+ /// </summary>
+ const string LINE_SEPARATOR = "\r\n";
+
+ /// <summary>
+ /// Request output stream.
+ /// </summary>
+ StreamWriter m_writer;
+
+ //=================================================================
+===
+ /// <summary>
+ /// Construct a request object tied to the specified url.
+ /// </summary>
+ /// <param name="url">url the request is for</param>
+
+ internal HttpPostRequest(string url) : base(url, "POST")
+ {
+ m_req.ContentType = "multipart/form-data; boundary=" +
+BOUNDARY;
+
+ m_writer = new StreamWriter(m_req.GetRequestStream());
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// Beginning of message.
+ /// </summary>
+
+ internal void BeginMessage()
+ {
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// Write the specified name/value pair.
+ /// </summary>
+ /// <param name="name">data name</param>
+ /// <param name="val">data value</param>
+
+ internal void Write(string name, string val)
+ {
+ m_writer.Write(START_BOUNDARY);
+ m_writer.Write(LINE_SEPARATOR);
+ m_writer.Write("Content-disposition: form-data;
+name=\""+name+"\"");
+ m_writer.Write(LINE_SEPARATOR);
+ m_writer.Write(LINE_SEPARATOR);
+ m_writer.Write(val);
+ m_writer.Write(LINE_SEPARATOR);
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// Write the specified command/XML pair.
+ /// </summary>
+ /// <param name="cmd">X machine command to be performed</param>
+ /// <param name="node">XML that the command is for</param>
+
+ internal void Write(string cmd, XmlNode node)
+ {
+ m_writer.Write(START_BOUNDARY);
+ m_writer.Write(LINE_SEPARATOR);
+ m_writer.Write("Content-disposition: form-data;
+name=\""+cmd+"\"");
+ m_writer.Write(LINE_SEPARATOR);
+ m_writer.Write("Content-Type: "+"text/xml");
+ m_writer.Write(LINE_SEPARATOR);
+ m_writer.Write(LINE_SEPARATOR);
+ XmlTextWriter xtw = new XmlTextWriter(m_writer);
+ node.WriteTo(xtw);
+ m_writer.Write(LINE_SEPARATOR);
+ }
+
+ //=================================================================
+===
+ /// <summary>
+ /// End of message.
+ /// </summary>
+
+ internal void EndMessage()
+ {
+ m_writer.Write(END_BOUNDARY);
+ m_writer.Flush();
+
+ m_writer.Close();
+ }
+}
+
+public class InsertDocuments
+{
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main(string[] args)
+ {
+ // load the XML data
+ XmlDocument data = new XmlDocument();
+ data.LoadXml(XML);
+
+ HttpPostRequest req = new HttpPostRequest
+("http://localhost:8000/tamino/mydb/ino:etc");
+ req.BeginMessage();
+ req.Write("_encoding", "utf-8");
+ req.Write("_process", data.DocumentElement);
+ req.EndMessage();
+ }
+
+ const string XML =
+@"<DataBlob>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+<Item>
+123456789012345678901234567890123456789012345678901234567890123456789012345
+67890
+</Item>
+</DataBlob>
+";
+}