Пример #1
0
        /// <summary>
        /// MultiformUploadRequest
        /// </summary>
        /// <param name="input"></param>
        /// <param name="boundary"></param>
        public MultiformUploadRequest(Stream input, string boundary)
        {
            parser                     = new StreamingMultipartFormDataParser(input, boundary, Encoding.UTF8, 1024 * 1024);
            parser.FileHandler         = new StreamingMultipartFormDataParser.FileStreamDelegate(FileStreamHandler);
            parser.ParameterHandler    = new StreamingMultipartFormDataParser.ParameterDelegate(ParameterHandler);
            parser.StreamClosedHandler = new StreamingMultipartFormDataParser.StreamClosedDelegate(StreamClosedHandler);

            parser.Run();
        }
Пример #2
0
        public void ParseAsMultipartStream(Action <string, string, string, string, byte[], int> onData, Action <string, string> onParameter = null)
        {
            var parser = new StreamingMultipartFormDataParser(this.InputStream);

            if (onParameter != null)
            {
                parser.ParameterHandler += parameter => onParameter(parameter.Name, parameter.Data);
            }
            parser.FileHandler += (name, fileName, type, disposition, buffer, bytes) => onData(name, fileName, type, disposition, buffer, bytes);
            parser.Run();
        }
Пример #3
0
        /// <summary>
        /// 处理多段表单数据
        /// </summary>
        /// <param name="req"></param>
        /// <param name="parameterHandler"></param>
        /// <param name="fileHandler"></param>
        public static void HandleMultipartData(IOwinRequest req,
                                               StreamingMultipartFormDataParser.ParameterDelegate parameterHandler,
                                               StreamingMultipartFormDataParser.FileStreamDelegate fileHandler,
                                               StreamingMultipartFormDataParser.StreamClosedDelegate streamClosedDelegate = null)
        {
            if (!req.ContentType.StartsWith("multipart/form-data;"))
            {
                throw new ArgumentException("'ContentType' not start with 'multipart/form-data;'.");
            }
            var parser = new StreamingMultipartFormDataParser(req.Body);

            parser.ParameterHandler    = parameterHandler;
            parser.FileHandler         = fileHandler;
            parser.StreamClosedHandler = streamClosedDelegate;
            parser.Run();
        }
Пример #4
0
        /// <summary>
        ///     Save multipart form-data from request body, if any, to a file in the specified directory
        /// </summary>
        /// <param name="filePath">The directory to placed to file in</param>
        /// <param name="filerenamer">Function to rename the file(s)</param>
        /// <param name="maxSizeKb">The max filesize allowed</param>
        /// <returns>Whether the file was saved succesfully</returns>
        public Task <bool> SaveBodyToFile(string filePath, Func <string, string> filerenamer = null, long maxSizeKb = 1024)
        {
            if (!UnderlyingRequest.HasEntityBody)
            {
                return(Task.FromResult(false));
            }
            var maxbytes    = maxSizeKb << 10;
            var tcs         = new TaskCompletionSource <bool>();
            var filestreams = new Dictionary <string, Stream>();
            var files       = new Dictionary <string, string>();
            var sizes       = new Dictionary <string, long>();
            var failed      = false;
            var parser      = new StreamingMultipartFormDataParser(UnderlyingRequest.InputStream);

            parser.FileHandler += (name, fname, type, disposition, buffer, bytes) =>
            {
                if (failed)
                {
                    return;
                }
                if (bytes > maxbytes)
                {
                    tcs.TrySetResult(false);
                    return;
                }
                if (filerenamer != null)
                {
                    string rename;
                    if (!files.TryGetValue(fname, out rename))
                    {
                        rename = filerenamer(fname);
                        files.Add(fname, rename);
                    }
                    fname = rename;
                }
                if (!sizes.ContainsKey(fname))
                {
                    sizes[fname] = bytes;
                }
                else
                {
                    sizes[fname] += bytes;
                }
                if (sizes[fname] > maxbytes)
                {
                    failed = true;
                    foreach (var str in filestreams.Values)
                    {
                        str.Close();
                    }
                    tcs.TrySetResult(false);
                    return;
                }
                Stream stream;
                if (!filestreams.TryGetValue(fname, out stream))
                {
                    stream = File.Create(Path.Combine(filePath, fname));
                    filestreams.Add(fname, stream);
                }
                stream.Write(buffer, 0, bytes);
                stream.Flush();
            };
            parser.StreamClosedHandler += () =>
            {
                foreach (var stream in filestreams.Values)
                {
                    stream.Close();
                }
                tcs.TrySetResult(true);
            };
            parser.Run();
            return(tcs.Task);
        }
