MultipartContentParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / MultipartContentParser.cs / 1305376 / MultipartContentParser.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * Multipart content parser. 
 *
 * Copyright (c) 1998 Microsoft Corporation 
 */

namespace System.Web {
    using System.Text; 

    using System.Collections; 
    using System.Globalization; 
    using System.Web.Util;
 
    /*
     * Element of the multipart content
     */
    internal sealed class MultipartContentElement { 
        private String _name;
        private String _filename; 
        private String _contentType; 
        private HttpRawUploadedContent _data;
        private int _offset; 
        private int _length;

        internal MultipartContentElement(String name, String filename, String contentType, HttpRawUploadedContent data, int offset, int length) {
            _name = name; 
            _filename = filename;
            _contentType = contentType; 
            _data = data; 
            _offset = offset;
            _length = length; 
        }

        internal bool IsFile {
            get { return(_filename != null);} 
        }
 
        internal bool IsFormItem { 
            get { return(_filename == null);}
        } 

        internal String Name {
            get { return _name;}
        } 

        internal HttpPostedFile GetAsPostedFile() { 
            return new HttpPostedFile( 
                                     _filename,
                                     _contentType, 
                                     new HttpInputStream(_data, _offset, _length));
        }

        internal String GetAsString(Encoding encoding) { 
            if (_length > 0) {
                return encoding.GetString(_data.GetAsByteArray(_offset, _length)); 
            } 
            else {
                return String.Empty; 
            }
        }
    }
 
    /*
     * Multipart content parser. Split content into elements. 
     */ 
    internal sealed class HttpMultipartContentTemplateParser {
        private HttpRawUploadedContent _data; 
        private int _length;

        private int _pos;
        private ArrayList _elements = new ArrayList(); 

        // currently parsed line 
        private int _lineStart = -1; 
        private int _lineLength = -1;
 
        // last boundary has extra --
        private bool _lastBoundaryFound;

        // part separator 
        private byte[] _boundary;
 
        // current header values 
        private String _partName;
        private String _partFilename; 
        private String _partContentType;

        // current part's content data
        private int _partDataStart = -1; 
        private int _partDataLength = -1;
 
        // encoding 
        private Encoding _encoding;
 

        private HttpMultipartContentTemplateParser(HttpRawUploadedContent data, int length, byte[] boundary, Encoding encoding) {
            _data = data;
            _length = length; 
            _boundary = boundary;
            _encoding = encoding; 
        } 

        private bool AtEndOfData() { 
            return(_pos >= _length || _lastBoundaryFound);
        }

        private bool GetNextLine() { 
            int i = _pos;
 
            _lineStart = -1; 

            while (i < _length) { 
                if (_data[i] == 10) { // '\n'
                    _lineStart = _pos;
                    _lineLength = i - _pos;
                    _pos = i+1; 

                    // ignore \r 
                    if (_lineLength > 0 && _data[i-1] == 13) 
                        _lineLength--;
 
                    // line found
                    break;
                }
 
                if (++i == _length) {
                    // last line doesn't end with \n 
                    _lineStart = _pos; 
                    _lineLength = i - _pos;
                    _pos = _length; 
                }
            }

            return(_lineStart >= 0); 
        }
 
        private String ExtractValueFromContentDispositionHeader(String l, int pos, String name) { 
            String pattern = name + "=\"";
            int i1 = CultureInfo.InvariantCulture.CompareInfo.IndexOf(l, pattern, pos, CompareOptions.IgnoreCase); 

            if (i1 < 0)
                return null;
            i1 += pattern.Length; 

            int i2 = l.IndexOf('"', i1); 
            if (i2 < 0) 
                return null;
            if (i2 == i1) 
                return String.Empty;

            return l.Substring(i1, i2-i1);
        } 

        private void ParsePartHeaders() { 
            _partName = null; 
            _partFilename = null;
            _partContentType = null; 

            while (GetNextLine()) {
                if (_lineLength == 0)
                    break;  // empty line signals end of headers 

                // get line as String 
                byte[] lineBytes = new byte[_lineLength]; 
                _data.CopyBytes(_lineStart, lineBytes, 0, _lineLength);
                String line = _encoding.GetString(lineBytes); 

                // parse into header and value
                int ic = line.IndexOf(':');
                if (ic < 0) 
                    continue;   // not a header
 
                // remeber header 
                String header = line.Substring(0, ic);
 
                if (StringUtil.EqualsIgnoreCase(header, "Content-Disposition")) {
                    // parse name and filename
                    _partName     = ExtractValueFromContentDispositionHeader(line, ic+1, "name");
                    _partFilename = ExtractValueFromContentDispositionHeader(line, ic+1, "filename"); 
                }
                else if (StringUtil.EqualsIgnoreCase(header, "Content-Type")) { 
                    _partContentType = line.Substring(ic+1).Trim(); 
                }
            } 
        }

        private bool AtBoundaryLine() {
            // check for either regular or last boundary line length 

            int len = _boundary.Length; 
 
            if (_lineLength != len && _lineLength != len+2)
                return false; 

            // match with boundary

            for (int i = 0; i < len; i++) { 
                if (_data[_lineStart+i] != _boundary[i])
                    return false; 
            } 

            // regular boundary line? 

            if (_lineLength == len)
                return true;
 
            // last boundary line? (has to end with "--")
 
            if (_data[_lineStart+len] != 45 || _data[_lineStart+len+1] != 45) 
                return false;
 
            _lastBoundaryFound = true; // remember that it is last
            return true;
        }
 
        private void ParsePartData() {
            _partDataStart = _pos; 
            _partDataLength = -1; 

            while (GetNextLine()) { 
                if (AtBoundaryLine()) {
                    // calc length: adjust to exclude [\r]\n before the separator
                    int iEnd = _lineStart - 1;
                    if (_data[iEnd] == 10)   // \n 
                        iEnd--;
                    if (_data[iEnd] == 13)   // \r 
                        iEnd--; 

                    _partDataLength = iEnd - _partDataStart + 1; 
                    break;
                }
            }
        } 

        private void ParseIntoElementList() { 
            // 
            // Skip until first boundary
            // 

            while (GetNextLine()) {
                if (AtBoundaryLine())
                    break; 
            }
 
            if (AtEndOfData()) 
                return;
 
            //
            // Parse the parts
            //
 
            do {
                // Parse current part's headers 
 
                ParsePartHeaders();
 
                if (AtEndOfData())
                    break;          // cannot stop after headers

                // Parse current part's data 

                ParsePartData(); 
 
                if (_partDataLength == -1)
                    break;          // ending boundary not found 

                // Remember the current part (if named)

                if (_partName != null) { 
                    _elements.Add(new MultipartContentElement(
                                                             _partName, 
                                                             _partFilename, 
                                                             _partContentType,
                                                             _data, 
                                                             _partDataStart,
                                                             _partDataLength));
                }
            } 
            while (!AtEndOfData());
        } 
 
        /*
         * Static method to do the parsing 
         */
        internal static MultipartContentElement[] Parse(HttpRawUploadedContent data, int length, byte[] boundary, Encoding encoding) {
            HttpMultipartContentTemplateParser parser = new HttpMultipartContentTemplateParser(data, length, boundary, encoding);
            parser.ParseIntoElementList(); 
            return (MultipartContentElement[])parser._elements.ToArray(typeof(MultipartContentElement));
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK