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()) {
|
if (HasProtocol()) {
|
||||||
fUrlString << fProtocol << ':';
|
fUrlString << fProtocol << ':';
|
||||||
if (HasAuthority())
|
|
||||||
fUrlString << "//";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fUrlString << Authority();
|
if (HasAuthority()) {
|
||||||
|
fUrlString << "//";
|
||||||
|
fUrlString << Authority();
|
||||||
|
}
|
||||||
fUrlString << Path();
|
fUrlString << Path();
|
||||||
|
|
||||||
if (HasRequest())
|
if (HasRequest())
|
||||||
@@ -922,7 +923,6 @@ enum explode_url_parse_state {
|
|||||||
EXPLODE_PATH,
|
EXPLODE_PATH,
|
||||||
EXPLODE_REQUEST, // query
|
EXPLODE_REQUEST, // query
|
||||||
EXPLODE_FRAGMENT,
|
EXPLODE_FRAGMENT,
|
||||||
EXPLODE_ERROR,
|
|
||||||
EXPLODE_COMPLETE
|
EXPLODE_COMPLETE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -992,7 +992,7 @@ BUrl::_ExplodeUrlString(const BString& url)
|
|||||||
// The ensuing logic attempts to simulate the behaviour of extracting the groups
|
// The ensuing logic attempts to simulate the behaviour of extracting the groups
|
||||||
// from the string without requiring a group-capable regex engine.
|
// from the string without requiring a group-capable regex engine.
|
||||||
|
|
||||||
while (state != EXPLODE_ERROR && offset < length) {
|
while (offset < length) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
|
||||||
case EXPLODE_PROTOCOL:
|
case EXPLODE_PROTOCOL:
|
||||||
@@ -1005,11 +1005,11 @@ BUrl::_ExplodeUrlString(const BString& url)
|
|||||||
state = EXPLODE_PROTOCOLTERMINATOR;
|
state = EXPLODE_PROTOCOLTERMINATOR;
|
||||||
offset = end_protocol;
|
offset = end_protocol;
|
||||||
} else {
|
} else {
|
||||||
#if DEBUG
|
// No protocol was found, try parsing from the string
|
||||||
fprintf(stderr,
|
// start, beginning with authority or path
|
||||||
"unexpected end of url when parsing the protocol\n");
|
SetProtocol("");
|
||||||
#endif
|
offset = 0;
|
||||||
state = EXPLODE_ERROR;
|
state = EXPLODE_AUTHORITYORPATH;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1017,21 +1017,21 @@ BUrl::_ExplodeUrlString(const BString& url)
|
|||||||
case EXPLODE_PROTOCOLTERMINATOR:
|
case EXPLODE_PROTOCOLTERMINATOR:
|
||||||
{
|
{
|
||||||
if (url[offset] == ':') {
|
if (url[offset] == ':') {
|
||||||
state = EXPLODE_AUTHORITYORPATH;
|
|
||||||
offset++;
|
offset++;
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG
|
// No protocol was found, try parsing from the string
|
||||||
fprintf(stderr,
|
// start, beginning with authority or path
|
||||||
"unexpected character '%c' terminating the protocol\n",
|
SetProtocol("");
|
||||||
url_c[offset]);
|
offset = 0;
|
||||||
#endif
|
|
||||||
state = EXPLODE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
state = EXPLODE_AUTHORITYORPATH;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EXPLODE_AUTHORITYORPATH:
|
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) {
|
if (strncmp(&url_c[offset], "//", 2) == 0) {
|
||||||
state = EXPLODE_AUTHORITY;
|
state = EXPLODE_AUTHORITY;
|
||||||
offset += 2;
|
offset += 2;
|
||||||
@@ -1085,7 +1085,6 @@ BUrl::_ExplodeUrlString(const BString& url)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EXPLODE_ERROR:
|
|
||||||
case EXPLODE_COMPLETE:
|
case EXPLODE_COMPLETE:
|
||||||
// should never be reached - keeps the compiler happy
|
// should never be reached - keeps the compiler happy
|
||||||
break;
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void UrlTest::TestIsValid()
|
|||||||
!url.IsValid());
|
!url.IsValid());
|
||||||
|
|
||||||
url.SetHost("<invalid>");
|
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.SetUrlString("");
|
||||||
url.SetProtocol("\t \n");
|
url.SetProtocol("\t \n");
|
||||||
@@ -193,10 +193,16 @@ const ExplodeTest kTestExplode[] =
|
|||||||
{ "urn", "", "", "", 0, "oasis:names:specification:docbook:dtd:xml:4.1.2", "", "" } },
|
{ "urn", "", "", "", 0, "oasis:names:specification:docbook:dtd:xml:4.1.2", "", "" } },
|
||||||
{ "http://www.goodsearch.com/login?return_path=/",
|
{ "http://www.goodsearch.com/login?return_path=/",
|
||||||
{ "http", "", "", "www.goodsearch.com", 0, "/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]",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"} }
|
{ "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()
|
void UrlTest::ExplodeImplodeTest()
|
||||||
|
|||||||
Reference in New Issue
Block a user