Пример #5
0
        /// <summary>
        /// Processes the request to get the form values.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="bodyStream">The stream for the request's body.</param>
        /// <returns>The collection with all values from the form. The collection is possibly empty.</returns>
        public static NameValueCollection GetForm(this HttpListenerRequest request, Stream bodyStream)
        {
            if (request == null || bodyStream == null)
            {
                return(new NameValueCollection());
            }

            if (!request.HasEntityBody)
            {
                return(new NameValueCollection());
            }

            // Case #1: Just a form
            //		Content Type = application/x-www-form-urlencoded
            //		Body = MAX_FILE_SIZE=100000&t%C3%A4stValue=das+ist+ein+test
            if (request.ContentType.Contains("application/x-www-form-urlencoded"))
            {
                using (bodyStream)
                {
                    using (var reader = new StreamReader(bodyStream))
                    {
                        return(reader.ReadToEnd().GetQueryString(true));
                    }
                }
            }

            // Case #2: Just a file
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            //
            // ==> Does not matter
            //

            // Case #3: Multiple files
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFile2"; filename="fsdfsdf.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            //
            // ==> Does not matter
            //

            // Case #4: A file and form data
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="einsÖÄÜ"
            //
            //		2354öäpü
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="zwei"
            //
            //		[email protected]
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            //
            // ==> Does not matter, use case #5.
            //

            // Case #5: Multiple files and form data
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="einsÖÄÜ"
            //
            //		2354öäpü
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="zwei"
            //
            //		[email protected]
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFile3"; filename="Ssdfsdfd.fdf"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="rterz"
            //
            //		[email protected]
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            // Check the requirements:
            if (!request.ContentType.Contains("multipart/form-data; boundary="))
            {
                return(new NameValueCollection());
            }

            // Store the result here:
            var result = new NameValueCollection();

            using (bodyStream)
            {
                // Dummy to consume the name of each parameter:
                var dummy = string.Empty;

                // Create the parser for the body:
                var smftp = new StreamingMultipartFormDataParser(bodyStream);

                // The handler for parameters:
                smftp.ParameterHandler += parameter =>
                {
                    result.Add(parameter.Name, parameter.Data);
                };

                // The parser requires both, the parameter and the file handler:
                smftp.FileHandler += (name, fileName, type, disposition, buffer, bytes) =>
                {
                    // Perform a dummy OP:
                    dummy = name;
                };

                // Start the processing. This call will block until end of processing:
                smftp.Run();
            }

            return(result);
        }
