Rewritten Metalink XML parser.

Now we don't strip white spaces while parsing Metalink V3 document.
Expat implementation does not included in this change.
pull/2/head
Tatsuhiro Tsujikawa 2011-11-10 22:38:01 +09:00
parent f114a6fba4
commit 440f29aca3
22 changed files with 1096 additions and 988 deletions

View File

@ -231,10 +231,8 @@ else
AM_CONDITIONAL([ENABLE_METALINK], false)
fi
AM_CONDITIONAL([ENABLE_METALINK_LIBXML2],
[test "x$enable_metalink" = "xyes" && test "x$have_libxml2" = "xyes"])
AM_CONDITIONAL([ENABLE_METALINK_LIBEXPAT],
[test "x$enable_metalink" = "xyes" && test "x$have_libexpat" = "xyes"])
AM_CONDITIONAL([HAVE_SOME_XMLLIB],
[test "x$have_libxml2" = "xyes" || test "x$have_libexpat" = "xyes"])
if test "x$have_libxml2" = "xyes" || test "x$have_libexpat" = "xyes"; then
enable_xml_rpc=yes

View File

@ -228,6 +228,12 @@ if MINGW_BUILD
SRCS += WinConsoleFile.cc WinConsoleFile.h
endif # MINGW_BUILD
if HAVE_SOME_XMLLIB
SRCS += XmlAttr.cc XmlAttr.h\
XmlParser.h\
ParserStateMachine.h
endif # HAVE_SOME_XMLLIB
if ENABLE_XML_RPC
SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\
XmlRpcRequestParserStateMachine.cc XmlRpcRequestParserStateMachine.h\
@ -487,7 +493,6 @@ SRCS += Metalinker.cc Metalinker.h\
MetalinkEntry.cc MetalinkEntry.h\
MetalinkResource.cc MetalinkResource.h\
MetalinkMetaurl.cc MetalinkMetaurl.h\
MetalinkProcessor.h\
MetalinkParserController.cc MetalinkParserController.h\
MetalinkParserStateMachine.cc MetalinkParserStateMachine.h\
MetalinkParserState.cc MetalinkParserState.h\
@ -497,16 +502,17 @@ SRCS += Metalinker.cc Metalinker.h\
Metalink2RequestGroup.cc Metalink2RequestGroup.h\
MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\
metalink_helper.cc metalink_helper.h
if HAVE_LIBXML2
SRCS += Xml2XmlParser.cc Xml2XmlParser.h
endif # HAVE_LIBXML2
if HAVE_LIBEXPAT
SRCS += ExpatXmlParser.cc ExpatXmlParser.h
endif # HAVE_LIBEXPAT
endif # ENABLE_METALINK
if ENABLE_METALINK_LIBXML2
SRCS += XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h
endif # ENABLE_METALINK_LIBXML2
if ENABLE_METALINK_LIBEXPAT
SRCS += ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h
endif # ENABLE_METALINK_LIBEXPAT
if !HAVE_ASCTIME_R
SRCS += asctime_r.c asctime_r.h
endif # !HAVE_ASCTIME_R

View File

@ -136,7 +136,7 @@ Metalink2RequestGroup::generate
const std::string& baseUri)
{
std::vector<SharedHandle<MetalinkEntry> > entries;
metalink::parseAndQuery(entries, binaryStream, option.get(), baseUri);
metalink::parseAndQuery(entries, binaryStream.get(), option.get(), baseUri);
std::vector<SharedHandle<RequestGroup> > tempgroups;
createRequestGroup(tempgroups, entries, option);
SharedHandle<MetadataInfo> mi(new MetadataInfo());

View File

@ -36,23 +36,4 @@
namespace aria2 {
XmlAttr::XmlAttr() {}
XmlAttr::XmlAttr(const XmlAttr& c)
: localname(c.localname), prefix(c.prefix), nsUri(c.nsUri), value(c.value)
{}
XmlAttr::~XmlAttr() {}
XmlAttr& XmlAttr::operator=(const XmlAttr& c)
{
if(this != &c) {
localname = c.localname;
prefix = c.prefix;
nsUri = c.nsUri;
value = c.value;
}
return *this;
}
} // namespace aria2

View File

@ -43,18 +43,7 @@
namespace aria2 {
class MetalinkParserStateMachine;
struct XmlAttr {
std::string localname;
std::string prefix;
std::string nsUri;
std::string value;
XmlAttr();
XmlAttr(const XmlAttr& attr);
~XmlAttr();
XmlAttr& operator=(const XmlAttr&);
};
class XmlAttr;
class MetalinkParserState
{
@ -63,16 +52,16 @@ public:
virtual void beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs) {}
virtual void endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters) {}
virtual bool needsCharactersBuffering() const

View File

@ -33,36 +33,69 @@
*/
/* copyright --> */
#include "MetalinkParserStateImpl.h"
#include <cstring>
#include "MetalinkParserStateV3Impl.h"
#include "MetalinkParserStateV4Impl.h"
#include "MetalinkParserStateMachine.h"
#include "XmlAttr.h"
namespace aria2 {
namespace {
class FindAttr {
private:
const char* localname_;
const char* nsUri_;
public:
FindAttr(const char* localname, const char* nsUri)
: localname_(localname),
nsUri_(nsUri)
{}
bool operator()(const XmlAttr& attr) const
{
return strcmp(attr.localname, localname_) == 0 &&
(attr.nsUri == 0 || strcmp(attr.nsUri, nsUri_) == 0);
}
};
} // namespace
std::vector<XmlAttr>::const_iterator findAttr
(const std::vector<XmlAttr>& attrs,
const char* localname,
const char* nsUri)
{
return std::find_if(attrs.begin(), attrs.end(), FindAttr(localname, nsUri));
}
void InitialMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri == METALINK4_NAMESPACE_URI && localname == "metalink") {
stm->setMetalinkStateV4();
} else if(nsUri == METALINK3_NAMESPACE_URI && localname == "metalink") {
stm->setMetalinkState();
if(!nsUri || strcmp(localname, "metalink") != 0) {
psm->setSkipTagState();
} else if(strcmp(nsUri, METALINK4_NAMESPACE_URI) == 0) {
psm->setMetalinkStateV4();
} else if(strcmp(nsUri, METALINK3_NAMESPACE_URI) == 0) {
psm->setMetalinkState();
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void SkipTagMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
stm->setSkipTagState();
psm->setSkipTagState();
}
} // namespace aria2

View File

@ -39,23 +39,28 @@
namespace aria2 {
std::vector<XmlAttr>::const_iterator findAttr
(const std::vector<XmlAttr>& attrs,
const char* localname,
const char* nsUri);
class SkipTagMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
};
class InitialMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
};

View File

