diff --git a/src/dom/uri.cpp b/src/dom/uri.cpp
index 286857e4177c7c87bb160991f90fd613f3f5f729..ff5e91ff8180d78a84d17962024b44f0db805c09 100644 (file)
--- a/src/dom/uri.cpp
+++ b/src/dom/uri.cpp
return path;
}
+DOMString URI::getNativePath() const
+{
+ DOMString npath;
+#ifdef __WIN32__
+ unsigned int firstChar = 0;
+ if (path.size() >= 3)
+ {
+ if (path[0] == '/' &&
+ isLetter(path[1]) &&
+ path[2] == ':')
+ firstChar++;
+ }
+ for (unsigned int i=firstChar ; i<path.size() ; i++)
+ {
+ XMLCh ch = (XMLCh) path[i];
+ if (ch == '/')
+ npath.push_back((XMLCh)'\\');
+ else
+ npath.push_back(ch);
+ }
+#else
+ npath = path;
+#endif
+ return npath;
+}
+
bool URI::isAbsolute() const
{
unsigned int pos = path.rfind('/');
if (pos != path.npos)
{
- DOMString tpath = path.substr(pos);
+ DOMString tpath = path.substr(0, pos+1);
tpath.append(other.path);
newUri.path = tpath;
- newUri.normalize();
}
}
}
+
+ newUri.normalize();
return newUri;
}
/**
- *
+ * This follows the Java URI algorithm:
+ * 1. All "." segments are removed.
+ * 2. If a ".." segment is preceded by a non-".." segment
+ * then both of these segments are removed. This step
+ * is repeated until it is no longer applicable.
+ * 3. If the path is relative, and if its first segment
+ * contains a colon character (':'), then a "." segment
+ * is prepended. This prevents a relative URI with a path
+ * such as "a:b/c/d" from later being re-parsed as an
+ * opaque URI with a scheme of "a" and a scheme-specific
+ * part of "b/c/d". (Deviation from RFC 2396)
*/
-void URI::normalize() const
+void URI::normalize()
{
+ std::vector<DOMString> segments;
+ //## Collect segments
+ if (path.size()<2)
+ return;
+ bool abs = false;
+ unsigned int pos=0;
+ if (path[0]=='/')
+ {
+ abs = true;
+ pos++;
+ }
+ while (pos < path.size())
+ {
+ unsigned int pos2 = path.find('/', pos);
+ if (pos2==path.npos)
+ {
+ DOMString seg = path.substr(pos);
+ //printf("last segment:%s\n", seg.c_str());
+ segments.push_back(seg);
+ break;
+ }
+ if (pos2>pos)
+ {
+ DOMString seg = path.substr(pos, pos2-pos);
+ //printf("segment:%s\n", seg.c_str());
+ segments.push_back(seg);
+ }
+ pos = pos2;
+ pos++;
+ }
+ //## Clean up (normalize) segments
+ bool edited = false;
+ std::vector<DOMString>::iterator iter;
+ for (iter=segments.begin() ; iter!=segments.end() ; )
+ {
+ DOMString s = *iter;
+ if (s == ".")
+ {
+ iter = segments.erase(iter);
+ edited = true;
+ }
+ else if (s == ".." &&
+ iter != segments.begin() &&
+ *(iter-1) != "..")
+ {
+ iter--; //back up, then erase two entries
+ iter = segments.erase(iter);
+ iter = segments.erase(iter);
+ edited = true;
+ }
+ else
+ iter++;
+ }
-
-
+ //## Rebuild path, if necessary
+ if (edited)
+ {
+ path.clear();
+ if (abs)
+ {
+ path.append("/");
+ }
+ std::vector<DOMString>::iterator iter;
+ for (iter=segments.begin() ; iter!=segments.end() ; iter++)
+ {
+ if (iter != segments.begin())
+ path.append("/");
+ path.append(*iter);
+ }
+ }
}
//# Are we absolute?
ch = peek(p);
- if (ch == '/')
+ if (isLetter(ch) && peek(p+1)==':')
+ {
+ absolute = true;
+ path.push_back((XMLCh)'/');
+ }
+ else if (ch == '/')
{
absolute = true;
if (p>p0) //in other words, if '/' is not the first char
{
parselen = str.size();
- DOMString tmp = str;
+
+ DOMString tmp;
+ for (unsigned int i=0 ; i<str.size() ; i++)
+ {
+ XMLCh ch = (XMLCh) str[i];
+ if (ch == '\\')
+ tmp.push_back((XMLCh)'/');
+ else
+ tmp.push_back(ch);
+ }
parsebuf = (char *) tmp.c_str();
int p = parse(0);
+ normalize();
if (p < 0)
{