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.Util;
38 using System.Reflection;
41 * this class needs to be rewritten to support usage of the
42 * IRemoteWebConfigurationHostServer interface. Once that's done, we
43 * need an implementation of that interface that talks (through a web
44 * service?) to a remote site..
46 * for now, though, just implement it as we do
47 * System.Configuration.InternalConfigurationHost, i.e. the local
50 namespace System.Web.Configuration
52 class WebConfigurationHost: IInternalConfigHost
54 WebConfigurationFileMap map;
55 const string MachinePath = ":machine:";
56 const string MachineWebPath = ":web:";
58 public virtual object CreateConfigurationContext (string configPath, string locationSubPath)
60 return new WebContext (WebApplicationLevel.AtApplication /* XXX */,
62 "" /* application path XXX */,
67 public virtual object CreateDeprecatedConfigContext (string configPath)
69 throw new NotImplementedException ();
72 public virtual string DecryptSection (string encryptedXml, ProtectedConfigurationProvider protectionProvider,
73 ProtectedConfigurationSection protectedSection)
75 throw new NotImplementedException ();
78 public virtual void DeleteStream (string streamName)
80 File.Delete (streamName);
83 public virtual string EncryptSection (string encryptedXml, ProtectedConfigurationProvider protectionProvider,
84 ProtectedConfigurationSection protectedSection)
86 throw new NotImplementedException ();
89 public virtual string GetConfigPathFromLocationSubPath (string configPath, string locatinSubPath)
91 return configPath + "/" + locatinSubPath;
94 public virtual Type GetConfigType (string typeName, bool throwOnError)
96 Type type = HttpApplication.LoadType (typeName);
97 if (type == null && throwOnError)
98 throw new ConfigurationErrorsException ("Type not found: '" + typeName + "'");
102 public virtual string GetConfigTypeName (Type t)
104 return t.AssemblyQualifiedName;
107 public virtual void GetRestrictedPermissions (IInternalConfigRecord configRecord, out PermissionSet permissionSet,
108 out bool isHostReady)
110 throw new NotImplementedException ();
113 public virtual string GetStreamName (string configPath)
115 if (configPath == MachinePath) {
117 return System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile;
119 return map.MachineConfigFilename;
120 } else if (configPath == MachineWebPath) {
126 // check META-INF/web.config exists
127 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
130 java.net.URL url = cl.getResource ("META-INF/web.config");
134 return "/META-INF/web.config";
137 mdir = Path.GetDirectoryName (System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile);
140 mdir = Path.GetDirectoryName (map.MachineConfigFilename);
142 return GetWebConfigFileName (mdir);
145 string dir = MapPath (configPath);
146 return GetWebConfigFileName (dir);
149 public virtual string GetStreamNameForConfigSource (string streamName, string configSource)
151 throw new NotImplementedException ();
154 public virtual object GetStreamVersion (string streamName)
156 throw new NotImplementedException ();
159 public virtual IDisposable Impersonate ()
161 throw new NotImplementedException ();
164 public virtual void Init (IInternalConfigRoot root, params object[] hostInitParams)
168 public virtual void InitForConfiguration (ref string locationSubPath, out string configPath,
169 out string locationConfigPath, IInternalConfigRoot root,
170 params object[] hostInitConfigurationParams)
172 string fullPath = (string) hostInitConfigurationParams [1];
173 map = (WebConfigurationFileMap) hostInitConfigurationParams [0];
175 if (locationSubPath == MachineWebPath) {
176 locationSubPath = MachinePath;
177 configPath = MachineWebPath;
178 locationConfigPath = null;
179 } else if (locationSubPath == MachinePath) {
180 locationSubPath = null;
181 configPath = MachinePath;
182 locationConfigPath = null;
185 if (locationSubPath == null)
187 configPath = fullPath;
188 if (configPath.Length > 1)
189 configPath = VirtualPathUtility.RemoveTrailingSlash (configPath);
192 configPath = locationSubPath;
194 if (configPath == HttpRuntime.AppDomainAppVirtualPath
195 || configPath == "/")
198 i = configPath.LastIndexOf ("/");
201 locationConfigPath = configPath.Substring (i+1);
204 locationSubPath = "/";
206 locationSubPath = fullPath.Substring (0, i);
208 locationSubPath = MachineWebPath;
209 locationConfigPath = null;
214 public string MapPath (string virtualPath)
217 return MapPathFromMapper (virtualPath);
218 else if (HttpContext.Current != null && HttpContext.Current.Request != null)
219 return HttpContext.Current.Request.MapPath (virtualPath);
220 else if (HttpRuntime.AppDomainAppVirtualPath != null &&
221 virtualPath.StartsWith (HttpRuntime.AppDomainAppVirtualPath)) {
222 if (virtualPath == HttpRuntime.AppDomainAppVirtualPath)
223 return HttpRuntime.AppDomainAppPath;
224 return UrlUtils.Combine (HttpRuntime.AppDomainAppPath,
225 virtualPath.Substring (HttpRuntime.AppDomainAppVirtualPath.Length));
231 public string NormalizeVirtualPath (string virtualPath)
233 if (virtualPath == null || virtualPath.Length == 0)
236 virtualPath = virtualPath.Trim ();
238 if (virtualPath [0] == '~' && virtualPath.Length > 2 && virtualPath [1] == '/')
239 virtualPath = virtualPath.Substring (1);
241 if (System.IO.Path.DirectorySeparatorChar != '/')
242 virtualPath = virtualPath.Replace (System.IO.Path.DirectorySeparatorChar, '/');
244 if (UrlUtils.IsRooted (virtualPath)) {
245 virtualPath = UrlUtils.Canonic (virtualPath);
247 if (map.VirtualDirectories.Count > 0) {
248 string root = map.VirtualDirectories [0].VirtualDirectory;
249 virtualPath = UrlUtils.Combine (root, virtualPath);
250 virtualPath = UrlUtils.Canonic (virtualPath);
256 public string MapPathFromMapper (string virtualPath)
258 string path = NormalizeVirtualPath (virtualPath);
260 foreach (VirtualDirectoryMapping mapping in map.VirtualDirectories) {
261 if (path.StartsWith (mapping.VirtualDirectory)) {
262 int i = mapping.VirtualDirectory.Length;
263 if (path.Length == i) {
264 return mapping.PhysicalDirectory;
266 else if (path [i] == '/') {
267 string pathPart = path.Substring (i + 1).Replace ('/', Path.DirectorySeparatorChar);
268 return Path.Combine (mapping.PhysicalDirectory, pathPart);
272 throw new HttpException ("Invalid virtual directory: " + virtualPath);
275 string GetWebConfigFileName (string dir)
278 DirectoryInfo d = GetCaseSensitiveExistingDirectory (new DirectoryInfo (dir));
282 FileInfo file = (FileInfo) FindByName ("web.config", d.GetFiles ("W*"));
284 file = (FileInfo) FindByName ("web.config", d.GetFiles ("w*"));
287 return file.FullName;
289 string[] filenames = new string[] {"Web.Config", "Web.config", "web.config" };
291 foreach (string fn in filenames) {
292 string file = Path.Combine (dir, fn);
293 if (File.Exists (file))
300 static DirectoryInfo GetCaseSensitiveExistingDirectory (DirectoryInfo dir) {
304 DirectoryInfo parent = GetCaseSensitiveExistingDirectory (dir.Parent);
308 return (DirectoryInfo) FindByName (dir.Name, parent.GetDirectories ());
311 static FileSystemInfo FindByName (string name, FileSystemInfo [] infos)
313 for (int i = 0; i < infos.Length; i++) {
314 if (String.Compare (name, infos [i].Name, StringComparison.OrdinalIgnoreCase) == 0)
320 public virtual bool IsAboveApplication (string configPath)
322 throw new NotImplementedException ();
325 public virtual bool IsConfigRecordRequired (string configPath)
327 throw new NotImplementedException ();
330 public virtual bool IsDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
331 ConfigurationAllowExeDefinition allowExeDefinition)
333 switch (allowDefinition) {
334 case ConfigurationAllowDefinition.MachineOnly:
335 return configPath == MachinePath || configPath == MachineWebPath;
336 case ConfigurationAllowDefinition.MachineToWebRoot:
337 case ConfigurationAllowDefinition.MachineToApplication:
338 return configPath == MachinePath || configPath == MachineWebPath || configPath == "/" ||
339 configPath == HttpRuntime.AppDomainAppVirtualPath;
345 public virtual bool IsFile (string streamName)
347 throw new NotImplementedException ();
350 public virtual bool IsLocationApplicable (string configPath)
352 throw new NotImplementedException ();
355 public virtual Stream OpenStreamForRead (string streamName)
357 if (!File.Exists (streamName)) {
359 if (streamName != null && (streamName.EndsWith ("machine.config") ||
360 streamName.EndsWith ("web.config"))) {
361 if (streamName.StartsWith ("/"))
362 streamName = streamName.Substring (1);
363 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
365 java.io.InputStream inputStream = cl.getResourceAsStream (streamName);
366 return (Stream) vmw.common.IOUtils.getStream (inputStream);
370 throw new ConfigurationException ("File '" + streamName + "' not found");
373 return new FileStream (streamName, FileMode.Open, FileAccess.Read);
376 [MonoTODO ("Not implemented")]
377 public virtual Stream OpenStreamForRead (string streamName, bool assertPermissions)
379 throw new NotImplementedException ();
382 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext)
384 return new FileStream (streamName, FileMode.Create, FileAccess.Write);
387 [MonoTODO ("Not implemented")]
388 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext,
389 bool assertPermissions)
391 throw new NotImplementedException ();
394 public virtual bool PrefetchAll (string configPath, string streamName)
396 throw new NotImplementedException ();
399 public virtual bool PrefetchSection (string sectionGroupName, string sectionName)
401 throw new NotImplementedException ();
404 [MonoTODO ("Not implemented")]
405 public virtual void RequireCompleteInit (IInternalConfigRecord configRecord)
407 throw new NotImplementedException ();
410 public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
412 throw new NotImplementedException ();
415 public virtual void StopMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
417 throw new NotImplementedException ();
420 public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
421 ConfigurationAllowExeDefinition allowExeDefinition,
422 IConfigErrorInfo errorInfo)
424 if (!IsDefinitionAllowed (configPath, allowDefinition, allowExeDefinition))
425 throw new ConfigurationErrorsException ("The section can't be defined in this file (the allowed definition context is '" + allowDefinition + "').", errorInfo.Filename, errorInfo.LineNumber);
428 [MonoTODO("Does nothing")]
429 public virtual void WriteCompleted (string streamName, bool success, object writeContext)
433 [MonoTODO("Does nothing")]
434 public virtual void WriteCompleted (string streamName, bool success, object writeContext, bool assertPermissions)
438 public virtual bool SupportsChangeNotifications {
439 get { return false; }
442 public virtual bool SupportsLocation {
443 get { return false; }
446 public virtual bool SupportsPath {
447 get { return false; }
450 public virtual bool SupportsRefresh {
451 get { return false; }
454 [MonoTODO("Always returns false")]
455 public virtual bool IsRemote {
456 get { return false; }
459 [MonoTODO ("Not implemented")]
460 public virtual bool IsFullTrustSectionWithoutAptcaAllowed (IInternalConfigRecord configRecord)
462 throw new NotImplementedException ();
465 [MonoTODO ("Not implemented")]
466 public virtual bool IsInitDelayed (IInternalConfigRecord configRecord)
468 throw new NotImplementedException ();
471 [MonoTODO ("Not implemented")]
472 public virtual bool IsSecondaryRoot (string configPath)
474 throw new NotImplementedException ();
477 [MonoTODO ("Not implemented")]
478 public virtual bool IsTrustedConfigPath (string configPath)
480 throw new NotImplementedException ();