2007-07-21 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Hosting / ApplicationHost.cs
index 43220e0120580dee9ca3ebe4fe89e37797ab1fc3..0159bbb4fe22253e3e1e36c25dc42189bb579c91 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
 using System.IO;
+using System.Security.Permissions;
 using System.Security.Policy;
 
 namespace System.Web.Hosting {
 
+       // CAS - no InheritanceDemand here as the class is sealed
+       [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        public sealed class ApplicationHost {
 
-               static string [] types = { "Web.config", "web.config" };
+               static string [] types = { "Web.config", "Web.Config", "web.config" };
 
                private ApplicationHost ()
                {
@@ -55,38 +57,101 @@ namespace System.Web.Hosting {
                        return r;
                }
 
+#if NET_2_0
+               static object create_dir = new object ();
+#endif
+
+               internal static bool ClearDynamicBaseDirectory (string directory)
+               {
+                       string[] entries = null;
+                       
+                       try {
+                               entries = Directory.GetDirectories (directory);
+                       } catch {
+                               // ignore
+                       }
+
+                       bool dirEmpty = true;
+                       if (entries != null && entries.Length > 0) {
+                               foreach (string e in entries) {
+                                       if (ClearDynamicBaseDirectory (e)) {
+                                               try {
+                                                       Directory.Delete (e);
+                                               } catch {
+                                                       dirEmpty = false;
+                                               }
+                                       }
+                               }
+                       }
+
+                       try {
+                               entries = Directory.GetFiles (directory);
+                       } catch {
+                               entries = null;
+                       }
+
+                       if (entries != null && entries.Length > 0) {
+                               foreach (string e in entries) {
+                                       try {
+                                               File.Delete (e);
+                                       } catch {
+                                               dirEmpty = false;
+                                       }
+                               }
+                       }
+
+                       return dirEmpty;
+               }
+               
+               static bool CreateDirectory (string directory)
+               {
+#if NET_2_0
+                       lock (create_dir) {
+#endif
+                               if (!Directory.Exists (directory)) {
+                                       Directory.CreateDirectory (directory);
+                                       return false;
+                               } else
+                                       return true;
+#if NET_2_0
+                       }
+#endif
+               }
+
+               static string GetBinPath (string physicalDir)
+               {
+                       string ret = Path.Combine (physicalDir, "Bin");
+                       if (Directory.Exists (ret))
+                               return ret;
+                       ret = Path.Combine (physicalDir, "bin");
+                       return ret;
+               }
+               
                //
-               // For furthe details see `Hosting the ASP.NET runtime'
+               // For further details see `Hosting the ASP.NET runtime'
                //
                //    http://www.west-wind.com/presentations/aspnetruntime/aspnetruntime.asp
                // 
+#if TARGET_JVM
+               [MonoNotSupported ("")]
+#endif
+               [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
                public static object CreateApplicationHost (Type hostType, string virtualDir, string physicalDir)
                {
                        if (physicalDir == null)
                                throw new NullReferenceException ();
 
-#pragma warning disable 219
-                       //
-                       // This is done just for validation: it might throw an exception
-                       //
-                       Uri u = new Uri (physicalDir);
-#pragma warning restore 219 
+                       // Make sure physicalDir has file system semantics
+                       // and not uri semantics ( '\' and not '/' ).
+                       physicalDir = Path.GetFullPath (physicalDir);
 
                        if (hostType == null)
-                               throw new NullReferenceException ();
+                               throw new ArgumentException ("hostType can't be null");
 
                        if (virtualDir == null)
-                               throw new NullReferenceException ();
-
-                       if (hostType == null || virtualDir == null || physicalDir == null)
-                               throw new NullReferenceException ();
+                               throw new ArgumentNullException ("virtualDir");
 
                        Evidence evidence = new Evidence (AppDomain.CurrentDomain.Evidence);
-
-                       // 
-                       // Unique Domain ID
-                       //
-                       string domain_id = "ASPHOST_" + DateTime.Now.ToString().GetHashCode().ToString("x");
                        
                        //
                        // Setup
@@ -98,11 +163,43 @@ namespace System.Web.Hosting {
                        setup.CachePath = null;
                        setup.ConfigurationFile = FindWebConfig (physicalDir);
                        setup.DisallowCodeDownload = true;
-                       setup.PrivateBinPath = "bin";
+                       string bin_path = GetBinPath (physicalDir);
+                       setup.PrivateBinPath = bin_path;
                        setup.PrivateBinPathProbe = "*";
                        setup.ShadowCopyFiles = "true";
-                       UriBuilder b = new UriBuilder ("file://", null, 0, Path.Combine (physicalDir, "bin"));
-                       setup.ShadowCopyDirectories = b.Uri.ToString ();
+                       setup.ShadowCopyDirectories = bin_path;
+
+                       string dynamic_dir = null;
+                       string user = Environment.UserName;
+                       int tempDirTag = 0;
+                       
+                       for (int i = 0; ; i++){
+                               string d = Path.Combine (Path.GetTempPath (),
+                                       String.Format ("{0}-temp-aspnet-{1:x}", user, i));
+                       
+                               try {
+                                       CreateDirectory (d);
+                                       string stamp = Path.Combine (d, "stamp");
+                                       CreateDirectory (stamp);
+                                       dynamic_dir = d;
+                                       Directory.Delete (stamp);
+                                       tempDirTag = i.GetHashCode ();
+                                       break;
+                               } catch (UnauthorizedAccessException){
+                                       continue;
+                               }
+                       }
+                       // 
+                       // Unique Domain ID
+                       //
+                       string domain_id = (virtualDir.GetHashCode () ^ physicalDir.GetHashCode () ^ tempDirTag).ToString ("x");
+
+                       setup.ApplicationName = domain_id;
+                       setup.DynamicBase = dynamic_dir;
+
+                       string dynamic_base = setup.DynamicBase;
+                       if (CreateDirectory (dynamic_base) && (Environment.GetEnvironmentVariable ("MONO_ASPNET_NODELETE") == null))
+                               ClearDynamicBaseDirectory (dynamic_base);
 
                        //
                        // Create app domain
@@ -115,12 +212,17 @@ namespace System.Web.Hosting {
                        // few, but third party apps might use others:
                        //
                        appdomain.SetData (".appDomain", "*");
+                       int l = physicalDir.Length;
+                       if (physicalDir [l - 1] != Path.DirectorySeparatorChar)
+                               physicalDir += Path.DirectorySeparatorChar;
                        appdomain.SetData (".appPath", physicalDir);
                        appdomain.SetData (".appVPath", virtualDir);
                        appdomain.SetData (".domainId", domain_id);
                        appdomain.SetData (".hostingVirtualPath", virtualDir);
                        appdomain.SetData (".hostingInstallDir", Path.GetDirectoryName (typeof (Object).Assembly.CodeBase));
-
+#if NET_2_0
+                       appdomain.SetData ("DataDirectory", Path.Combine (physicalDir, "App_Data"));
+#endif
                        return appdomain.CreateInstanceAndUnwrap (hostType.Module.Assembly.FullName, hostType.FullName);
                }
        }