1 //------------------------------------------------------------------------------
2 // <copyright file="VirtualDirectoryMapping.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.Web.Configuration {
8     using System;
9     using System.Configuration;
10     using System.IO;
11     using System.Web.Util;
12     using System.Security.Permissions;
13 
14     //
15     // Maps a virtual directory to a physical directory and its config file.
16     //
17     public sealed class VirtualDirectoryMapping {
18         VirtualPath  _virtualDirectory;
19         string  _physicalDirectory;
20         string  _configFileBaseName;
21         bool    _isAppRoot;
22 
23         const string DEFAULT_BASE_NAME = "web.config";
24 
VirtualDirectoryMapping(string physicalDirectory, bool isAppRoot)25         public VirtualDirectoryMapping(string physicalDirectory, bool isAppRoot)
26             : this(null, physicalDirectory, isAppRoot, DEFAULT_BASE_NAME) {
27 
28         }
29 
VirtualDirectoryMapping(string physicalDirectory, bool isAppRoot, string configFileBaseName)30         public VirtualDirectoryMapping(string physicalDirectory, bool isAppRoot, string configFileBaseName)
31             : this(null, physicalDirectory, isAppRoot, configFileBaseName) {
32         }
33 
VirtualDirectoryMapping(VirtualPath virtualDirectory, string physicalDirectory, bool isAppRoot, string configFileBaseName)34         private VirtualDirectoryMapping(VirtualPath virtualDirectory, string physicalDirectory, bool isAppRoot, string configFileBaseName) {
35             _virtualDirectory = virtualDirectory;
36             _isAppRoot = isAppRoot;
37 
38             PhysicalDirectory = physicalDirectory;
39             ConfigFileBaseName = configFileBaseName;
40         }
41 
Clone()42         internal VirtualDirectoryMapping Clone() {
43             return new VirtualDirectoryMapping(_virtualDirectory, _physicalDirectory, _isAppRoot, _configFileBaseName);
44         }
45 
46         //
47         // Get the virtual directory.
48         // Not settable because it is set when it is added to a collection.
49         //
50         public string VirtualDirectory {
51             get {
52                 return (_virtualDirectory != null) ? _virtualDirectory.VirtualPathString : string.Empty;
53             }
54         }
55 
56         internal VirtualPath VirtualDirectoryObject {
57             get {
58                 return _virtualDirectory;
59             }
60         }
61 
SetVirtualDirectory(VirtualPath virtualDirectory)62         internal void SetVirtualDirectory(VirtualPath virtualDirectory) {
63             _virtualDirectory = virtualDirectory;
64         }
65 
66         //
67         // The physical directory.
68         //
69         public string PhysicalDirectory {
70             get {
71                 return _physicalDirectory;
72             }
73 
74             set {
75                 string physicalDirectory = value;
76                 if (String.IsNullOrEmpty(physicalDirectory)) {
77                     physicalDirectory = null;
78                 }
79                 else {
80                     // remove trailing '\' if any
81                     if (UrlPath.PathEndsWithExtraSlash(physicalDirectory)) {
82                         physicalDirectory = physicalDirectory.Substring(0, physicalDirectory.Length - 1);
83                     }
84 
85                     // Throw if the resulting physical path is not canonical, to prevent potential
86                     // security issues (VSWhidbey 418125)
87                     if (FileUtil.IsSuspiciousPhysicalPath(physicalDirectory)) {
88                         throw ExceptionUtil.ParameterInvalid("PhysicalDirectory");
89                     }
90                 }
91 
92                 _physicalDirectory = physicalDirectory;
93             }
94         }
95 
96         //
97         // Indicates whether the virtual directory is the location of an application.
98         //
99         public bool IsAppRoot {
100             get {
101                 return _isAppRoot;
102             }
103 
104             set {
105                 _isAppRoot = value;
106             }
107 
108         }
109 
110         //
111         // The base name of the config file.
112         // If not specified, "web.config" is used.
113         //
114         public string ConfigFileBaseName {
115             get {
116                 return _configFileBaseName;
117             }
118 
119             set {
120                 if (string.IsNullOrEmpty(value)) {
121                     throw ExceptionUtil.PropertyInvalid("ConfigFileBaseName");
122                 }
123 
124                 _configFileBaseName = value;
125             }
126         }
127 
Validate()128         internal void Validate() {
129             if (_physicalDirectory != null) {
130                 //
131                 // Ensure that the caller has PathDiscovery to the resulting config file,
132                 // and that the web.config file does not have ".." that could lead to a
133                 // different directory.
134                 //
135                 string configFilename = Path.Combine(_physicalDirectory, _configFileBaseName);
136                 string fullConfigFilename = Path.GetFullPath(configFilename);
137                 if (    Path.GetDirectoryName(fullConfigFilename) != _physicalDirectory ||
138                         Path.GetFileName(fullConfigFilename) != _configFileBaseName ||
139                         FileUtil.IsSuspiciousPhysicalPath(configFilename)) {
140 
141                     throw ExceptionUtil.ParameterInvalid("configFileBaseName");
142                 }
143             }
144         }
145     }
146 }
147