📄 uri.as
字号:
// Check to see if the port is the default port.
if (thisPort != thatPort)
return URI.NOT_RELATED;
if (compareStr(thisURI.path, thatURI.path, caseSensitive))
return URI.EQUAL;
// Special case check. If we are here, the scheme, authority,
// and port match, and it is not a relative path, but the
// paths did not match. There is a special case where we
// could have:
// http://something.com/
// http://something.com
// Technically, these are equal. So lets, check for this case.
var thisPath:String = thisURI.path;
var thatPath:String = thatURI.path;
if ( (thisPath == "/" || thatPath == "/") &&
(thisPath == "" || thatPath == "") )
{
// We hit the special case. These two are equal.
return URI.EQUAL;
}
// Ok, the paths do not match, but one path may be a parent/child
// of the other. For example, we may have:
// http://something.com/path/to/homepage/
// http://something.com/path/to/homepage/images/logo.gif
// In this case, the first is a parent of the second (or the second
// is a child of the first, depending on which you compare to the
// other). To make this comparison, we must split the path into
// its component parts (split the string on the '/' path delimiter).
// We then compare the
var thisParts:Array, thatParts:Array;
var thisPart:String, thatPart:String;
var i:int;
thisParts = thisPath.split("/");
thatParts = thatPath.split("/");
if (thisParts.length > thatParts.length)
{
thatPart = thatParts[thatParts.length - 1];
if (thatPart.length > 0)
{
// if the last part is not empty, the passed URI is
// not a directory. There is no way the passed URI
// can be a parent.
return URI.NOT_RELATED;
}
else
{
// Remove the empty trailing part
thatParts.pop();
}
// This may be a child of the one passed in
for (i = 0; i < thatParts.length; i++)
{
thisPart = thisParts[i];
thatPart = thatParts[i];
if (compareStr(thisPart, thatPart, caseSensitive) == false)
return URI.NOT_RELATED;
}
return URI.CHILD;
}
else if (thisParts.length < thatParts.length)
{
thisPart = thisParts[thisParts.length - 1];
if (thisPart.length > 0)
{
// if the last part is not empty, this URI is not a
// directory. There is no way this object can be
// a parent.
return URI.NOT_RELATED;
}
else
{
// Remove the empty trailing part
thisParts.pop();
}
// This may be the parent of the one passed in
for (i = 0; i < thisParts.length; i++)
{
thisPart = thisParts[i];
thatPart = thatParts[i];
if (compareStr(thisPart, thatPart, caseSensitive) == false)
return URI.NOT_RELATED;
}
return URI.PARENT;
}
else
{
// Both URI's have the same number of path components, but
// it failed the equivelence check above. This means that
// the two URI's are not related.
return URI.NOT_RELATED;
}
// If we got here, the scheme and authority are the same,
// but the paths pointed to two different locations that
// were in different parts of the file system tree
return URI.NOT_RELATED;
}
/**
* Given another URI, return the common parent between this one
* and the provided URI.
*
* @param uri the other URI from which to find a common parent
* @para caseSensitive true if this operation should be done
* with case sensitive comparisons.
*
* @return the parent URI if successful, null otherwise.
*/
public function getCommonParent(uri:URI, caseSensitive:Boolean = true) : URI
{
var thisURI:URI = URI.resolve(this);
var thatURI:URI = URI.resolve(uri);
if(!thisURI.isAbsolute() || !thatURI.isAbsolute() ||
thisURI.isHierarchical() == false ||
thatURI.isHierarchical() == false)
{
// Both URI's must be absolute hierarchical for this to
// make sense.
return null;
}
var relation:int = thisURI.getRelation(thatURI);
if (relation == URI.NOT_RELATED)
{
// The given URI is not related to this one. No
// common parent.
return null;
}
thisURI.chdir(".");
thatURI.chdir(".");
var strBefore:String, strAfter:String;
do
{
relation = thisURI.getRelation(thatURI, caseSensitive);
if(relation == URI.EQUAL || relation == URI.PARENT)
break;
// If strBefore and strAfter end up being the same,
// we know we are at the root of the path because
// chdir("..") is doing nothing.
strBefore = thisURI.toString();
thisURI.chdir("..");
strAfter = thisURI.toString();
}
while(strBefore != strAfter);
return thisURI;
}
/**
* This function is used to move around in a URI in a way similar
* to the 'cd' or 'chdir' commands on Unix. These operations are
* completely string based, using the context of the URI to
* determine the position within the path. The heuristics used
* to determine the action are based off Appendix C in RFC 2396.
*
* <p>URI paths that end in '/' are considered paths that point to
* directories, while paths that do not end in '/' are files. For
* example, if you execute chdir("d") on the following URI's:<br/>
* 1. http://something.com/a/b/c/ (directory)<br/>
* 2. http://something.com/a/b/c (not directory)<br/>
* you will get:<br/>
* 1. http://something.com/a/b/c/d<br/>
* 2. http://something.com/a/b/d<br/></p>
*
* <p>See RFC 2396, Appendix C for more info.</p>
*
* @param reference the URI or path to "cd" to.
* @param escape true if the passed reference string should be URI
* escaped before using it.
*
* @return true if the chdir was successful, false otherwise.
*/
public function chdir(reference:String, escape:Boolean = false) : Boolean
{
var uriReference:URI;
var ref:String = reference;
if (escape)
ref = URI.escapeChars(reference);
if (ref == "")
{
// NOOP
return true;
}
else if (ref.substr(0, 2) == "//")
{
// Special case. This is an absolute URI but without the scheme.
// Take the scheme from this URI and tack it on. This is
// intended to make working with chdir() a little more
// tolerant.
var final:String = this.scheme + ":" + ref;
return constructURI(final);
}
else if (ref.charAt(0) == "?")
{
// A relative URI that is just a query part is essentially
// a "./?query". We tack on the "./" here to make the rest
// of our logic work.
ref = "./" + ref;
}
// Parse the reference passed in as a URI. This way we
// get any query and fragments parsed out as well.
uriReference = new URI(ref);
if (uriReference.isAbsolute() ||
uriReference.isHierarchical() == false)
{
// If the URI given is a full URI, it replaces this one.
copyURI(uriReference);
return true;
}
var thisPath:String, thatPath:String;
var thisParts:Array, thatParts:Array;
var thisIsDir:Boolean = false, thatIsDir:Boolean = false;
var thisIsAbs:Boolean = false, thatIsAbs:Boolean = false;
var lastIsDotOperation:Boolean = false;
var curDir:String;
var i:int;
thisPath = this.path;
thatPath = uriReference.path;
if (thisPath.length > 0)
thisParts = thisPath.split("/");
else
thisParts = new Array();
if (thatPath.length > 0)
thatParts = thatPath.split("/");
else
thatParts = new Array();
if (thisParts.length > 0 && thisParts[0] == "")
{
thisIsAbs = true;
thisParts.shift(); // pop the first one off the array
}
if (thisParts.length > 0 && thisParts[thisParts.length - 1] == "")
{
thisIsDir = true;
thisParts.pop(); // pop the last one off the array
}
if (thatParts.length > 0 && thatParts[0] == "")
{
thatIsAbs = true;
thatParts.shift(); // pop the first one off the array
}
if (thatParts.length > 0 && thatParts[thatParts.length - 1] == "")
{
thatIsDir = true;
thatParts.pop(); // pop the last one off the array
}
if (thatIsAbs)
{
// The reference is an absolute path (starts with a slash).
// It replaces this path wholesale.
this.path = uriReference.path;
// And it inherits the query and fragment
this.queryRaw = uriReference.queryRaw;
this.fragment = uriReference.fragment;
return true;
}
else if (thatParts.length == 0 && uriReference.query == "")
{
// The reference must have only been a fragment. Fragments just
// get appended to whatever the current path is. We don't want
// to overwrite any query that may already exist, so this case
// only takes on the new fragment.
this.fragment = uriReference.fragment;
return true;
}
else if (thisIsDir == false && thisParts.length > 0)
{
// This path ends in a file. It goes away no matter what.
thisParts.pop();
}
// By default, this assumes the query and fragment of the reference
this.queryRaw = uriReference.queryRaw;
this.fragment = uriReference.fragment;
// Append the parts of the path from the passed in reference
// to this object's path.
thisParts = thisParts.concat(thatParts);
for(i = 0; i < thisParts.length; i++)
{
curDir = thisParts[i];
lastIsDotOperation = false;
if (curDir == ".")
{
thisParts.splice(i, 1);
i = i - 1; // account for removing this item
lastIsDotOperation = true;
}
else if (curDir == "..")
{
if (i >= 1)
{
if (thisParts[i - 1] == "..")
{
// If the previous is a "..", we must have skipped
// it due to this URI being relative. We can't
// collapse leading ".."s in a relative URI, so
// do nothing.
}
else
{
thisParts.splice(i - 1, 2);
i = i - 2; // move back to account for the 2 we removed
}
}
else
{
// This is the first thing in the path.
if (isRelative())
{
// We can't collapse leading ".."s in a relative
// path. Do noting.
}
else
{
// This is an abnormal case. We have dot-dotted up
// past the base of our "file system". This is a
// case where we had a /path/like/this.htm and were
// given a path to chdir to like this:
// ../../../../../../mydir
// Obviously, it has too many ".." and will take us
// up beyond the top of the URI. However, according
// RFC 2396 Appendix C.2, we should try to handle
// these abnormal cases appropriately. In this case,
// we will do what UNIX command lines do if you are
// at the root (/) of the filesystem and execute:
// # cd ../../../../../bin
// Which will put you in /bin. Essentially, the extra
// ".."'s will just get eaten.
thisParts.splice(i, 1);
i = i - 1; // account for the ".." we just removed
}
}
lastIsDotOperation = true;
}
}
var finalPath:String = "";
// If the last thing in the path was a "." or "..", then this thing is a
// directory. If the last thing isn't a dot-op, then we don't want to
// blow away any information about the directory (hence the "|=" binary
// assignment).
thatIsDir = thatIsDir || lastIsDotOperation;
// Reconstruct the path with the abs/dir info we have
finalPath = joinPath(thisParts, thisIsAbs, thatIsDir);
// Set the path (automatically escaping it)
this.path = finalPath;
return true;
}
/**
* @private
* Join an array of path parts back into a URI style path string.
* This is used by the various path logic functions to recombine
* a path. This is different than the standard Array.join()
* function because we need to take into account the starting and
* ending path delimiters if this is an absolute path or a
* directory.
*
* @param parts the Array that contains strings of each path part.
* @param isAbs true if the given path is absolute
* @param isDir true if the given path is a directory
*
* @return the combined path string.
*/
protected function joinPath(parts:Array, isAbs:Boolean, isDir:Boolean) : String
{
var pathStr:String = "";
var i:int;
for (i = 0; i < parts.length; i++)
{
if (pathStr.length > 0)
pathStr += "/";
pathStr += parts[i];
}
// If this path is a directory, tack on the directory delimiter,
// but only if the path contains something. Adding this to an
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -