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))
300 Assembly asm = Assembly.GetEntryAssembly () ?? Assembly.GetCallingAssembly ();
301 string name = Path.GetFileName (asm.Location);
302 string[] fileNames = new string[] {name + ".config", name + ".Config"};
303 string appDir = domain.BaseDirectory;
306 foreach (string fn in fileNames) {
307 file = Path.Combine (appDir, fn);
308 if (File.Exists (file))
316 static DirectoryInfo GetCaseSensitiveExistingDirectory (DirectoryInfo dir) {
322 DirectoryInfo parent = GetCaseSensitiveExistingDirectory (dir.Parent);
326 return (DirectoryInfo) FindByName (dir.Name, parent.GetDirectories ());
329 static FileSystemInfo FindByName (string name, FileSystemInfo [] infos)
331 for (int i = 0; i < infos.Length; i++) {
332 if (String.Compare (name, infos [i].Name, StringComparison.OrdinalIgnoreCase) == 0)
338 public virtual bool IsAboveApplication (string configPath)
340 throw new NotImplementedException ();
343 public virtual bool IsConfigRecordRequired (string configPath)
345 throw new NotImplementedException ();
348 public virtual bool IsDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
349 ConfigurationAllowExeDefinition allowExeDefinition)
351 switch (allowDefinition) {
352 case ConfigurationAllowDefinition.MachineOnly:
353 return configPath == MachinePath || configPath == MachineWebPath;
354 case ConfigurationAllowDefinition.MachineToWebRoot:
355 case ConfigurationAllowDefinition.MachineToApplication:
356 return configPath == MachinePath || configPath == MachineWebPath || configPath == "/" ||
357 configPath == HttpRuntime.AppDomainAppVirtualPath;
363 public virtual bool IsFile (string streamName)
365 throw new NotImplementedException ();
368 public virtual bool IsLocationApplicable (string configPath)
370 throw new NotImplementedException ();
373 public virtual Stream OpenStreamForRead (string streamName)
375 if (!File.Exists (streamName)) {
377 if (streamName != null && (streamName.EndsWith ("machine.config") ||
378 streamName.EndsWith ("web.config"))) {
379 if (streamName.StartsWith ("/"))
380 streamName = streamName.Substring (1);
381 java.lang.ClassLoader cl = (java.lang.ClassLoader) AppDomain.CurrentDomain.GetData ("GH_ContextClassLoader");
383 java.io.InputStream inputStream = cl.getResourceAsStream (streamName);
384 return (Stream) vmw.common.IOUtils.getStream (inputStream);
388 throw new ConfigurationException ("File '" + streamName + "' not found");
391 return new FileStream (streamName, FileMode.Open, FileAccess.Read);
394 [MonoTODO ("Not implemented")]
395 public virtual Stream OpenStreamForRead (string streamName, bool assertPermissions)
397 throw new NotImplementedException ();
400 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext)
402 return new FileStream (streamName, FileMode.Create, FileAccess.Write);
405 [MonoTODO ("Not implemented")]
406 public virtual Stream OpenStreamForWrite (string streamName, string templateStreamName, ref object writeContext,
407 bool assertPermissions)
409 throw new NotImplementedException ();
412 public virtual bool PrefetchAll (string configPath, string streamName)
414 throw new NotImplementedException ();
417 public virtual bool PrefetchSection (string sectionGroupName, string sectionName)
419 throw new NotImplementedException ();
422 [MonoTODO ("Not implemented")]
423 public virtual void RequireCompleteInit (IInternalConfigRecord configRecord)
425 throw new NotImplementedException ();
428 public virtual object StartMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
430 throw new NotImplementedException ();
433 public virtual void StopMonitoringStreamForChanges (string streamName, StreamChangeCallback callback)
435 throw new NotImplementedException ();
438 public virtual void VerifyDefinitionAllowed (string configPath, ConfigurationAllowDefinition allowDefinition,
439 ConfigurationAllowExeDefinition allowExeDefinition,
440 IConfigErrorInfo errorInfo)
442 if (!IsDefinitionAllowed (configPath, allowDefinition, allowExeDefinition))
443 throw new ConfigurationErrorsException ("The section can't be defined in this file (the allowed definition context is '" + allowDefinition + "').", errorInfo.Filename, errorInfo.LineNumber);
446 [MonoTODO("Does nothing")]
447 public virtual void WriteCompleted (string streamName, bool success, object writeContext)
451 [MonoTODO("Does nothing")]
452 public virtual void WriteCompleted (string streamName, bool success, object writeContext, bool assertPermissions)
456 public virtual bool SupportsChangeNotifications {
457 get { return false; }
460 public virtual bool SupportsLocation {
461 get { return false; }
464 public virtual bool SupportsPath {
465 get { return false; }
468 public virtual bool SupportsRefresh {
469 get { return false; }
472 [MonoTODO("Always returns false")]
473 public virtual bool IsRemote {
474 get { return false; }
477 [MonoTODO ("Not implemented")]
478 public virtual bool IsFullTrustSectionWithoutAptcaAllowed (IInternalConfigRecord configRecord)
480 throw new NotImplementedException ();
483 [MonoTODO ("Not implemented")]
484 public virtual bool IsInitDelayed (IInternalConfigRecord configRecord)
486 throw new NotImplementedException ();
489 [MonoTODO ("Not implemented")]
490 public virtual bool IsSecondaryRoot (string configPath)
492 throw new NotImplementedException ();
495 [MonoTODO ("Not implemented")]
496 public virtual bool IsTrustedConfigPath (string configPath)
498 throw new NotImplementedException ();