@ -502,18 +502,18 @@ void MetalinkParserStateMachine::cancelMetaurlTransaction()
}
void MetalinkParserStateMachine::beginElement
(const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
stateStack_.top()->beginElement(this, localname, prefix, nsUri, attrs);
}
void MetalinkParserStateMachine::endElement
(const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stateStack_.top()->endElement(this, localname, prefix, nsUri, characters);

View File

@ -35,7 +35,8 @@
#ifndef D_METALINK_PARSER_STATE_MACHINE_H
#define D_METALINK_PARSER_STATE_MACHINE_H
#include "common.h"
#include "ParserStateMachine.h"
#include <string>
#include <vector>
#include <stack>
@ -48,7 +49,7 @@ namespace aria2 {
class Metalinker;
class MetalinkParserStateMachine {
class MetalinkParserStateMachine : public ParserStateMachine {
private:
SharedHandle<MetalinkParserController> ctrl_;
@ -92,7 +93,23 @@ private:
public:
MetalinkParserStateMachine();
~MetalinkParserStateMachine();
virtual ~MetalinkParserStateMachine();
virtual bool needsCharactersBuffering() const;
virtual bool finished() const;
virtual void beginElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual void endElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
void setSkipTagState();
@ -138,20 +155,6 @@ public:
void setURLStateV4();
void setMetaurlStateV4();
bool finished() const;
void beginElement
(const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
const std::vector<XmlAttr>& attrs);
void endElement
(const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
const std::string& characters);
void newEntryTransaction();
void setFileNameOfEntry(const std::string& filename);
@ -250,8 +253,6 @@ public:
void cancelMetaurlTransaction();
bool needsCharactersBuffering() const;
// Only stores first 10 errors.
void logError(const std::string& log);

View File

@ -33,412 +33,385 @@
*/
/* copyright --> */
#include "MetalinkParserStateV3Impl.h"
#include <cstring>
#include "MetalinkParserStateMachine.h"
#include "RecoverableException.h"
#include "MetalinkResource.h"
#include "util.h"
#include "XmlAttr.h"
namespace aria2 {
namespace {
const std::string FILE("file");
const std::string FILES("files");
const std::string HASH("hash");
const std::string LANGUAGE("language");
const std::string LENGTH("length");
const std::string LOCATION("location");
const std::string MAXCONNECTIONS("maxconnections");
// Can't use name VERSION because it is used as a macro.
const std::string METALINK_VERSION("version");
const std::string NAME("name");
const std::string OS("os");
const std::string PIECE("piece");
const std::string PIECES("pieces");
const std::string PREFERENCE("preference");
const std::string RESOURCES("resources");
const std::string SIGNATURE("signature");
const std::string SIZE("size");
const std::string TYPE("type");
const std::string URL("url");
const std::string VERIFICATION("verification");
} // namespace
const std::string METALINK3_NAMESPACE_URI("http://www.metalinker.org/");
const char METALINK3_NAMESPACE_URI[] = "http://www.metalinker.org/";
namespace {
class FindAttr {
private:
const std::string& localname_;
public:
FindAttr(const std::string& localname):localname_(localname) {}
bool operator()(const XmlAttr& attr) const
{
return attr.localname == localname_ &&
(attr.nsUri.empty() || attr.nsUri == METALINK3_NAMESPACE_URI);
}
};
} // namespace
namespace {
template<typename Container>
typename Container::const_iterator findAttr
(const Container& attrs, const std::string& localname)
bool checkNsUri(const char* nsUri)
{
return std::find_if(attrs.begin(), attrs.end(), FindAttr(localname));
return nsUri && strcmp(nsUri, METALINK3_NAMESPACE_URI) == 0;
}
} // namespace
void MetalinkMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri == METALINK3_NAMESPACE_URI && localname == FILES) {
stm->setFilesState();
if(checkNsUri(nsUri) && strcmp(localname, "files") == 0) {
psm->setFilesState();
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void FilesMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri == METALINK3_NAMESPACE_URI && localname == FILE) {
stm->setFileState();
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
if(checkNsUri(nsUri) && strcmp(localname, "file") == 0) {
psm->setFileState();
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "name", METALINK3_NAMESPACE_URI);
if(itr != attrs.end()) {
std::string name = util::strip((*itr).value);
std::string name((*itr).value, (*itr).valueLength);
if(name.empty() || util::detectDirTraversal(name)) {
return;
}
stm->newEntryTransaction();
stm->setFileNameOfEntry(name);
psm->newEntryTransaction();
psm->setFileNameOfEntry(name);
}
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void FileMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri != METALINK3_NAMESPACE_URI) {
stm->setSkipTagState();
} else if(localname == SIZE) {
stm->setSizeState();
} else if(localname == METALINK_VERSION) {
stm->setVersionState();
} else if(localname == LANGUAGE) {
stm->setLanguageState();
} else if(localname == OS) {
stm->setOSState();
} else if(localname == VERIFICATION) {
stm->setVerificationState();
} else if(localname == RESOURCES) {
stm->setResourcesState();
if(!checkNsUri(nsUri)) {
psm->setSkipTagState();
} else if(strcmp(localname, "size") == 0) {
psm->setSizeState();
} else if(strcmp(localname, "version") == 0) {
psm->setVersionState();
} else if(strcmp(localname, "language") == 0) {
psm->setLanguageState();
} else if(strcmp(localname, "os") == 0) {
psm->setOSState();
} else if(strcmp(localname, "verification") == 0) {
psm->setVerificationState();
} else if(strcmp(localname, "resources") == 0) {
psm->setResourcesState();
int maxConnections;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs,MAXCONNECTIONS);
if(itr == attrs.end()) {
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "maxconnections", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
maxConnections = -1;
} else {
if(!util::parseIntNoThrow
(maxConnections,(*itr).value, (*itr).value+(*itr).valueLength) ||
maxConnections <= 0) {
maxConnections = -1;
} else {
try {
maxConnections =
util::parseInt((*itr).value.begin(), (*itr).value.end());
} catch(RecoverableException& e) {
maxConnections = -1;
}
}
}
stm->setMaxConnectionsOfEntry(maxConnections);
psm->setMaxConnectionsOfEntry(maxConnections);
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void FileMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->commitEntryTransaction();
psm->commitEntryTransaction();
}
void SizeMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
try {
stm->setFileLengthOfEntry
(util::parseULLInt(characters.begin(), characters.end()));
} catch(RecoverableException& e) {
// current metalink specification doesn't require size element.
// current metalink specification doesn't require size element.
int64_t size;
if(util::parseLLIntNoThrow(size, characters.begin(), characters.end()) &&
size >= 0) {
psm->setFileLengthOfEntry(size);
}
}
void VersionMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setVersionOfEntry(util::strip(characters));
psm->setVersionOfEntry(characters);
}
void LanguageMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setLanguageOfEntry(util::strip(characters));
psm->setLanguageOfEntry(characters);
}
void OSMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setOSOfEntry(util::strip(characters));
psm->setOSOfEntry(characters);
}
void VerificationMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri != METALINK3_NAMESPACE_URI) {
stm->setSkipTagState();
if(!checkNsUri(nsUri)) {
psm->setSkipTagState();
} else
#ifdef ENABLE_MESSAGE_DIGEST
if(localname == HASH) {
stm->setHashState();
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
if(itr == attrs.end()) {
return;
} else {
std::string type = util::strip((*itr).value);
stm->newChecksumTransaction();
stm->setTypeOfChecksum(type);
}
} else if(localname == PIECES) {
stm->setPiecesState();
try {
size_t length;
if(strcmp(localname, "hash") == 0) {
psm->setHashState();
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
return;
} else {
psm->newChecksumTransaction();
psm->setTypeOfChecksum(std::string((*itr).value, (*itr).valueLength));
}
} else if(strcmp(localname, "pieces") == 0) {
psm->setPiecesState();
int32_t length;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LENGTH);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "length", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
return;
} else {
length = util::parseInt((*itr).value.begin(), (*itr).value.end());
if(!util::parseIntNoThrow
(length, (*itr).value, (*itr).value+(*itr).valueLength) ||
length < 0) {
return;
}
}
}
std::string type;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
return;
} else {
type = util::strip((*itr).value);
type.assign((*itr).value, (*itr).valueLength);
}
}
stm->newChunkChecksumTransaction();
stm->setLengthOfChunkChecksum(length);
stm->setTypeOfChunkChecksum(type);
} catch(RecoverableException& e) {
stm->cancelChunkChecksumTransaction();
}
} else
psm->newChunkChecksumTransaction();
psm->setLengthOfChunkChecksum(length);
psm->setTypeOfChunkChecksum(type);
} else
#endif // ENABLE_MESSAGE_DIGEST
if(localname == SIGNATURE) {
stm->setSignatureState();
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
if(itr == attrs.end()) {
return;
} else {
stm->newSignatureTransaction();
stm->setTypeOfSignature(util::strip((*itr).value));
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, FILE);
if(itr != attrs.end()) {
std::string file = util::strip((*itr).value);
if(!util::detectDirTraversal(file)) {
stm->setFileOfSignature(file);
if(strcmp(localname, "signature") == 0) {
psm->setSignatureState();
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
return;
} else {
psm->newSignatureTransaction();
psm->setTypeOfSignature
(std::string((*itr).value, (*itr).valueLength));
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "file", METALINK3_NAMESPACE_URI);
if(itr != attrs.end()) {
std::string file((*itr).value, (*itr).valueLength);
if(!util::detectDirTraversal(file)) {
psm->setFileOfSignature(file);
}
}
}
} else {
psm->setSkipTagState();
}
} else {
stm->setSkipTagState();
}
}
void HashMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setHashOfChecksum(util::strip(characters));
stm->commitChecksumTransaction();
psm->setHashOfChecksum(characters);
psm->commitChecksumTransaction();
}
void PiecesMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri == METALINK3_NAMESPACE_URI && localname == HASH) {
stm->setPieceHashState();
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PIECE);
if(checkNsUri(nsUri) && strcmp(localname, "hash") == 0) {
psm->setPieceHashState();
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "piece", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
stm->cancelChunkChecksumTransaction();
psm->cancelChunkChecksumTransaction();
} else {
try {
stm->createNewHashOfChunkChecksum
(util::parseInt((*itr).value.begin(), (*itr).value.end()));
} catch(RecoverableException& e) {
stm->cancelChunkChecksumTransaction();
int32_t idx;
if(util::parseIntNoThrow
(idx, (*itr).value, (*itr).value+(*itr).valueLength) && idx >= 0) {
psm->createNewHashOfChunkChecksum(idx);
} else {
psm->cancelChunkChecksumTransaction();
}
}
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void PiecesMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->commitChunkChecksumTransaction();
psm->commitChunkChecksumTransaction();
}
void PieceHashMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setMessageDigestOfChunkChecksum(util::strip(characters));
stm->addHashOfChunkChecksum();
psm->setMessageDigestOfChunkChecksum(characters);
psm->addHashOfChunkChecksum();
}
void SignatureMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setBodyOfSignature(util::strip(characters));
stm->commitSignatureTransaction();
psm->setBodyOfSignature(characters);
psm->commitSignatureTransaction();
}
void ResourcesMetalinkParserState::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri != METALINK3_NAMESPACE_URI) {
stm->setSkipTagState();
} else if(localname == URL) {
stm->setURLState();
if(!checkNsUri(nsUri)) {
psm->setSkipTagState();
} else if(strcmp(localname, "url") == 0) {
psm->setURLState();
std::string type;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
return;
} else {
type = util::strip((*itr).value);
type.assign((*itr).value, (*itr).valueLength);
}
}
std::string location;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LOCATION);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "location", METALINK3_NAMESPACE_URI);
if(itr != attrs.end()) {
location = util::strip((*itr).value);
location.assign((*itr).value, (*itr).valueLength);
}
}
int preference;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PREFERENCE);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "preference", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
preference = MetalinkResource::getLowestPriority();
} else {
try {
if(util::parseIntNoThrow
(preference, (*itr).value, (*itr).value+(*itr).valueLength) &&
preference >= 0) {
// In Metalink3Spec, highest prefernce value is 100. We
// uses Metalink4Spec priority unit system in which 1 is
// use Metalink4Spec priority unit system in which 1 is
// higest.
preference =
101-util::parseInt((*itr).value.begin(), (*itr).value.end());
} catch(RecoverableException& e) {
preference = 101-preference;
} else {
preference = MetalinkResource::getLowestPriority();
}
}
}
int maxConnections;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs,MAXCONNECTIONS);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "maxconnections", METALINK3_NAMESPACE_URI);
if(itr == attrs.end()) {
maxConnections = -1;
} else {
try {
maxConnections =
util::parseInt((*itr).value.begin(), (*itr).value.end());
} catch(RecoverableException& e) {
if(!util::parseIntNoThrow
(maxConnections, (*itr).value, (*itr).value+(*itr).valueLength) ||
maxConnections <= 0) {
maxConnections = -1;
}
}
}
stm->newResourceTransaction();
stm->setTypeOfResource(type);
stm->setLocationOfResource(location);
stm->setPriorityOfResource(preference);
stm->setMaxConnectionsOfResource(maxConnections);
psm->newResourceTransaction();
psm->setTypeOfResource(type);
psm->setLocationOfResource(location);
psm->setPriorityOfResource(preference);
psm->setMaxConnectionsOfResource(maxConnections);
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void URLMetalinkParserState::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setURLOfResource(util::strip(characters));
stm->commitResourceTransaction();
psm->setURLOfResource(characters);
psm->commitResourceTransaction();
}
} // namespace aria2

