Navigation Menu

Skip to content
This repository has been archived by the owner on Nov 19, 2022. It is now read-only.

Commit

Permalink
[xsp] Partial fix for bug #575600. MonoWorkerRequest.MapPath with mul…
Browse files Browse the repository at this point in the history
…tiple apps should use physical server root.

When xsp is configured to serve two virtual applications and one of them attempts to map a file from
the other, the returned physical path must be composed using the XSP's physical root as the base path - not
the current application's physical path. This is consistent with the way IIS works.
To achieve this, the commit adds a new PhysicalRoot property to the ApplicationServer class. The property is
used in MonoWorkerRequest.MapPath ().
  • Loading branch information
grendello committed Aug 11, 2010
1 parent f01ef84 commit 5f535fe
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/Mono.WebServer.Apache/main.cs
Expand Up @@ -366,7 +366,7 @@ public int RealMain (string [] args, bool root, IApplicationHost ext_apphost, bo
return (res) ? 0 : 1;
}

ApplicationServer server = new ApplicationServer (webSource);
ApplicationServer server = new ApplicationServer (webSource, rootDir);
server.Verbose = verbose;
server.SingleApplication = !root;

Expand Down
2 changes: 1 addition & 1 deletion src/Mono.WebServer.FastCgi/main.cs
Expand Up @@ -288,7 +288,7 @@ public static int Main (string [] args)
root_dir = Environment.CurrentDirectory;
bool auto_map = false; //(bool) configmanager ["automappaths"];
WebSource webSource = new WebSource ();
appserver = new ApplicationServer (webSource);
appserver = new ApplicationServer (webSource, root_dir);
appserver.Verbose = (bool) configmanager ["verbose"];

string applications = (string)
Expand Down
2 changes: 1 addition & 1 deletion src/Mono.WebServer.XSP/main.cs
Expand Up @@ -426,7 +426,7 @@ public int RealMain (string [] args, bool root, IApplicationHost ext_apphost, bo
webSource = new XSPWebSource (ipaddr, port, !root);
}

ApplicationServer server = new ApplicationServer (webSource);
ApplicationServer server = new ApplicationServer (webSource, settings.RootDir);
server.Verbose = settings.Verbose;
server.SingleApplication = !root;

Expand Down
15 changes: 13 additions & 2 deletions src/Mono.WebServer/ApplicationServer.cs
Expand Up @@ -90,6 +90,7 @@ public class ApplicationServer : MarshalByRefObject
Socket listen_socket;
bool single_app;
Exception initialException;
string physicalRoot;

Thread runner;

Expand Down Expand Up @@ -127,10 +128,20 @@ public class ApplicationServer : MarshalByRefObject
return iep.Port;
}
}

public string PhysicalRoot {
get { return physicalRoot; }
}

public ApplicationServer (WebSource source)
public ApplicationServer (WebSource source, string physicalRoot)
{
webSource = source;
if (source == null)
throw new ArgumentNullException ("source");
if (physicalRoot == null || physicalRoot.Length == 0)
throw new ArgumentNullException ("physicalRoot");

this.webSource = source;
this.physicalRoot = physicalRoot;
}

public bool Verbose {
Expand Down
83 changes: 70 additions & 13 deletions src/Mono.WebServer/MonoWorkerRequest.cs
Expand Up @@ -175,8 +175,12 @@ public MapPathEventArgs (string path)
/// </summary>
public abstract class MonoWorkerRequest : SimpleWorkerRequest
{
static readonly char[] mapPathTrimStartChars = { '/' };

static bool runningOnWindows;
static bool checkFileAccess = true;
static bool needToReplacePathSeparator;
static char pathSeparatorChar;

/// <summary>
/// Contains the application host used by the current
Expand Down Expand Up @@ -218,6 +222,8 @@ public abstract class MonoWorkerRequest : SimpleWorkerRequest
/// as read from the application host.
/// </summary>
string hostPath;

string hostPhysicalRoot;

/// <summary>
/// Contains the <see cref="EndOfSendNotification" />
Expand Down Expand Up @@ -274,6 +280,11 @@ static MonoWorkerRequest ()
#endif
);

if (Path.DirectorySeparatorChar != '/') {
needToReplacePathSeparator = true;
pathSeparatorChar = Path.DirectorySeparatorChar;
}

try {
#if NET_2_0
string v = ConfigurationManager.AppSettings ["MonoServerCheckHiddenFiles"];
Expand Down Expand Up @@ -381,6 +392,15 @@ public MonoWorkerRequest (IApplicationHost appHost)
}
}

