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 return (String.Compare (configPath, MachinePath, StringComparison.Ordinal) == 0) ||
364 (String.Compare (configPath, MachineWebPath, StringComparison.Ordinal) == 0) ||
365 (String.Compare (configPath, "/", StringComparison.Ordinal) == 0) ||
366 (String.Compare (configPath, "~", StringComparison.Ordinal) == 0) ||
367 (String.Compare (configPath, HttpRuntime.AppDomainAppVirtualPath) == 0);
373 public virtual bool IsFile (string streamName)
375 throw new NotImplementedException ();
378 public virtual bool IsLocationApplicable (string configPath)
380 throw new NotImplementedException ();
383 public virtual Stream OpenStreamForRead (string streamName)
385 if (!File.Exists (streamName)) {
387 if (streamName != null && (streamName.EndsWith ("machine.config") ||
388 streamName.EndsWith ("web.config"))) {
389 if (streamName.StartsWith ("/"))
390 streamName = streamName.Substring (1);
391 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
393 java.io.InputStream inputStream = cl.getResourceAsStream (streamName);
394 return new System.Web.J2EE.J2EEUtils.InputStreamWrapper (inputStream);
398 throw new ConfigurationException ("File '" + streamName + "' not found");
401 return new FileStream (streamName, FileMode.Open, FileAccess.Read);
404 [MonoTODO ("Not implemented")]
405 public virtual Stream OpenStreamForRead (string streamName, bool assertPermissions)
407 throw new NotImplementedException ();
410 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext)
412 return new FileStream (streamName, FileMode.Create, FileAccess.Write);
415 [MonoTODO ("Not implemented")]
416 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext,
417 bool assertPermissions)
419 throw new NotImplementedException ();
422 public virtual bool PrefetchAll (string configPath, string streamName)
424 throw new NotImplementedException ();
427 public virtual bool PrefetchSection (string sectionGroupName, string sectionName)
429 throw new NotImplementedException ();
432 [MonoTODO ("Not implemented")]
433 public virtual void RequireCompleteInit (IInternalConfigRecord configRecord)
435 throw new NotImplementedException ();
438 public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
440 throw new NotImplementedException ();
443 public virtual void StopMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
445 throw new NotImplementedException ();
448 public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
449 ConfigurationAllowExeDefinition allowExeDefinition,
450 IConfigErrorInfo errorInfo)
452 if (!IsDefinitionAllowed (configPath, allowDefinition, allowExeDefinition))
453 throw new ConfigurationErrorsException ("The section can't be defined in this file (the allowed definition context is '" + allowDefinition + "').", errorInfo.Filename, errorInfo.LineNumber);
456 [MonoTODO("Does nothing")]
457 public virtual void WriteCompleted (string streamName, bool success, object writeContext)
461 [MonoTODO("Does nothing")]
462 public virtual void WriteCompleted (string streamName, bool success, object writeContext, bool assertPermissions)
466 public virtual bool SupportsChangeNotifications {
467 get { return false; }
470 public virtual bool SupportsLocation {
471 get { return false; }
474 public virtual bool SupportsPath {
475 get { return false; }
478 public virtual bool SupportsRefresh {
479 get { return false; }
482 [MonoTODO("Always returns false")]
483 public virtual bool IsRemote {
484 get { return false; }
487 [MonoTODO ("Not implemented")]
488 public virtual bool IsFullTrustSectionWithoutAptcaAllowed (IInternalConfigRecord configRecord)
490 throw new NotImplementedException ();
493 [MonoTODO ("Not implemented")]
494 public virtual bool IsInitDelayed (IInternalConfigRecord configRecord)
496 throw new NotImplementedException ();
499 [MonoTODO ("Not implemented")]
500 public virtual bool IsSecondaryRoot (string configPath)
502 throw new NotImplementedException ();
505 [MonoTODO ("Not implemented")]
506 public virtual bool IsTrustedConfigPath (string configPath)
508 throw new NotImplementedException ();