devtutor: How to Avoid Using Parent Paths
What is Parent Pathing?
A good deal of web scripters start first in the HTML realm and later
learn how to develop server-side scripts. Unfortunately, most of us also
bring a bad HTML habit with us into the scripting realm: the use of parent
pathing. The use of parent paths refers to the technique of "addressing
up" a directory level and then going elsewhere.
Parent Path Example:
If I'm currently working on a page with a URL of http://ase.tufts.edu/its/webParentPath.htm
and need to access an image (using an <img/> tag) located at http://ase.tufts.edu/its/images/image.gif,
my HTML source would look like so...
<img
src="../images/image.gif">
The "../" in the src property is the parent path which basically says
"move up on level to its and then down through images to
image.gif.
Basically, parent pathing allows you to address resources relative to
the object (HTML page, script page, etc.). While this is fine to do in
straight HTML, there are quite a few security issues caused by parent pathing
in scripting. As such, the default setting for parent pathing for sites
hosted on in the Arts & Sciences web hosting environment is off.
Thus, another method needs to be used to avoid needing to use parent
pathing. The best method to avoid parent pathing is using Root Relative
Pathing.
What is Root Relative Pathing?
The use of root relative pathing refers to the technique of addressing
resources relative to the root of the site.
Root Relative Path Example:
If I'm currently working on a page with a URL of http://ase.tufts.edu/its/web/webRootRelative.htm
and need to access an image (using an <img/> tag) located at
http://ase.tufts.edu/its/images/image.gif, my HTML source would look like so...
<img
src="/its/images/image.gif">
The first "/" in the src property specifies that the address is root relative
which basically says "from http://ase.tufts.edu, go down through its to
images and finally to image.gif
The use of root relative pathing, therefore, allows resources to be
accessed from a "top down" approach rather than from a file relative approach.
One very nice side effect of using root relative pathing is that it is
extremely easy to do global find/replaces if you need to move resources (i.e.
just search for "/its/images/image.gif" and replace with
"/its/images/new/image.gif" if the name of the image was to be moved into a new
subdirectory). This isn't all that easy to do if you were using parent
pathing because, depending on the directory structure of your site, the number
of parent "../" to include in the global find/replace wouldn't be as
predictable.
Root Relative Pathing and Include Files
Many sites (especially ASP sites) make use of Include files to
encapsulate commonly used code into a central location. Unfortunately,
many of us also use a parent pathing method of addressing these files.
Include File Parent Pathing Example:
If I'm working on a page with a URL of
http://ase.tufts.edu/its/webIncludeParentPath.asp and need to include an
Include file located at http://ase.tufts.edu/its/includes/include.inc, my
include directive would look like this...
<!-- #Include
File="../includes/include.inc" -->
As in the <img/> example above, the "../" parent path implies that
the address needs to move up one level to its before going through includes
to include. As sites hosted in the A&S web hosting
environment should be avoiding parent paths, include files should be addressed
in a root relative fashion.
Include File Root Relative Example:
If I'm working on a page with a URL of
http://ase.tufts.edu/its/webIncludeRootRelative.asp and need to include an
Include file located at http://ase.tufts.edu/its/includes/include.inc, my
include directive would look like this...
<!-- #Include
Virtual="its/includes/include.inc" -->
The Virtual directive implies that the pathing starts at
http://ase.tufts.edu and can then move through its to includes
and finally to include.inc.
Determining the Absolute Path from a Root Relative Path for
use in Server Side Script
If you site makes use of file IO in any of its server side script, it is
often necessary to know the absolute path of the file so it can be properly
accessed. While some sites may hard code this value into an include file
for use, this is typically not an optimal technique. If an absolute path
is hard coded into an application, the application looses a great deal of
flexibility. If, the site is moved to a different directory for any
reason (sometimes prompted by disk usage and expansion), the script will break.
It is therefore preferable to create a routine to determine the absolute
path based on the root relative path. In ASP and ASP.NET, this can easily
be accomplished using the Server object.
Determining the Absolute Path from the Root Relative Path
Example:
If I need to determine the absolute path of
http://ase.tufts.edu/its/database/myDb.mdb, I would only need to realize that
the root relative path is "its/database/myDb.mdb", and then the Server object
can do the rest of the work. In ASP (using VBScript) the code would look
like this...
Dim strDatabasePath
strDatabasePath = Server.MapPath("/its/database/myDb.mdb")
In ASP.NET (using C#) the code would look like this...
string strDatabasePath =
Server.MapPath("/its/database/myDb.mdb");
Obviously, as you can then accomplish absolute path navigation in your
code by doing the appropriate substitutions on the absolute path we have just
obtained.
Please note, it seems that under the .Net v1.0 Framework, this method will not
produce the desired results if the sub-directory you are targetting is actually
a virtual directory. For example, if the "database" sub-directory was
actually a virtual directory that lived outside of the "its" pathing structure,
the MapPath method would return a result as if the "database" sub-directory was
actually inside the "its" pathing structure.
Determining the Absolute Directory Path from an Absolute File
Path
If I need to know the absolute directory path of
http://ase.tufts.edu/its/dabase/ (for file listing, etc.), we simply make use
of the absolute file path we determined above.
Determining the Absolute Directory Path from an Absolute File
Path Example:
Using ASP & VBScript, the code would look like this...
Dim strDatabase
strDatabase = Server.MapPath("/its/database/myDb.mdb")
strDatabase = Replace(strDatabase, "myDb.mdb", "")
In ASP.NET & C#, the code would look like this...
string strDatabase =
Server.MapPath("/its/database/myDb.mdb").Replace("myDb.mdb","");
Replicating Parent Pathing Functionality Using Root
Relative/Absolute Pathing
While the use of parent pathing is something that you should try to
avoid in general, there are times when it is really quite necessary. For
example, let's say your script needs to access a data file that is placed
completely outside of the web root (for security purposes), but is located
relative to the web root. In such a case, you'd need to replicate parent
pathing functionality using a combination of root relative and absolute
pathing.
This is done by first determining the absolute path of your starting point, then
moving up the directory structure in the required number of steps, and finally,
moving down to the file you're trying to access.
Replicating Parent Pathing Functionality Using Root
Relative/Absolute Pathing Example:
For this example, let us assume that our script is at
http://ase.tufts.edu/its/parentPath.asp(x). Furthermore, there is a directory
called "dataStorage" that is on the same level (and, thus, outside) of the web
root directory (called "wwwroot"). Finally, the file we're trying to access
named "myDb.mdb" is located in a sub-directory of "dataStorage" called "its".
If we were to use parent pathing to access this file the path would be...
../../dataStorage/its/myDb.mdb
To access this file by the method I described above, the code would look
something like this using ASP & VBScript:
' First, get the absolute path of our
starting point.
Dim strDatabase
Dim intCount
Dim intPosition
strDatabase = Server.MapPath("/its/parentPath.asp")
' We now have the absolute path to our starting point.
' Now, we need to address the directory of our starting point
' and then move up two levels.
strDatabase = Replace(strDatabase, "\parentPath.asp", "")
For intCount = 1 To 2
intPosition = InStrRev(strDatabase, "\")
strDatabase = Left(strDatabase, (intPosition - 1))
Next
' We now have the absolute path of the directory
' containing "wwwroot" and "dataStorage".
' Finally, we need to move down the structure to the file.
strDatabase = strDatabase & "\dataStorage\ite\myDb.mdb"
' File path determined!
In ASP.NET & C#, the code would look like this:
// First, get the absolute path of our
starting point.
string sDatabase = Server.MapPath("/its/parentPath.aspx");
// Now, access the directory of the starting point
// and then move up two levels.
sDatabase = sDatabase.Replace("\\parentPath.aspx", "");
for ( int iCount = 0; iCount < 2; iCount++)
{
int iPosition = sDatabase.LastIndexOf("\\");
sDatabase = sDatabase.Substring(0, iPosition);
}
// Finally, move down the structure to the file.
sDatabase += "\\dataStorage\\its\\myDb.mdb";
My thanks to
Mike Hosking for posing the question of how to access files outside the
web root without using parent paths.
Conclusion
As you can see, with just a bit of planning, your site's code need not
depend upon parent pathing. This will enable you to make use of a secure
and more predictable site. Please email any comments regarding this
tutorial to
Will Hilley. Enjoy!!!
|