예제 #1
0
 public override string GetKnownRequestHeader(int index)
 {
     if (index == HttpWorkerRequest.HeaderContentLength)
     {
         ParseMultipart();
         return(preloadedEntityBody.Length.ToString());
     }
     return(OrigWorker.GetKnownRequestHeader(index));
 }
예제 #2
0
        private bool ParseOrThrow()
        {
            origPreloadedBody = OrigWorker.GetPreloadedEntityBody();
            string contentTypeHeader      = OrigWorker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);
            string contentLengthHeader    = OrigWorker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength);
            string transferEncodingHeader = OrigWorker.GetKnownRequestHeader(HttpWorkerRequest.HeaderTransferEncoding);

            if (contentLengthHeader != null)
            {
                origContentLength = Int64.Parse(contentLengthHeader);
            }

            if (Config.Current.DebugDirectory != null)
            {
                string logEntityBodyBaseName = Path.Combine(Config.Current.DebugDirectory.FullName,
                                                            DateTime.Now.Ticks.ToString());
                LogEntityBodyStream      = File.Create(logEntityBodyBaseName + ".body");
                LogEntityBodySizesStream = File.CreateText(logEntityBodyBaseName + ".sizes");
                LogEntityBodySizesStream.WriteLine(contentTypeHeader);
                LogEntityBodySizesStream.WriteLine(contentLengthHeader);
                if (origPreloadedBody != null)
                {
                    LogEntityBodyStream.Write(origPreloadedBody, 0, origPreloadedBody.Length);
                    LogEntityBodySizesStream.WriteLine(origPreloadedBody.Length);
                }
                else
                {
                    LogEntityBodySizesStream.WriteLine(0);
                }
            }

            FieldNameTranslator translator = new FieldNameTranslator();

            if (MultiRequestControlID == null && UploadState != null)
            {
                UploadState.BytesTotal += origContentLength;
            }
            if (log.IsDebugEnabled)
            {
                log.Debug("=" + contentLengthHeader + " -> " + origContentLength);
            }

            boundary = System.Text.Encoding.ASCII.GetBytes("--" + GetAttribute(contentTypeHeader, "boundary"));
            if (log.IsDebugEnabled)
            {
                log.Debug("boundary=" + System.Text.Encoding.ASCII.GetString(boundary));
            }

            string charset = GetAttribute(contentTypeHeader, "charset");

            if (charset != null)
            {
                try
                {
                    System.Text.Encoding encoding = System.Text.Encoding.GetEncoding(charset);
                    ContentEncoding = encoding;
                }
                catch (NotSupportedException)
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Ignoring unsupported charset " + charset + ".  Using utf-8.");
                    }
                }
            }
            else
            {
                ContentEncoding = HttpContext.Current.Response.ContentEncoding;
            }
            preloadedEntityBodyStream = new MemoryStream();
            Hashtable storageConfigStreamTable = new Hashtable();
            Stream    postBackIDStream         = null;

            outputStream = preloadedEntityBodyStream;
            readPos      = writePos = parsePos = 0;
            while (CopyUntilBoundary())
            {
                // If we were writing to a file, close it
                if (outputStream == fileStream && outputStream != null)
                {
                    UploadState.Files.Add(controlID, uploadedFile);
                    outputStream.Close();
                }

                // If we were receiving the value generated by the HiddenPostBackID control, set the postback ID.
                if (postBackIDStream != null)
                {
                    postBackIDStream.Seek(0, System.IO.SeekOrigin.Begin);
                    StreamReader sr = new System.IO.StreamReader(postBackIDStream);
                    translator.PostBackID = sr.ReadToEnd();
                    postBackIDStream      = null;
                }

                // parse the headers
                string name = null, fileName = null, contentType = null;
                if (boundary[0] != (byte)'\r')
                {
                    byte[] newBoundary = new byte[boundary.Length + 2];
                    Buffer.BlockCopy(boundary, 0, newBoundary, 2, boundary.Length);
                    newBoundary[0] = (byte)'\r';
                    newBoundary[1] = (byte)'\n';
                    boundary       = newBoundary;
                }
                else
                {
                    GetLine();             // Blank line
                }
                GetLine();                 // boundary line
                string header;
                while (null != (header = GetLine()))
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("header=" + header);
                    }
                    int colonPos = header.IndexOf(':');
                    if (colonPos < 0)
                    {
                        break;
                    }
                    string headerName = header.Substring(0, colonPos);
                    if (String.Compare(headerName, "Content-Disposition", true) == 0)
                    {
                        name     = GetAttribute(header, "name");
                        fileName = GetAttribute(header, "filename");
                    }
                    else if (String.Compare(headerName, "Content-Type", true) == 0)
                    {
                        contentType = header.Substring(colonPos + 1).Trim();
                    }
                }
                if (log.IsDebugEnabled)
                {
                    log.Debug("name = " + name);
                }
                if (log.IsDebugEnabled)
                {
                    log.Debug("fileName = " + fileName);
                }
                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("name = " + name);
                }
                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("fileName = " + fileName);
                }
                controlID = null;
                if (name == Config.Current.PostBackIDQueryParam && postBackIDStream == null)
                {
                    postBackIDStream = outputStream = new System.IO.MemoryStream();
                    readPos          = parsePos;            // Skip past the boundary and headers
                }
                else if (name != null &&
                         null != (controlID = translator.ConfigFieldNameToControlID(name)))
                {
                    storageConfigStreamTable[controlID] = outputStream = new System.IO.MemoryStream();
                    readPos = parsePos;                     // Skip past the boundary and headers
                }
                else if (name != null &&
                         null != (controlID = translator.FileFieldNameToControlID(name)))
                {
                    if (log.IsDebugEnabled)
                    {
                        log.DebugFormat("name != null && controlID != null");
                    }
                    if (UploadState == null)
                    {
                        UploadState = UploadStateStore.OpenReadWriteOrCreate(translator.FileFieldNameToPostBackID(name));
                        if (transferEncodingHeader != "chunked")
                        {
                            UploadState.Status = UploadStatus.NormalInProgress;
                        }
                        else
                        {
                            UploadState.Status = UploadStatus.ChunkedInProgress;
                        }
                        UploadState.BytesTotal += origContentLength;
                        UploadState.BytesRead  += grandTotalBytesRead;
                    }

                    UploadStorageConfig storageConfig = null;

                    if (UploadState.MultiRequestObject != null)
                    {
                        string secureStorageConfigString = UploadState.MultiRequestObject as string;
                        if (secureStorageConfigString != null)
                        {
                            storageConfig = UploadStorage.CreateUploadStorageConfig();
                            storageConfig.Unprotect(secureStorageConfigString);
                            if (log.IsDebugEnabled)
                            {
                                log.DebugFormat("storageConfig[tempDirectory]={0}", storageConfig["tempDirectory"]);
                            }
                        }
                    }
                    string       configID            = translator.FileIDToConfigID(controlID);
                    MemoryStream storageConfigStream = storageConfigStreamTable[configID] as MemoryStream;
                    if (storageConfigStream != null)
                    {
                        storageConfigStream.Seek(0, System.IO.SeekOrigin.Begin);
                        StreamReader sr = new System.IO.StreamReader(storageConfigStream);
                        string       secureStorageConfigString = sr.ReadToEnd();
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("storageConfigStream = " + secureStorageConfigString);
                        }
                        storageConfig = UploadStorage.CreateUploadStorageConfig();
                        storageConfig.Unprotect(secureStorageConfigString);

                        // Write out a part for the config hidden field
                        if (log.IsDebugEnabled)
                        {
                            log.DebugFormat("Calling WriteReplacementFormField({0}, {1})", configID, secureStorageConfigString);
                        }
                        WriteReplacementFormField(configID, secureStorageConfigString);
                        // Remove the stream from the table, so we don't write the replacement field again.
                        storageConfigStreamTable.Remove(configID);
                    }

                    if (fileName != null)
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.DebugFormat("filename != null");
                        }
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Calling UploadContext.Current.CreateUploadedFile(" + controlID + "...)");
                        }
                        UploadContext tempUploadContext = new UploadContext();
                        tempUploadContext._ContentLength = origContentLength;
                        uploadedFile
                            = UploadStorage.CreateUploadedFile(tempUploadContext, controlID, fileName, contentType, storageConfig);
                        if (MultiRequestControlID == null)
                        {
                            UploadStorage.DisposeAtEndOfRequest(uploadedFile);
                        }
                        outputStream = fileStream = uploadedFile.CreateStream();
                        UploadState.CurrentFileName = uploadedFile.FileName;
                        readPos = parsePos; // Skip past the boundary and headers

                        // If the client-specified content length is too large, we set the status to
                        // RejectedRequestTooLarge so that progress displays will stop.  We do this after
                        // having created the UploadedFile because that is necessary for the progress display
                        // to find the uploadContext.
                        if (origContentLength > UploadHttpModule.MaxRequestLength)
                        {
                            if (log.IsDebugEnabled)
                            {
                                log.Debug("contentLength > MaxRequestLength");
                            }
                            throw new UploadTooLargeException(UploadHttpModule.MaxRequestLength, origContentLength);
                        }

                        // Write out a replacement part that just contains the filename as the value.
                        WriteReplacementFormField(controlID, fileName);
                    }
                    else
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.DebugFormat("filename == null");
                        }
                        // Since filename==null this must just be a hidden field with a name that
                        // looks like a file field.  It is just an indication that when this request
                        // ends, the associated uploaded files should be disposed.
                        if (MultiRequestControlID == null)
                        {
                            if (log.IsDebugEnabled)
                            {
                                log.DebugFormat("MultiRequestControlID == null");
                            }
                            RegisterFilesForDisposal(controlID);
                        }
                        outputStream = preloadedEntityBodyStream;
                    }
                }
                else
                {
                    outputStream = preloadedEntityBodyStream;
                }
            }
            if (log.IsDebugEnabled)
            {
                log.Debug("Done parsing.");
            }
            outputStream.WriteByte(10);
            outputStream.Close();
            preloadedEntityBody       = preloadedEntityBodyStream.ToArray();
            preloadedEntityBodyStream = null;
            if (grandTotalBytesRead < origContentLength)
            {
                return(false);
            }
            return(true);
        }