2 // System.Web.Configuration.WebConfigurationHost.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
32 using System.Collections;
34 using System.Security;
35 using System.Configuration;
36 using System.Configuration.Internal;
37 using System.Web.Hosting;
38 using System.Web.Util;
39 using System.Reflection;
42 * this class needs to be rewritten to support usage of the
43 * IRemoteWebConfigurationHostServer interface. Once that's done, we
44 * need an implementation of that interface that talks (through a web
45 * service?) to a remote site..
47 * for now, though, just implement it as we do
48 * System.Configuration.InternalConfigurationHost, i.e. the local
51 namespace System.Web.Configuration
53 class WebConfigurationHost: IInternalConfigHost
55 WebConfigurationFileMap map;
56 const string MachinePath = ":machine:";
57 const string MachineWebPath = ":web:";
59 public virtual object CreateConfigurationContext (string configPath, string locationSubPath)
61 return new WebContext (WebApplicationLevel.AtApplication /* XXX */,
63 "" /* application path XXX */,
68 public virtual object CreateDeprecatedConfigContext (string configPath)
70 throw new NotImplementedException ();
73 public virtual string DecryptSection (string encryptedXml, ProtectedConfigurationProvider protectionProvider,
74 ProtectedConfigurationSection protectedSection)
76 throw new NotImplementedException ();
79 public virtual void DeleteStream (string streamName)
81 File.Delete (streamName);
84 public virtual string EncryptSection (string encryptedXml, ProtectedConfigurationProvider protectionProvider,
85 ProtectedConfigurationSection protectedSection)
87 throw new NotImplementedException ();
90 public virtual string GetConfigPathFromLocationSubPath (string configPath, string locatinSubPath)
92 return configPath + "/" + locatinSubPath;
95 public virtual Type GetConfigType (string typeName, bool throwOnError)
97 Type type = HttpApplication.LoadType (typeName);
98 if (type == null && throwOnError)
99 throw new ConfigurationErrorsException ("Type not found: '" + typeName + "'");
103 public virtual string GetConfigTypeName (Type t)
105 return t.AssemblyQualifiedName;
108 public virtual void GetRestrictedPermissions (IInternalConfigRecord configRecord, out PermissionSet permissionSet,
109 out bool isHostReady)
111 throw new NotImplementedException ();
114 public virtual string GetStreamName (string configPath)
116 if (configPath == MachinePath) {
118 return System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile;
120 return map.MachineConfigFilename;
121 } else if (configPath == MachineWebPath) {
127 // check META-INF/web.config exists
128 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
131 java.net.URL url = cl.getResource ("META-INF/web.config");
135 return "/META-INF/web.config";
138 mdir = Path.GetDirectoryName (System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile);
141 mdir = Path.GetDirectoryName (map.MachineConfigFilename);
143 return GetWebConfigFileName (mdir);
146 string dir = MapPath (configPath);
147 return GetWebConfigFileName (dir);
150 public virtual string GetStreamNameForConfigSource (string streamName, string configSource)
152 throw new NotImplementedException ();
155 public virtual object GetStreamVersion (string streamName)
157 throw new NotImplementedException ();
160 public virtual IDisposable Impersonate ()
162 throw new NotImplementedException ();
165 public virtual void Init (IInternalConfigRoot root, params object[] hostInitParams)
169 public virtual void InitForConfiguration (ref string locationSubPath, out string configPath,
170 out string locationConfigPath, IInternalConfigRoot root,
171 params object[] hostInitConfigurationParams)
173 string fullPath = (string) hostInitConfigurationParams [1];
174 map = (WebConfigurationFileMap) hostInitConfigurationParams [0];
176 if (locationSubPath == MachineWebPath) {
177 locationSubPath = MachinePath;
178 configPath = MachineWebPath;
179 locationConfigPath = null;
180 } else if (locationSubPath == MachinePath) {
181 locationSubPath = null;
182 configPath = MachinePath;
183 locationConfigPath = null;
186 if (locationSubPath == null)
188 configPath = fullPath;
189 if (configPath.Length > 1)
190 configPath = VirtualPathUtility.RemoveTrailingSlash (configPath);
193 configPath = locationSubPath;
195 if (configPath == HttpRuntime.AppDomainAppVirtualPath
196 || configPath == "/")
199 i = configPath.LastIndexOf ("/");
202 locationConfigPath = configPath.Substring (i+1);
205 locationSubPath = "/";
207 locationSubPath = fullPath.Substring (0, i);
209 locationSubPath = MachineWebPath;
210 locationConfigPath = null;
215 public string MapPath (string virtualPath)
218 return MapPathFromMapper (virtualPath);
219 else if (HttpContext.Current != null && HttpContext.Current.Request != null)
220 return HttpContext.Current.Request.MapPath (virtualPath);
221 else if (HttpRuntime.AppDomainAppVirtualPath != null &&
222 virtualPath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) {
223 if (virtualPath == HttpRuntime.AppDomainAppVirtualPath)
224 return HttpRuntime.AppDomainAppPath;
225 return UrlUtils.Combine (HttpRuntime.AppDomainAppPath,
226 virtualPath.Substring (HttpRuntime.AppDomainAppVirtualPath.Length));
232 public string NormalizeVirtualPath (string virtualPath)
234 if (virtualPath == null || virtualPath.Length == 0)
237 virtualPath = virtualPath.Trim ();
239 if (virtualPath [0] == '~' && virtualPath.Length > 2 && virtualPath [1] == '/')
240 virtualPath = virtualPath.Substring (1);
242 if (System.IO.Path.DirectorySeparatorChar != '/')
243 virtualPath = virtualPath.Replace (System.IO.Path.DirectorySeparatorChar, '/');
245 if (UrlUtils.IsRooted (virtualPath)) {
246 virtualPath = UrlUtils.Canonic (virtualPath);
248 if (map.VirtualDirectories.Count > 0) {
249 string root = map.VirtualDirectories [0].VirtualDirectory;
250 virtualPath = UrlUtils.Combine (root, virtualPath);
251 virtualPath = UrlUtils.Canonic (virtualPath);
257 public string MapPathFromMapper (string virtualPath)
259 string path = NormalizeVirtualPath (virtualPath);
261 foreach (VirtualDirectoryMapping mapping in map.VirtualDirectories) {
262 if (path.StartsWith (mapping.VirtualDirectory)) {
263 int i = mapping.VirtualDirectory.Length;
264 if (path.Length == i) {
265 return mapping.PhysicalDirectory;
267 else if (path [i] == '/') {
268 string pathPart = path.Substring (i + 1).Replace ('/', Path.DirectorySeparatorChar);
269 return Path.Combine (mapping.PhysicalDirectory, pathPart);
273 throw new HttpException ("Invalid virtual directory: " + virtualPath);
276 string GetWebConfigFileName (string dir)
279 DirectoryInfo d = GetCaseSensitiveExistingDirectory (new DirectoryInfo (dir));
283 FileInfo file = (FileInfo) FindByName ("web.config", d.GetFiles ("W*"));
285 file = (FileInfo) FindByName ("web.config", d.GetFiles ("w*"));
288 return file.FullName;
290 AppDomain domain = AppDomain.CurrentDomain;
291 bool hosted = (domain.GetData (ApplicationHost.MonoHostedDataKey) as string) == "yes";
294 foreach (string fn in ApplicationHost.WebConfigFileNames) {
295 string file = Path.Combine (dir, fn);
296 if (File.Exists (file))
301 Assembly asm = Assembly.GetEntryAssembly () ?? Assembly.GetCallingAssembly ();
302 string name = Path.GetFileName (asm.Location);
303 string[] fileNames = new string[] {name + ".config", name + ".Config"};
304 string appDir = domain.BaseDirectory;
307 foreach (string fn in fileNames) {
308 file = Path.Combine (appDir, fn);
309 if (File.Exists (file))
317 static DirectoryInfo GetCaseSensitiveExistingDirectory (DirectoryInfo dir) {
323 DirectoryInfo parent = GetCaseSensitiveExistingDirectory (dir.Parent);
327 return (DirectoryInfo) FindByName (dir.Name, parent.GetDirectories ());
330 static FileSystemInfo FindByName (string name, FileSystemInfo [] infos)
332 for (int i = 0; i < infos.Length; i++) {
333 if (String.Compare (name, infos [i].Name, StringComparison.OrdinalIgnoreCase) == 0)
339 public virtual bool IsAboveApplication (string configPath)
341 throw new NotImplementedException ();
344 public virtual bool IsConfigRecordRequired (string configPath)
346 throw new NotImplementedException ();
349 public virtual bool IsDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
350 ConfigurationAllowExeDefinition allowExeDefinition)
352 switch (allowDefinition) {
353 case ConfigurationAllowDefinition.MachineOnly:
354 return configPath == MachinePath || configPath == MachineWebPath;
355 case ConfigurationAllowDefinition.MachineToWebRoot:
356 case ConfigurationAllowDefinition.MachineToApplication:
357 return configPath == MachinePath || configPath == MachineWebPath || configPath == "/" ||
358 configPath == HttpRuntime.AppDomainAppVirtualPath;
364 public virtual bool IsFile (string streamName)
366 throw new NotImplementedException ();
369 public virtual bool IsLocationApplicable (string configPath)
371 throw new NotImplementedException ();
374 public virtual Stream OpenStreamForRead (string streamName)
376 if (!File.Exists (streamName)) {
378 if (streamName != null && (streamName.EndsWith ("machine.config") ||
379 streamName.EndsWith ("web.config"))) {
380 if (streamName.StartsWith ("/"))
381 streamName = streamName.Substring (1);
382 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
384 java.io.InputStream inputStream = cl.getResourceAsStream (streamName);
385 return (Stream) vmw.common.IOUtils.getStream (inputStream);
389 throw new ConfigurationException ("File '" + streamName + "' not found");
392 return new FileStream (streamName, FileMode.Open, FileAccess.Read);
395 [MonoTODO ("Not implemented")]
396 public virtual Stream OpenStreamForRead (string streamName, bool assertPermissions)
398 throw new NotImplementedException ();
401 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext)
403 return new FileStream (streamName, FileMode.Create, FileAccess.Write);
406 [MonoTODO ("Not implemented")]
407 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext,
408 bool assertPermissions)
410 throw new NotImplementedException ();
413 public virtual bool PrefetchAll (string configPath, string streamName)
415 throw new NotImplementedException ();
418 public virtual bool PrefetchSection (string sectionGroupName, string sectionName)
420 throw new NotImplementedException ();
423 [MonoTODO ("Not implemented")]
424 public virtual void RequireCompleteInit (IInternalConfigRecord configRecord)
426 throw new NotImplementedException ();
429 public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
431 throw new NotImplementedException ();
434 public virtual void StopMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
436 throw new NotImplementedException ();
439 public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
440 ConfigurationAllowExeDefinition allowExeDefinition,
441 IConfigErrorInfo errorInfo)
443 if (!IsDefinitionAllowed (configPath, allowDefinition, allowExeDefinition))
444 throw new ConfigurationErrorsException ("The section can't be defined in this file (the allowed definition context is '" + allowDefinition + "').", errorInfo.Filename, errorInfo.LineNumber);
447 [MonoTODO("Does nothing")]
448 public virtual void WriteCompleted (string streamName, bool success, object writeContext)
452 [MonoTODO("Does nothing")]
453 public virtual void WriteCompleted (string streamName, bool success, object writeContext, bool assertPermissions)
457 public virtual bool SupportsChangeNotifications {
458 get { return false; }
461 public virtual bool SupportsLocation {
462 get { return false; }
465 public virtual bool SupportsPath {
466 get { return false; }
469 public virtual bool SupportsRefresh {
470 get { return false; }
473 [MonoTODO("Always returns false")]
474 public virtual bool IsRemote {
475 get { return false; }
478 [MonoTODO ("Not implemented")]
479 public virtual bool IsFullTrustSectionWithoutAptcaAllowed (IInternalConfigRecord configRecord)
481 throw new NotImplementedException ();
484 [MonoTODO ("Not implemented")]
485 public virtual bool IsInitDelayed (IInternalConfigRecord configRecord)
487 throw new NotImplementedException ();
490 [MonoTODO ("Not implemented")]
491 public virtual bool IsSecondaryRoot (string configPath)
493 throw new NotImplementedException ();
496 [MonoTODO ("Not implemented")]
497 public virtual bool IsTrustedConfigPath (string configPath)
499 throw new NotImplementedException ();