mirror of https://github.com/aria2/aria2
2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added bencode helper functions and BDE class. They will replace MetaFileUtil and Dictionary/List/Data classes. * src/Makefile.am * src/bencode.cc * src/bencode.h * test/BencodeTest.cc * test/Makefile.ampull/1/head
parent
bd8645262d
commit
1b54e64d34
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Added bencode helper functions and BDE class.
|
||||
They will replace MetaFileUtil and Dictionary/List/Data classes.
|
||||
* src/Makefile.am
|
||||
* src/bencode.cc
|
||||
* src/bencode.h
|
||||
* test/BencodeTest.cc
|
||||
* test/Makefile.am
|
||||
|
||||
2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Fixed the bug that bad URI is sent to the tracker when the announe
|
||||
|
|
|
@ -193,7 +193,8 @@ SRCS = Socket.h\
|
|||
NsCookieParser.cc NsCookieParser.h\
|
||||
CookieStorage.cc CookieStorage.h\
|
||||
SocketBuffer.cc SocketBuffer.h\
|
||||
OptionHandlerException.cc OptionHandlerException.h
|
||||
OptionHandlerException.cc OptionHandlerException.h\
|
||||
bencode.cc bencode.h
|
||||
|
||||
if ENABLE_SSL
|
||||
SRCS += TLSContext.h
|
||||
|
|
|
@ -417,9 +417,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
ServerStatURISelector.h NsCookieParser.cc NsCookieParser.h \
|
||||
CookieStorage.cc CookieStorage.h SocketBuffer.cc \
|
||||
SocketBuffer.h OptionHandlerException.cc \
|
||||
OptionHandlerException.h TLSContext.h LibgnutlsTLSContext.cc \
|
||||
LibgnutlsTLSContext.h LibsslTLSContext.cc LibsslTLSContext.h \
|
||||
GZipDecoder.cc GZipDecoder.h Sqlite3MozCookieParser.cc \
|
||||
OptionHandlerException.h bencode.cc bencode.h TLSContext.h \
|
||||
LibgnutlsTLSContext.cc LibgnutlsTLSContext.h \
|
||||
LibsslTLSContext.cc LibsslTLSContext.h GZipDecoder.cc \
|
||||
GZipDecoder.h Sqlite3MozCookieParser.cc \
|
||||
Sqlite3MozCookieParser.h AsyncNameResolver.cc \
|
||||
AsyncNameResolver.h IteratableChunkChecksumValidator.cc \
|
||||
IteratableChunkChecksumValidator.h \
|
||||
|
@ -813,14 +814,14 @@ am__objects_21 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
|
|||
ServerStatMan.$(OBJEXT) InOrderURISelector.$(OBJEXT) \
|
||||
ServerStatURISelector.$(OBJEXT) NsCookieParser.$(OBJEXT) \
|
||||
CookieStorage.$(OBJEXT) SocketBuffer.$(OBJEXT) \
|
||||
OptionHandlerException.$(OBJEXT) $(am__objects_1) \
|
||||
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
||||
$(am__objects_5) $(am__objects_6) $(am__objects_7) \
|
||||
$(am__objects_8) $(am__objects_9) $(am__objects_10) \
|
||||
$(am__objects_11) $(am__objects_12) $(am__objects_13) \
|
||||
$(am__objects_14) $(am__objects_15) $(am__objects_16) \
|
||||
$(am__objects_17) $(am__objects_18) $(am__objects_19) \
|
||||
$(am__objects_20)
|
||||
OptionHandlerException.$(OBJEXT) bencode.$(OBJEXT) \
|
||||
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
|
||||
$(am__objects_7) $(am__objects_8) $(am__objects_9) \
|
||||
$(am__objects_10) $(am__objects_11) $(am__objects_12) \
|
||||
$(am__objects_13) $(am__objects_14) $(am__objects_15) \
|
||||
$(am__objects_16) $(am__objects_17) $(am__objects_18) \
|
||||
$(am__objects_19) $(am__objects_20)
|
||||
am_libaria2c_a_OBJECTS = $(am__objects_21)
|
||||
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
|
@ -1144,13 +1145,14 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
|
|||
ServerStatURISelector.h NsCookieParser.cc NsCookieParser.h \
|
||||
CookieStorage.cc CookieStorage.h SocketBuffer.cc \
|
||||
SocketBuffer.h OptionHandlerException.cc \
|
||||
OptionHandlerException.h $(am__append_1) $(am__append_2) \
|
||||
$(am__append_3) $(am__append_4) $(am__append_5) \
|
||||
$(am__append_6) $(am__append_7) $(am__append_8) \
|
||||
$(am__append_9) $(am__append_10) $(am__append_11) \
|
||||
$(am__append_12) $(am__append_13) $(am__append_14) \
|
||||
$(am__append_15) $(am__append_16) $(am__append_17) \
|
||||
$(am__append_18) $(am__append_19) $(am__append_20)
|
||||
OptionHandlerException.h bencode.cc bencode.h $(am__append_1) \
|
||||
$(am__append_2) $(am__append_3) $(am__append_4) \
|
||||
$(am__append_5) $(am__append_6) $(am__append_7) \
|
||||
$(am__append_8) $(am__append_9) $(am__append_10) \
|
||||
$(am__append_11) $(am__append_12) $(am__append_13) \
|
||||
$(am__append_14) $(am__append_15) $(am__append_16) \
|
||||
$(am__append_17) $(am__append_18) $(am__append_19) \
|
||||
$(am__append_20)
|
||||
noinst_LIBRARIES = libaria2c.a
|
||||
libaria2c_a_SOURCES = $(SRCS)
|
||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
||||
|
@ -1522,6 +1524,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VersionMetalinkParserState.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XML2SAXMetalinkProcessor.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asctime_r.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bencode.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/download_helper.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gai_strerror.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getaddrinfo.Po@am__quote@
|
||||
|
|
|
@ -0,0 +1,469 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 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 "bencode.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "StringFormat.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
namespace bencode {
|
||||
|
||||
const BDE BDE::none;
|
||||
|
||||
BDE::BDE() throw():_type(TYPE_NONE) {}
|
||||
|
||||
BDE::BDE(Integer integer) throw():_type(TYPE_INTEGER),
|
||||
_integer(new Integer(integer)) {}
|
||||
|
||||
|
||||
BDE::BDE(const std::string& string) throw():_type(TYPE_STRING),
|
||||
_string(new std::string(string)) {}
|
||||
|
||||
BDE::BDE(const char* cstring) throw():_type(TYPE_STRING),
|
||||
_string(new std::string(cstring)) {}
|
||||
|
||||
BDE::BDE(const char* data, size_t length) throw():
|
||||
_type(TYPE_STRING),
|
||||
_string(new std::string(&data[0], &data[length])) {}
|
||||
|
||||
BDE::BDE(const unsigned char* data, size_t length) throw():
|
||||
_type(TYPE_STRING),
|
||||
_string(new std::string(&data[0], &data[length])) {}
|
||||
|
||||
BDE BDE::dict() throw()
|
||||
{
|
||||
BDE bde;
|
||||
bde._type = TYPE_DICT;
|
||||
bde._dict.reset(new Dict());
|
||||
return bde;
|
||||
}
|
||||
|
||||
BDE BDE::list() throw()
|
||||
{
|
||||
BDE bde;
|
||||
bde._type = TYPE_LIST;
|
||||
bde._list.reset(new List());
|
||||
return bde;
|
||||
}
|
||||
|
||||
// Test for Null data
|
||||
bool BDE::isNone() const throw()
|
||||
{
|
||||
return _type == TYPE_NONE;
|
||||
}
|
||||
|
||||
// Integer Interface
|
||||
|
||||
bool BDE::isInteger() const throw()
|
||||
{
|
||||
return _type == TYPE_INTEGER;
|
||||
}
|
||||
|
||||
BDE::Integer BDE::i() const throw(RecoverableException)
|
||||
{
|
||||
if(isInteger()) {
|
||||
return *_integer.get();
|
||||
} else {
|
||||
throw RecoverableException("Not Integer");
|
||||
}
|
||||
}
|
||||
|
||||
// String Interface
|
||||
|
||||
bool BDE::isString() const throw()
|
||||
{
|
||||
return _type == TYPE_STRING;
|
||||
}
|
||||
|
||||
const std::string& BDE::s() const throw(RecoverableException)
|
||||
{
|
||||
if(isString()) {
|
||||
return *_string.get();
|
||||
} else {
|
||||
throw RecoverableException("Not String");
|
||||
}
|
||||
}
|
||||
|
||||
// Dictionary Interface
|
||||
|
||||
bool BDE::isDict() const throw()
|
||||
{
|
||||
return _type == TYPE_DICT;
|
||||
}
|
||||
|
||||
BDE& BDE::operator[](const std::string& key) throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return (*_dict.get())[key];
|
||||
} else {
|
||||
throw RecoverableException("Not Dict");
|
||||
}
|
||||
}
|
||||
|
||||
const BDE& BDE::operator[](const std::string& key) const
|
||||
throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
BDE::Dict::const_iterator i = _dict->find(key);
|
||||
if(i == _dict->end()) {
|
||||
return none;
|
||||
} else {
|
||||
return (*i).second;
|
||||
}
|
||||
} else {
|
||||
throw RecoverableException("Not Dict");
|
||||
}
|
||||
}
|
||||
|
||||
bool BDE::containsKey(const std::string& key) const throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return _dict->find(key) != _dict->end();
|
||||
} else {
|
||||
throw RecoverableException("Not Dict");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BDE::Dict::iterator BDE::dictBegin() throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return _dict->begin();
|
||||
} else {
|
||||
throw RecoverableException("Not Dict");
|
||||
}
|
||||
}
|
||||
|
||||
BDE::Dict::const_iterator BDE::dictBegin() const throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return _dict->begin();
|
||||
} else {
|
||||
throw RecoverableException("Not Dict");
|
||||
}
|
||||
}
|
||||
|
||||
BDE::Dict::iterator BDE::dictEnd() throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return _dict->end();
|
||||
} else {
|
||||
throw RecoverableException("Not Dict");
|
||||
}
|
||||
}
|
||||
|
||||
BDE::Dict::const_iterator BDE::dictEnd() const throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return _dict->end();
|
||||
} else {
|
||||
throw RecoverableException("Not Dict");
|
||||
}
|
||||
}
|
||||
|
||||
// List Interface
|
||||
|
||||
bool BDE::isList() const throw()
|
||||
{
|
||||
return _type == TYPE_LIST;
|
||||
}
|
||||
|
||||
void BDE::append(const BDE& bde) throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
_list->push_back(bde);
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
void BDE::operator<<(const BDE& bde) throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
_list->push_back(bde);
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
BDE& BDE::operator[](size_t index) throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
return (*_list.get())[index];
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
const BDE& BDE::operator[](size_t index) const throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
return (*_list.get())[index];
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
BDE::List::iterator BDE::listBegin() throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
return _list->begin();
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
BDE::List::const_iterator BDE::listBegin() const throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
return _list->begin();
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
BDE::List::iterator BDE::listEnd() throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
return _list->end();
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
BDE::List::const_iterator BDE::listEnd() const throw(RecoverableException)
|
||||
{
|
||||
if(isList()) {
|
||||
return _list->end();
|
||||
} else {
|
||||
throw RecoverableException("Not List");
|
||||
}
|
||||
}
|
||||
|
||||
// Callable from List and Dict
|
||||
size_t BDE::size() const throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return _dict->size();
|
||||
} else if(isList()) {
|
||||
return _list->size();
|
||||
} else {
|
||||
throw RecoverableException("Not Dict nor List");
|
||||
}
|
||||
}
|
||||
|
||||
// Callable from List and Dict
|
||||
bool BDE::empty() const throw(RecoverableException)
|
||||
{
|
||||
if(isDict()) {
|
||||
return _dict->empty();
|
||||
} else if(isList()) {
|
||||
return _list->empty();
|
||||
} else {
|
||||
throw RecoverableException("Not Dict nor List");
|
||||
}
|
||||
}
|
||||
|
||||
static BDE decodeiter(std::istream& ss) throw(RecoverableException);
|
||||
|
||||
static void checkdelim(std::istream& ss, const char delim = ':')
|
||||
throw(RecoverableException)
|
||||
{
|
||||
char d;
|
||||
if(!(ss.get(d) && d == delim)) {
|
||||
throw RecoverableException
|
||||
(StringFormat("Delimiter '%c' not found.", delim).str());
|
||||
}
|
||||
}
|
||||
|
||||
static std::string decoderawstring(std::istream& ss)
|
||||
throw(RecoverableException)
|
||||
{
|
||||
size_t length;
|
||||
ss >> length;
|
||||
if(!ss) {
|
||||
throw RecoverableException("Integer expected but none found.");
|
||||
}
|
||||
// TODO check length, it must be less than or equal to INT_MAX
|
||||
checkdelim(ss);
|
||||
char* buf = new char[length];
|
||||
ss.read(buf, length);
|
||||
if(ss.gcount() != static_cast<int>(length)) {
|
||||
throw RecoverableException
|
||||
(StringFormat("Expected %lu bytes of data, but only %d read.",
|
||||
static_cast<unsigned long>(length), ss.gcount()).str());
|
||||
}
|
||||
std::string str(&buf[0], &buf[length]);
|
||||
delete [] buf;
|
||||
return str;
|
||||
}
|
||||
|
||||
static BDE decodestring(std::istream& ss) throw(RecoverableException)
|
||||
{
|
||||
return BDE(decoderawstring(ss));
|
||||
}
|
||||
|
||||
static BDE decodeinteger(std::istream& ss) throw(RecoverableException)
|
||||
{
|
||||
BDE::Integer integer;
|
||||
ss >> integer;
|
||||
if(!ss) {
|
||||
throw RecoverableException("Integer expected but none found");
|
||||
}
|
||||
checkdelim(ss, 'e');
|
||||
return BDE(integer);
|
||||
}
|
||||
|
||||
static BDE decodedict(std::istream& ss) throw(RecoverableException)
|
||||
{
|
||||
BDE dict = BDE::dict();
|
||||
char c;
|
||||
while(ss.get(c)) {
|
||||
if(c == 'e') {
|
||||
return dict;
|
||||
} else {
|
||||
ss.unget();
|
||||
std::string key = decoderawstring(ss);
|
||||
dict[key] = decodeiter(ss);
|
||||
}
|
||||
}
|
||||
throw RecoverableException("Unexpected EOF in dict context. 'e' expected.");
|
||||
}
|
||||
|
||||
static BDE decodelist(std::istream& ss) throw(RecoverableException)
|
||||
{
|
||||
BDE list = BDE::list();
|
||||
char c;
|
||||
while(ss.get(c)) {
|
||||
if(c == 'e') {
|
||||
return list;
|
||||
} else {
|
||||
ss.unget();
|
||||
list << decodeiter(ss);
|
||||
}
|
||||
}
|
||||
throw RecoverableException("Unexpected EOF in list context. 'e' expected.");
|
||||
}
|
||||
|
||||
static BDE decodeiter(std::istream& ss) throw(RecoverableException)
|
||||
{
|
||||
char c;
|
||||
if(!ss.get(c)) {
|
||||
throw RecoverableException("Unexpected EOF in term context."
|
||||
" 'd', 'l', 'i' or digit is expected.");
|
||||
}
|
||||
if(c == 'd') {
|
||||
return decodedict(ss);
|
||||
} else if(c == 'l') {
|
||||
return decodelist(ss);
|
||||
} else if(c == 'i') {
|
||||
return decodeinteger(ss);
|
||||
} else {
|
||||
ss.unget();
|
||||
return decodestring(ss);
|
||||
}
|
||||
}
|
||||
|
||||
BDE decode(std::istream& in) throw(RecoverableException)
|
||||
{
|
||||
return decodeiter(in);
|
||||
}
|
||||
|
||||
BDE decode(const std::string& s) throw(RecoverableException)
|
||||
{
|
||||
if(s.empty()) {
|
||||
return BDE::none;
|
||||
}
|
||||
std::istringstream ss(s);
|
||||
|
||||
return decodeiter(ss);
|
||||
}
|
||||
|
||||
BDE decode(const unsigned char* data, size_t length) throw(RecoverableException)
|
||||
{
|
||||
return decode(std::string(&data[0], &data[length]));
|
||||
}
|
||||
|
||||
BDE decodeFromFile(const std::string& filename) throw(RecoverableException)
|
||||
{
|
||||
std::ifstream f(filename.c_str());
|
||||
if(f) {
|
||||
return decode(f);
|
||||
} else {
|
||||
throw RecoverableException
|
||||
(StringFormat("Cannot open file '%s'.", filename.c_str()).str());
|
||||
}
|
||||
}
|
||||
|
||||
static void encodeIter(std::ostream& o, const BDE& bde) throw()
|
||||
{
|
||||
if(bde.isInteger()) {
|
||||
o << "i" << bde.i() << "e";
|
||||
} else if(bde.isString()) {
|
||||
const std::string& s = bde.s();
|
||||
o << s.size() << ":";
|
||||
o.write(s.data(), s.size());
|
||||
} else if(bde.isDict()) {
|
||||
o << "d";
|
||||
for(BDE::Dict::const_iterator i = bde.dictBegin(); i != bde.dictEnd(); ++i){
|
||||
const std::string& key = (*i).first;
|
||||
o << key.size() << ":";
|
||||
o.write(key.data(), key.size());
|
||||
encodeIter(o, (*i).second);
|
||||
}
|
||||
o << "e";
|
||||
} else if(bde.isList()) {
|
||||
o << "l";
|
||||
for(BDE::List::const_iterator i = bde.listBegin(); i != bde.listEnd(); ++i){
|
||||
encodeIter(o, *i);
|
||||
}
|
||||
o << "e";
|
||||
}
|
||||
}
|
||||
|
||||
std::string encode(const BDE& bde) throw()
|
||||
{
|
||||
std::ostringstream ss;
|
||||
encodeIter(ss, bde);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace bencode
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,214 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 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 "common.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <iosfwd>
|
||||
|
||||
#include "SharedHandle.h"
|
||||
#include "RecoverableException.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
namespace bencode {
|
||||
|
||||
class BDE;
|
||||
|
||||
class BDE {
|
||||
public:
|
||||
typedef std::map<std::string, BDE> Dict;
|
||||
typedef std::deque<BDE> List;
|
||||
typedef int64_t Integer;
|
||||
private:
|
||||
enum TYPE{
|
||||
TYPE_NONE,
|
||||
TYPE_INTEGER,
|
||||
TYPE_STRING,
|
||||
TYPE_DICT,
|
||||
TYPE_LIST,
|
||||
};
|
||||
|
||||
TYPE _type;
|
||||
SharedHandle<Dict> _dict;
|
||||
SharedHandle<List> _list;
|
||||
SharedHandle<std::string> _string;
|
||||
SharedHandle<Integer> _integer;
|
||||
|
||||
public:
|
||||
BDE() throw();
|
||||
|
||||
static BDE dict() throw();
|
||||
|
||||
static BDE list() throw();
|
||||
|
||||
static const BDE none;
|
||||
|
||||
// Test for Null data
|
||||
// Return true if the type of this object is None.
|
||||
bool isNone() const throw();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Integer Interface
|
||||
|
||||
BDE(Integer integer) throw();
|
||||
|
||||
// Returns true if the type of this object is Integer.
|
||||
bool isInteger() const throw();
|
||||
|
||||
// Returns Integer. Requires this object to be Integer.
|
||||
Integer i() const throw(RecoverableException);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// String Interface
|
||||
|
||||
BDE(const std::string& string) throw();
|
||||
|
||||
// Made explicit to avoid ambiguity with BDE(Integer).
|
||||
explicit BDE(const char* cstring) throw();
|
||||
|
||||
BDE(const char* data, size_t length) throw();
|
||||
|
||||
BDE(const unsigned char* data, size_t length) throw();
|
||||
|
||||
// Returns true if the type of this object is String.
|
||||
bool isString() const throw();
|
||||
|
||||
// Returns std::string. Requires this object to be String
|
||||
const std::string& s() const throw(RecoverableException);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Dictionary Interface
|
||||
|
||||
// Returns true if the type of this object is Dict.
|
||||
bool isDict() const throw();
|
||||
|
||||
// Returns the reference to BDE object associated with given key.
|
||||
// If the key is not found, new pair with that key is created using default
|
||||
// values, which is then returned. In other words, this is the same behavior
|
||||
// of std::map's operator[].
|
||||
// Requires this object to be Dict.
|
||||
BDE& operator[](const std::string& key) throw(RecoverableException);
|
||||
|
||||
// Returns the const reference to BDE ojbect associated with given key.
|
||||
// If the key is not found, BDE::none is returned.
|
||||
// Requires this object to be Dict.
|
||||
const BDE& operator[](const std::string& key) const
|
||||
throw(RecoverableException);
|
||||
|
||||
// Returns true if the given key is found in dict.
|
||||
// Requires this object to be Dict.
|
||||
bool containsKey(const std::string& key) const throw(RecoverableException);
|
||||
|
||||
// Returns a read/write iterator that points to the first pair in the dict.
|
||||
// Requires this object to be Dict.
|
||||
Dict::iterator dictBegin() throw(RecoverableException);
|
||||
|
||||
// Returns a read/write read-only iterator that points to the first pair in
|
||||
// the dict.
|
||||
// Requires this object to be Dict.
|
||||
Dict::const_iterator dictBegin() const throw(RecoverableException);
|
||||
|
||||
// Returns a read/write read-only iterator that points to one past the last
|
||||
// pair in the dict.
|
||||
// Requires this object to be Dict.
|
||||
Dict::iterator dictEnd() throw(RecoverableException);
|
||||
|
||||
// Returns a read/write read-only iterator that points to one past the last
|
||||
// pair in the dict.
|
||||
// Requires this object to be Dict.
|
||||
Dict::const_iterator dictEnd() const throw(RecoverableException);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// List Interface
|
||||
|
||||
// Returns true if the type of this object is List.
|
||||
bool isList() const throw();
|
||||
|
||||
// Appends given bde to list. Required the type of this object to be List.
|
||||
void append(const BDE& bde) throw(RecoverableException);
|
||||
|
||||
// Alias for append()
|
||||
void operator<<(const BDE& bde) throw(RecoverableException);
|
||||
|
||||
// Returns the reference of the object at the given index. Required this
|
||||
// object to be List.
|
||||
BDE& operator[](size_t index) throw(RecoverableException);
|
||||
|
||||
// Returns the const reference of the object at the given index.
|
||||
// Required this object to be List.
|
||||
const BDE& operator[](size_t index) const throw(RecoverableException);
|
||||
|
||||
// Returns a read/write iterator that points to the first object in list.
|
||||
// Required this object to be List.
|
||||
List::iterator listBegin() throw(RecoverableException);
|
||||
|
||||
// Returns a read/write read-only iterator that points to the first object
|
||||
// in list. Required this object to be List.
|
||||
List::const_iterator listBegin() const throw(RecoverableException);
|
||||
|
||||
// Returns a read/write iterator that points to the one past the last object
|
||||
// in list. Required this object to be List.
|
||||
List::iterator listEnd() throw(RecoverableException);
|
||||
|
||||
// Returns a read/write read-only iterator that points to the one past the
|
||||
// last object in list. Required this object to be List.
|
||||
List::const_iterator listEnd() const throw(RecoverableException);
|
||||
|
||||
// For List type: Returns size of list.
|
||||
// For Dict type: Returns size of dict.
|
||||
size_t size() const throw(RecoverableException);
|
||||
|
||||
// For List type: Returns true if size of list is 0.
|
||||
// For Dict type: Returns true if size of dict is 0.
|
||||
bool empty() const throw(RecoverableException);
|
||||
};
|
||||
|
||||
BDE decode(std::istream& in) throw(RecoverableException);
|
||||
|
||||
// Decode the data in s.
|
||||
BDE decode(const std::string& s) throw(RecoverableException);
|
||||
|
||||
BDE decode(const unsigned char* data, size_t length)
|
||||
throw(RecoverableException);
|
||||
|
||||
BDE decodeFromFile(const std::string& filename) throw(RecoverableException);
|
||||
|
||||
std::string encode(const BDE& bde) throw();
|
||||
|
||||
} // namespace bencode
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,272 @@
|
|||
#include "bencode.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class BencodeTest:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(BencodeTest);
|
||||
CPPUNIT_TEST(testString);
|
||||
CPPUNIT_TEST(testInteger);
|
||||
CPPUNIT_TEST(testDict);
|
||||
CPPUNIT_TEST(testDictIter);
|
||||
CPPUNIT_TEST(testList);
|
||||
CPPUNIT_TEST(testListIter);
|
||||
CPPUNIT_TEST(testDecode);
|
||||
CPPUNIT_TEST(testEncode);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
|
||||
public:
|
||||
void testString();
|
||||
void testInteger();
|
||||
void testDict();
|
||||
void testDictIter();
|
||||
void testList();
|
||||
void testListIter();
|
||||
void testDecode();
|
||||
void testEncode();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( BencodeTest );
|
||||
|
||||
void BencodeTest::testString()
|
||||
{
|
||||
bencode::BDE s(std::string("aria2"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), s.s());
|
||||
|
||||
unsigned char dataWithNull[] = { 0xf0, '\0', 0x0f };
|
||||
bencode::BDE sWithNull(dataWithNull, sizeof(dataWithNull));
|
||||
CPPUNIT_ASSERT(memcmp(dataWithNull, sWithNull.s().c_str(),
|
||||
sizeof(dataWithNull)) == 0);
|
||||
|
||||
bencode::BDE zero("");
|
||||
CPPUNIT_ASSERT_EQUAL(std::string(""), zero.s());
|
||||
}
|
||||
|
||||
void BencodeTest::testInteger()
|
||||
{
|
||||
bencode::BDE integer(INT64_MAX);
|
||||
CPPUNIT_ASSERT_EQUAL(INT64_MAX, integer.i());
|
||||
}
|
||||
|
||||
void BencodeTest::testDict()
|
||||
{
|
||||
bencode::BDE dict = bencode::BDE::dict();
|
||||
CPPUNIT_ASSERT(dict.empty());
|
||||
|
||||
dict["ki"] = 7;
|
||||
dict["ks"] = std::string("abc");
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), dict.size());
|
||||
CPPUNIT_ASSERT(dict.containsKey("ki"));
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<bencode::BDE::Integer>(7), dict["ki"].i());
|
||||
CPPUNIT_ASSERT(dict.containsKey("ks"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("abc"), dict["ks"].s());
|
||||
|
||||
CPPUNIT_ASSERT(dict["kn"].isNone()); // This adds kn key with default value.
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), dict.size());
|
||||
CPPUNIT_ASSERT(dict.containsKey("kn"));
|
||||
|
||||
const bencode::BDE& ref = dict;
|
||||
ref["kn2"]; // This doesn't add kn2 key.
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), ref.size());
|
||||
CPPUNIT_ASSERT(!ref.containsKey("kn2"));
|
||||
}
|
||||
|
||||
void BencodeTest::testDictIter()
|
||||
{
|
||||
bencode::BDE dict = bencode::BDE::dict();
|
||||
dict["alpha2"] = std::string("alpha2");
|
||||
dict["charlie"] = std::string("charlie");
|
||||
dict["bravo"] = std::string("bravo");
|
||||
dict["alpha"] = std::string("alpha");
|
||||
|
||||
bencode::BDE::Dict::iterator i = dict.dictBegin();
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("alpha"), (*i++).first);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("alpha2"), (*i++).first);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("bravo"), (*i++).first);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("charlie"), (*i++).first);
|
||||
CPPUNIT_ASSERT(dict.dictEnd() == i);
|
||||
|
||||
const bencode::BDE& ref = dict;
|
||||
bencode::BDE::Dict::const_iterator ci = ref.dictBegin();
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("alpha"), (*ci++).first);
|
||||
std::advance(ci, 3);
|
||||
CPPUNIT_ASSERT(ref.dictEnd() == ci);
|
||||
}
|
||||
|
||||
void BencodeTest::testList()
|
||||
{
|
||||
bencode::BDE list = bencode::BDE::list();
|
||||
CPPUNIT_ASSERT(list.empty());
|
||||
list << 7;
|
||||
list << std::string("aria2");
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), list.size());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<bencode::BDE::Integer>(7), list[0].i());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), list[1].s());
|
||||
|
||||
const bencode::BDE& ref = list;
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<bencode::BDE::Integer>(7), ref[0].i());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), ref[1].s());
|
||||
}
|
||||
|
||||
void BencodeTest::testListIter()
|
||||
{
|
||||
bencode::BDE list = bencode::BDE::list();
|
||||
list << std::string("alpha2");
|
||||
list << std::string("charlie");
|
||||
list << std::string("bravo");
|
||||
list << std::string("alpha");
|
||||
|
||||
bencode::BDE::List::iterator i = list.listBegin();
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("alpha2"), (*i++).s());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("charlie"), (*i++).s());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("bravo"), (*i++).s());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("alpha"), (*i++).s());
|
||||
CPPUNIT_ASSERT(list.listEnd() == i);
|
||||
|
||||
const bencode::BDE& ref = list;
|
||||
bencode::BDE::List::const_iterator ci = ref.listBegin();
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("alpha2"), (*ci++).s());
|
||||
std::advance(ci, 3);
|
||||
CPPUNIT_ASSERT(ref.listEnd() == ci);
|
||||
}
|
||||
|
||||
void BencodeTest::testDecode()
|
||||
{
|
||||
{
|
||||
// string, integer and list in dict
|
||||
bencode::BDE dict =
|
||||
bencode::decode("d4:name5:aria24:sizei12345678900e5:filesl3:bin3:docee");
|
||||
CPPUNIT_ASSERT(dict.isDict());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), dict["name"].s());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<bencode::BDE::Integer>(12345678900LL),
|
||||
dict["size"].i());
|
||||
bencode::BDE list = dict["files"];
|
||||
CPPUNIT_ASSERT(list.isList());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), list.size());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("bin"), list[0].s());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("doc"), list[1].s());
|
||||
}
|
||||
{
|
||||
// dict in list
|
||||
bencode::BDE list = bencode::decode("ld1:ki123eee");
|
||||
CPPUNIT_ASSERT(list.isList());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), list.size());
|
||||
bencode::BDE dict = list[0];
|
||||
CPPUNIT_ASSERT(dict.isDict());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<bencode::BDE::Integer>(123),
|
||||
dict["k"].i());
|
||||
}
|
||||
{
|
||||
// empty key is allowed
|
||||
bencode::BDE s = bencode::decode("d0:1:ve");
|
||||
}
|
||||
{
|
||||
// empty string
|
||||
bencode::BDE s = bencode::decode("0:");
|
||||
CPPUNIT_ASSERT_EQUAL(std::string(""), s.s());
|
||||
}
|
||||
{
|
||||
// empty dict
|
||||
bencode::BDE d = bencode::decode("de");
|
||||
CPPUNIT_ASSERT(d.empty());
|
||||
}
|
||||
{
|
||||
// empty list
|
||||
bencode::BDE l = bencode::decode("le");
|
||||
CPPUNIT_ASSERT(l.empty());
|
||||
}
|
||||
{
|
||||
// integer, without ending 'e'
|
||||
try {
|
||||
bencode::decode("i3");
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Delimiter 'e' not found."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// dict, without ending 'e'
|
||||
try {
|
||||
bencode::decode("d");
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Unexpected EOF in dict context."
|
||||
" 'e' expected."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// list, without ending 'e'
|
||||
try {
|
||||
bencode::decode("l");
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Unexpected EOF in list context."
|
||||
" 'e' expected."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// string, less than the specified length.
|
||||
try {
|
||||
bencode::decode("3:ab");
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Expected 3 bytes of data,"
|
||||
" but only 2 read."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// string, but length is invalid
|
||||
try {
|
||||
bencode::decode("x:abc");
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Integer expected but none found."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// empty encoded data
|
||||
CPPUNIT_ASSERT(bencode::decode("").isNone());
|
||||
}
|
||||
{
|
||||
// ignore trailing garbage at the end of the input.
|
||||
bencode::BDE s = bencode::decode("5:aria2trail");
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), s.s());
|
||||
}
|
||||
}
|
||||
|
||||
void BencodeTest::testEncode()
|
||||
{
|
||||
{
|
||||
bencode::BDE dict = bencode::BDE::dict();
|
||||
dict["name"] = std::string("aria2");
|
||||
dict["loc"] = 80000;
|
||||
dict["files"] = bencode::BDE::list();
|
||||
dict["files"] << std::string("aria2c");
|
||||
dict["attrs"] = bencode::BDE::dict();
|
||||
dict["attrs"]["license"] = std::string("GPL");
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("d"
|
||||
"5:attrsd7:license3:GPLe"
|
||||
"5:filesl6:aria2ce"
|
||||
"3:loci80000e"
|
||||
"4:name5:aria2"
|
||||
"e"),
|
||||
bencode::encode(dict));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -63,7 +63,8 @@ aria2c_SOURCES = AllTest.cc\
|
|||
FtpConnectionTest.cc\
|
||||
OptionParserTest.cc\
|
||||
SimpleDNSCacheTest.cc\
|
||||
DownloadHelperTest.cc
|
||||
DownloadHelperTest.cc\
|
||||
BencodeTest.cc
|
||||
|
||||
if HAVE_LIBZ
|
||||
aria2c_SOURCES += GZipDecoderTest.cc
|
||||
|
|
|
@ -197,7 +197,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
|||
DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \
|
||||
TimeTest.cc CopyDiskAdaptorTest.cc FtpConnectionTest.cc \
|
||||
OptionParserTest.cc SimpleDNSCacheTest.cc \
|
||||
DownloadHelperTest.cc GZipDecoderTest.cc \
|
||||
DownloadHelperTest.cc BencodeTest.cc GZipDecoderTest.cc \
|
||||
Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \
|
||||
IteratableChunkChecksumValidatorTest.cc \
|
||||
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
|
||||
|
@ -371,8 +371,8 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \
|
|||
TimeTest.$(OBJEXT) CopyDiskAdaptorTest.$(OBJEXT) \
|
||||
FtpConnectionTest.$(OBJEXT) OptionParserTest.$(OBJEXT) \
|
||||
SimpleDNSCacheTest.$(OBJEXT) DownloadHelperTest.$(OBJEXT) \
|
||||
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||
$(am__objects_4) $(am__objects_5)
|
||||
BencodeTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
||||
$(am__objects_3) $(am__objects_4) $(am__objects_5)
|
||||
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
aria2c_DEPENDENCIES = ../src/libaria2c.a ../src/download_helper.o \
|
||||
|
@ -595,8 +595,9 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \
|
|||
DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \
|
||||
TimeTest.cc CopyDiskAdaptorTest.cc FtpConnectionTest.cc \
|
||||
OptionParserTest.cc SimpleDNSCacheTest.cc \
|
||||
DownloadHelperTest.cc $(am__append_1) $(am__append_2) \
|
||||
$(am__append_3) $(am__append_4) $(am__append_5)
|
||||
DownloadHelperTest.cc BencodeTest.cc $(am__append_1) \
|
||||
$(am__append_2) $(am__append_3) $(am__append_4) \
|
||||
$(am__append_5)
|
||||
|
||||
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
||||
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
||||
|
@ -692,6 +693,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfigFactoryTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BNodeTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64Test.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BencodeTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BencodeVisitorTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldManTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtAllowedFastMessageTest.Po@am__quote@
|
||||
|
|
Loading…
Reference in New Issue