+ if (data == null)\r
+ throw new ArgumentNullException ("data"); // MS throws a nullref\r
+\r
+ string cType = Headers ["Content-Type"];\r
+ if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)\r
+ throw new WebException ("Content-Type header cannot be changed from its default " +\r
+ "value for this request.");\r
+\r
+ Headers ["Content-Type"] = urlEncodedCType;\r
+ WebRequest request = SetupRequest (address, method);\r
+ Stream rqStream = request.GetRequestStream ();\r
+ MemoryStream tmpStream = new MemoryStream ();\r
+ foreach (string key in data) {\r
+ byte [] bytes = Encoding.ASCII.GetBytes (key);\r
+ UrlEncodeAndWrite (tmpStream, bytes);\r
+ tmpStream.WriteByte ((byte) '=');\r
+ bytes = Encoding.ASCII.GetBytes (data [key]);\r
+ UrlEncodeAndWrite (tmpStream, bytes);\r
+ tmpStream.WriteByte ((byte) '&');\r
+ }\r
+\r
+ int length = (int) tmpStream.Length;\r
+ if (length > 0)\r
+ tmpStream.SetLength (--length); // remove trailing '&'\r
+\r
+ tmpStream.WriteByte ((byte) '\r');\r
+ tmpStream.WriteByte ((byte) '\n');\r
+\r
+ byte [] buf = tmpStream.GetBuffer ();\r
+ rqStream.Write (buf, 0, length + 2);\r
+ rqStream.Close ();\r
+ tmpStream.Close ();\r
+\r
+ WebResponse response = request.GetResponse ();\r
+ Stream st = ProcessResponse (response);\r
+ return ReadAll (st, (int) response.ContentLength);\r
+ }\r
+\r
+ Uri MakeUri (string path)\r
+ {\r
+ string query = null;\r
+ if (queryString != null && queryString.Count != 0) {\r
+ // This is not the same as UploadValues, because these 'keys' are not\r
+ // urlencoded here.\r
+ StringBuilder sb = new StringBuilder ();\r
+ sb.Append ('?');\r
+ foreach (string key in queryString)\r
+ sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));\r
+\r
+ if (sb.Length != 0) {\r
+ sb.Length--; // remove trailing '&'\r
+ query = sb.ToString ();\r
+ }\r
+ }\r
+ \r
+\r
+ if (baseAddress == null && query == null) {\r
+ try {\r
+ return new Uri (path);\r
+ }\r
+ catch (System.UriFormatException ufe) {\r
+ return new Uri ("file://" + path);\r
+ }\r
+ }\r
+\r
+ if (baseAddress == null)\r
+ return new Uri (path + query, (query != null));\r
+\r
+ if (query == null)\r
+ return new Uri (baseAddress, path);\r
+\r
+ return new Uri (baseAddress, path + query, (query != null));\r
+ }\r
+ \r
+ WebRequest SetupRequest (string address)\r
+ {\r
+ Uri uri = MakeUri (address);\r
+ WebRequest request = WebRequest.Create (uri);\r
+ request.Credentials = credentials;\r
+\r
+ // Special headers. These are properties of HttpWebRequest.\r
+ // What do we do with other requests differnt from HttpWebRequest?\r
+ if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {\r
+ HttpWebRequest req = (HttpWebRequest) request;\r
+ string expect = headers ["Expect"];\r
+ string contentType = headers ["Content-Type"];\r
+ string accept = headers ["Accept"];\r
+ string connection = headers ["Connection"];\r
+ string userAgent = headers ["User-Agent"];\r
+ string referer = headers ["Referer"];\r
+ headers.RemoveInternal ("Expect");\r
+ headers.RemoveInternal ("Content-Type");\r
+ headers.RemoveInternal ("Accept");\r
+ headers.RemoveInternal ("Connection");\r
+ headers.RemoveInternal ("Referer");\r
+ headers.RemoveInternal ("User-Agent");\r
+ request.Headers = headers;\r
+\r
+ if (expect != null && expect != "")\r
+ req.Expect = expect;\r
+\r
+ if (accept != null && accept != "")\r
+ req.Accept = accept;\r
+\r
+ if (contentType != null && contentType != "")\r
+ req.ContentType = contentType;\r
+\r
+ if (connection != null && connection != "")\r
+ req.Connection = connection;\r
+\r
+ if (userAgent != null && userAgent != "")\r
+ req.UserAgent = userAgent;\r
+\r
+ if (referer != null && referer != "")\r
+ req.Referer = referer;\r
+ }\r
+\r
+ responseHeaders = null;\r
+ return request;\r
+ }\r
+\r
+ WebRequest SetupRequest (string address, string method)\r
+ {\r
+ WebRequest request = SetupRequest (address);\r
+ request.Method = method;\r
+ return request;\r
+ }\r
+\r
+ WebRequest SetupRequest (string address, string method, int contentLength)\r
+ {\r
+ WebRequest request = SetupRequest (address, method);\r
+ request.ContentLength = contentLength;\r
+ return request;\r
+ }\r
+\r
+ Stream ProcessResponse (WebResponse response)\r
+ {\r
+ responseHeaders = response.Headers;\r
+ return response.GetResponseStream ();\r
+ }\r
+\r
+ static byte [] ReadAll (Stream stream, int length)\r
+ {\r
+ MemoryStream ms = null;\r
+ \r
+ bool nolength = (length == -1);\r
+ int size = ((nolength) ? 8192 : length);\r
+ if (nolength)\r
+ ms = new MemoryStream ();\r
+\r
+ int nread = 0;\r
+ int offset = 0;\r
+ byte [] buffer = new byte [size];\r
+ while ((nread = stream.Read (buffer, offset, size)) != 0) {\r
+ if (nolength) {\r
+ ms.Write (buffer, 0, nread);\r
+ } else {\r
+ offset += nread;\r
+ size -= nread;\r
+ }\r
+ }\r
+\r
+ if (nolength)\r
+ return ms.ToArray ();\r
+\r
+ return buffer;\r
+ }\r
+\r
+ string UrlEncode (string str)\r
+ {\r
+ StringBuilder result = new StringBuilder ();\r
+\r
+ int len = str.Length;\r
+ for (int i = 0; i < len; i++) {\r
+ char c = str [i];\r
+ if (c == ' ')\r
+ result.Append ('+');\r
+ else if ((c < '0' && c != '-' && c != '.') ||\r
+ (c < 'A' && c > '9') ||\r
+ (c > 'Z' && c < 'a' && c != '_') ||\r
+ (c > 'z')) {\r
+ result.Append ('%');\r
+ int idx = ((int) c) >> 4;\r
+ result.Append ((char) hexBytes [idx]);\r
+ idx = ((int) c) & 0x0F;\r
+ result.Append ((char) hexBytes [idx]);\r
+ } else {\r
+ result.Append (c);\r
+ }\r
+ }\r
+\r
+ return result.ToString ();\r
+ }\r
+\r
+ static void UrlEncodeAndWrite (Stream stream, byte [] bytes)\r
+ {\r
+ if (bytes == null)\r
+ return;\r
+\r
+ int len = bytes.Length;\r
+ if (len == 0)\r
+ return;\r
+\r
+ for (int i = 0; i < len; i++) {\r
+ char c = (char) bytes [i];\r
+ if (c == ' ')\r
+ stream.WriteByte ((byte) '+');\r
+ else if ((c < '0' && c != '-' && c != '.') ||\r
+ (c < 'A' && c > '9') ||\r
+ (c > 'Z' && c < 'a' && c != '_') ||\r
+ (c > 'z')) {\r
+ stream.WriteByte ((byte) '%');\r
+ int idx = ((int) c) >> 4;\r
+ stream.WriteByte (hexBytes [idx]);\r
+ idx = ((int) c) & 0x0F;\r
+ stream.WriteByte (hexBytes [idx]);\r
+ } else {\r
+ stream.WriteByte ((byte) c);\r
+ }\r
+ }\r