View File

@ -40,25 +40,25 @@
namespace aria2 {
extern const std::string METALINK3_NAMESPACE_URI;
extern const char METALINK3_NAMESPACE_URI[];
class MetalinkMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
};
class FilesMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual bool needsCharactersBuffering() const
@ -70,16 +70,16 @@ public:
class FileMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -91,10 +91,10 @@ public:
class SizeMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -106,10 +106,10 @@ public:
class VersionMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -121,10 +121,10 @@ public:
class LanguageMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -136,10 +136,10 @@ public:
class OSMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -151,10 +151,10 @@ public:
class VerificationMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual bool needsCharactersBuffering() const
@ -166,10 +166,10 @@ public:
class HashMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -181,16 +181,16 @@ public:
class PiecesMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -202,10 +202,10 @@ public:
class PieceHashMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -217,10 +217,10 @@ public:
class SignatureMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -232,10 +232,10 @@ public:
class ResourcesMetalinkParserState:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual bool needsCharactersBuffering() const
@ -247,10 +247,10 @@ public:
class URLMetalinkParserState:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const

View File

@ -33,370 +33,343 @@
*/
/* copyright --> */
#include "MetalinkParserStateV4Impl.h"
#include <cstring>
#include "MetalinkParserStateMachine.h"
#include "RecoverableException.h"
#include "MetalinkResource.h"
#include "util.h"
#include "XmlAttr.h"
namespace aria2 {
namespace {
const std::string FILE("file");
const std::string HASH("hash");
const std::string LANGUAGE("language");
const std::string LENGTH("length");
const std::string LOCATION("location");
const std::string METALINK("metalink");
// Can't use name VERSION because it is used as a macro.
const std::string METALINK_VERSION("version");
const std::string METAURL("metaurl");
const std::string NAME("name");
const std::string OS("os");
const std::string PIECE("piece");
const std::string PIECES("pieces");
const std::string PRIORITY("priority");
const std::string SIGNATURE("signature");
const std::string SIZE("size");
const std::string TYPE("type");
const std::string MEDIATYPE("mediatype");
const std::string URL("url");
} // namespace
const std::string METALINK4_NAMESPACE_URI("urn:ietf:params:xml:ns:metalink");
const char METALINK4_NAMESPACE_URI[] = "urn:ietf:params:xml:ns:metalink";
namespace {
class FindAttr {
private:
const std::string& localname_;
public:
FindAttr(const std::string& localname):localname_(localname) {}
bool operator()(const XmlAttr& attr) const
{
return attr.localname == localname_ &&
(attr.nsUri.empty() || attr.nsUri == METALINK4_NAMESPACE_URI);
}
};
} // namespace
namespace {
template<typename Container>
typename Container::const_iterator findAttr
(const Container& attrs, const std::string& localname)
bool checkNsUri(const char* nsUri)
{
return std::find_if(attrs.begin(), attrs.end(), FindAttr(localname));
return nsUri && strcmp(nsUri, METALINK4_NAMESPACE_URI) == 0;
}
} // namespace
void MetalinkMetalinkParserStateV4::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
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() || (*itr).value.empty()) {
stm->logError("Missing file@name");
return;
} else if(util::detectDirTraversal((*itr).value)) {
stm->logError("Bad file@name");
if(checkNsUri(nsUri) && strcmp(localname, "file") == 0) {
psm->setFileStateV4();
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "name", METALINK4_NAMESPACE_URI);
if(itr == attrs.end() || (*itr).valueLength == 0) {
psm->logError("Missing file@name");
return;
}
stm->newEntryTransaction();
stm->setFileNameOfEntry((*itr).value);
std::string name((*itr).value, (*itr).valueLength);
if(util::detectDirTraversal(name)) {
psm->logError("Bad file@name");
return;
}
psm->newEntryTransaction();
psm->setFileNameOfEntry(name);
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void FileMetalinkParserStateV4::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri != METALINK4_NAMESPACE_URI) {
stm->setSkipTagState();
} else if(localname == SIZE) {
stm->setSizeStateV4();
} else if(localname == METALINK_VERSION) {
stm->setVersionStateV4();
} else if(localname == LANGUAGE) {
stm->setLanguageStateV4();
} else if(localname == OS) {
stm->setOSStateV4();
} else if(localname == METAURL) {
stm->setMetaurlStateV4();
if(!checkNsUri(nsUri)) {
psm->setSkipTagState();
} else if(strcmp(localname, "size") == 0) {
psm->setSizeStateV4();
} else if(strcmp(localname, "version") == 0) {
psm->setVersionStateV4();
} else if(strcmp(localname, "language") == 0) {
psm->setLanguageStateV4();
} else if(strcmp(localname, "os") == 0) {
psm->setOSStateV4();
} else if(strcmp(localname, "metaurl") == 0) {
psm->setMetaurlStateV4();
std::string name;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "name", METALINK4_NAMESPACE_URI);
if(itr != attrs.end()) {
if((*itr).value.empty() || util::detectDirTraversal((*itr).value)) {
stm->logError("Bad metaurl@name");
name.assign((*itr).value, (*itr).valueLength);
if(name.empty() || util::detectDirTraversal(name)) {
psm->logError("Bad metaurl@name");
return;
} else {
name = (*itr).value;
}
}
}
int priority;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PRIORITY);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "priority", METALINK4_NAMESPACE_URI);
if(itr == attrs.end()) {
priority = MetalinkResource::getLowestPriority();
} else {
try {
priority = util::parseInt((*itr).value.begin(), (*itr).value.end());
if(util::parseIntNoThrow
(priority, (*itr).value, (*itr).value+(*itr).valueLength)) {
if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
stm->logError("metaurl@priority is out of range");
psm->logError("metaurl@priority is out of range");
return;
}
} catch(RecoverableException& e) {
stm->logError("Bad metaurl@priority");
} else {
psm->logError("Bad metaurl@priority");
return;
}
}
}
std::string mediatype;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, MEDIATYPE);
if(itr == attrs.end() || (*itr).value.empty()) {
stm->logError("Missing metaurl@mediatype");
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "mediatype", METALINK4_NAMESPACE_URI);
if(itr == attrs.end() || (*itr).valueLength == 0) {
psm->logError("Missing metaurl@mediatype");
return;
} else {
mediatype = (*itr).value;
mediatype.assign((*itr).value, (*itr).valueLength);
}
}
stm->newMetaurlTransaction();
stm->setPriorityOfMetaurl(priority);
stm->setMediatypeOfMetaurl(mediatype);
stm->setNameOfMetaurl(name);
} else if(localname == URL) {
stm->setURLStateV4();
psm->newMetaurlTransaction();
psm->setPriorityOfMetaurl(priority);
psm->setMediatypeOfMetaurl(mediatype);
psm->setNameOfMetaurl(name);
} else if(strcmp(localname, "url") == 0) {
psm->setURLStateV4();
std::string location;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LOCATION);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "location", METALINK4_NAMESPACE_URI);
if(itr != attrs.end()) {
location = (*itr).value;
location.assign((*itr).value, (*itr).valueLength);
}
}
int priority;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PRIORITY);
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "priority", METALINK4_NAMESPACE_URI);
if(itr == attrs.end()) {
priority = MetalinkResource::getLowestPriority();
} else {
try {
priority = util::parseInt((*itr).value.begin(), (*itr).value.end());
if(util::parseIntNoThrow
(priority, (*itr).value, (*itr).value+(*itr).valueLength)) {
if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
stm->logError("url@priority is out of range");
psm->logError("url@priority is out of range");
return;
}
} catch(RecoverableException& e) {
stm->logError("Bad url@priority");
} else {
psm->logError("Bad url@priority");
return;
}
}
}
stm->newResourceTransaction();
stm->setLocationOfResource(location);
stm->setPriorityOfResource(priority);
psm->newResourceTransaction();
psm->setLocationOfResource(location);
psm->setPriorityOfResource(priority);
}
#ifdef ENABLE_MESSAGE_DIGEST
else if(localname == HASH) {
stm->setHashStateV4();
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
if(itr == attrs.end() || (*itr).value.empty()) {
stm->logError("Missing hash@type");
else if(strcmp(localname, "hash") == 0) {
psm->setHashStateV4();
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "type", METALINK4_NAMESPACE_URI);
if(itr == attrs.end() || (*itr).valueLength == 0) {
psm->logError("Missing hash@type");
return;
} else {
std::string type = (*itr).value;
stm->newChecksumTransaction();
stm->setTypeOfChecksum(type);
psm->newChecksumTransaction();
psm->setTypeOfChecksum(std::string((*itr).value, (*itr).valueLength));
}
} else if(localname == PIECES) {
stm->setPiecesStateV4();
size_t length;
} else if(strcmp(localname, "pieces") == 0) {
psm->setPiecesStateV4();
int32_t length;
{
std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LENGTH);
if(itr == attrs.end() || (*itr).value.empty()) {
stm->logError("Missing pieces@length");
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "length", METALINK4_NAMESPACE_URI);
if(itr == attrs.end() || (*itr).valueLength == 0) {
psm->logError("Missing pieces@length");
return;
} else if(!util::parseIntNoThrow
(length, (*itr).value, (*itr).value+(*itr).valueLength) ||
length < 0) {
psm->logError("Bad pieces@length");
return;
} else {
try {
length = util::parseInt((*itr).value.begin(), (*itr).value.end());
} 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() || (*itr).value.empty()) {
stm->logError("Missing pieces@type");
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "type", METALINK4_NAMESPACE_URI);
if(itr == attrs.end() || (*itr).valueLength == 0) {
psm->logError("Missing pieces@type");
return;
} else {
type = (*itr).value;
type.assign((*itr).value, (*itr).valueLength);
}
}
stm->newChunkChecksumTransactionV4();
stm->setLengthOfChunkChecksumV4(length);
stm->setTypeOfChunkChecksumV4(type);
psm->newChunkChecksumTransactionV4();
psm->setLengthOfChunkChecksumV4(length);
psm->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() || (*itr).value.empty()) {
stm->logError("Missing signature@mediatype");
else if(strcmp(localname, "signature") == 0) {
psm->setSignatureStateV4();
std::vector<XmlAttr>::const_iterator itr =
findAttr(attrs, "mediatype", METALINK4_NAMESPACE_URI);
if(itr == attrs.end() || (*itr).valueLength == 0) {
psm->logError("Missing signature@mediatype");
return;
}
stm->newSignatureTransaction();
stm->setTypeOfSignature((*itr).value);
psm->newSignatureTransaction();
psm->setTypeOfSignature(std::string((*itr).value, (*itr).valueLength));
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void FileMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->commitEntryTransaction();
psm->commitEntryTransaction();
}
void SizeMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
try {
stm->setFileLengthOfEntry
(util::parseULLInt(characters.begin(), characters.end()));
} catch(RecoverableException& e) {
stm->cancelEntryTransaction();
stm->logError("Bad size");
int64_t size;
if(util::parseLLIntNoThrow(size, characters.begin(), characters.end()) &&
size >= 0) {
psm->setFileLengthOfEntry(size);
} else {
psm->cancelEntryTransaction();
psm->logError("Bad size");
}
}
void VersionMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setVersionOfEntry(characters);
psm->setVersionOfEntry(characters);
}
void LanguageMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setLanguageOfEntry(characters);
psm->setLanguageOfEntry(characters);
}
void OSMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setOSOfEntry(characters);
psm->setOSOfEntry(characters);
}
void HashMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setHashOfChecksum(characters);
stm->commitChecksumTransaction();
psm->setHashOfChecksum(characters);
psm->commitChecksumTransaction();
}
void PiecesMetalinkParserStateV4::beginElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
if(nsUri == METALINK4_NAMESPACE_URI && localname == HASH) {
stm->setPieceHashStateV4();
if(checkNsUri(nsUri) && strcmp(localname, "hash") == 0) {
psm->setPieceHashStateV4();
} else {
stm->setSkipTagState();
psm->setSkipTagState();
}
}
void PiecesMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->commitChunkChecksumTransactionV4();
psm->commitChunkChecksumTransactionV4();
}
void PieceHashMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->addHashOfChunkChecksumV4(characters);
psm->addHashOfChunkChecksumV4(characters);
}
void SignatureMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setBodyOfSignature(characters);
stm->commitSignatureTransaction();
psm->setBodyOfSignature(characters);
psm->commitSignatureTransaction();
}
void URLMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setURLOfResource(characters);
stm->commitResourceTransaction();
psm->setURLOfResource(characters);
psm->commitResourceTransaction();
}
void MetaurlMetalinkParserStateV4::endElement
(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stm->setURLOfMetaurl(characters);
stm->commitMetaurlTransaction();
psm->setURLOfMetaurl(characters);
psm->commitMetaurlTransaction();
}
} // namespace aria2

