context: //
  // System.Web.HttpPostedFile.cs
  //
  // Author:
  //	Dick Porter  <dick@ximian.com>
  //      Ben Maurer   <benm@ximian.com>
  //      Miguel de Icaza <miguel@novell.com>
  //
  // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  using System.IO;
  using System.Security.Permissions;
  
  namespace System.Web
  {
  	// CAS - no InheritanceDemand here as the class is sealed
  	[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  	public sealed class HttpPostedFile {
  		string name;
  		string content_type;
  		Stream stream;
  		
  		class ReadSubStream : Stream {
  			Stream s;
  			long offset;
  			long end;
  			long position;
  	
  			public ReadSubStream (Stream s, long offset, long length)
  			{
  				this.s = s;
  				this.offset = offset;
  				this.end = offset + length;
  				position = offset;
  			}
  	
  			public override void Flush ()
  			{
  			}
  	
  			public override int Read (byte [] buffer, int dest_offset, int count)
  			{
  				if (buffer == null)
  					throw new ArgumentNullException ("buffer");
  
  				if (dest_offset < 0)
  					throw new ArgumentOutOfRangeException ("dest_offset", "< 0");
  
  				if (count < 0)
  					throw new ArgumentOutOfRangeException ("count", "< 0");
  
  				int len = buffer.Length;
  				if (dest_offset > len)
  					throw new ArgumentException ("destination offset is beyond array size");
  				// reordered to avoid possible integer overflow
  				if (dest_offset > len - count)
  					throw new ArgumentException ("Reading would overrun buffer");
  
  				if (count > end - position)
  					count = (int) (end - position);
  
  				if (count <= 0)
  					return 0;
  
  				s.Position = position;
  				int result = s.Read (buffer, dest_offset, count);
  				if (result > 0)
  					position += result;
  				else
  					position = end;
  
  				return result;
  			}
  	
  			public override int ReadByte ()
  			{
  				if (position >= end)
  					return -1;
  
  				s.Position = position;
  				int result = s.ReadByte ();
  				if (result < 0)
  					position = end;
  				else
  					position++;
  
  				return result;
  			}
  	
  			public override long Seek (long d, SeekOrigin origin)
  			{
  				long real;
  				switch (origin) {
  				case SeekOrigin.Begin:
  					real = offset + d;
  					break;
  				case SeekOrigin.End:
  					real = end + d;
  					break;
  				case SeekOrigin.Current:
  					real = position + d;
  					break;
  				default:
  					throw new ArgumentException ();
  				}
  
  				long virt = real - offset;
  				if (virt < 0 || virt > Length)
  					throw new ArgumentException ();
  
  				position = s.Seek (real, SeekOrigin.Begin);
  				return position;
  			}
  	
  			public override void SetLength (long value)
  			{
  				throw new NotSupportedException ();
  			}
  
  			public override void Write (byte [] buffer, int offset, int count)
  			{
  				throw new NotSupportedException ();
  			}
  
  			public override bool CanRead {
  				get { return true; }
  			}
  			public override bool CanSeek {
  				get { return true; }
  			}
  			public override bool CanWrite {
  				get { return false; }
  			}
  	
  			public override long Length {
  				get { return end - offset; }
  			}
  	
  			public override long Position {
  				get {
  					return position - offset;
  				}
  				set {
  					if (value > Length)
  						throw new ArgumentOutOfRangeException ();
  
  					position = Seek (value, SeekOrigin.Begin);
  				}
  			}
  		}
  
  		internal HttpPostedFile (string name, string content_type, Stream base_stream, long offset, long length)
  		{
  			this.name = name;
  			this.content_type = content_type;
  			this.stream = new ReadSubStream (base_stream, offset, length);
  		}
  		
  		public string ContentType {
  			get {
  				return (content_type);
  			}
  		}
  
  		public int ContentLength {
  			get {
  		  		return (int)stream.Length;
  			}
  		}
  
  		public string FileName 
  		{
  			get {
  				return (name);
  			}
  		}
  
  		public Stream InputStream 
  		{
  			get {
  				return (stream);
  			}
  		}
  
  		public void SaveAs (string filename)
  		{
  			byte [] buffer = new byte [16*1024];
  			long old_post = stream.Position;
  
  			try {
  				File.Delete (filename);
  				using (FileStream fs = File.Create (filename)){
  					stream.Position = 0;
  					int n;
  					
  					while ((n = stream.Read (buffer, 0, 16*1024)) != 0){
  
gt: 						fs.Write (buffer, 0, n);