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)
220 return MapPathFromMapper (virtualPath);
221 else if (HttpContext.Current != null && HttpContext.Current.Request != null)
222 return HttpContext.Current.Request.MapPath (virtualPath);
223 else if (HttpRuntime.AppDomainAppVirtualPath != null &&
224 virtualPath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) {
225 if (virtualPath == HttpRuntime.AppDomainAppVirtualPath)
226 return HttpRuntime.AppDomainAppPath;
227 return UrlUtils.Combine (HttpRuntime.AppDomainAppPath,
228 virtualPath.Substring (HttpRuntime.AppDomainAppVirtualPath.Length));
234 public string NormalizeVirtualPath (string virtualPath)
236 if (virtualPath == null || virtualPath.Length == 0)
239 virtualPath = virtualPath.Trim ();
241 if (virtualPath [0] == '~' && virtualPath.Length > 2 && virtualPath [1] == '/')
242 virtualPath = virtualPath.Substring (1);
244 if (System.IO.Path.DirectorySeparatorChar != '/')
245 virtualPath = virtualPath.Replace (System.IO.Path.DirectorySeparatorChar, '/');
247 if (UrlUtils.IsRooted (virtualPath)) {
248 virtualPath = UrlUtils.Canonic (virtualPath);
250 if (map.VirtualDirectories.Count > 0) {
251 string root = map.VirtualDirectories [0].VirtualDirectory;
252 virtualPath = UrlUtils.Combine (root, virtualPath);
253 virtualPath = UrlUtils.Canonic (virtualPath);
259 public string MapPathFromMapper (string virtualPath)
261 string path = NormalizeVirtualPath (virtualPath);
263 foreach (VirtualDirectoryMapping mapping in map.VirtualDirectories) {
264 if (path.StartsWith (mapping.VirtualDirectory)) {
265 int i = mapping.VirtualDirectory.Length;
266 if (path.Length == i) {
267 return mapping.PhysicalDirectory;
269 else if (path [i] == '/') {
270 string pathPart = path.Substring (i + 1).Replace ('/', Path.DirectorySeparatorChar);
271 return Path.Combine (mapping.PhysicalDirectory, pathPart);
275 throw new HttpException ("Invalid virtual directory: " + virtualPath);
278 string GetWebConfigFileName (string dir)
281 DirectoryInfo d = GetCaseSensitiveExistingDirectory (new DirectoryInfo (dir));
285 FileInfo file = (FileInfo) FindByName ("web.config", d.GetFiles ("W*"));
287 file = (FileInfo) FindByName ("web.config", d.GetFiles ("w*"));
290 return file.FullName;
292 AppDomain domain = AppDomain.CurrentDomain;
293 bool hosted = (domain.GetData (ApplicationHost.MonoHostedDataKey) as string) == "yes";
296 foreach (string fn in ApplicationHost.WebConfigFileNames) {
297 string file = Path.Combine (dir, fn);
298 if (File.Exists (file))
302 Assembly asm = Assembly.GetEntryAssembly () ?? Assembly.GetCallingAssembly ();
303 string name = Path.GetFileName (asm.Location);
304 string[] fileNames = new string[] {name + ".config", name + ".Config"};
305 string appDir = domain.BaseDirectory;
308 foreach (string fn in fileNames) {
309 file = Path.Combine (appDir, fn);
310 if (File.Exists (file))
318 static DirectoryInfo GetCaseSensitiveExistingDirectory (DirectoryInfo dir) {
324 DirectoryInfo parent = GetCaseSensitiveExistingDirectory (dir.Parent);
328 return (DirectoryInfo) FindByName (dir.Name, parent.GetDirectories ());
331 static FileSystemInfo FindByName (string name, FileSystemInfo [] infos)
333 for (int i = 0; i < infos.Length; i++) {
334 if (String.Compare (name, infos [i].Name, StringComparison.OrdinalIgnoreCase) == 0)
340 public virtual bool IsAboveApplication (string configPath)
342 throw new NotImplementedException ();
345 public virtual bool IsConfigRecordRequired (string configPath)
347 throw new NotImplementedException ();
350 public virtual bool IsDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
351 ConfigurationAllowExeDefinition allowExeDefinition)
353 switch (allowDefinition) {
354 case ConfigurationAllowDefinition.MachineOnly:
355 return configPath == MachinePath || configPath == MachineWebPath;
356 case ConfigurationAllowDefinition.MachineToWebRoot:
357 case ConfigurationAllowDefinition.MachineToApplication:
358 return configPath == MachinePath || configPath == MachineWebPath || configPath == "/" ||
359 configPath == HttpRuntime.AppDomainAppVirtualPath;
365 public virtual bool IsFile (string streamName)
367 throw new NotImplementedException ();
370 public virtual bool IsLocationApplicable (string configPath)
372 throw new NotImplementedException ();
375 public virtual Stream OpenStreamForRead (string streamName)
377 if (!File.Exists (streamName)) {
379 if (streamName != null && (streamName.EndsWith ("machine.config") ||
380 streamName.EndsWith ("web.config"))) {
381 if (streamName.StartsWith ("/"))
382 streamName = streamName.Substring (1);
383 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
385 java.io.InputStream inputStream = cl.getResourceAsStream (streamName);
386 return new System.Web.J2EE.J2EEUtils.InputStreamWrapper (inputStream);
390 throw new ConfigurationException ("File '" + streamName + "' not found");
393 return new FileStream (streamName, FileMode.Open, FileAccess.Read);
396 [MonoTODO ("Not implemented")]
397 public virtual Stream OpenStreamForRead (string streamName, bool assertPermissions)
399 throw new NotImplementedException ();
402 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext)
404 return new FileStream (streamName, FileMode.Create, FileAccess.Write);
407 [MonoTODO ("Not implemented")]
408 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext,
409 bool assertPermissions)
411 throw new NotImplementedException ();
414 public virtual bool PrefetchAll (string configPath, string streamName)
416 throw new NotImplementedException ();
419 public virtual bool PrefetchSection (string sectionGroupName, string sectionName)
421 throw new NotImplementedException ();
424 [MonoTODO ("Not implemented")]
425 public virtual void RequireCompleteInit (IInternalConfigRecord configRecord)
427 throw new NotImplementedException ();
430 public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
432 throw new NotImplementedException ();
435 public virtual void StopMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
437 throw new NotImplementedException ();
440 public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
441 ConfigurationAllowExeDefinition allowExeDefinition,
442 IConfigErrorInfo errorInfo)
444 if (!IsDefinitionAllowed (configPath, allowDefinition, allowExeDefinition))
445 throw new ConfigurationErrorsException ("The section can't be defined in this file (the allowed definition context is '" + allowDefinition + "').", errorInfo.Filename, errorInfo.LineNumber);
448 [MonoTODO("Does nothing")]
449 public virtual void WriteCompleted (string streamName, bool success, object writeContext)
453 [MonoTODO("Does nothing")]
454 public virtual void WriteCompleted (string streamName, bool success, object writeContext, bool assertPermissions)
458 public virtual bool SupportsChangeNotifications {
459 get { return false; }
462 public virtual bool SupportsLocation {
463 get { return false; }
466 public virtual bool SupportsPath {
467 get { return false; }
470 public virtual bool SupportsRefresh {
471 get { return false; }
474 [MonoTODO("Always returns false")]
475 public virtual bool IsRemote {
476 get { return false; }
479 [MonoTODO ("Not implemented")]
480 public virtual bool IsFullTrustSectionWithoutAptcaAllowed (IInternalConfigRecord configRecord)
482 throw new NotImplementedException ();
485 [MonoTODO ("Not implemented")]
486 public virtual bool IsInitDelayed (IInternalConfigRecord configRecord)
488 throw new NotImplementedException ();
491 [MonoTODO ("Not implemented")]
492 public virtual bool IsSecondaryRoot (string configPath)
494 throw new NotImplementedException ();
497 [MonoTODO ("Not implemented")]
498 public virtual bool IsTrustedConfigPath (string configPath)
500 throw new NotImplementedException ();