2010-06-30 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpServerUtility.cs
index f285b238fe204d6f75aea912c92cf6997973b87a..58b5caeee32c92461ed37e99be82e73eef09a71a 100644 (file)
@@ -8,7 +8,7 @@
 //
 
 //
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2010 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
@@ -36,9 +36,12 @@ using System.Web.Util;
 using System.Collections.Specialized;
 using System.Security.Permissions;
 using System.Text;
+using System.Threading;
+using System.Web.Configuration;
+using System.Web.SessionState;
 
-namespace System.Web {
-
+namespace System.Web
+{
        //
        // Methods exposed through HttpContext.Server property
        //
@@ -86,19 +89,17 @@ namespace System.Web {
                        Execute (path, writer, true);
                }
 
-#if NET_2_0
                public void Execute (string path, bool preserveForm)
                {
                        Execute (path, null, preserveForm);
                }
-#endif
-               
-#if NET_2_0
-               public
-#else
-               internal
-#endif
-               void Execute (string path, TextWriter writer, bool preserveForm)
+
+               public void Execute (string path, TextWriter writer, bool preserveForm)
+               {                       
+                       Execute (path, writer, preserveForm, false);
+               }
+
+               void Execute (string path, TextWriter writer, bool preserveForm, bool isTransfer)
                {
                        if (path == null)
                                throw new ArgumentNullException ("path");
@@ -106,56 +107,90 @@ namespace System.Web {
                        if (path.IndexOf (':') != -1)
                                throw new ArgumentException ("Invalid path.");
 
-                       HttpRequest request = context.Request;
-                       string oldQuery = request.QueryStringRaw;
+                       string queryString = null;
                        int qmark = path.IndexOf ('?');
                        if (qmark != -1) {
-                               request.QueryStringRaw = path.Substring (qmark + 1);
+                               queryString = path.Substring (qmark + 1);
                                path = path.Substring (0, qmark);
+                       }
+
+                       string exePath = UrlUtils.Combine (context.Request.BaseVirtualDir, path);
+                       bool cookieless = false;
+                       SessionStateSection config = WebConfigurationManager.GetWebApplicationSection ("system.web/sessionState") as SessionStateSection;
+                       cookieless = SessionStateModule.IsCookieLess (context, config);
+                       
+                       if (cookieless)
+                               exePath = UrlUtils.RemoveSessionId (VirtualPathUtility.GetDirectory (exePath), exePath);
+                       
+                       IHttpHandler handler = context.ApplicationInstance.GetHandler (context, exePath, true);
+                       Execute (handler, writer, preserveForm, exePath, queryString, isTransfer, true);
+               }
+
+               internal void Execute (IHttpHandler handler, TextWriter writer, bool preserveForm, string exePath, string queryString, bool isTransfer, bool isInclude)
+               {
+#if !TARGET_J2EE
+                       // If the target handler is not Page, the transfer must not occur.
+                       // InTransit == true means we're being called from Transfer
+                       bool is_static = (handler is StaticFileHandler);
+                       if (isTransfer && !(handler is Page) && !is_static)
+                               throw new HttpException ("Transfer is only allowed to .aspx and static files");
+#endif
+
+                       HttpRequest request = context.Request;
+                       string oldQuery = request.QueryStringRaw;
+                       if (queryString != null) {
+                               request.QueryStringRaw = queryString;
                        } else if (!preserveForm) {
-                               request.QueryStringRaw = "";
+                               request.QueryStringRaw = String.Empty;
                        }
 
                        HttpResponse response = context.Response;
-                       WebROCollection oldForm = null;
+                       WebROCollection oldForm = request.Form as WebROCollection;
                        if (!preserveForm) {
-                               oldForm = request.Form as WebROCollection;
                                request.SetForm (new WebROCollection ());
                        }
 
                        TextWriter output = writer;
                        if (output == null)
                                output = response.Output;
-
-                       string oldFilePath = request.FilePath;
-                       request.SetCurrentExePath (UrlUtils.Combine (request.BaseVirtualDir, path));
-                       IHttpHandler handler = context.ApplicationInstance.GetHandler (context);
-                       TextWriter previous = null;
+                       
+                       TextWriter previous = response.SetTextWriter (output);
+                       string oldExePath = request.CurrentExecutionFilePath;
+                       bool oldIsInclude = context.IsProcessingInclude;
                        try {
-#if NET_2_0
                                context.PushHandler (handler);
-#endif
-                               previous = response.SetTextWriter (output);
+                               if (is_static) // Not sure if this should apply to Page too
+                                       request.SetFilePath (exePath);
+
+                               request.SetCurrentExePath (exePath);
+                               context.IsProcessingInclude = isInclude;
+                               
                                if (!(handler is IHttpAsyncHandler)) {
                                        handler.ProcessRequest (context);
                                } else {
                                        IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler) handler;
                                        IAsyncResult ar = asyncHandler.BeginProcessRequest (context, null, null);
-                                       ar.AsyncWaitHandle.WaitOne ();
+                                       WaitHandle asyncWaitHandle = ar != null ? ar.AsyncWaitHandle : null;
+                                       if (asyncWaitHandle != null)
+                                               asyncWaitHandle.WaitOne ();
                                        asyncHandler.EndProcessRequest (ar);
                                }
                        } finally {
-                               request.SetCurrentExePath (oldFilePath);
-                               if (oldQuery != null && oldQuery != "" && oldQuery != request.QueryStringRaw) {
-                                       oldQuery = oldQuery.Substring (1); // Ignore initial '?'
-                                       request.QueryStringRaw = oldQuery; // which is added here.
+                               if (oldQuery != request.QueryStringRaw) {
+                                       if (oldQuery != null && oldQuery.Length > 0) {
+                                               oldQuery = oldQuery.Substring (1); // Ignore initial '?'
+                                               request.QueryStringRaw = oldQuery; // which is added here.
+                                       } else
+                                               request.QueryStringRaw = String.Empty;
                                }
+                               
                                response.SetTextWriter (previous);
                                if (!preserveForm)
                                        request.SetForm (oldForm);
-#if NET_2_0
+
                                context.PopHandler ();
-#endif
+                               request.SetCurrentExePath (oldExePath);
+                               context.IsProcessingInclude = oldIsInclude;
                        }
                }
 
@@ -191,25 +226,33 @@ namespace System.Web {
                        return context.Request.MapPath (path);
                }
 
-               public void Transfer (string path)
+               
+               public void TransferRequest (string path)
                {
-                       // If it's a page and a postback, don't pass form data
-                       // See bug #65613.
-                       bool preserveForm = true;
-                       if (context.Handler is Page) {
-                               Page page = (Page) context.Handler;
-                               preserveForm = !page.IsPostBack;
-                       }
-
-                       Transfer (path, preserveForm);
+                       TransferRequest (path, false, null, null);
+               }
+               
+               public void TransferRequest (string path, bool preserveForm)
+               {
+                       TransferRequest (path, preserveForm, null, null);
                }
 
-               public void Transfer (string path, bool preserveForm)
+               [MonoTODO ("Always throws PlatformNotSupportedException.")]
+               public void TransferRequest (string path, bool preserveForm, string method, NameValueCollection headers)
                {
-                       Execute (path, null, preserveForm);
+                       throw new PlatformNotSupportedException ();
+               }
+               
+               public void Transfer (string path)
+               {
+                       Transfer (path, true);
+               }
+
+               public void Transfer (string path, bool preserveForm) {
+                       Execute (path, null, preserveForm, true);
                        context.Response.End ();
                }
-#if NET_2_0
+
                public void Transfer (IHttpHandler handler, bool preserveForm)
                {
                        if (handler == null)
@@ -218,8 +261,7 @@ namespace System.Web {
                        // TODO: see the MS doc and search for "enableViewStateMac": this method is not
                        // allowed for pages when preserveForm is true and the page IsCallback property
                        // is true.
-
-                       Execute (handler, null, preserveForm);
+                       Execute (handler, null, preserveForm, context.Request.CurrentExecutionFilePath, null, true, true);
                        context.Response.End ();
                }
 
@@ -228,43 +270,7 @@ namespace System.Web {
                        if (handler == null)
                                throw new ArgumentNullException ("handler");
 
-                       HttpRequest request = context.Request;
-                       string oldQuery = request.QueryStringRaw;
-                       if (!preserveForm) {
-                               request.QueryStringRaw = "";
-                       }
-
-                       HttpResponse response = context.Response;
-                       WebROCollection oldForm = null;
-                       if (!preserveForm) {
-                               oldForm = request.Form as WebROCollection;
-                               request.SetForm (new WebROCollection ());
-                       }
-
-                       TextWriter output = writer;
-                       if (output == null)
-                               output = response.Output;
-
-                       TextWriter previous = null;
-                       try {
-                               previous = response.SetTextWriter (output);
-                               if (!(handler is IHttpAsyncHandler)) {
-                                       handler.ProcessRequest (context);
-                               } else {
-                                       IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler) handler;
-                                       IAsyncResult ar = asyncHandler.BeginProcessRequest (context, null, null);
-                                       ar.AsyncWaitHandle.WaitOne ();
-                                       asyncHandler.EndProcessRequest (ar);
-                               }
-                       } finally {
-                               if (oldQuery != null && oldQuery != "" && oldQuery != request.QueryStringRaw) {
-                                       oldQuery = oldQuery.Substring (1); // Ignore initial '?'
-                                       request.QueryStringRaw = oldQuery; // which is added here.
-                               }
-                               response.SetTextWriter (previous);
-                               if (!preserveForm)
-                                       request.SetForm (oldForm);
-                       }
+                       Execute (handler, writer, preserveForm, context.Request.CurrentExecutionFilePath, null, false, true);
                }
 
                public static byte[] UrlTokenDecode (string input)
@@ -346,28 +352,35 @@ namespace System.Web {
                        }
                        return new string (chars);
                }
-#endif
 
                public string UrlDecode (string s)
                {
-                       return HttpUtility.UrlDecode (s);
+                       HttpRequest request = context.Request;
+                       if(request != null)
+                               return HttpUtility.UrlDecode (s, request.ContentEncoding);
+                       else
+                               return HttpUtility.UrlDecode (s);
                }
 
                public void UrlDecode (string s, TextWriter output)
                {
                        if (s != null)
-                               output.Write (HttpUtility.UrlDecode (s));
+                               output.Write (UrlDecode (s));
                }
 
                public string UrlEncode (string s)
                {
-                       return HttpUtility.UrlEncode (s);
+                       HttpResponse response = context.Response;
+                       if (response != null)
+                               return HttpUtility.UrlEncode (s, response.ContentEncoding);
+                       else
+                               return HttpUtility.UrlEncode (s);
                }
 
                public void UrlEncode (string s, TextWriter output)
                {
                        if (s != null)
-                               output.Write (HttpUtility.UrlEncode (s));
+                               output.Write (UrlEncode (s));
                }
 
                public string UrlPathEncode (string s)
@@ -375,10 +388,10 @@ namespace System.Web {
                        if (s == null)
                                return null;
 
-                       int idx = s.IndexOf ("?");
+                       int idx = s.IndexOf ('?');
                        string s2 = null;
                        if (idx != -1) {
-                               s2 = s.Substring (0, idx-1);
+                               s2 = s.Substring (0, idx);
                                s2 = HttpUtility.UrlEncode (s2) + s.Substring (idx);
                        } else {
                                s2 = HttpUtility.UrlEncode (s);
@@ -398,7 +411,7 @@ namespace System.Web {
                public int ScriptTimeout {
                        get { return (int) context.ConfigTimeout.TotalSeconds; }
                        [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Medium)]
-                       set { context.ConfigTimeout = new TimeSpan (0, 0, value); }
+                       set { context.ConfigTimeout = TimeSpan.FromSeconds (value); }
                }
        }
 }