View File

@ -40,31 +40,31 @@
namespace aria2 {
extern const std::string METALINK4_NAMESPACE_URI;
extern const char METALINK4_NAMESPACE_URI[];
class MetalinkMetalinkParserStateV4:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
};
class FileMetalinkParserStateV4:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -76,10 +76,10 @@ public:
class SizeMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -91,10 +91,10 @@ public:
class VersionMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -106,10 +106,10 @@ public:
class LanguageMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -121,10 +121,10 @@ public:
class OSMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -136,10 +136,10 @@ public:
class HashMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -151,16 +151,16 @@ public:
class PiecesMetalinkParserStateV4:public MetalinkParserState
{
public:
virtual void beginElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void beginElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -172,10 +172,10 @@ public:
class PieceHashMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -187,10 +187,10 @@ public:
class SignatureMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -202,10 +202,10 @@ public:
class URLMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const
@ -217,10 +217,10 @@ public:
class MetaurlMetalinkParserStateV4:public SkipTagMetalinkParserState
{
public:
virtual void endElement(MetalinkParserStateMachine* stm,
const std::string& localname,
const std::string& prefix,
const std::string& nsUri,
virtual void endElement(MetalinkParserStateMachine* psm,
const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
virtual bool needsCharactersBuffering() const

70
src/ParserStateMachine.h Normal file
View File

@ -0,0 +1,70 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2011 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_PARSER_STATE_MACHINE_H
#define D_PARSER_STATE_MACHINE_H
#include "common.h"
#include <string>
#include <vector>
namespace aria2 {
class XmlAttr;
class ParserStateMachine {
public:
virtual ~ParserStateMachine() {}
virtual bool needsCharactersBuffering() const = 0;
virtual bool finished() const = 0;
virtual void beginElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs) = 0;
virtual void endElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters) = 0;
};
} // namespace aria2
#endif // D_PARSER_STATE_MACHINE_H

View File

@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
* Copyright (C) 2011 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
@ -32,75 +32,70 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "XML2SAXMetalinkProcessor.h"
#include "XmlParser.h"
#include <cassert>
#include <cstring>
#include <deque>
#include <libxml/parser.h>
#include "a2io.h"
#include "BinaryStream.h"
#include "MetalinkParserStateMachine.h"
#include "Metalinker.h"
#include "MetalinkEntry.h"
#include "util.h"
#include "ParserStateMachine.h"
#include "message.h"
#include "DlAbortEx.h"
#include "A2STR.h"
#include "error_code.h"
#include "a2functional.h"
#include "XmlAttr.h"
namespace aria2 {
namespace {
class SessionData {
public:
SharedHandle<MetalinkParserStateMachine> stm_;
struct SessionData {
std::deque<std::string> charactersStack_;
SessionData(const SharedHandle<MetalinkParserStateMachine>& stm):stm_(stm) {}
ParserStateMachine* psm_;
SessionData(ParserStateMachine* psm)
: psm_(psm)
{}
};
} // namespace
namespace {
void mlStartElement
(void* userData,
const xmlChar* srcLocalname,
const xmlChar* srcPrefix,
const xmlChar* srcNsUri,
const xmlChar* localname,
const xmlChar* prefix,
const xmlChar* nsUri,
int numNamespaces,
const xmlChar **namespaces,
const xmlChar** namespaces,
int numAttrs,
int numDefaulted,
const xmlChar **attrs)
const xmlChar** attrs)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
std::vector<XmlAttr> xmlAttrs;
size_t index = 0;
for(int attrIndex = 0; attrIndex < numAttrs; ++attrIndex, index += 5) {
const char** pattrs = reinterpret_cast<const char**>(attrs);
for(size_t i = 0, max = numAttrs*5; i < max; i += 5) {
XmlAttr xmlAttr;
assert(attrs[index]);
xmlAttr.localname = reinterpret_cast<const char*>(attrs[index]);
if(attrs[index+1]) {
xmlAttr.prefix = reinterpret_cast<const char*>(attrs[index+1]);
assert(pattrs[i]);
xmlAttr.localname = pattrs[i];
if(pattrs[i+1]) {
xmlAttr.prefix = pattrs[i+1];
}
if(attrs[index+2]) {
xmlAttr.nsUri = reinterpret_cast<const char*>(attrs[index+2]);
if(attrs[i+2]) {
xmlAttr.nsUri = pattrs[i+2];
}
const char* valueBegin = reinterpret_cast<const char*>(attrs[index+3]);
const char* valueEnd = reinterpret_cast<const char*>(attrs[index+4]);
xmlAttr.value.assign(valueBegin, valueEnd);
xmlAttr.value = pattrs[i+3];
xmlAttr.valueLength = pattrs[i+4]-xmlAttr.value;
xmlAttrs.push_back(xmlAttr);
}
assert(srcLocalname);
std::string localname = reinterpret_cast<const char*>(srcLocalname);
std::string prefix;
std::string nsUri;
if(srcPrefix) {
prefix = reinterpret_cast<const char*>(srcPrefix);
}
if(srcNsUri) {
nsUri = reinterpret_cast<const char*>(srcNsUri);
}
sd->stm_->beginElement(localname, prefix, nsUri, xmlAttrs);
if(sd->stm_->needsCharactersBuffering()) {
sd->psm_->beginElement
(reinterpret_cast<const char*>(localname),
reinterpret_cast<const char*>(prefix),
reinterpret_cast<const char*>(nsUri),
xmlAttrs);
if(sd->psm_->needsCharactersBuffering()) {
sd->charactersStack_.push_front(A2STR::NIL);
}
}
@ -109,26 +104,21 @@ void mlStartElement
namespace {
void mlEndElement
(void* userData,
const xmlChar* srcLocalname,
const xmlChar* srcPrefix,
const xmlChar* srcNsUri)
const xmlChar* localname,
const xmlChar* prefix,
const xmlChar* nsUri)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
std::string characters;
if(sd->stm_->needsCharactersBuffering()) {
if(sd->psm_->needsCharactersBuffering()) {
characters = sd->charactersStack_.front();
sd->charactersStack_.pop_front();
}
std::string localname = reinterpret_cast<const char*>(srcLocalname);
std::string prefix;
std::string nsUri;
if(srcPrefix) {
prefix = reinterpret_cast<const char*>(srcPrefix);
}
if(srcNsUri) {
nsUri = reinterpret_cast<const char*>(srcNsUri);
}
sd->stm_->endElement(localname, prefix, nsUri, characters);
sd->psm_->endElement
(reinterpret_cast<const char*>(localname),
reinterpret_cast<const char*>(prefix),
reinterpret_cast<const char*>(nsUri),
characters);
}
} // namespace
@ -136,7 +126,7 @@ namespace {
void mlCharacters(void* userData, const xmlChar* ch, int len)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
if(sd->stm_->needsCharactersBuffering()) {
if(sd->psm_->needsCharactersBuffering()) {
sd->charactersStack_.front().append(&ch[0], &ch[len]);
}
}
@ -180,89 +170,62 @@ xmlSAXHandler mySAXHandler =
};
} // namespace
MetalinkProcessor::MetalinkProcessor() {}
XmlParser::XmlParser(ParserStateMachine* psm)
: psm_(psm)
{}
MetalinkProcessor::~MetalinkProcessor() {}
XmlParser::~XmlParser() {}
SharedHandle<Metalinker>
MetalinkProcessor::parseFile
(const std::string& filename,
const std::string& baseUri)
bool XmlParser::parseFile(const char* filename)
{
stm_.reset(new MetalinkParserStateMachine());
stm_->setBaseUri(baseUri);
SharedHandle<SessionData> sessionData(new SessionData(stm_));
SessionData sessionData(psm_);
// Old libxml2(at least 2.7.6, Ubuntu 10.04LTS) does not read stdin
// when "/dev/stdin" is passed as filename while 2.7.7 does. So we
// convert DEV_STDIN to "-" for compatibility.
std::string nfilename;
if(filename == DEV_STDIN) {
const char* nfilename;
if(strcmp(filename, DEV_STDIN) == 0) {
nfilename = "-";
} else {
nfilename = filename;
}
int retval = xmlSAXUserParseFile(&mySAXHandler, sessionData.get(),
nfilename.c_str());
if(retval != 0) {
throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK,
error_code::METALINK_PARSE_ERROR);
}
if(!stm_->finished()) {
throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK,
error_code::METALINK_PARSE_ERROR);
}
if(!stm_->getErrors().empty()) {
throw DL_ABORT_EX2(stm_->getErrorString(),
error_code::METALINK_PARSE_ERROR);
}
return stm_->getResult();
int r = xmlSAXUserParseFile(&mySAXHandler, &sessionData, nfilename);
return r == 0 && psm_->finished();
}
SharedHandle<Metalinker>
MetalinkProcessor::parseFromBinaryStream
(const SharedHandle<BinaryStream>& binaryStream,
const std::string& baseUri)
bool XmlParser::parseBinaryStream(BinaryStream* bs)
{
stm_.reset(new MetalinkParserStateMachine());
stm_->setBaseUri(baseUri);
size_t bufSize = 4096;
const size_t bufSize = 4096;
unsigned char buf[bufSize];
ssize_t res = binaryStream->readData(buf, 4, 0);
ssize_t res = bs->readData(buf, 4, 0);
if(res != 4) {
throw DL_ABORT_EX2("Too small data for parsing XML.",
error_code::METALINK_PARSE_ERROR);
return false;
}
SharedHandle<SessionData> sessionData(new SessionData(stm_));
SessionData sessionData(psm_);
xmlParserCtxtPtr ctx = xmlCreatePushParserCtxt
(&mySAXHandler, sessionData.get(),
(&mySAXHandler, &sessionData,
reinterpret_cast<const char*>(buf), res, 0);
auto_delete<xmlParserCtxtPtr> deleter(ctx, xmlFreeParserCtxt);
off_t readOffset = res;
while(1) {
ssize_t res = binaryStream->readData(buf, bufSize, readOffset);
ssize_t res = bs->readData(buf, bufSize, readOffset);
if(res == 0) {
break;
}
if(xmlParseChunk(ctx, reinterpret_cast<const char*>(buf), res, 0) != 0) {
throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK,
error_code::METALINK_PARSE_ERROR);
// TODO we need this? Just break is not suffice?
return false;
}
readOffset += res;
}
xmlParseChunk(ctx, reinterpret_cast<const char*>(buf), 0, 1);
return psm_->finished();
}
if(!stm_->finished()) {
throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK,
error_code::METALINK_PARSE_ERROR);
}
if(!stm_->getErrors().empty()) {
throw DL_ABORT_EX2(stm_->getErrorString(),
error_code::METALINK_PARSE_ERROR);
}
return stm_->getResult();
bool XmlParser::parseMemory(const char* xml, size_t len)
{
SessionData sessionData(psm_);
int r = xmlSAXUserParseMemory(&mySAXHandler, &sessionData, xml, len);
return r == 0 && psm_->finished();
}
} // namespace aria2

View File

@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
* Copyright (C) 2011 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
@ -32,42 +32,30 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_XML2_SAX_METALINK_PROCESSOR_H
#define D_XML2_SAX_METALINK_PROCESSOR_H
#ifndef D_XML2_XML_PARSER_H
#define D_XML2_XML_PARSER_H
#include "common.h"
#include <string>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include "SharedHandle.h"
#include "A2STR.h"
#include <cstdlib>
namespace aria2 {
class Metalinker;
class BinaryStream;
class MetalinkParserStateMachine;
class ParserStateMachine;
class MetalinkProcessor {
private:
SharedHandle<MetalinkParserStateMachine> stm_;
class XmlParser {
public:
MetalinkProcessor();
~MetalinkProcessor();
SharedHandle<Metalinker> parseFile
(const std::string& filename,
const std::string& baseUri = A2STR::NIL);
SharedHandle<Metalinker> parseFromBinaryStream
(const SharedHandle<BinaryStream>& binaryStream,
const std::string& baseUri = A2STR::NIL);
// This object does not delete psm.
XmlParser(ParserStateMachine* psm);
~XmlParser();
bool parseFile(const char* filename);
bool parseBinaryStream(BinaryStream* binaryStream);
bool parseMemory(const char* xml, size_t size);
private:
ParserStateMachine* psm_;
};
} // namespace aria2
#endif // D_XML2_SAX_METALINK_PROCESSOR_H
#endif // D_XML2_XML_PARSER_H

47
src/XmlAttr.cc Normal file
View File

@ -0,0 +1,47 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2011 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 "XmlAttr.h"
namespace aria2 {
XmlAttr::XmlAttr()
: localname(0),
prefix(0),
nsUri(0),
value(0),
valueLength(0)
{}
} // namespace aria2

59
src/XmlAttr.h Normal file
View File

@ -0,0 +1,59 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2011 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_XML_ATTR_H
#define D_XML_ATTR_H
#include "common.h"
#include <cstdlib>
namespace aria2 {
struct XmlAttr {
const char* localname;
const char* prefix;
const char* nsUri;
const char* value;
size_t valueLength;
XmlAttr();
// XmlAttr(const XmlAttr& attr);
// ~XmlAttr();
// XmlAttr& operator=(const XmlAttr&);
};
} // namespace aria2
#endif // D_XML_ATTR_H

View File

@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
* Copyright (C) 2011 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
@ -32,15 +32,15 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_METALINK_PROCESSOR_H
#define D_METALINK_PROCESSOR_H
#ifndef D_XML_PARSER_H
#define D_XML_PARSER_H
#include "common.h"
#ifdef HAVE_LIBXML2
# include "XML2SAXMetalinkProcessor.h"
# include "Xml2XmlParser.h"
#elif HAVE_LIBEXPAT
# include "ExpatMetalinkProcessor.h"
# include "Expat2XmlParser.h"
#endif
#endif // D_METALINK_PROCESSOR_H
#endif // D_XML_PARSER_H

View File

@ -37,7 +37,7 @@
#include "MetalinkEntry.h"
#include "MetalinkParserStateMachine.h"
#include "Metalinker.h"
#include "MetalinkProcessor.h"
#include "XmlParser.h"
#include "prefs.h"
#include "DlAbortEx.h"
#include "BinaryStream.h"
@ -68,20 +68,17 @@ void parseAndQuery
const Option* option,
const std::string& baseUri)
{
MetalinkProcessor proc;
SharedHandle<Metalinker> metalinker = proc.parseFile(filename, baseUri);
SharedHandle<Metalinker> metalinker = parseFile(filename, baseUri);
query(result, metalinker, option);
}
void parseAndQuery
(std::vector<SharedHandle<MetalinkEntry> >& result,
const SharedHandle<BinaryStream>& binaryStream,
BinaryStream* bs,
const Option* option,
const std::string& baseUri)
{
MetalinkProcessor proc;
SharedHandle<Metalinker> metalinker =
proc.parseFromBinaryStream(binaryStream, baseUri);
SharedHandle<Metalinker> metalinker = parseBinaryStream(bs, baseUri);
query(result, metalinker, option);
}
@ -122,6 +119,40 @@ void groupEntryByMetaurlName
}
}
SharedHandle<Metalinker> parseFile
(const std::string& filename,
const std::string& baseUri)
{
MetalinkParserStateMachine psm;
psm.setBaseUri(baseUri);
if(!XmlParser(&psm).parseFile(filename.c_str())) {
throw DL_ABORT_EX2("Could not parse Metalink XML document.",
error_code::METALINK_PARSE_ERROR);
}
if(!psm.getErrors().empty()) {
throw DL_ABORT_EX2(psm.getErrorString(),
error_code::METALINK_PARSE_ERROR);
}
return psm.getResult();
}
SharedHandle<Metalinker> parseBinaryStream
(BinaryStream* bs,
const std::string& baseUri)
{
MetalinkParserStateMachine psm;
psm.setBaseUri(baseUri);
if(!XmlParser(&psm).parseBinaryStream(bs)) {
throw DL_ABORT_EX2("Could not parse Metalink XML document.",
error_code::METALINK_PARSE_ERROR);
}
if(!psm.getErrors().empty()) {
throw DL_ABORT_EX2(psm.getErrorString(),
error_code::METALINK_PARSE_ERROR);
}
return psm.getResult();
}
} // namespace metalink
} // namespace aria2

