mirror of https://github.com/aria2/aria2
2010-03-02 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added strict attribute validation for metalink4. When specification violation is found, discard the whole document. * src/ExpatMetalinkProcessor.cc * src/MetalinkParserStateMachine.cc * src/MetalinkParserStateMachine.h * src/MetalinkParserStateV4Impl.cc * src/XML2SAXMetalinkProcessor.cc * test/Makefile.am * test/MetalinkProcessorTest.cc * test/metalink4-attrs.xml: Removed * test/metalink4-dirtraversal.xml: Removedpull/1/head
parent
eb32f56479
commit
ba78b6f167
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2010-03-02 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Added strict attribute validation for metalink4. When
|
||||
specification violation is found, discard the whole document.
|
||||
* src/ExpatMetalinkProcessor.cc
|
||||
* src/MetalinkParserStateMachine.cc
|
||||
* src/MetalinkParserStateMachine.h
|
||||
* src/MetalinkParserStateV4Impl.cc
|
||||
* src/XML2SAXMetalinkProcessor.cc
|
||||
* test/Makefile.am
|
||||
* test/MetalinkProcessorTest.cc
|
||||
* test/metalink4-attrs.xml: Removed
|
||||
* test/metalink4-dirtraversal.xml: Removed
|
||||
|
||||
2010-03-02 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Added test for Metaurl transaction.
|
||||
|
|
|
@ -147,34 +147,32 @@ MetalinkProcessor::parseFromBinaryStream(const SharedHandle<BinaryStream>& binar
|
|||
|
||||
SharedHandle<SessionData> sessionData(new SessionData(_stm));
|
||||
XML_Parser parser = XML_ParserCreateNS(0, static_cast<const XML_Char>('\t'));
|
||||
try {
|
||||
XML_SetUserData(parser, sessionData.get());
|
||||
XML_SetElementHandler(parser, &mlStartElement, &mlEndElement);
|
||||
XML_SetCharacterDataHandler(parser, &mlCharacters);
|
||||
auto_delete<XML_Parser> deleter(parser, XML_ParserFree);
|
||||
XML_SetUserData(parser, sessionData.get());
|
||||
XML_SetElementHandler(parser, &mlStartElement, &mlEndElement);
|
||||
XML_SetCharacterDataHandler(parser, &mlCharacters);
|
||||
|
||||
off_t readOffset = 0;
|
||||
while(1) {
|
||||
ssize_t res = binaryStream->readData(buf, bufSize, readOffset);
|
||||
if(res == 0) {
|
||||
break;
|
||||
}
|
||||
if(XML_Parse(parser, reinterpret_cast<const char*>(buf), res, 0) ==
|
||||
XML_STATUS_ERROR) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
readOffset += res;
|
||||
off_t readOffset = 0;
|
||||
while(1) {
|
||||
ssize_t res = binaryStream->readData(buf, bufSize, readOffset);
|
||||
if(res == 0) {
|
||||
break;
|
||||
}
|
||||
if(XML_Parse(parser, 0, 0, 1) == XML_STATUS_ERROR) {
|
||||
if(XML_Parse(parser, reinterpret_cast<const char*>(buf), res, 0) ==
|
||||
XML_STATUS_ERROR) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
} catch(Exception& e) {
|
||||
XML_ParserFree(parser);
|
||||
throw;
|
||||
readOffset += res;
|
||||
}
|
||||
if(XML_Parse(parser, 0, 0, 1) == XML_STATUS_ERROR) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
XML_ParserFree(parser);
|
||||
if(!_stm->finished()) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
if(!_stm->getErrors().empty()) {
|
||||
throw DL_ABORT_EX(_stm->getErrorString());
|
||||
}
|
||||
return _stm->getResult();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
*/
|
||||
/* copyright --> */
|
||||
#include "MetalinkParserStateMachine.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
|
||||
#include "MetalinkParserStateImpl.h"
|
||||
#include "MetalinkParserStateV3Impl.h"
|
||||
#include "MetalinkParserStateV4Impl.h"
|
||||
|
@ -514,4 +518,21 @@ bool MetalinkParserStateMachine::needsCharactersBuffering() const
|
|||
return _stateStack.top()->needsCharactersBuffering();
|
||||
}
|
||||
|
||||
void MetalinkParserStateMachine::logError(const std::string& log)
|
||||
{
|
||||
if(_errors.size() < 10) {
|
||||
_errors.push_back(log);
|
||||
}
|
||||
}
|
||||
|
||||
std::string MetalinkParserStateMachine::getErrorString() const
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Specification violation: ";
|
||||
std::copy(_errors.begin(), _errors.end(),
|
||||
std::ostream_iterator<std::string>(error, ", "));
|
||||
return error.str();
|
||||
}
|
||||
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -54,6 +54,9 @@ private:
|
|||
|
||||
std::stack<MetalinkParserState*> _stateStack;
|
||||
|
||||
// Error messages encountered while parsing document.
|
||||
std::vector<std::string> _errors;
|
||||
|
||||
static MetalinkParserState* _initialState;
|
||||
static MetalinkParserState* _skipTagState;
|
||||
|
||||
|
@ -245,6 +248,16 @@ public:
|
|||
|
||||
bool needsCharactersBuffering() const;
|
||||
|
||||
// Only stores first 10 errors.
|
||||
void logError(const std::string& log);
|
||||
|
||||
const std::vector<std::string>& getErrors() const
|
||||
{
|
||||
return _errors;
|
||||
}
|
||||
|
||||
std::string getErrorString() const;
|
||||
|
||||
const SharedHandle<Metalinker>& getResult() const
|
||||
{
|
||||
return _ctrl->getResult();
|
||||
|
|
|
@ -95,16 +95,17 @@ void MetalinkMetalinkParserStateV4::beginElement
|
|||
const std::vector<XmlAttr>& attrs)
|
||||
{
|
||||
if(nsUri == METALINK4_NAMESPACE_URI && localname == FILE) {
|
||||
stm->setFileStateV4();
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
|
||||
if(itr != attrs.end()) {
|
||||
if((*itr).value.empty() || util::detectDirTraversal((*itr).value)) {
|
||||
stm->setSkipTagState();
|
||||
} else {
|
||||
stm->setFileStateV4();
|
||||
stm->newEntryTransaction();
|
||||
stm->setFileNameOfEntry((*itr).value);
|
||||
}
|
||||
if(itr == attrs.end() || (*itr).value.empty()) {
|
||||
stm->logError("Missing file@name");
|
||||
return;
|
||||
} else if(util::detectDirTraversal((*itr).value)) {
|
||||
stm->logError("Bad file@name");
|
||||
return;
|
||||
}
|
||||
stm->newEntryTransaction();
|
||||
stm->setFileNameOfEntry((*itr).value);
|
||||
} else {
|
||||
stm->setSkipTagState();
|
||||
}
|
||||
|
@ -133,9 +134,11 @@ void FileMetalinkParserStateV4::beginElement
|
|||
{
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
|
||||
if(itr != attrs.end()) {
|
||||
name = (*itr).value;
|
||||
if(util::detectDirTraversal(name)) {
|
||||
if((*itr).value.empty() || util::detectDirTraversal((*itr).value)) {
|
||||
stm->logError("Bad metaurl@name");
|
||||
return;
|
||||
} else {
|
||||
name = (*itr).value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,17 +151,20 @@ void FileMetalinkParserStateV4::beginElement
|
|||
try {
|
||||
priority = util::parseInt((*itr).value);
|
||||
if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
|
||||
priority = MetalinkResource::getLowestPriority();
|
||||
stm->logError("metaurl@priority is out of range");
|
||||
return;
|
||||
}
|
||||
} catch(RecoverableException& e) {
|
||||
priority = MetalinkResource::getLowestPriority();
|
||||
stm->logError("Bad metaurl@priority");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string mediatype;
|
||||
{
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, MEDIATYPE);
|
||||
if(itr == attrs.end()) {
|
||||
if(itr == attrs.end() || (*itr).value.empty()) {
|
||||
stm->logError("Missing metaurl@mediatype");
|
||||
return;
|
||||
} else {
|
||||
mediatype = (*itr).value;
|
||||
|
@ -186,10 +192,12 @@ void FileMetalinkParserStateV4::beginElement
|
|||
try {
|
||||
priority = util::parseInt((*itr).value);
|
||||
if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
|
||||
priority = MetalinkResource::getLowestPriority();
|
||||
stm->logError("url@priority is out of range");
|
||||
return;
|
||||
}
|
||||
} catch(RecoverableException& e) {
|
||||
priority = MetalinkResource::getLowestPriority();
|
||||
stm->logError("Bad url@priority");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +209,8 @@ void FileMetalinkParserStateV4::beginElement
|
|||
else if(localname == HASH) {
|
||||
stm->setHashStateV4();
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
|
||||
if(itr == attrs.end()) {
|
||||
if(itr == attrs.end() || (*itr).value.empty()) {
|
||||
stm->logError("Missing hash@type");
|
||||
return;
|
||||
} else {
|
||||
std::string type = (*itr).value;
|
||||
|
@ -210,42 +219,45 @@ void FileMetalinkParserStateV4::beginElement
|
|||
}
|
||||
} else if(localname == PIECES) {
|
||||
stm->setPiecesStateV4();
|
||||
try {
|
||||
size_t length;
|
||||
{
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LENGTH);
|
||||
if(itr == attrs.end()) {
|
||||
return;
|
||||
} else {
|
||||
length = util::parseInt((*itr).value);
|
||||
}
|
||||
size_t length;
|
||||
{
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LENGTH);
|
||||
if(itr == attrs.end() || (*itr).value.empty()) {
|
||||
stm->logError("Missing pieces@length");
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
length = util::parseInt((*itr).value);
|
||||
} catch(RecoverableException& e) {
|
||||
stm->logError("Bad pieces@length");
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::string type;
|
||||
{
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
|
||||
if(itr == attrs.end()) {
|
||||
return;
|
||||
} else {
|
||||
type = (*itr).value;
|
||||
}
|
||||
}
|
||||
stm->newChunkChecksumTransactionV4();
|
||||
stm->setLengthOfChunkChecksumV4(length);
|
||||
stm->setTypeOfChunkChecksumV4(type);
|
||||
} catch(RecoverableException& e) {
|
||||
stm->cancelChunkChecksumTransactionV4();
|
||||
}
|
||||
std::string type;
|
||||
{
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
|
||||
if(itr == attrs.end() || (*itr).value.empty()) {
|
||||
stm->logError("Missing pieces@type");
|
||||
return;
|
||||
} else {
|
||||
type = (*itr).value;
|
||||
}
|
||||
}
|
||||
stm->newChunkChecksumTransactionV4();
|
||||
stm->setLengthOfChunkChecksumV4(length);
|
||||
stm->setTypeOfChunkChecksumV4(type);
|
||||
}
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
else if(localname == SIGNATURE) {
|
||||
stm->setSignatureStateV4();
|
||||
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, MEDIATYPE);
|
||||
if(itr == attrs.end()) {
|
||||
if(itr == attrs.end() || (*itr).value.empty()) {
|
||||
stm->logError("Missing signature@mediatype");
|
||||
return;
|
||||
} else {
|
||||
stm->newSignatureTransaction();
|
||||
stm->setTypeOfSignature((*itr).value);
|
||||
}
|
||||
stm->newSignatureTransaction();
|
||||
stm->setTypeOfSignature((*itr).value);
|
||||
} else {
|
||||
stm->setSkipTagState();
|
||||
}
|
||||
|
|
|
@ -179,6 +179,12 @@ MetalinkProcessor::parseFile(const std::string& filename)
|
|||
if(retval != 0) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
if(!_stm->finished()) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
if(!_stm->getErrors().empty()) {
|
||||
throw DL_ABORT_EX(_stm->getErrorString());
|
||||
}
|
||||
return _stm->getResult();
|
||||
}
|
||||
|
||||
|
@ -198,28 +204,27 @@ MetalinkProcessor::parseFromBinaryStream(const SharedHandle<BinaryStream>& binar
|
|||
xmlParserCtxtPtr ctx = xmlCreatePushParserCtxt
|
||||
(&mySAXHandler, sessionData.get(),
|
||||
reinterpret_cast<const char*>(buf), res, 0);
|
||||
try {
|
||||
off_t readOffset = res;
|
||||
while(1) {
|
||||
ssize_t res = binaryStream->readData(buf, bufSize, readOffset);
|
||||
if(res == 0) {
|
||||
break;
|
||||
}
|
||||
if(xmlParseChunk(ctx, reinterpret_cast<const char*>(buf), res, 0) != 0) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
readOffset += res;
|
||||
auto_delete<xmlParserCtxtPtr> deleter(ctx, xmlFreeParserCtxt);
|
||||
|
||||
off_t readOffset = res;
|
||||
while(1) {
|
||||
ssize_t res = binaryStream->readData(buf, bufSize, readOffset);
|
||||
if(res == 0) {
|
||||
break;
|
||||
}
|
||||
xmlParseChunk(ctx, reinterpret_cast<const char*>(buf), 0, 1);
|
||||
} catch(Exception& e) {
|
||||
xmlFreeParserCtxt(ctx);
|
||||
throw;
|
||||
if(xmlParseChunk(ctx, reinterpret_cast<const char*>(buf), res, 0) != 0) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
readOffset += res;
|
||||
}
|
||||
xmlFreeParserCtxt(ctx);
|
||||
xmlParseChunk(ctx, reinterpret_cast<const char*>(buf), 0, 1);
|
||||
|
||||
if(!_stm->finished()) {
|
||||
throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK);
|
||||
}
|
||||
if(!_stm->getErrors().empty()) {
|
||||
throw DL_ABORT_EX(_stm->getErrorString());
|
||||
}
|
||||
return _stm->getResult();
|
||||
}
|
||||
|
||||
|
|
|
@ -249,7 +249,5 @@ EXTRA_DIST = 4096chunk.txt\
|
|||
2files.metalink\
|
||||
utf8.torrent\
|
||||
metalink4.xml\
|
||||
metalink4-attrs.xml\
|
||||
metalink4-dirtraversal.xml\
|
||||
metalink3-dirtraversal.xml\
|
||||
metalink4-groupbymetaurl.xml
|
||||
|
|
|
@ -687,8 +687,6 @@ EXTRA_DIST = 4096chunk.txt\
|
|||
2files.metalink\
|
||||
utf8.torrent\
|
||||
metalink4.xml\
|
||||
metalink4-attrs.xml\
|
||||
metalink4-dirtraversal.xml\
|
||||
metalink3-dirtraversal.xml\
|
||||
metalink4-groupbymetaurl.xml
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
# include "Checksum.h"
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
#include "Signature.h"
|
||||
#include "StringFormat.h"
|
||||
#include "RecoverableException.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
|
@ -24,7 +26,6 @@ class MetalinkProcessorTest:public CppUnit::TestFixture {
|
|||
|
||||
CPPUNIT_TEST_SUITE(MetalinkProcessorTest);
|
||||
CPPUNIT_TEST(testParseFileV4);
|
||||
CPPUNIT_TEST(testParseFileV4_dirtraversal);
|
||||
CPPUNIT_TEST(testParseFileV4_attrs);
|
||||
CPPUNIT_TEST(testParseFile);
|
||||
CPPUNIT_TEST(testParseFile_dirtraversal);
|
||||
|
@ -50,7 +51,6 @@ private:
|
|||
|
||||
public:
|
||||
void testParseFileV4();
|
||||
void testParseFileV4_dirtraversal();
|
||||
void testParseFileV4_attrs();
|
||||
void testParseFile();
|
||||
void testParseFile_dirtraversal();
|
||||
|
@ -80,7 +80,6 @@ void MetalinkProcessorTest::testParseFileV4()
|
|||
{
|
||||
MetalinkProcessor proc;
|
||||
SharedHandle<Metalinker> m = proc.parseFile("metalink4.xml");
|
||||
|
||||
SharedHandle<MetalinkEntry> e;
|
||||
SharedHandle<MetalinkResource> r;
|
||||
SharedHandle<MetalinkMetaurl> mu;
|
||||
|
@ -133,37 +132,327 @@ void MetalinkProcessorTest::testParseFileV4()
|
|||
#endif // !ENABLE_BITTORRENT
|
||||
}
|
||||
|
||||
void MetalinkProcessorTest::testParseFileV4_dirtraversal()
|
||||
{
|
||||
MetalinkProcessor proc;
|
||||
SharedHandle<Metalinker> m = proc.parseFile("metalink4-dirtraversal.xml");
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)0, m->entries[0]->resources.size());
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)0, m->entries[0]->metaurls.size());
|
||||
}
|
||||
|
||||
void MetalinkProcessorTest::testParseFileV4_attrs()
|
||||
{
|
||||
MetalinkProcessor proc;
|
||||
SharedHandle<Metalinker> m = proc.parseFile("metalink4-attrs.xml");
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
std::vector<SharedHandle<MetalinkResource> > resources =
|
||||
m->entries[0]->resources;
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)3, resources.size());
|
||||
CPPUNIT_ASSERT_EQUAL(999999, resources[0]->priority);
|
||||
CPPUNIT_ASSERT_EQUAL(999999, resources[1]->priority);
|
||||
CPPUNIT_ASSERT_EQUAL(999999, resources[2]->priority);
|
||||
SharedHandle<Metalinker> m;
|
||||
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
|
||||
{
|
||||
// Testing file@name
|
||||
const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"%s\">"
|
||||
"<url>http://example.org</url>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
dw->setString(StringFormat(tmpl, "foo").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
std::vector<SharedHandle<MetalinkMetaurl> > metaurls =
|
||||
m->entries[0]->metaurls;
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)3, metaurls.size());
|
||||
CPPUNIT_ASSERT_EQUAL(999999, metaurls[0]->priority);
|
||||
CPPUNIT_ASSERT_EQUAL(999999, metaurls[1]->priority);
|
||||
CPPUNIT_ASSERT_EQUAL(999999, metaurls[2]->priority);
|
||||
#else // !ENABLE_BITTORRENT
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)0, metaurls.size());
|
||||
#endif // !ENABLE_BITTORRENT
|
||||
// empty name
|
||||
dw->setString(StringFormat(tmpl, "").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
|
||||
// dir traversing
|
||||
dw->setString(StringFormat(tmpl, "../doughnuts").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
{
|
||||
// Testing url@priority
|
||||
const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url priority=\"%s\">http://example.org</url>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
dw->setString(StringFormat(tmpl, "0").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
|
||||
dw->setString(StringFormat(tmpl, "1").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
dw->setString(StringFormat(tmpl, "100").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
dw->setString(StringFormat(tmpl, "999999").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
dw->setString(StringFormat(tmpl, "1000000").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
{
|
||||
// Testing metaurl@priority
|
||||
const char* tmpl =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<metaurl priority=\"%s\" mediatype=\"torrent\">http://example.org</metaurl>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
dw->setString(StringFormat(tmpl, "0").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
|
||||
dw->setString(StringFormat(tmpl, "1").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
dw->setString(StringFormat(tmpl, "100").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
dw->setString(StringFormat(tmpl, "999999").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
dw->setString(StringFormat(tmpl, "1000000").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
{
|
||||
// Testing metaurl@mediatype
|
||||
|
||||
// no mediatype
|
||||
dw->setString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<metaurl>http://example.org</metaurl>"
|
||||
"</file>"
|
||||
"</metalink>");
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
|
||||
const char* tmpl =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<metaurl mediatype=\"%s\">http://example.org</metaurl>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
|
||||
dw->setString(StringFormat(tmpl, "torrent").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
// empty mediatype
|
||||
dw->setString(StringFormat(tmpl, "").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
{
|
||||
// Testing metaurl@name
|
||||
const char* tmpl =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<metaurl mediatype=\"torrent\" name=\"%s\">http://example.org</metaurl>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
|
||||
dw->setString(StringFormat(tmpl, "foo").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
|
||||
|
||||
// dir traversing
|
||||
dw->setString(StringFormat(tmpl, "../doughnuts").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
// empty name
|
||||
dw->setString(StringFormat(tmpl, "").str());
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
{
|
||||
// Testing pieces@length
|
||||
// No pieces@length
|
||||
dw->setString
|
||||
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<pieces type=\"sha-1\">"
|
||||
"<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
|
||||
"</pieces>"
|
||||
"</file>"
|
||||
"</metalink>");
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
|
||||
const char* tmpl =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<pieces length=\"%s\" type=\"sha-1\">"
|
||||
"<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
|
||||
"</pieces>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
|
||||
dw->setString(StringFormat(tmpl, "262144").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
// empty
|
||||
try {
|
||||
dw->setString(StringFormat(tmpl, "").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
}
|
||||
{
|
||||
// Testing pieces@type
|
||||
// No pieces@type
|
||||
dw->setString
|
||||
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<pieces length=\"262144\">"
|
||||
"<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
|
||||
"</pieces>"
|
||||
"</file>"
|
||||
"</metalink>");
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
|
||||
const char* tmpl =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<pieces length=\"262144\" type=\"%s\">"
|
||||
"<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
|
||||
"</pieces>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
|
||||
dw->setString(StringFormat(tmpl, "sha-1").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
// empty
|
||||
try {
|
||||
dw->setString(StringFormat(tmpl, "").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
}
|
||||
{
|
||||
// Testing hash@type
|
||||
// No hash@type
|
||||
dw->setString
|
||||
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
|
||||
"</file>"
|
||||
"</metalink>");
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
|
||||
const char* tmpl =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<hash type=\"%s\">0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
|
||||
dw->setString(StringFormat(tmpl, "sha-1").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
// empty
|
||||
try {
|
||||
dw->setString(StringFormat(tmpl, "").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
}
|
||||
{
|
||||
// Testing signature@mediatype
|
||||
// No hash@type
|
||||
dw->setString
|
||||
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<signature>sig</signature>"
|
||||
"</file>"
|
||||
"</metalink>");
|
||||
try {
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
|
||||
const char* tmpl =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
|
||||
"<file name=\"example.ext\">"
|
||||
"<url>http://example.org</url>"
|
||||
"<signature mediatype=\"%s\">sig</signature>"
|
||||
"</file>"
|
||||
"</metalink>";
|
||||
|
||||
dw->setString(StringFormat(tmpl, "application/pgp-signature").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
// empty
|
||||
try {
|
||||
dw->setString(StringFormat(tmpl, "").str());
|
||||
m = proc.parseFromBinaryStream(dw);
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {}
|
||||
}
|
||||
}
|
||||
|
||||
void MetalinkProcessorTest::testParseFile()
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metalink xmlns="urn:ietf:params:xml:ns:metalink">
|
||||
<file name="priority/example.ext">
|
||||
<url location="de" priority="0">ftp://ftp.example.com/example.ext</url>
|
||||
<url location="fr" priority="">http://example.com/example.ext</url>
|
||||
<url location="jp" priority="1000000">http://example.org/example.ext</url>
|
||||
<metaurl mediatype="torrent" priority="0">http://example.com/example.ext.torrent</metaurl>
|
||||
<metaurl mediatype="torrent" priority="">http://example.org/example.ext.torrent</metaurl>
|
||||
<metaurl mediatype="torrent" priority="1000000">http://example.net/example.ext.torrent</metaurl>
|
||||
</file>
|
||||
</metalink>
|
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metalink xmlns="urn:ietf:params:xml:ns:metalink">
|
||||
<file name="/example1.ext">
|
||||
<url location="fr" priority="1">http://example.com/example.ext</url>
|
||||
</file>
|
||||
<file name="./example2.ext">
|
||||
<url location="fr" priority="1">http://example.com/example.ext</url>
|
||||
</file>
|
||||
<file name="../example3.ext">
|
||||
<url location="fr" priority="1">http://example.com/example.ext</url>
|
||||
</file>
|
||||
<file name="dir/../example4.ext">
|
||||
<url location="fr" priority="1">http://example.com/example.ext</url>
|
||||
</file>
|
||||
<file name="example5.ext/..">
|
||||
<url location="fr" priority="1">http://example.com/example.ext</url>
|
||||
</file>
|
||||
<file name=".">
|
||||
<url location="fr" priority="1">http://example.com/example.ext</url>
|
||||
</file>
|
||||
<file name="..">
|
||||
<url location="fr" priority="1">http://example.com/example.ext</url>
|
||||
</file>
|
||||
<file name="foo">
|
||||
<metaurl name="../foo" mediatype="torrent">http://example.com/example.torrent</metaurl>
|
||||
</file>
|
||||
</metalink>
|
Loading…
Reference in New Issue