// // System.Web.HttpPostedFile.cs // // Author: // Dick Porter // Ben Maurer // Miguel de Icaza // // 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){ fs.Write (buffer, 0, n); } } } finally { stream.Position = old_post; } } } }