Rewritten URI parser

pull/28/head
Tatsuhiro Tsujikawa 2012-10-14 00:14:50 +09:00
parent 5367c34de3
commit 692f978978
7 changed files with 1034 additions and 165 deletions

View File

@ -197,6 +197,7 @@ SRCS = Socket.h\
ChunkedDecodingStreamFilter.cc ChunkedDecodingStreamFilter.h\
NullSinkStreamFilter.cc NullSinkStreamFilter.h\
uri.cc uri.h\
uri_split.c uri_split.h\
Triplet.h\
cookie_helper.cc cookie_helper.h\
json.cc json.h\

View File

@ -36,6 +36,7 @@
#include "A2STR.h"
#include "FeatureConfig.h"
#include "util.h"
#include "uri_split.h"
namespace aria2 {
@ -101,150 +102,69 @@ void swap(UriStruct& lhs, UriStruct& rhs)
bool parse(UriStruct& result, const std::string& uri)
{
// http://user:password@aria2.sourceforge.net:80/dir/file?query#fragment
// | || || | | | |
// | || hostLast| | | | |
// | || portFirst| | | |
// authorityFirst || authorityLast | | |
// || | | | |
// userInfoLast | | | |
// | | | | |
// hostPortFirst | | | |
// | | | |
// dirFirst dirLast| |
// | |
// queryFirst fragmentFirst
// find fragment part
std::string::const_iterator fragmentFirst = uri.begin();
for(; fragmentFirst != uri.end(); ++fragmentFirst) {
if(*fragmentFirst == '#') break;
}
// find query part
std::string::const_iterator queryFirst = uri.begin();
for(; queryFirst != fragmentFirst; ++queryFirst) {
if(*queryFirst == '?') break;
}
result.query.assign(queryFirst, fragmentFirst);
// find protocol
std::string::size_type protocolOffset = uri.find("://");
if(protocolOffset == std::string::npos) return false;
result.protocol.assign(uri.begin(), uri.begin()+protocolOffset);
uint16_t defPort;
if((defPort = getDefaultPort(result.protocol)) == 0) {
return false;
}
// find authority
std::string::const_iterator authorityFirst = uri.begin()+protocolOffset+3;
std::string::const_iterator authorityLast = authorityFirst;
for(; authorityLast != queryFirst; ++authorityLast) {
if(*authorityLast == '/') break;
}
if(authorityFirst == authorityLast) {
// No authority found
return false;
}
// find userinfo(username and password) in authority if they exist
result.username = A2STR::NIL;
result.password = A2STR::NIL;
result.hasPassword = false;
std::string::const_iterator userInfoLast = authorityLast;
std::string::const_iterator hostPortFirst = authorityFirst;
for(; userInfoLast != authorityFirst-1; --userInfoLast) {
if(*userInfoLast == '@') {
hostPortFirst = userInfoLast;
++hostPortFirst;
std::string::const_iterator userLast = authorityFirst;
for(; userLast != userInfoLast; ++userLast) {
if(*userLast == ':') {
result.password =
util::percentDecode(userLast+1,userInfoLast);
result.hasPassword = true;
break;
}
}
result.username =
util::percentDecode(authorityFirst, userLast);
break;
}
}
std::string::const_iterator hostLast = hostPortFirst;
std::string::const_iterator portFirst = authorityLast;
result.ipv6LiteralAddress = false;
if(*hostPortFirst == '[') {
// Detected IPv6 literal address in square brackets
for(; hostLast != authorityLast; ++hostLast) {
if(*hostLast == ']') {
++hostLast;
if(hostLast == authorityLast) {
result.ipv6LiteralAddress = true;
} else {
if(*hostLast == ':') {
portFirst = hostLast;
++portFirst;
result.ipv6LiteralAddress = true;
}
}
break;
}
}
if(!result.ipv6LiteralAddress) {
return false;
}
} else {
for(; hostLast != authorityLast; ++hostLast) {
if(*hostLast == ':') {
portFirst = hostLast;
++portFirst;
break;
}
}
}
if(hostPortFirst == hostLast) {
// No host
return false;
}
if(portFirst == authorityLast) {
// If port is not specified, then we set it to default port of
// its protocol..
result.port = defPort;
} else {
uint32_t tempPort;
if(util::parseUIntNoThrow(tempPort,
std::string(portFirst, authorityLast))) {
if(65535 < tempPort) {
uri_split_result res;
int rv;
const char* p = uri.c_str();
rv = uri_split(&res, p);
if(rv == 0) {
result.protocol.assign(p + res.fields[USR_SCHEME].off,
res.fields[USR_SCHEME].len);
result.host.assign(p + res.fields[USR_HOST].off, res.fields[USR_HOST].len);
if(res.port == 0) {
uint16_t defPort;
if((defPort = getDefaultPort(result.protocol)) == 0) {
return false;
}
result.port = tempPort;
result.port = defPort;
} else {
return false;
result.port = res.port;
}
}
if(result.ipv6LiteralAddress) {
result.host.assign(hostPortFirst+1, hostLast-1);
} else {
result.host.assign(hostPortFirst, hostLast);
}
// find directory and file part
std::string::const_iterator dirLast = authorityLast;
for(std::string::const_iterator i = authorityLast;
i != queryFirst; ++i) {
if(*i == '/') {
dirLast = i+1;
if(res.field_set & (1 << USR_PATH)) {
if(res.field_set & (1 << USR_BASENAME)) {
result.dir.assign(p + res.fields[USR_PATH].off,
res.fields[USR_PATH].len -
res.fields[USR_BASENAME].len);
result.file.assign(p + res.fields[USR_BASENAME].off,
res.fields[USR_BASENAME].len);
} else {
result.dir.assign(p + res.fields[USR_PATH].off,
res.fields[USR_PATH].len);
result.file = A2STR::NIL;
}
} else {
result.dir = "/";
result.file = A2STR::NIL;
}
}
if(dirLast == queryFirst) {
result.file = A2STR::NIL;
if(res.field_set & (1 << USR_QUERY)) {
result.query = "?";
result.query.append(p + res.fields[USR_QUERY].off,
res.fields[USR_QUERY].len);
} else {
result.query = A2STR::NIL;
}
if(res.field_set & (1 << USR_USER)) {
result.username.assign(p + res.fields[USR_USER].off,
res.fields[USR_USER].len);
result.username = util::percentDecode(result.username.begin(),
result.username.end());
} else {
result.username = A2STR::NIL;
}
if(res.field_set & (1 << USR_PASSWD)) {
result.hasPassword = true;
result.password.assign(p + res.fields[USR_PASSWD].off,
res.fields[USR_PASSWD].len);
result.password = util::percentDecode(result.password.begin(),
result.password.end());
} else {
result.hasPassword = false;
result.password = A2STR::NIL;
}
result.ipv6LiteralAddress = res.flags & USF_IPV6ADDR;
return true;
} else {
result.file.assign(dirLast, queryFirst);
return false;
}
// dirFirst == authorityLast
if(authorityLast == dirLast) {
result.dir = "/";
} else {
result.dir.assign(authorityLast, dirLast);
}
return true;
}
std::string construct(const UriStruct& us)

488
src/uri_split.c Normal file
View File

@ -0,0 +1,488 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2012 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "uri_split.h"
#include <stdlib.h>
typedef enum {
URI_BEFORE_SCHEME,
URI_SCHEME,
URI_SCHEME_SLASH1,
URI_SCHEME_SLASH2,
URI_BEFORE_MAYBE_USER,
URI_MAYBE_USER,
URI_BEFORE_MAYBE_PASSWD,
URI_MAYBE_PASSWD,
URI_BEFORE_HOST,
URI_HOST,
URI_BEFORE_IPV6HOST,
URI_IPV6HOST,
URI_AFTER_IPV6HOST,
URI_BEFORE_PORT,
URI_PORT,
URI_PATH,
URI_BEFORE_QUERY,
URI_QUERY,
URI_BEFORE_FRAGMENT,
URI_FRAGMENT
} uri_split_state;
static void uri_set_field(uri_split_result *res, int field,
const char *first, const char *last, const char *uri)
{
if(first) {
res->field_set |= 1 << field;
res->fields[field].off = first - uri;
res->fields[field].len = last - first;
}
}
static int is_digit(char c)
{
return '0' <= c && c <= '9';
}
int uri_split(uri_split_result *res, const char *uri)
{
int state = URI_BEFORE_SCHEME;
const char *scheme_first = NULL, *scheme_last = NULL,
*host_first = NULL, *host_last = NULL,
*path_first = NULL, *path_last = NULL,
*query_first = NULL, *query_last = NULL,
*fragment_first = NULL, *fragment_last = NULL,
*user_first = NULL, *user_last = NULL,
*passwd_first = NULL, *passwd_last = NULL,
*last_atmark = NULL, *last_slash = NULL,
*p = uri;
int32_t port = -1;
uint8_t flags = 0;
for(; *p; ++p) {
switch(state) {
case URI_BEFORE_SCHEME:
scheme_first = p;
state = URI_SCHEME;
break;
case URI_SCHEME:
if(*p == ':') {
scheme_last = p;
state = URI_SCHEME_SLASH1;
}
break;
case URI_SCHEME_SLASH1:
if(*p == '/') {
state = URI_SCHEME_SLASH2;
} else {
return -1;
}
break;
case URI_SCHEME_SLASH2:
if(*p == '/') {
state = URI_BEFORE_MAYBE_USER;
} else {
return -1;
}
break;
case URI_BEFORE_MAYBE_USER:
switch(*p) {
case '@':
case ':':
case '/':
return -1;
case '[':
state = URI_BEFORE_IPV6HOST;
break;
default:
user_first = p;
state = URI_MAYBE_USER;
}
break;
case URI_MAYBE_USER:
switch(*p) {
case '@':
last_atmark = p;
break;
case ':':
user_last = p;
state = URI_BEFORE_MAYBE_PASSWD;
break;
case '[':
if(last_atmark == p - 1) {
user_last = last_atmark;
state = URI_BEFORE_IPV6HOST;
} else {
return -1;
}
break;
case '/':
case '?':
case '#':
/* It turns out that this is only host or user + host if
last_atmark is not NULL. */
if(last_atmark) {
host_first = last_atmark + 1;
host_last = p;
user_last = last_atmark;
} else {
host_first = user_first;
host_last = p;
user_first = user_last = NULL;
}
switch(*p) {
case '/':
path_first = last_slash = p;
state = URI_PATH;
break;
case '?':
state = URI_BEFORE_QUERY;
break;
case '#':
state = URI_BEFORE_FRAGMENT;
break;
}
break;
}
break;
case URI_BEFORE_MAYBE_PASSWD:
passwd_first = p;
switch(*p) {
case '@':
passwd_last = last_atmark = p;
state = URI_BEFORE_HOST;
break;
case '/':
return -1;
default:
/* sums up port number in case of port. */
if(is_digit(*p)) {
port = *p - '0';
}
state = URI_MAYBE_PASSWD;
}
break;
case URI_MAYBE_PASSWD:
switch(*p) {
case '@':
passwd_last = last_atmark = p;
/* Passwd confirmed, reset port to -1. */
port = -1;
state = URI_BEFORE_HOST;
break;
case '[':
return -1;
case '/':
case '?':
case '#':
/* This is port not password. port is in [passwd_first, p) */
if(port == -1) {
return -1;
}
if(last_atmark) {
host_first = last_atmark + 1;
host_last = passwd_first - 1;
user_last = last_atmark;
} else {
host_first = user_first;
host_last = passwd_first - 1;
user_first = user_last = NULL;
}
passwd_first = passwd_last = NULL;
switch(*p) {
case '/':
path_first = last_slash = p;
state = URI_PATH;
break;
case '?':
state = URI_BEFORE_QUERY;
break;
case '#':
state = URI_BEFORE_FRAGMENT;
break;
}
break;
default:
if(port != -1) {
if(is_digit(*p)) {
port *= 10;
port += *p - '0';
if(port > UINT16_MAX) {
port = -1;
}
} else {
port = -1;
}
}
break;
}
break;
case URI_BEFORE_HOST:
switch(*p) {
case ':':
case '/':
return -1;
case '[':
state = URI_BEFORE_IPV6HOST;
break;
default:
host_first = p;
state = URI_HOST;
break;
}
break;
case URI_HOST:
switch(*p) {
case ':':
host_last = p;
state = URI_BEFORE_PORT;
break;
case '/':
host_last = path_first = p;
state = URI_PATH;
break;
case '?':
host_last = p;
state = URI_BEFORE_QUERY;
break;
case '#':
host_last = p;
state = URI_BEFORE_FRAGMENT;
break;
}
break;
case URI_BEFORE_IPV6HOST:
if(*p == ']') {
return -1;
}
host_first = p;
state = URI_IPV6HOST;
break;
case URI_IPV6HOST:
if(*p == ']') {
flags |= USF_IPV6ADDR;
host_last = p;
state = URI_AFTER_IPV6HOST;
}
break;
case URI_AFTER_IPV6HOST:
switch(*p) {
case ':':
state = URI_BEFORE_PORT;
break;
case '/':
path_first = p;
state = URI_PATH;
break;
case '?':
state = URI_BEFORE_QUERY;
break;
case '#':
state = URI_BEFORE_FRAGMENT;
break;
default:
return -1;
}
break;
case URI_BEFORE_PORT:
if(is_digit(*p)) {
port = *p - '0';
state = URI_PORT;
} else {
return -1;
}
break;
case URI_PORT:
switch(*p) {
case '/':
path_first = p;
state = URI_PATH;
break;
case '?':
state = URI_BEFORE_QUERY;
break;
case '#':
state = URI_BEFORE_FRAGMENT;
break;
default:
if(is_digit(*p)) {
port *= 10;
port += *p - '0';
if(port > UINT16_MAX) {
return -1;
}
} else {
return -1;
}
}
break;
case URI_PATH:
switch(*p) {
case '/':
last_slash = p;
break;
case '?':
path_last = p;
state = URI_BEFORE_QUERY;
break;
case '#':
path_last = p;
state = URI_BEFORE_FRAGMENT;
break;
}
break;
case URI_BEFORE_QUERY:
query_first = p;
if(*p == '#') {
query_last = p;
state = URI_BEFORE_FRAGMENT;
} else {
state = URI_QUERY;
}
break;
case URI_QUERY:
if(*p == '#') {
query_last = p;
state = URI_BEFORE_FRAGMENT;
}
break;
case URI_BEFORE_FRAGMENT:
fragment_first = p;
state = URI_FRAGMENT;
break;
case URI_FRAGMENT:
break;
}
}
/* Handle premature states */
switch(state) {
case URI_BEFORE_SCHEME:
case URI_SCHEME:
case URI_SCHEME_SLASH1:
case URI_SCHEME_SLASH2:
return -1;
case URI_BEFORE_MAYBE_USER:
return -1;
case URI_MAYBE_USER:
if(last_atmark) {
host_first = last_atmark + 1;
host_last = p;
if(host_first == host_last) {
return -1;
}
user_last = last_atmark;
} else {
host_first = user_first;
host_last = p;
user_first = user_last = NULL;
}
break;
case URI_BEFORE_MAYBE_PASSWD:
return -1;
case URI_MAYBE_PASSWD:
if(port == -1) {
return -1;
}
if(last_atmark) {
host_first = last_atmark + 1;
host_last = passwd_first - 1;
user_last = last_atmark;
} else {
host_first = user_first;
host_last = passwd_first - 1;
user_first = user_last = NULL;
}
passwd_first = passwd_last = NULL;
break;
case URI_BEFORE_HOST:
return -1;
case URI_HOST:
host_last = p;
break;
case URI_BEFORE_IPV6HOST:
case URI_IPV6HOST:
return -1;
case URI_AFTER_IPV6HOST:
break;
case URI_BEFORE_PORT:
return -1;
case URI_PORT:
if(port == -1) {
return -1;
}
break;
case URI_PATH:
path_last = p;
break;
case URI_BEFORE_QUERY:
query_first = query_last = p;
break;
case URI_QUERY:
query_last = p;
break;
case URI_BEFORE_FRAGMENT:
fragment_first = fragment_last = p;
break;
case URI_FRAGMENT:
fragment_last = p;
break;
default:
return -1;
};
if(res) {
res->field_set = 0;
res->port = 0;
res->flags = flags;
uri_set_field(res, USR_SCHEME, scheme_first, scheme_last, uri);
uri_set_field(res, USR_HOST, host_first, host_last, uri);
uri_set_field(res, USR_PATH, path_first, path_last, uri);
uri_set_field(res, USR_QUERY, query_first, query_last, uri);
uri_set_field(res, USR_FRAGMENT, fragment_first, fragment_last, uri);
uri_set_field(res, USR_USER, user_first, user_last, uri);
uri_set_field(res, USR_PASSWD, passwd_first, passwd_last, uri);
if(res->field_set & (1 << USR_USER)) {
uri_set_field(res, USR_USERINFO, user_first, last_atmark, uri);
}
if(last_slash && last_slash + 1 != path_last) {
uri_set_field(res, USR_BASENAME, last_slash + 1, path_last, uri);
}
if(port != -1) {
res->field_set |= 1 << USR_PORT;
res->port = port;
}
}
return 0;
}

92
src/uri_split.h Normal file
View File

@ -0,0 +1,92 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2012 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_URI_SPLIT_H
#define D_URI_SPLIT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <stdint.h>
typedef enum {
USR_SCHEME,
USR_HOST,
USR_PORT,
USR_PATH,
USR_QUERY,
USR_FRAGMENT,
USR_USERINFO,
USR_USER,
USR_PASSWD,
USR_BASENAME,
USR_MAX
} uri_split_field;
typedef enum {
USF_IPV6ADDR = 1
} uri_split_flag;
/* The structure is based on http-parser by Joyent, Inc and other Node
contributors. https://github.com/joyent/http-parser */
typedef struct {
uint16_t field_set;
uint16_t port;
struct {
uint16_t off;
uint16_t len;
} fields[USR_MAX];
uint8_t flags;
} uri_split_result;
/* Splits URI |uri| and stores the results in the |res|. To check
* particular URI component is available, evaluate |res->field_set|
* with 1 shifted by the field defined in uri_split_field. If the
* |res| is NULL, processing is done but the result will not stored.
* If the host component of the |uri| is IPv6 numeric address, then
* USF_IPV6ADDR & res->flags will be nonzero.
*
* This function returns 0 if it succeeds, or -1.
*/
int uri_split(uri_split_result *res, const char *uri);
#ifdef __cplusplus
}
#endif
#endif /* D_URI_SPLIT_H */

View File

@ -71,6 +71,7 @@ aria2c_SOURCES = AllTest.cc\
ValueBaseTest.cc\
ChunkedDecodingStreamFilterTest.cc\
UriTest.cc\
UriSplitTest.cc\
MockSegment.h\
TripletTest.cc\
CookieHelperTest.cc\

389
test/UriSplitTest.cc Normal file
View File

@ -0,0 +1,389 @@
#include "uri_split.h"
#include <cstring>
#include <cppunit/extensions/HelperMacros.h>
#include "uri_split.h"
namespace aria2 {
class UriSplitTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(UriSplitTest);
CPPUNIT_TEST(testUriSplit);
CPPUNIT_TEST(testUriSplit_fail);
CPPUNIT_TEST_SUITE_END();
public:
void testUriSplit();
void testUriSplit_fail();
};
CPPUNIT_TEST_SUITE_REGISTRATION( UriSplitTest );
namespace {
const char* fieldstr[] = {
"USR_SCHEME",
"USR_HOST",
"USR_PORT",
"USR_PATH",
"USR_QUERY",
"USR_FRAGMENT",
"USR_USERINFO",
"USR_USER",
"USR_PASSWD",
"USR_BASENAME"
};
} // namespace
#define CHECK_FIELD_SET(RES, FLAGS) \
for(int i = 0; i < USR_MAX; ++i) { \
int mask = 1 << i; \
if((FLAGS) & mask) { \
CPPUNIT_ASSERT_MESSAGE(fieldstr[i], RES.field_set & mask); \
} else { \
CPPUNIT_ASSERT_MESSAGE(fieldstr[i], !(RES.field_set & mask)); \
} \
}
namespace {
std::string mkstr(const uri_split_result& res, int field, const char* base)
{
return std::string(base + res.fields[field].off, res.fields[field].len);
}
} // namespace
void UriSplitTest::testUriSplit()
{
uri_split_result res;
const char* uri;
uri = "http://aria2.sf.net/path/";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH));
CPPUNIT_ASSERT_EQUAL(std::string("http"), mkstr(res, USR_SCHEME, uri));
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sf.net"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/path/"), mkstr(res, USR_PATH, uri));
uri = "http://user@aria2.sf.net/path/";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_USERINFO) | (1 << USR_USER));
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sf.net"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/path/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
uri = "http://user:pass@aria2.sf.net/path/";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_USERINFO) | (1 << USR_USER) | (1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sf.net"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/path/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user:pass"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
// According to RFC 3986, @ in userinfo is illegal. But many people
// have e-mail account as username and don't understand
// percent-encoding and keep getting erros putting it in URI in
// unecoded form. Because of this, we support @ in username.
uri = "http://user@foo.com:pass@aria2.sf.net/path/";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_USERINFO) | (1 << USR_USER) | (1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sf.net"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/path/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user@foo.com:pass"),
mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user@foo.com"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
// Port processed in URI_MAYBE_USER -> URI_PORT
uri = "https://aria2.sf.net:443/path/";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT) |
(1 << USR_PATH));
CPPUNIT_ASSERT_EQUAL(std::string("https"), mkstr(res, USR_SCHEME, uri));
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sf.net"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/path/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
// Port processed in URI_PORT
uri = "https://user:pass@aria2.sf.net:443/path/";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT) |
(1 << USR_PATH) | (1 << USR_USERINFO) | (1 << USR_USER) |
(1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sf.net"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/path/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user:pass"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
// Port processed in URI_MAYBE_PASSWD
uri = "https://user@aria2.sf.net:443/path/";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT) |
(1 << USR_PATH) | (1 << USR_USERINFO) | (1 << USR_USER));
CPPUNIT_ASSERT_EQUAL(std::string("aria2.sf.net"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/path/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
// Port processed in URI_MAYBE_PASSWD
uri = "http://aria2";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
uri = "http://aria2:8080";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)8080, res.port);
uri = "http://user@aria2";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_USERINFO) | (1 << USR_USER));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
uri = "http://user:@aria2";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_USERINFO) | (1 << USR_USER) | (1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user:"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string(""), mkstr(res, USR_PASSWD, uri));
uri = "http://aria2/?foo#bar";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_QUERY) | (1 << USR_FRAGMENT));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("foo"), mkstr(res, USR_QUERY, uri));
CPPUNIT_ASSERT_EQUAL(std::string("bar"), mkstr(res, USR_FRAGMENT, uri));
// URI_MAYBE_USER
uri = "http://aria2?foo";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_QUERY));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("foo"), mkstr(res, USR_QUERY, uri));
// URI_MAYBE_USER
uri = "http://aria2#bar";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_FRAGMENT));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("bar"), mkstr(res, USR_FRAGMENT, uri));
// URI_MAYBE_PASSWD
uri = "https://aria2:443?foo";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT) |
(1 << USR_QUERY));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("foo"), mkstr(res, USR_QUERY, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
// URI_MAYBE_PASSWD
uri = "https://aria2:443#bar";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT) |
(1 << USR_FRAGMENT));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("bar"), mkstr(res, USR_FRAGMENT, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
// URI_PORT
uri = "https://user:pass@aria2:443?foo";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT) |
(1 << USR_QUERY) | (1 << USR_USERINFO) | (1 << USR_USER) |
(1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
CPPUNIT_ASSERT_EQUAL(std::string("foo"), mkstr(res, USR_QUERY, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
// URI_PORT
uri = "https://user:pass@aria2:443#bar";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT) |
(1 << USR_FRAGMENT) | (1 << USR_USERINFO) | (1 << USR_USER) |
(1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
CPPUNIT_ASSERT_EQUAL(std::string("bar"), mkstr(res, USR_FRAGMENT, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
// URI_HOST
uri = "http://user:pass@aria2?foo";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_QUERY) | (1 << USR_USERINFO) |
(1 << USR_USER) | (1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
CPPUNIT_ASSERT_EQUAL(std::string("foo"), mkstr(res, USR_QUERY, uri));
// URI_HOST
uri = "http://user:pass@aria2#bar";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_FRAGMENT) | (1 << USR_USERINFO) |
(1 << USR_USER) | (1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
CPPUNIT_ASSERT_EQUAL(std::string("bar"), mkstr(res, USR_FRAGMENT, uri));
// empty query
uri = "http://aria2/?";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_QUERY));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string(""), mkstr(res, USR_QUERY, uri));
// empty fragment
uri = "http://aria2/#";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_FRAGMENT));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string(""), mkstr(res, USR_FRAGMENT, uri));
// empty query and fragment
uri = "http://aria2/?#";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_QUERY) | (1 << USR_FRAGMENT));
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("/"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string(""), mkstr(res, USR_QUERY, uri));
CPPUNIT_ASSERT_EQUAL(std::string(""), mkstr(res, USR_FRAGMENT, uri));
// IPv6 numeric address
uri = "http://[::1]";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST));
CPPUNIT_ASSERT_EQUAL(std::string("::1"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT(res.flags & USF_IPV6ADDR);
uri = "https://[::1]:443";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PORT));
CPPUNIT_ASSERT_EQUAL(std::string("::1"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL((uint16_t)443, res.port);
CPPUNIT_ASSERT(res.flags & USF_IPV6ADDR);
// USR_MAYBE_USER
uri = "https://user@[::1]";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_USERINFO) | (1 << USR_USER));
CPPUNIT_ASSERT_EQUAL(std::string("::1"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT(res.flags & USF_IPV6ADDR);
// USR_BEFORE_HOST
uri = "https://user:pass@[::1]";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) |
(1 << USR_USERINFO) | (1 << USR_USER) | (1 << USR_PASSWD));
CPPUNIT_ASSERT_EQUAL(std::string("::1"), mkstr(res, USR_HOST, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user:pass"), mkstr(res, USR_USERINFO, uri));
CPPUNIT_ASSERT_EQUAL(std::string("user"), mkstr(res, USR_USER, uri));
CPPUNIT_ASSERT_EQUAL(std::string("pass"), mkstr(res, USR_PASSWD, uri));
CPPUNIT_ASSERT(res.flags & USF_IPV6ADDR);
uri = "http://aria2/f";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_BASENAME));
CPPUNIT_ASSERT_EQUAL(std::string("/f"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("f"), mkstr(res, USR_BASENAME, uri));
uri = "http://aria2/index.html?foo";
memset(&res, 0, sizeof(res));
CPPUNIT_ASSERT_EQUAL(0, uri_split(&res, uri));
CHECK_FIELD_SET(res, (1 << USR_SCHEME) | (1 << USR_HOST) | (1 << USR_PATH) |
(1 << USR_QUERY) | (1 << USR_BASENAME));
CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), mkstr(res, USR_PATH, uri));
CPPUNIT_ASSERT_EQUAL(std::string("index.html"),
mkstr(res, USR_BASENAME, uri));
CPPUNIT_ASSERT_EQUAL(std::string("foo"), mkstr(res, USR_QUERY, uri));
}
void UriSplitTest::testUriSplit_fail()
{
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, ""));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "h"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http:"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http:a"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http:/"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http:/a"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://:host"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://@user@host"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:pass"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:65536"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:pass?"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:pass@host:65536"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:pass@host:x"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:pass@host:80x"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user@"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://[]"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://[::"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user[::1]"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user[::1]x"));
CPPUNIT_ASSERT_EQUAL(-1, uri_split(NULL, "http://user:pass[::1]"));
}
} // namespace aria2

