void MakeInputStream () { if (input_stream != null) return; if (worker_request == null) { input_stream = new MemoryStream (new byte [0], 0, 0, false, true); DoFilter (new byte [1024]); return; } // // Use an unmanaged memory block as this might be a large // upload // int content_length = ContentLength; int content_length_kb = content_length / 1024; HttpRuntimeSection config = HttpRuntime.Section; if (content_length_kb > config.MaxRequestLength) throw HttpException.NewWithCode (400, "Upload size exceeds httpRuntime limit.", WebEventCodes.RuntimeErrorPostTooLarge); int total = 0; byte [] buffer; buffer = worker_request.GetPreloadedEntityBody (); // we check the instance field 'content_length' here, not the local var. if (this.content_length <= 0 || worker_request.IsEntireEntityBodyIsPreloaded ()) { if (buffer == null || content_length == 0) { input_stream = new MemoryStream (new byte [0], 0, 0, false, true); } else { input_stream = new MemoryStream (buffer, 0, buffer.Length, false, true); } DoFilter (new byte [1024]); return; } if (buffer != null) total = buffer.Length; if (content_length > 0 && content_length_kb >= config.RequestLengthDiskThreshold) { // Writes the request to disk total = Math.Min (content_length, total); request_file = GetTempStream (); Stream output = request_file; if (total > 0) output.Write (buffer, 0, total); if (total < content_length) { buffer = new byte [Math.Min (content_length, INPUT_BUFFER_SIZE)]; do { int n; int min = Math.Min (content_length - total, INPUT_BUFFER_SIZE); n = worker_request.ReadEntityBody (buffer, min); if (n <= 0) break; output.Write (buffer, 0, n); total += n; } while (total < content_length); } request_file.SetReadOnly (); input_stream = request_file; } else if (content_length > 0) { // Buffers the request in an IntPtrStream total = Math.Min (content_length, total); IntPtr content = Marshal.AllocHGlobal (content_length); if (content == (IntPtr) 0) throw HttpException.NewWithCode ( String.Format ("Not enough memory to allocate {0} bytes.", content_length), WebEventCodes.WebErrorOtherError); if (total > 0) Marshal.Copy (buffer, 0, content, total); if (total < content_length) { buffer = new byte [Math.Min (content_length, INPUT_BUFFER_SIZE)]; do { int n; int min = Math.Min (content_length - total, INPUT_BUFFER_SIZE); n = worker_request.ReadEntityBody (buffer, min); if (n <= 0) break; Marshal.Copy (buffer, 0, (IntPtr) ((long)content + total), n); total += n; } while (total < content_length); } input_stream = new IntPtrStream (content, total); } else { // Buffers the request in a MemoryStream or writes to disk if threshold exceeded MemoryStream ms = new MemoryStream (); Stream output = ms; if (total > 0) ms.Write (buffer, 0, total); buffer = new byte [INPUT_BUFFER_SIZE]; long maxlength = config.MaxRequestLength * 1024L; long disk_th = config.RequestLengthDiskThreshold * 1024L; int n; while (true) { n = worker_request.ReadEntityBody (buffer, INPUT_BUFFER_SIZE); if (n <= 0) break; total += n; if (total < 0 || total > maxlength) throw HttpException.NewWithCode (400, "Upload size exceeds httpRuntime limit.", WebEventCodes.RuntimeErrorPostTooLarge); if (ms != null && total > disk_th) { // Swith to on-disk file. request_file = GetTempStream (); ms.WriteTo (request_file); ms = null; output = request_file; } output.Write (buffer, 0, n); } if (ms != null) { input_stream = new MemoryStream (ms.GetBuffer (), 0, (int) ms.Length, false, true); } else { request_file.SetReadOnly (); input_stream = request_file; } } DoFilter (buffer); if (total < content_length) throw HttpException.NewWithCode (411, "The request body is incomplete.", WebEventCodes.WebErrorOtherError); }
internal void ReleaseResources () { Stream stream; if (input_stream != null){ stream = input_stream; input_stream = null; try { stream.Close (); } catch {} } if (request_file != null) { stream = request_file; request_file = null; try { stream.Close (); } catch {} } }
TempFileStream GetTempStream () { string tempdir = AppDomain.CurrentDomain.SetupInformation.DynamicBase; TempFileStream f = null; string path; Random rnd = new Random (); int num; do { num = rnd.Next (); num++; path = System.IO.Path.Combine (tempdir, "tmp" + num.ToString("x") + ".req"); try { f = new TempFileStream (path); } catch (SecurityException) { // avoid an endless loop throw; } catch { } } while (f == null); return f; }