View File

@ -60,7 +60,7 @@ void parseAndQuery
void parseAndQuery
(std::vector<SharedHandle<MetalinkEntry> >& result,
const SharedHandle<BinaryStream>& binaryStream,
BinaryStream* bs,
const Option* option,
const std::string& baseUri = A2STR::NIL);
@ -69,6 +69,14 @@ void groupEntryByMetaurlName
std::pair<std::string, std::vector<SharedHandle<MetalinkEntry> > > >& result,
const std::vector<SharedHandle<MetalinkEntry> >& entries);
SharedHandle<Metalinker> parseFile
(const std::string& filename,
const std::string& baseUri = A2STR::NIL);
SharedHandle<Metalinker> parseBinaryStream
(BinaryStream* bs,
const std::string& baseUri = A2STR::NIL);
} // namespace metalink
} // namespace aria2

View File

@ -21,6 +21,7 @@
#include "fmt.h"
#include "RecoverableException.h"
#include "util.h"
#include "metalink_helper.h"
namespace aria2 {
@ -31,7 +32,7 @@ class MetalinkProcessorTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testParseFileV4_attrs);
CPPUNIT_TEST(testParseFile);
CPPUNIT_TEST(testParseFile_dirtraversal);
CPPUNIT_TEST(testParseFromBinaryStream);
CPPUNIT_TEST(testParseBinaryStream);
CPPUNIT_TEST(testMalformedXML);
CPPUNIT_TEST(testMalformedXML2);
CPPUNIT_TEST(testBadSize);
@ -57,7 +58,7 @@ public:
void testParseFileV4_attrs();
void testParseFile();
void testParseFile_dirtraversal();
void testParseFromBinaryStream();
void testParseBinaryStream();
void testMalformedXML();
void testMalformedXML2();
void testBadSize();
@ -82,8 +83,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION( MetalinkProcessorTest );
void MetalinkProcessorTest::testParseFileV4()
{
MetalinkProcessor proc;
SharedHandle<Metalinker> m = proc.parseFile(A2_TEST_DIR"/metalink4.xml");
SharedHandle<Metalinker> m = metalink::parseFile(A2_TEST_DIR"/metalink4.xml");
SharedHandle<MetalinkEntry> e;
SharedHandle<MetalinkResource> r;
SharedHandle<MetalinkMetaurl> mu;
@ -152,9 +152,8 @@ void MetalinkProcessorTest::testParseFileV4()
void MetalinkProcessorTest::testParseFileV4_attrs()
{
MetalinkProcessor proc;
SharedHandle<Metalinker> m;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
ByteArrayDiskWriter dw;
{
// Testing file@name
const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
@ -163,27 +162,27 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"<url>http://example.org</url>"
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "foo"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "foo"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
// empty name
dw->setString(fmt(tmpl, ""));
dw.setString(fmt(tmpl, ""));
try {
m = proc.parseFromBinaryStream(dw);
metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
// dir traversing
dw->setString(fmt(tmpl, "../doughnuts"));
try {
m = proc.parseFromBinaryStream(dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
dw.setString(fmt(tmpl, "../doughnuts"));
try {
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
}
{
// Testing url@priority
@ -193,36 +192,36 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"<url priority=\"%s\">http://example.org</url>"
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "0"));
dw.setString(fmt(tmpl, "0"));
try {
m = proc.parseFromBinaryStream(dw);
metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
dw->setString(fmt(tmpl, "1"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "1"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
dw->setString(fmt(tmpl, "100"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "100"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
dw->setString(fmt(tmpl, "999999"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "999999"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
dw->setString(fmt(tmpl, "1000000"));
dw.setString(fmt(tmpl, "1000000"));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
dw->setString(fmt(tmpl, "A"));
dw.setString(fmt(tmpl, "A"));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
}
@ -235,36 +234,36 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"<metaurl priority=\"%s\" mediatype=\"torrent\">http://example.org</metaurl>"
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "0"));
dw.setString(fmt(tmpl, "0"));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
dw->setString(fmt(tmpl, "1"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "1"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
dw->setString(fmt(tmpl, "100"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "100"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
dw->setString(fmt(tmpl, "999999"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "999999"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
dw->setString(fmt(tmpl, "1000000"));
dw.setString(fmt(tmpl, "1000000"));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
dw->setString(fmt(tmpl, "A"));
dw.setString(fmt(tmpl, "A"));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
}
@ -272,14 +271,14 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
// Testing metaurl@mediatype
// no mediatype
dw->setString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
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);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
@ -293,14 +292,14 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "torrent"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "torrent"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
// empty mediatype
dw->setString(fmt(tmpl, ""));
dw.setString(fmt(tmpl, ""));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
@ -316,22 +315,22 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "foo"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "foo"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
// dir traversing
dw->setString(fmt(tmpl, "../doughnuts"));
dw.setString(fmt(tmpl, "../doughnuts"));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
// empty name
dw->setString(fmt(tmpl, ""));
dw.setString(fmt(tmpl, ""));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
@ -341,7 +340,7 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
{
// Testing pieces@length
// No pieces@length
dw->setString
dw.setString
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
"<file name=\"example.ext\">"
@ -352,7 +351,7 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>");
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
@ -367,25 +366,25 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "262144"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "262144"));
m = metalink::parseBinaryStream(&dw);
// empty
try {
dw->setString(fmt(tmpl, ""));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, ""));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
// not a number
try {
dw->setString(fmt(tmpl, "A"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "A"));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
}
{
// Testing pieces@type
// No pieces@type
dw->setString
dw.setString
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
"<file name=\"example.ext\">"
@ -396,7 +395,7 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>");
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
@ -411,19 +410,19 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "sha-1"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "sha-1"));
m = metalink::parseBinaryStream(&dw);
// empty
try {
dw->setString(fmt(tmpl, ""));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, ""));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
}
{
// Testing hash@type
// No hash@type
dw->setString
dw.setString
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
"<file name=\"example.ext\">"
@ -432,7 +431,7 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>");
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
@ -445,12 +444,12 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "sha-1"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "sha-1"));
m = metalink::parseBinaryStream(&dw);
// empty
try {
dw->setString(fmt(tmpl, ""));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, ""));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
}
@ -458,7 +457,7 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
{
// Testing signature@mediatype
// No hash@type
dw->setString
dw.setString
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
"<file name=\"example.ext\">"
@ -467,7 +466,7 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>");
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
@ -480,12 +479,12 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "application/pgp-signature"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "application/pgp-signature"));
m = metalink::parseBinaryStream(&dw);
// empty
try {
dw->setString(fmt(tmpl, ""));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, ""));
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
}
@ -493,9 +492,9 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
void MetalinkProcessorTest::testParseFile()
{
MetalinkProcessor proc;
try {
SharedHandle<Metalinker> metalinker = proc.parseFile(A2_TEST_DIR"/test.xml");
SharedHandle<Metalinker> metalinker =
metalink::parseFile(A2_TEST_DIR"/test.xml");
std::vector<SharedHandle<MetalinkEntry> >::const_iterator entryItr =
metalinker->getEntries().begin();
@ -516,16 +515,17 @@ void MetalinkProcessorTest::testParseFile()
CPPUNIT_ASSERT_EQUAL(std::string("pgp"), entry1->getSignature()->getType());
CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.2.tar.bz2.sig"),
entry1->getSignature()->getFile());
// Note that last '\n' character is trimmed.
// Note that we don't strip anything
CPPUNIT_ASSERT_EQUAL
(std::string
("-----BEGIN PGP SIGNATURE-----\n"
("\n-----BEGIN PGP SIGNATURE-----\n"
"Version: GnuPG v1.4.9 (GNU/Linux)\n"
"\n"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
"ffffffffffffffffffffffff\n"
"fffff\n"
"-----END PGP SIGNATURE-----"),
"-----END PGP SIGNATURE-----\n"
"\t"),
entry1->getSignature()->getBody());
std::vector<SharedHandle<MetalinkResource> >::iterator resourceItr1 =
@ -600,9 +600,8 @@ void MetalinkProcessorTest::testParseFile()
void MetalinkProcessorTest::testParseFile_dirtraversal()
{
MetalinkProcessor proc;
SharedHandle<Metalinker> metalinker =
proc.parseFile(A2_TEST_DIR"/metalink3-dirtraversal.xml");
metalink::parseFile(A2_TEST_DIR"/metalink3-dirtraversal.xml");
CPPUNIT_ASSERT_EQUAL((size_t)1, metalinker->getEntries().size());
SharedHandle<MetalinkEntry> e = metalinker->getEntries()[0];
CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.3.tar.bz2"), e->getPath());
@ -610,15 +609,14 @@ void MetalinkProcessorTest::testParseFile_dirtraversal()
CPPUNIT_ASSERT_EQUAL(std::string(""), e->getSignature()->getFile());
}
void MetalinkProcessorTest::testParseFromBinaryStream()
void MetalinkProcessorTest::testParseBinaryStream()
{
MetalinkProcessor proc;
DefaultDiskWriterHandle dw(new DefaultDiskWriter(A2_TEST_DIR"/test.xml"));
dw->enableReadOnly();
dw->openExistingFile();
DefaultDiskWriter dw(A2_TEST_DIR"/test.xml");
dw.enableReadOnly();
dw.openExistingFile();
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
std::vector<SharedHandle<MetalinkEntry> >::const_iterator entryItr =
m->getEntries().begin();
@ -631,12 +629,11 @@ void MetalinkProcessorTest::testParseFromBinaryStream()
void MetalinkProcessorTest::testMalformedXML()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\"><files></file></metalink>");
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\"><files></file></metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace() << std::endl;
@ -645,12 +642,11 @@ void MetalinkProcessorTest::testMalformedXML()
void MetalinkProcessorTest::testMalformedXML2()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\"><files></files>");
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\"><files></files>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception& e) {
std::cerr << e.stackTrace() << std::endl;
@ -659,9 +655,8 @@ void MetalinkProcessorTest::testMalformedXML2()
void MetalinkProcessorTest::testBadSizeV4()
{
MetalinkProcessor proc;
SharedHandle<Metalinker> m;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
ByteArrayDiskWriter dw;
const char* tmpl =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
@ -672,21 +667,20 @@ void MetalinkProcessorTest::testBadSizeV4()
"</file>"
"</metalink>";
dw->setString(fmt(tmpl, "9223372036854775807"));
m = proc.parseFromBinaryStream(dw);
dw.setString(fmt(tmpl, "9223372036854775807"));
m = metalink::parseBinaryStream(&dw);
dw->setString(fmt(tmpl, "-1"));
dw.setString(fmt(tmpl, "-1"));
try {
m = proc.parseFromBinaryStream(dw);
m = metalink::parseBinaryStream(&dw);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {}
}
void MetalinkProcessorTest::testBadSize()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2-0.5.2.tar.bz2\">"
" <size>abc</size>"
@ -698,7 +692,7 @@ void MetalinkProcessorTest::testBadSize()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
std::vector<SharedHandle<MetalinkEntry> >::const_iterator entryItr =
m->getEntries().begin();
@ -716,9 +710,8 @@ void MetalinkProcessorTest::testBadSize()
void MetalinkProcessorTest::testBadMaxConn()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2-0.5.2.tar.bz2\">"
" <size>43743838</size>"
@ -731,7 +724,7 @@ void MetalinkProcessorTest::testBadMaxConn()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
std::vector<SharedHandle<MetalinkEntry> >::const_iterator entryItr =
m->getEntries().begin();
@ -744,9 +737,8 @@ void MetalinkProcessorTest::testBadMaxConn()
void MetalinkProcessorTest::testNoName()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file>"
" <size>1024</size>"
@ -764,7 +756,7 @@ void MetalinkProcessorTest::testNoName()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
std::vector<SharedHandle<MetalinkEntry> >::const_iterator entryItr =
m->getEntries().begin();
@ -777,9 +769,8 @@ void MetalinkProcessorTest::testNoName()
void MetalinkProcessorTest::testBadURLPrefs()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2-0.5.2.tar.bz2\">"
" <size>43743838</size>"
@ -795,7 +786,7 @@ void MetalinkProcessorTest::testBadURLPrefs()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
SharedHandle<MetalinkResource> r = e->resources[0];
CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r->type);
@ -809,9 +800,8 @@ void MetalinkProcessorTest::testBadURLPrefs()
void MetalinkProcessorTest::testBadURLMaxConn()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2-0.5.2.tar.bz2\">"
" <size>43743838</size>"
@ -828,7 +818,7 @@ void MetalinkProcessorTest::testBadURLMaxConn()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
SharedHandle<MetalinkResource> r = e->resources[0];
CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r->type);
@ -843,9 +833,8 @@ void MetalinkProcessorTest::testBadURLMaxConn()
#ifdef ENABLE_MESSAGE_DIGEST
void MetalinkProcessorTest::testUnsupportedType()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2-0.5.2.tar.bz2\">"
" <size>43743838</size>"
@ -862,7 +851,7 @@ void MetalinkProcessorTest::testUnsupportedType()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
CPPUNIT_ASSERT_EQUAL((size_t)3, e->resources.size());
SharedHandle<MetalinkResource> r1 = e->resources[0];
@ -878,9 +867,8 @@ void MetalinkProcessorTest::testUnsupportedType()
void MetalinkProcessorTest::testMultiplePieces()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2.tar.bz2\">"
" <verification>"
@ -895,7 +883,7 @@ void MetalinkProcessorTest::testMultiplePieces()
try {
// aria2 prefers sha1
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
SharedHandle<ChunkChecksum> c = e->chunkChecksum;
@ -908,9 +896,8 @@ void MetalinkProcessorTest::testMultiplePieces()
void MetalinkProcessorTest::testBadPieceNo()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString
ByteArrayDiskWriter dw;
dw.setString
("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2.tar.bz2\">"
@ -928,7 +915,7 @@ void MetalinkProcessorTest::testBadPieceNo()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
SharedHandle<ChunkChecksum> c = e->chunkChecksum;
@ -942,9 +929,8 @@ void MetalinkProcessorTest::testBadPieceNo()
void MetalinkProcessorTest::testBadPieceLength()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString
ByteArrayDiskWriter dw;
dw.setString
("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2.tar.bz2\">"
@ -961,7 +947,7 @@ void MetalinkProcessorTest::testBadPieceLength()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
SharedHandle<ChunkChecksum> c = e->chunkChecksum;
@ -975,9 +961,8 @@ void MetalinkProcessorTest::testBadPieceLength()
void MetalinkProcessorTest::testUnsupportedType_piece()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString
ByteArrayDiskWriter dw;
dw.setString
("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"aria2.tar.bz2\">"
@ -994,7 +979,7 @@ void MetalinkProcessorTest::testUnsupportedType_piece()
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
SharedHandle<ChunkChecksum> c = e->chunkChecksum;
@ -1009,21 +994,20 @@ void MetalinkProcessorTest::testUnsupportedType_piece()
void MetalinkProcessorTest::testLargeFileSize()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"dvd.iso\">"
" <size>9223372036854775807</size>"
" <resources>"
" <url type=\"http\">ftp://mirror/</url>"
" </resources>"
"</file>"
"</files>"
"</metalink>");
ByteArrayDiskWriter dw;
dw.setString
("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
"<files>"
"<file name=\"dvd.iso\">"
" <size>9223372036854775807</size>"
" <resources>"
" <url type=\"http\">ftp://mirror/</url>"
" </resources>"
"</file>"
"</files>"
"</metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
CPPUNIT_ASSERT_EQUAL((uint64_t)9223372036854775807ULL, e->getLength());
} catch(Exception& e) {
@ -1033,9 +1017,8 @@ void MetalinkProcessorTest::testLargeFileSize()
void MetalinkProcessorTest::testXmlPrefixV3()
{
MetalinkProcessor proc;
SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
dw->setString("<m:metalink version=\"3.0\" xmlns:m=\"http://www.metalinker.org/\">"
ByteArrayDiskWriter dw;
dw.setString("<m:metalink version=\"3.0\" xmlns:m=\"http://www.metalinker.org/\">"
"<m:files>"
"<m:file name=\"dvd.iso\">"
" <m:size>9223372036854775807</m:size>"
@ -1047,7 +1030,7 @@ void MetalinkProcessorTest::testXmlPrefixV3()
"</m:metalink>");
try {
SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
SharedHandle<Metalinker> m = metalink::parseBinaryStream(&dw);
CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
SharedHandle<MetalinkEntry> e = m->getEntries()[0];
CPPUNIT_ASSERT_EQUAL((uint64_t)9223372036854775807ULL, e->getLength());