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 return new HttpConfigurationContext(configPath);
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.io.InputStream wcs = cl.getResourceAsStream ("META-INF/web.config");
137 return "/META-INF/web.config";
140 mdir = Path.GetDirectoryName (System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile);
143 mdir = Path.GetDirectoryName (map.MachineConfigFilename);
145 return GetWebConfigFileName (mdir);
148 string dir = MapPath (configPath);
149 return GetWebConfigFileName (dir);
152 public virtual string GetStreamNameForConfigSource (string streamName, string configSource)
154 throw new NotImplementedException ();
157 public virtual object GetStreamVersion (string streamName)
159 throw new NotImplementedException ();
162 public virtual IDisposable Impersonate ()
164 throw new NotImplementedException ();
167 public virtual void Init (IInternalConfigRoot root, params object[] hostInitParams)
171 public virtual void InitForConfiguration (ref string locationSubPath, out string configPath,
172 out string locationConfigPath, IInternalConfigRoot root,
173 params object[] hostInitConfigurationParams)
175 string fullPath = (string) hostInitConfigurationParams [1];
176 map = (WebConfigurationFileMap) hostInitConfigurationParams [0];
178 if (locationSubPath == MachineWebPath) {
179 locationSubPath = MachinePath;
180 configPath = MachineWebPath;
181 locationConfigPath = null;
182 } else if (locationSubPath == MachinePath) {
183 locationSubPath = null;
184 configPath = MachinePath;
185 locationConfigPath = null;
188 if (locationSubPath == null)
190 configPath = fullPath;
191 if (configPath.Length > 1)
192 configPath = VirtualPathUtility.RemoveTrailingSlash (configPath);
195 configPath = locationSubPath;
197 if (configPath == HttpRuntime.AppDomainAppVirtualPath
198 || configPath == "/")
201 i = configPath.LastIndexOf ("/");
204 locationConfigPath = configPath.Substring (i+1);
207 locationSubPath = "/";
209 locationSubPath = fullPath.Substring (0, i);
211 locationSubPath = MachineWebPath;
212 locationConfigPath = null;
217 public string MapPath (string virtualPath)
219 if (!String.IsNullOrEmpty (virtualPath)) {
220 if (virtualPath.StartsWith (System.Web.Compilation.BuildManager.FAKE_VIRTUAL_PATH_PREFIX, StringComparison.Ordinal))
221 return HttpRuntime.AppDomainAppPath;
225 return MapPathFromMapper (virtualPath);
226 else if (HttpContext.Current != null && HttpContext.Current.Request != null)
227 return HttpContext.Current.Request.MapPath (virtualPath);
228 else if (HttpRuntime.AppDomainAppVirtualPath != null &&
229 virtualPath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) {
230 if (virtualPath == HttpRuntime.AppDomainAppVirtualPath)
231 return HttpRuntime.AppDomainAppPath;
232 return UrlUtils.Combine (HttpRuntime.AppDomainAppPath,
233 virtualPath.Substring (HttpRuntime.AppDomainAppVirtualPath.Length));
239 public string NormalizeVirtualPath (string virtualPath)
241 if (virtualPath == null || virtualPath.Length == 0)
244 virtualPath = virtualPath.Trim ();
246 if (virtualPath [0] == '~' && virtualPath.Length > 2 && virtualPath [1] == '/')
247 virtualPath = virtualPath.Substring (1);
249 if (System.IO.Path.DirectorySeparatorChar != '/')
250 virtualPath = virtualPath.Replace (System.IO.Path.DirectorySeparatorChar, '/');
252 if (UrlUtils.IsRooted (virtualPath)) {
253 virtualPath = UrlUtils.Canonic (virtualPath);
255 if (map.VirtualDirectories.Count > 0) {
256 string root = map.VirtualDirectories [0].VirtualDirectory;
257 virtualPath = UrlUtils.Combine (root, virtualPath);
258 virtualPath = UrlUtils.Canonic (virtualPath);
264 public string MapPathFromMapper (string virtualPath)
266 string path = NormalizeVirtualPath (virtualPath);
268 foreach (VirtualDirectoryMapping mapping in map.VirtualDirectories) {
269 if (path.StartsWith (mapping.VirtualDirectory)) {
270 int i = mapping.VirtualDirectory.Length;
271 if (path.Length == i) {
272 return mapping.PhysicalDirectory;
274 else if (path [i] == '/') {
275 string pathPart = path.Substring (i + 1).Replace ('/', Path.DirectorySeparatorChar);
276 return Path.Combine (mapping.PhysicalDirectory, pathPart);
280 throw new HttpException ("Invalid virtual directory: " + virtualPath);
283 internal static string GetWebConfigFileName (string dir)
286 DirectoryInfo d = GetCaseSensitiveExistingDirectory (new DirectoryInfo (dir));
290 FileInfo file = (FileInfo) FindByName ("web.config", d.GetFiles ("W*"));
292 file = (FileInfo) FindByName ("web.config", d.GetFiles ("w*"));
295 return file.FullName;
297 AppDomain domain = AppDomain.CurrentDomain;
298 bool hosted = (domain.GetData (ApplicationHost.MonoHostedDataKey) as string) == "yes";
301 foreach (string fn in ApplicationHost.WebConfigFileNames) {
302 string file = Path.Combine (dir, fn);
303 if (File.Exists (file))
307 Assembly asm = Assembly.GetEntryAssembly () ?? Assembly.GetCallingAssembly ();
308 string name = Path.GetFileName (asm.Location);
309 string[] fileNames = new string[] {name + ".config", name + ".Config"};
310 string appDir = domain.BaseDirectory;
313 foreach (string fn in fileNames) {
314 file = Path.Combine (appDir, fn);
315 if (File.Exists (file))
323 static DirectoryInfo GetCaseSensitiveExistingDirectory (DirectoryInfo dir) {
329 DirectoryInfo parent = GetCaseSensitiveExistingDirectory (dir.Parent);
333 return (DirectoryInfo) FindByName (dir.Name, parent.GetDirectories ());
336 static FileSystemInfo FindByName (string name, FileSystemInfo [] infos)
338 for (int i = 0; i < infos.Length; i++) {
339 if (String.Compare (name, infos [i].Name, StringComparison.OrdinalIgnoreCase) == 0)
345 public virtual bool IsAboveApplication (string configPath)
347 throw new NotImplementedException ();
350 public virtual bool IsConfigRecordRequired (string configPath)
352 throw new NotImplementedException ();
355 public virtual bool IsDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
356 ConfigurationAllowExeDefinition allowExeDefinition)
358 switch (allowDefinition) {
359 case ConfigurationAllowDefinition.MachineOnly:
360 return configPath == MachinePath || configPath == MachineWebPath;
361 case ConfigurationAllowDefinition.MachineToWebRoot:
362 case ConfigurationAllowDefinition.MachineToApplication:
363 if (String.IsNullOrEmpty (configPath))
365 return (String.Compare (configPath, MachinePath, StringComparison.Ordinal) == 0) ||
366 (String.Compare (configPath, MachineWebPath, StringComparison.Ordinal) == 0) ||
367 (String.Compare (configPath, "/", StringComparison.Ordinal) == 0) ||
368 (String.Compare (configPath, "~", StringComparison.Ordinal) == 0) ||
369 (String.Compare (configPath, HttpRuntime.AppDomainAppVirtualPath) == 0);
375 public virtual bool IsFile (string streamName)
377 throw new NotImplementedException ();
380 public virtual bool IsLocationApplicable (string configPath)
382 throw new NotImplementedException ();
385 public virtual Stream OpenStreamForRead (string streamName)
387 if (!File.Exists (streamName)) {
389 if (streamName != null && (streamName.EndsWith ("machine.config") ||
390 streamName.EndsWith ("web.config"))) {
391 if (streamName.StartsWith ("/"))
392 streamName = streamName.Substring (1);
393 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
395 java.io.InputStream inputStream = cl.getResourceAsStream (streamName);
396 return new System.Web.J2EE.J2EEUtils.InputStreamWrapper (inputStream);
400 throw new ConfigurationException ("File '" + streamName + "' not found");
403 return new FileStream (streamName, FileMode.Open, FileAccess.Read);
406 [MonoTODO ("Not implemented")]
407 public virtual Stream OpenStreamForRead (string streamName, bool assertPermissions)
409 throw new NotImplementedException ();
412 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext)
414 return new FileStream (streamName, FileMode.Create, FileAccess.Write);
417 [MonoTODO ("Not implemented")]
418 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext,
419 bool assertPermissions)
421 throw new NotImplementedException ();
424 public virtual bool PrefetchAll (string configPath, string streamName)
426 throw new NotImplementedException ();
429 public virtual bool PrefetchSection (string sectionGroupName, string sectionName)
431 throw new NotImplementedException ();
434 [MonoTODO ("Not implemented")]
435 public virtual void RequireCompleteInit (IInternalConfigRecord configRecord)
437 throw new NotImplementedException ();
440 public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
442 throw new NotImplementedException ();
445 public virtual void StopMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
447 throw new NotImplementedException ();
450 public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
451 ConfigurationAllowExeDefinition allowExeDefinition,
452 IConfigErrorInfo errorInfo)
454 if (!IsDefinitionAllowed (configPath, allowDefinition, allowExeDefinition))
455 throw new ConfigurationErrorsException ("The section can't be defined in this file (the allowed definition context is '" + allowDefinition + "').", errorInfo.Filename, errorInfo.LineNumber);
458 [MonoTODO("Does nothing")]
459 public virtual void WriteCompleted (string streamName, bool success, object writeContext)
463 [MonoTODO("Does nothing")]
464 public virtual void WriteCompleted (string streamName, bool success, object writeContext, bool assertPermissions)
468 public virtual bool SupportsChangeNotifications {
469 get { return false; }
472 public virtual bool SupportsLocation {
473 get { return false; }
476 public virtual bool SupportsPath {
477 get { return false; }
480 public virtual bool SupportsRefresh {
481 get { return false; }
484 [MonoTODO("Always returns false")]
485 public virtual bool IsRemote {
486 get { return false; }
489 [MonoTODO ("Not implemented")]
490 public virtual bool IsFullTrustSectionWithoutAptcaAllowed (IInternalConfigRecord configRecord)
492 throw new NotImplementedException ();
495 [MonoTODO ("Not implemented")]
496 public virtual bool IsInitDelayed (IInternalConfigRecord configRecord)
498 throw new NotImplementedException ();
501 [MonoTODO ("Not implemented")]
502 public virtual bool IsSecondaryRoot (string configPath)
504 throw new NotImplementedException ();
507 [MonoTODO ("Not implemented")]
508 public virtual bool IsTrustedConfigPath (string configPath)
510 throw new NotImplementedException ();