View File

@ -302,34 +302,12 @@ void UriTest::testSetUri20()
void UriTest::testSetUri_zeroUsername()
{
UriStruct us;
CPPUNIT_ASSERT(parse(us, "ftp://@localhost/download/aria2-1.0.0.tar.bz2"));
CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol);
CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port);
CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host);
CPPUNIT_ASSERT_EQUAL(std::string("/download/"), us.dir);
CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file);
CPPUNIT_ASSERT_EQUAL(std::string(""), us.username);
CPPUNIT_ASSERT_EQUAL(std::string(""), us.password);
CPPUNIT_ASSERT(!parse(us, "ftp://@localhost/download/aria2-1.0.0.tar.bz2"));
CPPUNIT_ASSERT(parse(us, "ftp://:@localhost/download/aria2-1.0.0.tar.bz2"));
CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol);
CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port);
CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host);
CPPUNIT_ASSERT_EQUAL(std::string("/download/"), us.dir);
CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file);
CPPUNIT_ASSERT_EQUAL(std::string(""), us.username);
CPPUNIT_ASSERT_EQUAL(std::string(""), us.password);
CPPUNIT_ASSERT(parse(us,
"ftp://:pass@localhost/download/aria2-1.0.0.tar.bz2"));
CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol);
CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port);
CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host);
CPPUNIT_ASSERT_EQUAL(std::string("/download/"), us.dir);
CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file);
CPPUNIT_ASSERT_EQUAL(std::string(""), us.username);
CPPUNIT_ASSERT_EQUAL(std::string("pass"), us.password);
CPPUNIT_ASSERT(!parse(us, "ftp://:@localhost/download/aria2-1.0.0.tar.bz2"));
CPPUNIT_ASSERT(!parse(us,
"ftp://:pass@localhost/download/aria2-1.0.0.tar.bz2"));
}
void UriTest::testSetUri_username()
@ -354,11 +332,11 @@ void UriTest::testSetUri_usernamePassword()
"aria2-1.0.0.tar.bz2"));
CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol);
CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port);
CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host);
CPPUNIT_ASSERT_EQUAL(std::string("pass%40@localhost"), us.host);
CPPUNIT_ASSERT_EQUAL(std::string("/download/"), us.dir);
CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file);
CPPUNIT_ASSERT_EQUAL(std::string("aria2@user@"), us.username);
CPPUNIT_ASSERT_EQUAL(std::string("aria2@pass@"), us.password);
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), us.password);
// make sure that after new uri is set, username and password are updated.
CPPUNIT_ASSERT(parse(us, "ftp://localhost/download/aria2-1.0.0.tar.bz2"));