/Platters/classes/webpost.cs

http://skimpt.googlecode.com/ · C# · 322 lines · 193 code · 6 blank · 123 comment · 9 complexity · 5d97fcd7101f3274018ddb097a47b287 MD5 · raw file

  1. #region "License Agreement"
  2. /* Skimpt, an open source screenshot utility.
  3. Copyright (C) <year> <name of author>
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. this program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #endregion
  15. using System;
  16. using System.Net;
  17. using System.Text;
  18. using System.IO;
  19. using System.Collections;
  20. using System.Collections.Generic;
  21. /// <summary>
  22. /// Allow the transfer of data files using the W3C's specification
  23. /// for HTTP multipart form data. Microsoft's version has a bug
  24. /// where it does not format the ending boundary correctly.
  25. /// Written by: gregoryp@norvanco.com
  26. /// </summary>
  27. public class MultipartForm
  28. {
  29. public string InputBoxName;
  30. /// <summary>
  31. /// Holds any form fields and values that you
  32. /// wish to transfer with your data.
  33. /// </summary>
  34. private Hashtable coFormFields;
  35. /// <summary>
  36. /// Used mainly to avoid passing parameters to other routines.
  37. /// Could have been local to sendFile().
  38. /// </summary>
  39. protected HttpWebRequest coRequest;
  40. /// <summary>
  41. /// Used if we are testing and want to output the raw
  42. /// request, minus http headers, out to a file.
  43. /// </summary>
  44. System.IO.Stream coFileStream;
  45. /// <summary>
  46. /// Difined to build the form field data that is being
  47. /// passed along with the request.
  48. /// </summary>
  49. static string CONTENT_DISP = "Content-Disposition: form-data; name=";
  50. /// <summary>
  51. /// Allows you to specify the specific version of HTTP to use for uploads.
  52. /// The dot NET stuff currently does not allow you to remove the continue-100 header
  53. /// from 1.1 and 1.0 currently has a bug in it where it adds the continue-100. MS
  54. /// has sent a patch to remove the continue-100 in HTTP 1.0.
  55. /// </summary>
  56. public Version TransferHttpVersion
  57. { get { return coHttpVersion; } set { coHttpVersion = value; } }
  58. Version coHttpVersion;
  59. /// <summary>
  60. /// Used to change the content type of the file being sent.
  61. /// Currently defaults to: text/xml. Other options are
  62. /// text/plain or binary
  63. /// </summary>
  64. public string FileContentType
  65. { get { return coFileContentType; } set { coFileContentType = value; } }
  66. string coFileContentType;
  67. /// <summary>
  68. /// Initialize our class for use to send data files.
  69. /// </summary>
  70. /// <param name="url">The web address of the recipient of the data transfer.</param>
  71. public MultipartForm(string url)
  72. {
  73. URL = url;
  74. coFormFields = new Hashtable();
  75. ResponseText = new StringBuilder();
  76. BufferSize = 1024 * 10;
  77. BeginBoundary = "ou812--------------8c405ee4e38917c";
  78. TransferHttpVersion = HttpVersion.Version11;
  79. FileContentType = "text/xml";
  80. }
  81. //---------- BEGIN PROPERTIES SECTION ----------
  82. string _BeginBoundary;
  83. /// <summary>
  84. /// The string that defines the begining boundary of
  85. /// our multipart transfer as defined in the w3c specs.
  86. /// This method also sets the Content and Ending
  87. /// boundaries as defined by the w3c specs.
  88. /// </summary>
  89. public string BeginBoundary
  90. {
  91. get { return _BeginBoundary; }
  92. set
  93. {
  94. _BeginBoundary = value;
  95. ContentBoundary = "--" + BeginBoundary;
  96. EndingBoundary = ContentBoundary + "--";
  97. }
  98. }
  99. /// <summary>
  100. /// The string that defines the content boundary of
  101. /// our multipart transfer as defined in the w3c specs.
  102. /// </summary>
  103. protected string ContentBoundary
  104. { get { return _ContentBoundary; } set { _ContentBoundary = value; } }
  105. string _ContentBoundary;
  106. /// <summary>
  107. /// The string that defines the ending boundary of
  108. /// our multipart transfer as defined in the w3c specs.
  109. /// </summary>
  110. protected string EndingBoundary
  111. { get { return _EndingBoundary; } set { _EndingBoundary = value; } }
  112. string _EndingBoundary;
  113. /// <summary>
  114. /// The data returned to us after the transfer is completed.
  115. /// </summary>
  116. public StringBuilder ResponseText
  117. { get { return _ResponseText; } set { _ResponseText = value; } }
  118. StringBuilder _ResponseText;
  119. /// <summary>
  120. /// The web address of the recipient of the transfer.
  121. /// </summary>
  122. public string URL
  123. { get { return _URL; } set { _URL = value; } }
  124. string _URL;
  125. /// <summary>
  126. /// Allows us to determine the size of the buffer used
  127. /// to send a piece of the file at a time out the IO
  128. /// stream. Defaults to 1024 * 10.
  129. /// </summary>
  130. public int BufferSize
  131. { get { return _BufferSize; } set { _BufferSize = value; } }
  132. int _BufferSize;
  133. //---------- END PROPERTIES SECTION ----------
  134. /// <summary>
  135. /// Used to signal we want the output to go to a
  136. /// text file verses being transfered to a URL.
  137. /// </summary>
  138. /// <param name="path"></param>
  139. public void setFilename(string path)
  140. {
  141. coFileStream = new System.IO.FileStream(path, FileMode.Create, FileAccess.Write);
  142. }
  143. /// <summary>
  144. /// Allows you to add some additional field data to be
  145. /// sent along with the transfer. This is usually used
  146. /// for things like userid and password to validate the
  147. /// transfer.
  148. /// </summary>
  149. /// <param name="key">The form field name</param>
  150. /// <param name="str">The form field value</param>
  151. public void setField(string key, string str)
  152. {
  153. coFormFields[key] = str;
  154. }
  155. /// <summary>
  156. /// Determines if we have a file stream set, and returns either
  157. /// the HttpWebRequest stream of the file.
  158. /// </summary>
  159. /// <returns></returns>
  160. public virtual System.IO.Stream getStream()
  161. {
  162. System.IO.Stream io;
  163. if (null == coFileStream)
  164. io = coRequest.GetRequestStream();
  165. else
  166. io = coFileStream;
  167. return io;
  168. }
  169. /// <summary>
  170. /// Here we actually make the request to the web server and
  171. /// retrieve it's response into a text buffer.
  172. /// </summary>
  173. public virtual void getResponse()
  174. {
  175. if (null == coFileStream)
  176. {
  177. System.IO.Stream io;
  178. WebResponse oResponse;
  179. try
  180. {
  181. oResponse = coRequest.GetResponse();
  182. }
  183. catch (WebException web)
  184. {
  185. oResponse = web.Response;
  186. }
  187. if (null != oResponse)
  188. {
  189. io = oResponse.GetResponseStream();
  190. StreamReader sr = new StreamReader(io);
  191. string str;
  192. ResponseText.Length = 0;
  193. while ((str = sr.ReadLine()) != null)
  194. ResponseText.Append(str);
  195. oResponse.Close();
  196. }
  197. else
  198. throw new Exception("MultipartForm: Error retrieving server response");
  199. }
  200. }
  201. /// <summary>
  202. /// Transmits a file to the web server stated in the
  203. /// URL property. You may call this several times and it
  204. /// will use the values previously set for fields and URL.
  205. /// </summary>
  206. /// <param name="aFilename">The full path of file being transfered.</param>
  207. public void sendFile(string aFilename)
  208. {
  209. // The live of this object is only good during
  210. // this function. Used mainly to avoid passing
  211. // around parameters to other functions.
  212. coRequest = (HttpWebRequest)WebRequest.Create(URL);
  213. // Set use HTTP 1.0 or 1.1.
  214. coRequest.ProtocolVersion = TransferHttpVersion;
  215. coRequest.Method = "POST";
  216. coRequest.ContentType = "multipart/form-data; boundary=" + BeginBoundary;
  217. coRequest.Headers.Add("Cache-Control", "no-cache");
  218. coRequest.KeepAlive = true;
  219. string strFields = getFormfields();
  220. string strFileHdr = getFileheader(aFilename);
  221. string strFileTlr = getFiletrailer();
  222. FileInfo info = new FileInfo(aFilename);
  223. coRequest.ContentLength = strFields.Length +
  224. strFileHdr.Length +
  225. strFileTlr.Length +
  226. info.Length;
  227. System.IO.Stream io;
  228. io = getStream();
  229. writeString(io, strFields);
  230. writeString(io, strFileHdr);
  231. this.writeFile(io, aFilename);
  232. writeString(io, strFileTlr);
  233. getResponse();
  234. io.Close();
  235. // End the life time of this request object.
  236. coRequest = null;
  237. }
  238. /// <summary>
  239. /// Mainly used to turn the string into a byte buffer and then
  240. /// write it to our IO stream.
  241. /// </summary>
  242. /// <param name="io">The io stream for output.</param>
  243. /// <param name="str">The data to write.</param>
  244. public void writeString(System.IO.Stream io, string str)
  245. {
  246. byte[] PostData = System.Text.Encoding.ASCII.GetBytes(str);
  247. io.Write(PostData, 0, PostData.Length);
  248. }
  249. /// <summary>
  250. /// Builds the proper format of the multipart data that
  251. /// contains the form fields and their respective values.
  252. /// </summary>
  253. /// <returns>The data to send in the multipart upload.</returns>
  254. public string getFormfields()
  255. {
  256. string str = "";
  257. IDictionaryEnumerator myEnumerator = coFormFields.GetEnumerator();
  258. while (myEnumerator.MoveNext())
  259. {
  260. str += ContentBoundary + "\r\n" +
  261. CONTENT_DISP + '"' + myEnumerator.Key + "\"\r\n\r\n" +
  262. myEnumerator.Value + "\r\n";
  263. }
  264. return str;
  265. }
  266. /// <summary>
  267. /// Returns the proper content information for the
  268. /// file we are sending.
  269. /// </summary>
  270. /// <remarks>
  271. /// Hits Patel reported a bug when used with ActiveFile.
  272. /// Added semicolon after sendfile to resolve that issue.
  273. /// Tested for compatibility with IIS 5.0 and Java.
  274. /// </remarks>
  275. /// <param name="aFilename"></param>
  276. /// <returns></returns>
  277. public string getFileheader(string aFilename)
  278. {
  279. return ContentBoundary + "\r\n" +
  280. CONTENT_DISP +
  281. "\"" + InputBoxName.ToString() + "\"; filename=\"" +
  282. Path.GetFileName(aFilename) + "\"\r\n" +
  283. "Content-type: " + FileContentType + "\r\n\r\n";
  284. }
  285. /// <summary>
  286. /// Creates the proper ending boundary for the multipart upload.
  287. /// </summary>
  288. /// <returns>The ending boundary.</returns>
  289. public string getFiletrailer()
  290. {
  291. return "\r\n" + EndingBoundary;
  292. }
  293. /// <summary>
  294. /// Reads in the file a chunck at a time then sends it to the
  295. /// output stream.
  296. /// </summary>
  297. /// <param name="io">The io stream to write the file to.</param>
  298. /// <param name="aFilename">The name of the file to transfer.</param>
  299. public void writeFile(System.IO.Stream io, string aFilename)
  300. {
  301. FileStream readIn = new FileStream(aFilename, FileMode.Open, FileAccess.Read);
  302. readIn.Seek(0, SeekOrigin.Begin); // move to the start of the file
  303. byte[] fileData = new byte[BufferSize];
  304. int bytes;
  305. while ((bytes = readIn.Read(fileData, 0, BufferSize)) > 0)
  306. {
  307. // read the file data and send a chunk at a time
  308. io.Write(fileData, 0, bytes);
  309. }
  310. readIn.Close();
  311. }
  312. }