string HostPhysicalRoot {
get {
if (hostPhysicalRoot == null)
hostPhysicalRoot = appHostBase.Server.PhysicalRoot;

return hostPhysicalRoot;
}
}

/// <summary>
/// Gets the content encoding used by the current instance.
/// </summary>
Expand Down Expand Up @@ -595,30 +615,67 @@ string DoMapPathEvent (string path)
/// register a <see cref="MapPathEventHandler" /> with <see
/// cref="MapPathEvent" />.
/// </remarks>
//
// The logic here is as follows:
//
// If path is equal to the host's virtual path (including trailing slash),
// return the host virtual path.
//
// If path is absolute (starts with '/') then check if it's under our host vpath. If
// it is, base the mapping under the virtual application's physical path. If it
// isn't use the physical root of the application server to return the mapped
// path. If you have just one application configured, then the values computed in
// both of the above cases will be the same. If you have several applications
// configured for this xsp/mod-mono-server instance, then virtual paths outside our
// application virtual path will return physical paths relative to the server's
// physical root, not application's. This is consistent with the way IIS worker
// request works. See bug #575600
//
public override string MapPath (string path)
{
string eventResult = DoMapPathEvent (path);
if (eventResult != null)
return eventResult;

if (path == null || path.Length == 0 || path == HostVPath)
return HostPath.Replace ('/', Path.DirectorySeparatorChar);
string hostVPath = HostVPath;
int hostVPathLen = HostVPath.Length;
int pathLen = path != null ? path.Length : 0;
bool inThisApp;
#if NET_2_0
inThisApp = path.StartsWith (hostVPath, StringComparison.Ordinal);
#else
inThisApp = path.StartsWith (hostVPath);
#endif
if (pathLen == 0 || (inThisApp && (pathLen == hostVPathLen || (pathLen == hostVPathLen + 1 && path [pathLen - 1] == '/')))) {
if (needToReplacePathSeparator)
return HostPath.Replace ('/', pathSeparatorChar);
return HostPath;
}

if (path [0] == '~' && path.Length > 2 && path [1] == '/')
path = path.Substring (1);
string basePath = null;
switch (path [0]) {
case '~':
if (path.Length >= 2 && path [1] == '/')
path = path.Substring (1);
break;

case '/':
if (!inThisApp)
basePath = HostPhysicalRoot;
break;
}

int len = HostVPath.Length;
if (path.StartsWith (HostVPath) && (path.Length == len || path [len] == '/'))
path = path.Substring (len + 1);
if (basePath == null)
basePath = HostPath;

while (path.Length > 0 && path [0] == '/') {
path = path.Substring (1);
}
if (inThisApp && (path.Length == hostVPathLen || path [hostVPathLen] == '/'))
path = path.Substring (hostVPathLen + 1);

if (Path.DirectorySeparatorChar != '/')
path = path.Replace ('/', Path.DirectorySeparatorChar);
path = path.TrimStart (mapPathTrimStartChars);
if (needToReplacePathSeparator)
path = path.Replace ('/', pathSeparatorChar);

return Path.Combine (HostPath, path);
return Path.Combine (basePath, path);
}

/// <summary>
Expand Down

0 comments on commit 5f535fe

Please sign in to comment.