2010-04-21 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpPostedFile.cs
1 //
2 // System.Web.HttpPostedFile.cs
3 //
4 // Author:
5 //      Dick Porter  <dick@ximian.com>
6 //      Ben Maurer   <benm@ximian.com>
7 //      Miguel de Icaza <miguel@novell.com>
8 //
9 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.IO;
32 using System.Security.Permissions;
33
34 namespace System.Web
35 {
36         // CAS - no InheritanceDemand here as the class is sealed
37         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
38         public sealed class HttpPostedFile {
39                 string name;
40                 string content_type;
41                 Stream stream;
42                 
43                 class ReadSubStream : Stream {
44                         Stream s;
45                         long offset;
46                         long end;
47                         long position;
48         
49                         public ReadSubStream (Stream s, long offset, long length)
50                         {
51                                 this.s = s;
52                                 this.offset = offset;
53                                 this.end = offset + length;
54                                 position = offset;
55                         }
56         
57                         public override void Flush ()
58                         {
59                         }
60         
61                         public override int Read (byte [] buffer, int dest_offset, int count)
62                         {
63                                 if (buffer == null)
64                                         throw new ArgumentNullException ("buffer");
65
66                                 if (dest_offset < 0)
67                                         throw new ArgumentOutOfRangeException ("dest_offset", "< 0");
68
69                                 if (count < 0)
70                                         throw new ArgumentOutOfRangeException ("count", "< 0");
71
72                                 int len = buffer.Length;
73                                 if (dest_offset > len)
74                                         throw new ArgumentException ("destination offset is beyond array size");
75                                 // reordered to avoid possible integer overflow
76                                 if (dest_offset > len - count)
77                                         throw new ArgumentException ("Reading would overrun buffer");
78
79                                 if (count > end - position)
80                                         count = (int) (end - position);
81
82                                 if (count <= 0)
83                                         return 0;
84
85                                 s.Position = position;
86                                 int result = s.Read (buffer, dest_offset, count);
87                                 if (result > 0)
88                                         position += result;
89                                 else
90                                         position = end;
91
92                                 return result;
93                         }
94         
95                         public override int ReadByte ()
96                         {
97                                 if (position >= end)
98                                         return -1;
99
100                                 s.Position = position;
101                                 int result = s.ReadByte ();
102                                 if (result < 0)
103                                         position = end;
104                                 else
105                                         position++;
106
107                                 return result;
108                         }
109         
110                         public override long Seek (long d, SeekOrigin origin)
111                         {
112                                 long real;
113                                 switch (origin) {
114                                 case SeekOrigin.Begin:
115                                         real = offset + d;
116                                         break;
117                                 case SeekOrigin.End:
118                                         real = end + d;
119                                         break;
120                                 case SeekOrigin.Current:
121                                         real = position + d;
122                                         break;
123                                 default:
124                                         throw new ArgumentException ();
125                                 }
126
127                                 long virt = real - offset;
128                                 if (virt < 0 || virt > Length)
129                                         throw new ArgumentException ();
130
131                                 position = s.Seek (real, SeekOrigin.Begin);
132                                 return position;
133                         }
134         
135                         public override void SetLength (long value)
136                         {
137                                 throw new NotSupportedException ();
138                         }
139
140                         public override void Write (byte [] buffer, int offset, int count)
141                         {
142                                 throw new NotSupportedException ();
143                         }
144
145                         public override bool CanRead {
146                                 get { return true; }
147                         }
148                         public override bool CanSeek {
149                                 get { return true; }
150                         }
151                         public override bool CanWrite {
152                                 get { return false; }
153                         }
154         
155                         public override long Length {
156                                 get { return end - offset; }
157                         }
158         
159                         public override long Position {
160                                 get {
161                                         return position - offset;
162                                 }
163                                 set {
164                                         if (value > Length)
165                                                 throw new ArgumentOutOfRangeException ();
166
167                                         position = Seek (value, SeekOrigin.Begin);
168                                 }
169                         }
170                 }
171
172                 internal HttpPostedFile (string name, string content_type, Stream base_stream, long offset, long length)
173                 {
174                         this.name = name;
175                         this.content_type = content_type;
176                         this.stream = new ReadSubStream (base_stream, offset, length);
177                 }
178                 
179                 public string ContentType {
180                         get {
181                                 return (content_type);
182                         }
183                 }
184
185                 public int ContentLength {
186                         get {
187                                 return (int)stream.Length;
188                         }
189                 }
190
191                 public string FileName 
192                 {
193                         get {
194                                 return (name);
195                         }
196                 }
197
198                 public Stream InputStream 
199                 {
200                         get {
201                                 return (stream);
202                         }
203                 }
204
205                 public void SaveAs (string filename)
206                 {
207                         byte [] buffer = new byte [16*1024];
208                         long old_post = stream.Position;
209
210                         try {
211                                 File.Delete (filename);
212                                 using (FileStream fs = File.Create (filename)){
213                                         stream.Position = 0;
214                                         int n;
215                                         
216                                         while ((n = stream.Read (buffer, 0, 16*1024)) != 0){
217                                                 fs.Write (buffer, 0, n);
218                                         }
219                                 }
220                         } finally {
221                                 stream.Position = old_post;
222                         }
223                 }
224         }
225 }