PageRenderTime 20ms CodeModel.GetById 9ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

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