Пример #6
0
        /// <summary>
        /// Processes the request to get all uploaded files.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="bodyStream">The stream for the request's body.</param>
        /// <param name="tmpFolderPATH">The temporary folder for this request.</param>
        /// <param name="niiRequest">The NoIIS request to register additional open streams.</param>
        /// <returns>Returns the collection with all uploaded files. The collection is possibily empty.</returns>
        public static HttpFileCollectionBase GetFiles(this HttpListenerRequest request, Stream bodyStream, string tmpFolderPATH, NoIISRequest niiRequest)
        {
            if (request == null || tmpFolderPATH == null || bodyStream == null)
            {
                return(new NoIISFileCollection());
            }

            if (!request.HasEntityBody)
            {
                return(new NoIISFileCollection());
            }

            // Case #1: Just a form
            //		Content Type = application/x-www-form-urlencoded
            //		Body = MAX_FILE_SIZE=100000&t%C3%A4stValue=das+ist+ein+test

            //
            // ==> Does not matter
            //

            // Case #2: Just a file
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            //
            // ==> Does not matter
            //

            // Case #3: Multiple files
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFile2"; filename="fsdfsdf.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            //
            // ==> Does not matter
            //

            // Case #4: A file and form data
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="einsÖÄÜ"
            //
            //		2354öäpü
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="zwei"
            //
            //		[email protected]
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            //
            // ==> Does not matter, use case #5.
            //

            // Case #5: Multiple files and form data
            //      Content type = multipart/form-data; boundary=----WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Body =
            //      ------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFileö"; filename="Short Time Notes.txt"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="einsÖÄÜ"
            //
            //		2354öäpü
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="zwei"
            //
            //		[email protected]
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //      Content-Disposition: form-data; name="meinFile3"; filename="Ssdfsdfd.fdf"
            //      Content-Type: text/plain
            //
            //		DATA STREAM
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg
            //		Content-Disposition: form-data; name="rterz"
            //
            //		[email protected]
            //		------WebKitFormBoundaryeghC9TqseFEkpCXg--

            // If the request's content type does not match the requirements,
            // return here:
            if (!request.ContentType.Contains("multipart/form-data; boundary="))
            {
                return(new NoIISFileCollection());
            }

            // The cache for all tmp. filenames for files in the request:
            var cacheFilenames = new ConcurrentDictionary <string, NoIISPostedFile>();

            using (bodyStream)
            {
                // Dummy to consume the name of each parameter:
                var dummy = string.Empty;

                // Create the parser for the body:
                var smftp = new StreamingMultipartFormDataParser(bodyStream);

                // The parser requires both, the parameter and the file handler:
                smftp.ParameterHandler += parameter => dummy = parameter.Name;

                // The file handler gets called for every chunk of each file inside:
                smftp.FileHandler += (name, fileName, type, disposition, buffer, bytes) =>
                {
                    // Generate a key for this file:
                    var key = name + fileName + type + disposition;

                    // The destination tmp. file name:
                    var destination = string.Empty;
                    if (!cacheFilenames.ContainsKey(key))
                    {
                        // Case: A new file.
                        cacheFilenames[key] = new NoIISPostedFile();

                        // Generate the tmp. file name with path:
                        cacheFilenames[key].TMPFilenamePATH = tmpFolderPATH + Guid.NewGuid().ToString();
                        cacheFilenames[key].FormName        = name;
                        cacheFilenames[key].setContentType(type);
                        cacheFilenames[key].setFileName(fileName);
                    }

                    // Read the current destination:
                    destination = cacheFilenames[key].TMPFilenamePATH;

                    try
                    {
                        // Append the bytes to the tmp. file:
                        using (var fileStream = File.Open(destination, FileMode.Append, FileAccess.Write, FileShare.None))
                        {
                            fileStream.Write(buffer, 0, bytes);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception while processing the file upload '{1}' (name='{2}'): {0}", e.Message, fileName, name);
                        Console.WriteLine(e.StackTrace);
                    }
                };

                try
                {
                    // Start the processing. This call will block until end of processing:
                    smftp.Run();
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception while processing the file upload: {0}", e.Message);
                    Console.WriteLine(e.StackTrace);
                }
            }

            //
            // The files should now be available as tmp. data.
            //

            // The result's collection:
            var result = new List <NoIISPostedFile>(cacheFilenames.Count);

            // Loop over all files:
            foreach (var key in cacheFilenames.Keys)
            {
                // Get a file:
                var file = cacheFilenames[key];

                // Get the tmp. file's name:
                var filename = file.TMPFilenamePATH;

                // Get the stream to the file's content:
                var stream = File.OpenRead(filename);

                // Register this open stream:
                niiRequest.AddProbablyOpenStream(stream);

                // Store the file's length:
                file.setContentLength((int)stream.Length);

                // Store the stream:
                file.setInputStream(stream);

                // Store this file to the result:
                result.Add(file);
            }

            return(new NoIISFileCollection(result));
        }
Пример #7
0
        protected override bool Process(IInteraction parameters)
        {
            bool successful = true;

            IInteraction httpInteractionCandidate;

            if (successful = parameters.TryGetClosest(typeof(IHttpInteraction), out httpInteractionCandidate))
            {
                IHttpInteraction httpInteraction = (IHttpInteraction)httpInteractionCandidate;

                if (httpInteraction.ContentType.StartsWith(MimeTypePrefix))
                {
                    string headerBoundary = httpInteraction.ContentType.Substring(MimeTypePrefix.Length);

                    SimpleInteraction mappedValues = new SimpleInteraction(parameters);

                    StreamingMultipartFormDataParser parser = new StreamingMultipartFormDataParser(
                        httpInteraction.IncomingBody,
                        headerBoundary,
                        httpInteraction.Encoding,
                        this.BufferSize
                        );

                    parser.ParameterHandler += delegate(ParameterPart part) {
                        if (this.StringFieldWhiteList.Contains(part.Name))
                        {
                            mappedValues[part.Name] = part.Data;

                            successful &= this.Branches.Get(part.Name, Stub).TryProcess(
                                new WwwInputInteraction(part.Name, part.Data, parameters)
                                );
                        }
                    };

                    parser.FileHandler += delegate(
                        string name,
                        string fileName,
                        string contentType,
                        string contentDisposition,
                        byte[] buffer,
                        int bytes
                        ) {
                        if (this.StringFieldWhiteList.Contains(name))
                        {
                            MemoryStream stream = new MemoryStream(buffer, 0, bytes);

                            SimpleIncomingInteraction incoming = new SimpleIncomingInteraction(
                                stream,
                                mappedValues,
                                contentDisposition,
                                contentType
                                );

                            incoming ["mimetype"] = contentType;

                            incoming ["filename"] = fileName;

                            successful &= this.Branches.Get(name, Stub).TryProcess(incoming);

                            stream.Dispose();
                        }
                    };

                    parser.Run();

                    successful &= this.Mapped.TryProcess(mappedValues);
                }
                else
                {
                    Secretary.Report(5, "Require boundary content type for multipart forms");
                    successful &= Failure.TryProcess(parameters);
                }
            }
            else
            {
                Secretary.Report(5, "Require HttpInteraction for multipart forms");
                successful &= Failure.TryProcess(parameters);
            }

            return(successful);
        }