BUrl: allow URLs without protocol or authority again.
Parsing an URL can never fail. The regexp is designed to match any input. In the worst case, everything will end up in the "path" component. WebPositive relies on this to generate file URLs from a plain path. URLs without a protocol are also possible, and can be used with an implicit protocol. A typical example is network shares sometimes noted in "//host.domain/path/file" form. Add tests for these two cases and fix the parser to behave as expected.
This commit is contained in:
@@ -385,11 +385,12 @@ BUrl::UrlString() const
|
||||
|
||||
if (HasProtocol()) {
|
||||
fUrlString << fProtocol << ':';
|
||||
if (HasAuthority())
|
||||
fUrlString << "//";
|
||||
}
|
||||
|
||||
fUrlString << Authority();
|
||||
if (HasAuthority()) {
|
||||
fUrlString << "//";
|
||||
fUrlString << Authority();
|
||||
}
|
||||
fUrlString << Path();
|
||||
|
||||
if (HasRequest())
|
||||
@@ -922,7 +923,6 @@ enum explode_url_parse_state {
|
||||
EXPLODE_PATH,
|
||||
EXPLODE_REQUEST, // query
|
||||
EXPLODE_FRAGMENT,
|
||||
EXPLODE_ERROR,
|
||||
EXPLODE_COMPLETE
|
||||
};
|
||||
|
||||
@@ -992,7 +992,7 @@ BUrl::_ExplodeUrlString(const BString& url)
|
||||
// The ensuing logic attempts to simulate the behaviour of extracting the groups
|
||||
// from the string without requiring a group-capable regex engine.
|
||||
|
||||
while (state != EXPLODE_ERROR && offset < length) {
|
||||
while (offset < length) {
|
||||
switch (state) {
|
||||
|
||||
case EXPLODE_PROTOCOL:
|
||||
@@ -1005,11 +1005,11 @@ BUrl::_ExplodeUrlString(const BString& url)
|
||||
state = EXPLODE_PROTOCOLTERMINATOR;
|
||||
offset = end_protocol;
|
||||
} else {
|
||||
#if DEBUG
|
||||
fprintf(stderr,
|
||||
"unexpected end of url when parsing the protocol\n");
|
||||
#endif
|
||||
state = EXPLODE_ERROR;
|
||||
// No protocol was found, try parsing from the string
|
||||
// start, beginning with authority or path
|
||||
SetProtocol("");
|
||||
offset = 0;
|
||||
state = EXPLODE_AUTHORITYORPATH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1017,21 +1017,21 @@ BUrl::_ExplodeUrlString(const BString& url)
|
||||
case EXPLODE_PROTOCOLTERMINATOR:
|
||||
{
|
||||
if (url[offset] == ':') {
|
||||
state = EXPLODE_AUTHORITYORPATH;
|
||||
offset++;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"unexpected character '%c' terminating the protocol\n",
|
||||
url_c[offset]);
|
||||
#endif
|
||||
state = EXPLODE_ERROR;
|
||||
// No protocol was found, try parsing from the string
|
||||
// start, beginning with authority or path
|
||||
SetProtocol("");
|
||||
offset = 0;
|
||||
}
|
||||
state = EXPLODE_AUTHORITYORPATH;
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPLODE_AUTHORITYORPATH:
|
||||
{
|
||||
// The authority must start with //. If it isn't there, skip
|
||||
// to parsing the path.
|
||||
if (strncmp(&url_c[offset], "//", 2) == 0) {
|
||||
state = EXPLODE_AUTHORITY;
|
||||
offset += 2;
|
||||
@@ -1085,7 +1085,6 @@ BUrl::_ExplodeUrlString(const BString& url)
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPLODE_ERROR:
|
||||
case EXPLODE_COMPLETE:
|
||||
// should never be reached - keeps the compiler happy
|
||||
break;
|
||||
@@ -1093,14 +1092,6 @@ BUrl::_ExplodeUrlString(const BString& url)
|
||||
}
|
||||
}
|
||||
|
||||
if(state == EXPLODE_ERROR) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "failure to explode url\n");
|
||||
#endif
|
||||
_ResetFields();
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ void UrlTest::TestIsValid()
|
||||
!url.IsValid());
|
||||
|
||||
url.SetHost("<invalid>");
|
||||
CPPUNIT_ASSERT_MESSAGE("Set to an invalid host.", !url.IsValid());
|
||||
CPPUNIT_ASSERT_MESSAGE("Set to an invalid host", !url.IsValid());
|
||||
|
||||
url.SetUrlString("");
|
||||
url.SetProtocol("\t \n");
|
||||
@@ -193,10 +193,16 @@ const ExplodeTest kTestExplode[] =
|
||||
{ "urn", "", "", "", 0, "oasis:names:specification:docbook:dtd:xml:4.1.2", "", "" } },
|
||||
{ "http://www.goodsearch.com/login?return_path=/",
|
||||
{ "http", "", "", "www.goodsearch.com", 0, "/login", "return_path=/", "" } },
|
||||
{ "ldap://[2001:db8::7]/c=GB?objectClass?one",
|
||||
{ "ldap://[2001:db8::7]:389/c=GB?objectClass?one",
|
||||
{ "ldap", "", "", "[2001:db8::7]",389,"/c=GB", "objectClass?one", "" } },
|
||||
{ "ldap://[2001:db8::7]/c=GB?objectClass?one",
|
||||
{ "ldap", "", "", "[2001:db8::7]",0, "/c=GB", "objectClass?one", "" } },
|
||||
{ "HTTP://example.com.:80/%70a%74%68?a=%31#1%323",
|
||||
{ "HTTP", "", "", "example.com.",80, "/%70a%74%68","a=%31","1%323"} }
|
||||
{ "HTTP", "", "", "example.com.",80, "/%70a%74%68","a=%31","1%323"} },
|
||||
{ "/boot/home/Desktop/index.html",
|
||||
{ "", "", "", "", 0, "/boot/home/Desktop/index.html","",""} },
|
||||
{ "//remote.host/boot/home/Desktop",
|
||||
{ "", "", "", "remote.host", 0, "/boot/home/Desktop","",""} }
|
||||
};
|
||||
|
||||
void UrlTest::ExplodeImplodeTest()
|
||||
|
||||
Reference in New Issue
Block a user