| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152 |
- //
- // System.Web.HttpResponse.cs
- //
- //
- // Author:
- // Miguel de Icaza ([email protected])
- // Gonzalo Paniagua Javier ([email protected])
- //
- // 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.Text;
- using System.Web.UI;
- using System.Collections;
- using System.Collections.Specialized;
- using System.IO;
- using System.Web.Caching;
- using System.Threading;
- using System.Web.Util;
- using System.Web.Configuration;
- using System.Globalization;
- using System.Security.Permissions;
- using System.Web.Hosting;
- using System.Web.SessionState;
- namespace System.Web {
-
- // CAS - no InheritanceDemand here as the class is sealed
- [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
- public sealed partial class HttpResponse {
- internal HttpWorkerRequest WorkerRequest;
- internal HttpResponseStream output_stream;
- internal bool buffer = true;
- ArrayList fileDependencies;
-
- HttpContext context;
- TextWriter writer;
- HttpCachePolicy cache_policy;
- Encoding encoding;
- HttpCookieCollection cookies;
-
- int status_code = 200;
- string status_description = "OK";
- string content_type = "text/html";
- string charset;
- bool charset_set;
- CachedRawResponse cached_response;
- string user_cache_control = "private";
- string redirect_location;
-
- static string version_header;
-
- //
- // Negative Content-Length means we auto-compute the size of content-length
- // can be overwritten with AppendHeader ("Content-Length", value)
- //
- long content_length = -1;
- //
- // The list of the headers that we will send back to the client, except
- // the headers that we compute here.
- //
- NameValueCollection headers;
- bool headers_sent;
- NameValueCollection cached_headers;
- //
- // Transfer encoding state
- //
- string transfer_encoding;
- internal bool use_chunked;
-
- bool closed;
- internal bool suppress_content;
- //
- // Session State
- //
- string app_path_mod;
-
- #if NET_2_0
- bool is_request_being_redirected;
- Encoding headerEncoding;
- #endif
- static HttpResponse ()
- {
- #if NET_2_0
- HttpRuntimeSection config = WebConfigurationManager.GetWebApplicationSection ("system.web/httpRuntime") as HttpRuntimeSection;
- #else
- HttpRuntimeConfig config = HttpContext.GetAppConfig ("system.web/httpRuntime") as HttpRuntimeConfig;
- #endif
- if (config != null && config.EnableVersionHeader)
- version_header = Environment.Version.ToString (3);
- }
-
- internal HttpResponse ()
- {
- output_stream = new HttpResponseStream (this);
- }
- public HttpResponse (TextWriter writer) : this ()
- {
- this.writer = writer;
- }
- internal HttpResponse (HttpWorkerRequest worker_request, HttpContext context) : this ()
- {
- WorkerRequest = worker_request;
- this.context = context;
- #if !TARGET_J2EE
- if (worker_request != null)
- use_chunked = (worker_request.GetHttpVersion () == "HTTP/1.1");
- #endif
- }
-
- internal TextWriter SetTextWriter (TextWriter writer)
- {
- TextWriter prev = this.writer;
- this.writer = writer;
- return prev;
- }
- internal string[] FileDependencies {
- get {
- if (fileDependencies == null || fileDependencies.Count == 0)
- return new string[0] {};
- return (string[]) fileDependencies.ToArray (typeof (string));
- }
- }
-
- ArrayList FileDependenciesArray {
- get {
- if (fileDependencies == null)
- fileDependencies = new ArrayList ();
- return fileDependencies;
- }
- }
-
- public bool Buffer {
- get {
- return buffer;
- }
- set {
- buffer = value;
- }
- }
- public bool BufferOutput {
- get {
- return buffer;
- }
- set {
- buffer = value;
- }
- }
- //
- // Use the default from <globalization> section if the client has not set the encoding
- //
- public Encoding ContentEncoding {
- get {
- if (encoding == null) {
- if (context != null) {
- string client_content_type = context.Request.ContentType;
- string parameter = HttpRequest.GetParameter (client_content_type, "; charset=");
- if (parameter != null) {
- try {
- // Do what the #1 web server does
- encoding = Encoding.GetEncoding (parameter);
- } catch {
- }
- }
- }
- if (encoding == null)
- encoding = WebEncoding.ResponseEncoding;
- }
- return encoding;
- }
- set {
- if (value == null)
- throw new ArgumentException ("ContentEncoding can not be null");
- encoding = value;
- HttpWriter http_writer = writer as HttpWriter;
- if (http_writer != null)
- http_writer.SetEncoding (encoding);
- }
- }
-
- public string ContentType {
- get {
- return content_type;
- }
- set {
- content_type = value;
- }
- }
- public string Charset {
- get {
- if (charset == null)
- charset = ContentEncoding.WebName;
-
- return charset;
- }
- set {
- charset_set = true;
- charset = value;
- }
- }
-
- public HttpCookieCollection Cookies {
- get {
- if (cookies == null)
- cookies = new HttpCookieCollection (true, false);
- return cookies;
- }
- }
-
- public int Expires {
- get {
- if (cache_policy == null)
- return 0;
- return cache_policy.ExpireMinutes ();
- }
- set {
- Cache.SetExpires (DateTime.Now + new TimeSpan (0, value, 0));
- }
- }
-
- public DateTime ExpiresAbsolute {
- get {
- return Cache.Expires;
- }
- set {
- Cache.SetExpires (value);
- }
- }
- public Stream Filter {
- get {
- if (WorkerRequest == null)
- return null;
- return output_stream.Filter;
- }
- set {
- output_stream.Filter = value;
- }
- }
- #if NET_2_0
- public Encoding HeaderEncoding {
- get {
- if (headerEncoding == null) {
- GlobalizationSection gs = WebConfigurationManager.SafeGetSection ("system.web/globalization", typeof (GlobalizationSection)) as GlobalizationSection;
- if (gs == null)
- headerEncoding = Encoding.UTF8;
- else {
- headerEncoding = gs.ResponseHeaderEncoding;
- if (headerEncoding == Encoding.Unicode)
- throw new HttpException ("HeaderEncoding must not be Unicode");
- }
- }
- return headerEncoding;
- }
- set {
- if (headers_sent)
- throw new HttpException ("headers have already been sent");
- if (value == null)
- throw new ArgumentNullException ("HeaderEncoding");
- if (value == Encoding.Unicode)
- throw new HttpException ("HeaderEncoding must not be Unicode");
- headerEncoding = value;
- }
- }
- public
- #else
- internal
- #endif
- NameValueCollection Headers {
- get {
- if (headers == null)
- headers = new NameValueCollection ();
- return headers;
- }
- }
-
- public bool IsClientConnected {
- get {
- if (WorkerRequest == null)
- return true; // yep that's true
- return WorkerRequest.IsClientConnected ();
- }
- }
- #if NET_2_0
- public bool IsRequestBeingRedirected {
- get { return is_request_being_redirected; }
- }
- #endif
- public TextWriter Output {
- get {
- if (writer == null)
- writer = new HttpWriter (this);
- return writer;
- }
- }
- public Stream OutputStream {
- get {
- return output_stream;
- }
- }
-
- public string RedirectLocation {
- get {
- return redirect_location;
- }
- set {
- redirect_location = value;
- }
- }
-
- public string Status {
- get { return String.Concat (status_code.ToString (), " ", StatusDescription); }
- set {
- int p = value.IndexOf (' ');
- if (p == -1)
- throw new HttpException ("Invalid format for the Status property");
- string s = value.Substring (0, p);
-
- #if NET_2_0
- if (!Int32.TryParse (s, out status_code))
- throw new HttpException ("Invalid format for the Status property");
- #else
-
- try {
- status_code = Int32.Parse (s);
- } catch {
- throw new HttpException ("Invalid format for the Status property");
- }
- #endif
-
- status_description = value.Substring (p+1);
- }
- }
- public int StatusCode {
- get {
- return status_code;
- }
- set {
- if (headers_sent)
- throw new HttpException ("headers have already been sent");
-
- status_code = value;
- status_description = null;
- }
- }
- public string StatusDescription {
- get {
- if (status_description == null)
- status_description = HttpWorkerRequest.GetStatusDescription (status_code);
- return status_description;
- }
- set {
- if (headers_sent)
- throw new HttpException ("headers have already been sent");
-
- status_description = value;
- }
- }
-
- public bool SuppressContent {
- get {
- return suppress_content;
- }
- set {
- suppress_content = value;
- }
- }
- #if NET_2_0
- [MonoTODO ("Not implemented")]
- public void AddCacheDependency (CacheDependency[] dependencies)
- {
- throw new NotImplementedException ();
- }
- [MonoTODO ("Not implemented")]
- public void AddCacheItemDependencies (string[] cacheKeys)
- {
- throw new NotImplementedException ();
- }
- #endif
- [MonoTODO("Currently does nothing")]
- public void AddCacheItemDependencies (ArrayList cacheKeys)
- {
- // TODO: talk to jackson about the cache
- }
- [MonoTODO("Currently does nothing")]
- public void AddCacheItemDependency (string cacheKey)
- {
- // TODO: talk to jackson about the cache
- }
-
- public void AddFileDependencies (ArrayList filenames)
- {
- if (filenames == null || filenames.Count == 0)
- return;
- FileDependenciesArray.AddRange (filenames);
- }
- #if NET_2_0
- public void AddFileDependencies (string[] filenames)
- {
- if (filenames == null || filenames.Length == 0)
- return;
- FileDependenciesArray.AddRange (filenames);
- }
- #endif
- public void AddFileDependency (string filename)
- {
- if (filename == null || filename == String.Empty)
- return;
- FileDependenciesArray.Add (filename);
- }
- public void AddHeader (string name, string value)
- {
- AppendHeader (name, value);
- }
- public void AppendCookie (HttpCookie cookie)
- {
- Cookies.Add (cookie);
- }
- //
- // AppendHeader:
- // Special case for Content-Length, Content-Type, Transfer-Encoding and Cache-Control
- //
- //
- public void AppendHeader (string name, string value)
- {
- if (headers_sent)
- throw new HttpException ("headers have been already sent");
-
- #if !TARGET_J2EE
- if (String.Compare (name, "content-length", true, CultureInfo.InvariantCulture) == 0){
- content_length = (long) UInt64.Parse (value);
- use_chunked = false;
- return;
- }
- #endif
- if (String.Compare (name, "content-type", true, CultureInfo.InvariantCulture) == 0){
- ContentType = value;
- return;
- }
- #if !TARGET_J2EE
- if (String.Compare (name, "transfer-encoding", true, CultureInfo.InvariantCulture) == 0){
- transfer_encoding = value;
- use_chunked = false;
- return;
- }
- #endif
- if (String.Compare (name, "cache-control", true, CultureInfo.InvariantCulture) == 0){
- user_cache_control = value;
- return;
- }
- headers.Add (name, value);
- }
- [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
- public void AppendToLog (string param)
- {
- Console.Write ("System.Web: ");
- Console.WriteLine (param);
- }
-
- public string ApplyAppPathModifier (string virtualPath)
- {
- if (virtualPath == null)
- return null;
-
- if (virtualPath.Length == 0)
- return context.Request.RootVirtualDir;
- if (UrlUtils.IsRelativeUrl (virtualPath)) {
- virtualPath = UrlUtils.Combine (context.Request.RootVirtualDir, virtualPath);
- } else if (UrlUtils.IsRooted (virtualPath)) {
- virtualPath = UrlUtils.Canonic (virtualPath);
- }
- bool cookieless = false;
- #if NET_2_0
- SessionStateSection config = WebConfigurationManager.GetWebApplicationSection ("system.web/sessionState") as SessionStateSection;
- cookieless = SessionStateModule.IsCookieLess (context, config);
- #else
- SessionConfig config = HttpContext.GetAppConfig ("system.web/sessionState") as SessionConfig;
- cookieless = config.CookieLess;
- #endif
- if (!cookieless)
- return virtualPath;
- if (app_path_mod != null && virtualPath.IndexOf (app_path_mod) < 0) {
- if (UrlUtils.HasSessionId (virtualPath))
- virtualPath = UrlUtils.RemoveSessionId (VirtualPathUtility.GetDirectory (virtualPath), virtualPath);
- return UrlUtils.InsertSessionId (app_path_mod, virtualPath);
- }
-
- return virtualPath;
- }
- public void BinaryWrite (byte [] buffer)
- {
- output_stream.Write (buffer, 0, buffer.Length);
- }
- internal void BinaryWrite (byte [] buffer, int start, int len)
- {
- output_stream.Write (buffer, start, len);
- }
- public void Clear ()
- {
- ClearContent ();
- }
- public void ClearContent ()
- {
- output_stream.Clear ();
- content_length = -1;
- }
- public void ClearHeaders ()
- {
- if (headers_sent)
- throw new HttpException ("headers have been already sent");
- // Reset the special case headers.
- content_length = -1;
- content_type = "text/html";
- transfer_encoding = null;
- user_cache_control = null;
- if (headers != null)
- headers.Clear ();
- }
- internal bool HeadersSent {
- get {
- return headers_sent;
- }
- }
- public void Close ()
- {
- if (closed)
- return;
- if (WorkerRequest != null)
- WorkerRequest.CloseConnection ();
- closed = true;
- }
- #if NET_2_0
- public void DisableKernelCache ()
- {
- // does nothing in Mono
- }
- #endif
-
- public void End ()
- {
- if (context == null)
- return;
-
- if (context.TimeoutPossible) {
- Thread.CurrentThread.Abort (FlagEnd.Value);
- } else {
- // If this is called from an async event, signal the completion
- // but don't throw.
- HttpApplication app_instance = context.ApplicationInstance;
- if (app_instance != null)
- app_instance.CompleteRequest ();
- }
- }
- // Generate:
- // Content-Length
- // Content-Type
- // Transfer-Encoding (chunked)
- // Cache-Control
- // X-AspNet-Version
- void AddHeadersNoCache (NameValueCollection write_headers, bool final_flush)
- {
- #if !TARGET_J2EE
- //
- // Transfer-Encoding
- //
- if (use_chunked)
- write_headers.Add ("Transfer-Encoding", "chunked");
- else if (transfer_encoding != null)
- write_headers.Add ("Transfer-Encoding", transfer_encoding);
- #endif
- if (redirect_location != null)
- write_headers.Add ("Location", redirect_location);
-
- #if !TARGET_J2EE
- if (version_header != null)
- write_headers.Add ("X-AspNet-Version", version_header);
- //
- // If Content-Length is set.
- //
- if (content_length >= 0) {
- write_headers.Add (HttpWorkerRequest.GetKnownResponseHeaderName (HttpWorkerRequest.HeaderContentLength),
- content_length.ToString (CultureInfo.InvariantCulture));
- } else if (BufferOutput) {
- if (final_flush) {
- //
- // If we are buffering and this is the last flush, not a middle-flush,
- // we know the content-length.
- //
- content_length = output_stream.total;
- write_headers.Add (HttpWorkerRequest.GetKnownResponseHeaderName (HttpWorkerRequest.HeaderContentLength),
- content_length.ToString (CultureInfo.InvariantCulture));
- } else {
- //
- // We are buffering, and this is a flush in the middle.
- // If we are not chunked, we need to set "Connection: close".
- //
- if (use_chunked){
- write_headers.Add (HttpWorkerRequest.GetKnownResponseHeaderName (HttpWorkerRequest.HeaderConnection), "close");
- }
- }
- } else {
- //
- // If the content-length is not set, and we are not buffering, we must
- // close at the end.
- //
- if (use_chunked){
- write_headers.Add (HttpWorkerRequest.GetKnownResponseHeaderName (HttpWorkerRequest.HeaderConnection), "close");
- }
- }
- #endif
- //
- // Cache Control, the cache policy takes precedence over the cache_control property.
- //
- if (cache_policy != null)
- cache_policy.SetHeaders (this, headers);
- else
- write_headers.Add ("Cache-Control", CacheControl);
-
- //
- // Content-Type
- //
- if (content_type != null){
- string header = content_type;
- if (charset_set || header == "text/plain" || header == "text/html") {
- if (header.IndexOf ("charset=") == -1) {
- if (charset == null || charset == "")
- charset = ContentEncoding.HeaderName;
- header += "; charset=" + charset;
- }
- }
-
- write_headers.Add ("Content-Type", header);
- }
- if (cookies != null && cookies.Count != 0){
- int n = cookies.Count;
- for (int i = 0; i < n; i++)
- write_headers.Add ("Set-Cookie", cookies.Get (i).GetCookieHeaderValue ());
- #if TARGET_J2EE
- // For J2EE Portal support emulate cookies by storing them in the session.
- context.Request.SetSessionCookiesForPortal (cookies);
- #endif
- }
- }
- internal void WriteHeaders (bool final_flush)
- {
- if (headers_sent)
- return;
- //
- // Flush
- //
- if (context != null) {
- HttpApplication app_instance = context.ApplicationInstance;
- if (app_instance != null)
- app_instance.TriggerPreSendRequestHeaders ();
- }
- headers_sent = true;
- if (cached_response != null)
- cached_response.SetHeaders (headers);
- // If this page is cached use the cached headers
- // instead of the standard headers
- NameValueCollection write_headers;
- if (cached_headers != null)
- write_headers = cached_headers;
- else {
- write_headers = Headers;
- AddHeadersNoCache (write_headers, final_flush);
- }
-
- if (WorkerRequest != null)
- WorkerRequest.SendStatus (status_code, StatusDescription);
- if (WorkerRequest != null) {
- string header_name;
- string[] values;
-
- for (int i = 0; i < write_headers.Count; i++) {
- header_name = write_headers.GetKey (i);
- values = write_headers.GetValues (i);
- if (values == null)
- continue;
-
- foreach (string val in values)
- WorkerRequest.SendUnknownResponseHeader (header_name, val);
- }
- }
- }
- internal void DoFilter (bool close)
- {
- if (output_stream.HaveFilter && context != null && context.Error == null)
- output_stream.ApplyFilter (close);
- }
- internal void Flush (bool final_flush)
- {
- DoFilter (final_flush);
- if (!headers_sent){
- if (final_flush || status_code != 200)
- use_chunked = false;
- }
- bool head = ((context != null) && (context.Request.HttpMethod == "HEAD"));
- if (suppress_content || head) {
- if (!headers_sent)
- WriteHeaders (true);
- output_stream.Clear ();
- if (WorkerRequest != null)
- output_stream.Flush (WorkerRequest, true); // ignore final_flush here.
- return;
- }
- if (!headers_sent)
- WriteHeaders (final_flush);
- if (context != null) {
- HttpApplication app_instance = context.ApplicationInstance;
- if (app_instance != null)
- app_instance.TriggerPreSendRequestContent ();
- }
- if (IsCached) {
- MemoryStream ms = output_stream.GetData ();
- cached_response.ContentLength = (int) ms.Length;
- cached_response.SetData (ms.GetBuffer ());
- }
- if (WorkerRequest != null)
- output_stream.Flush (WorkerRequest, final_flush);
- }
- public void Flush ()
- {
- Flush (false);
- }
- public void Pics (string value)
- {
- AppendHeader ("PICS-Label", value);
- }
- public void Redirect (string url)
- {
- Redirect (url, true);
- }
- public void Redirect (string url, bool endResponse)
- {
- if (headers_sent)
- throw new HttpException ("Headers have already been sent");
- #if NET_2_0
- is_request_being_redirected = true;
- #endif
- ClearHeaders ();
- ClearContent ();
-
- StatusCode = 302;
- url = ApplyAppPathModifier (url);
- redirect_location = url;
- // Text for browsers that can't handle location header
- Write ("<html><head><title>Object moved</title></head><body>\r\n");
- Write ("<h2>Object moved to <a href=\"" + url + "\">here</a></h2>\r\n");
- Write ("</body><html>\r\n");
-
- if (endResponse)
- End ();
- #if NET_2_0
- is_request_being_redirected = false;
- #endif
- }
- public static void RemoveOutputCacheItem (string path)
- {
- if (path == null)
- throw new ArgumentNullException ("path");
- if (path.Length == 0)
- return;
- if (path [0] != '/')
- throw new ArgumentException ("'" + path + "' is not an absolute virtual path.");
- HttpRuntime.InternalCache.Remove (path);
- }
- public void SetCookie (HttpCookie cookie)
- {
- AppendCookie (cookie);
- }
- public void Write (char ch)
- {
- Output.Write (ch);
- }
- public void Write (object obj)
- {
- if (obj == null)
- return;
-
- Output.Write (obj.ToString ());
- }
-
- public void Write (string s)
- {
- Output.Write (s);
- }
-
- public void Write (char [] buffer, int index, int count)
- {
- Output.Write (buffer, index, count);
- }
- internal void WriteFile (FileStream fs, long offset, long size)
- {
- byte [] buffer = new byte [32*1024];
- if (offset != 0)
- fs.Position = offset;
- long remain = size;
- int n;
- while (remain > 0 && (n = fs.Read (buffer, 0, (int) Math.Min (remain, 32*1024))) != 0){
- remain -= n;
- output_stream.Write (buffer, 0, n);
- }
- }
-
- public void WriteFile (string filename)
- {
- WriteFile (filename, false);
- }
- public void WriteFile (string filename, bool readIntoMemory)
- {
- if (filename == null)
- throw new ArgumentNullException ("filename");
- if (readIntoMemory){
- using (FileStream fs = File.OpenRead (filename))
- WriteFile (fs, 0, fs.Length);
- } else {
- FileInfo fi = new FileInfo (filename);
- output_stream.WriteFile (filename, 0, fi.Length);
- }
- if (buffer)
- return;
- output_stream.ApplyFilter (false);
- Flush ();
- }
- #if TARGET_JVM
- public void WriteFile (IntPtr fileHandle, long offset, long size) {
- throw new PlatformNotSupportedException("IntPtr not supported");
- }
- #else
- public void WriteFile (IntPtr fileHandle, long offset, long size)
- {
- if (offset < 0)
- throw new ArgumentNullException ("offset can not be negative");
- if (size < 0)
- throw new ArgumentNullException ("size can not be negative");
- if (size == 0)
- return;
- // Note: this .ctor will throw a SecurityException if the caller
- // doesn't have the UnmanagedCode permission
- using (FileStream fs = new FileStream (fileHandle, FileAccess.Read))
- WriteFile (fs, offset, size);
- if (buffer)
- return;
- output_stream.ApplyFilter (false);
- Flush ();
- }
- #endif
- public void WriteFile (string filename, long offset, long size)
- {
- if (filename == null)
- throw new ArgumentNullException ("filename");
- if (offset < 0)
- throw new ArgumentNullException ("offset can not be negative");
- if (size < 0)
- throw new ArgumentNullException ("size can not be negative");
- if (size == 0)
- return;
-
- FileStream fs = File.OpenRead (filename);
- WriteFile (fs, offset, size);
- if (buffer)
- return;
- output_stream.ApplyFilter (false);
- Flush ();
- }
- #if NET_2_0
- [MonoTODO ("Not implemented")]
- public void WriteSubstitution (HttpResponseSubstitutionCallback callback)
- {
- throw new NotImplementedException ();
- }
- #endif
- //
- // Like WriteFile, but never buffers, so we manually Flush here
- //
- public void TransmitFile (string filename)
- {
- if (filename == null)
- throw new ArgumentNullException ("filename");
- TransmitFile (filename, false);
- }
- internal void TransmitFile (string filename, bool final_flush)
- {
- FileInfo fi = new FileInfo (filename);
- using (Stream s = fi.OpenRead ()); // Just check if we can read.
- output_stream.WriteFile (filename, 0, fi.Length);
- output_stream.ApplyFilter (final_flush);
- Flush (final_flush);
- }
- #if NET_2_0
- public void TransmitFile (string filename, long offset, long length)
- {
- output_stream.WriteFile (filename, offset, length);
- output_stream.ApplyFilter (false);
- Flush (false);
- }
-
- internal void TransmitFile (VirtualFile vf)
- {
- TransmitFile (vf, false);
- }
- const int bufLen = 65535;
- internal void TransmitFile (VirtualFile vf, bool final_flush)
- {
- if (vf == null)
- throw new ArgumentNullException ("vf");
- if (vf is DefaultVirtualFile) {
- TransmitFile (HostingEnvironment.MapPath (vf.VirtualPath), final_flush);
- return;
- }
-
- byte[] buf = new byte [bufLen];
- using (Stream s = vf.Open ()) {
- int readBytes;
- while ((readBytes = s.Read (buf, 0, bufLen)) > 0) {
- output_stream.Write (buf, 0, readBytes);
- output_stream.ApplyFilter (final_flush);
- Flush (false);
- }
- if (final_flush)
- Flush (true);
- }
- }
- #endif
-
- #region Session state support
- internal void SetAppPathModifier (string app_modifier)
- {
- app_path_mod = app_modifier;
- }
- #endregion
-
- #region Cache Support
- internal void SetCachedHeaders (NameValueCollection headers)
- {
- cached_headers = headers;
-
- }
- internal bool IsCached {
- get { return cached_response != null; }
- set {
- if (value)
- cached_response = new CachedRawResponse (cache_policy);
- else
- cached_response = null;
- }
- }
- public HttpCachePolicy Cache {
- get {
- if (cache_policy == null)
- cache_policy = new HttpCachePolicy ();
-
- return cache_policy;
- }
- }
- internal CachedRawResponse GetCachedResponse ()
- {
- if (cached_response != null) {
- cached_response.StatusCode = StatusCode;
- cached_response.StatusDescription = StatusDescription;
- }
-
- return cached_response;
- }
- //
- // This is one of the old ASP compatibility methods, the real cache
- // control is in the Cache property, and this is a second class citizen
- //
- public string CacheControl {
- set {
- if (value == null || value == "") {
- Cache.SetCacheability (HttpCacheability.NoCache);
- user_cache_control = null;
- } else if (String.Compare (value, "public", true, CultureInfo.InvariantCulture) == 0) {
- Cache.SetCacheability (HttpCacheability.Public);
- user_cache_control = "public";
- } else if (String.Compare (value, "private", true, CultureInfo.InvariantCulture) == 0) {
- Cache.SetCacheability (HttpCacheability.Private);
- user_cache_control = "private";
- } else if (String.Compare (value, "no-cache", true, CultureInfo.InvariantCulture) == 0) {
- Cache.SetCacheability (HttpCacheability.NoCache);
- user_cache_control = "no-cache";
- } else
- throw new ArgumentException ("CacheControl property only allows `public', " +
- "`private' or no-cache, for different uses, use " +
- "Response.AppendHeader");
- }
- get { return (user_cache_control != null) ? user_cache_control : "private"; }
- }
- #endregion
- internal int GetOutputByteCount ()
- {
- return output_stream.GetTotalLength ();
- }
- internal void ReleaseResources ()
- {
- output_stream.ReleaseResources (true);
- output_stream = null;
- }
- }
- #if TARGET_J2EE
- public
- #endif
- static class FlagEnd
- {
- public static readonly object Value = new object ();
- }
- }
|