in src/xalanc/PlatformSupport/XalanParsedURI.cpp [169:301]
void XalanParsedURI::resolve(
const XalanParsedURI &base
)
{
if (base.isSchemeDefined() == false)
{
// Protect against a base URI that is relative...
// This might become an assert or an exception.
}
// Handle references to the current document (step 2)
else if ((m_defined & (d_scheme | d_authority | d_query)) == 0 &&
m_path.empty())
{
m_defined = base.m_defined;
if (base.m_defined & d_scheme)
m_scheme = base.m_scheme;
if (base.m_defined & d_authority)
m_authority = base.m_authority;
m_path = base.m_path;
if (base.m_defined & d_query)
m_query = base.m_query;
// There is an error/unclarity in the specification in step 2 in that
// it doesn't state that the fragment should be inherited; however
// it is clear from the examples that it should be
if (!(m_defined & d_fragment))
{
m_fragment = base.m_fragment;
}
m_defined |= base.m_defined;
}
// A defined scheme component implies that this is an absolute URI (step 3)
// Also allow a scheme without authority that matches the base scheme to be
// interpreted as a relative URI
else if (!(m_defined & d_scheme) || (
(base.m_defined & d_scheme) && !(m_defined & d_authority)
&& equalsIgnoreCaseASCII(m_scheme, base.m_scheme)))
{
// Inherit the base scheme
if (base.m_defined & d_scheme)
{
m_scheme = base.m_scheme;
m_defined |= d_scheme;
}
// Step 4: If the authority is unm_defined then inherit it, otherwise skip to step 7
if (!(m_defined & d_authority))
{
// Inherit the base authority
if (base.m_defined & d_authority)
{
m_authority = base.m_authority;
m_defined |= d_authority;
}
// Step 5: if the path starts with a / then it is absolute
if (!(m_path.length() > 0 && m_path[0] == XalanUnicode::charSolidus))
{
// Step 6: merge relative path components
// a) strip off characters after the right most slash in the base path
XalanDOMString::size_type pathEnd = base.m_path.length();
while (pathEnd > 0 && base.m_path[pathEnd - 1] != XalanUnicode::charSolidus)
{
--pathEnd;
}
if (pathEnd > 0)
{
// b) append relative path
// This inserts the path portion from base...
m_path.insert(0, base.m_path, 0, pathEnd);
}
else
{
// TODO, maybe raise an error here as this
// is a severely wonky looking URI
}
// c)->g remove various "./" and "../" segments
for (XalanDOMString::size_type index = 0; index < m_path.length(); )
{
// remove '<segment>/../' and ./
if (m_path[index] == XalanUnicode::charFullStop)
{
if (index < m_path.length()-1 &&
m_path[index+1] == XalanUnicode::charSolidus) // ./
{
m_path.erase(index,2);
continue;
}
else if (index == m_path.length()-1) // trailing /.
{
m_path.erase(index,1);
continue;
}
// Note: also strips leading ../ in an attempt to get
// something out of a bad m_path
else if (index < m_path.length()-2 &&
m_path[index+1] == XalanUnicode::charFullStop &&
m_path[index+2] == XalanUnicode::charSolidus) // ../
{
const XalanDOMString::size_type end = index + 2;
if (index > 0) --index;
for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
;
if (index > 0) --index;
m_path.erase(index, end - index);
continue;
}
else if (index == m_path.length()-2 &&
m_path[index+1] == XalanUnicode::charFullStop) // trailing /..
{
const XalanDOMString::size_type end = index + 2;
if (index > 0) --index;
for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
;
m_path.erase(index, end - index);
continue;
}
}
for ( ; index < m_path.length() && m_path[index] != XalanUnicode::charSolidus ; ++index)
{
}
++index;
}
}
}
}
}