From 936ce09b8339e2827e949385a0701a6f53a321a9 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 4 Dec 2007 11:12:56 +0000 Subject: [PATCH] 2007-12-04 Tatsuhiro Tsujikawa Added XML2SAXMetalinkProcessor class, which is a lot faster than the predecessor, Xml2MetalinkParser class. I tested them against 94KB metalink file with 1234 chunk checksums. The new one parsed it in 22msec, while it took 6000msec with old one. * src/XML2SAXMetalinkProcessor.{h, cc} * test/XML2SAXMetalinkProcessorTest.cc * src/MetalinkParserController.{h, cc} * test/MetalinkParserControllerTest.cc * src/MetalinkParserState.h: Also added 16 subclasses. * src/main.cc * src/Metalink2RequestGroup.cc * src/MetalinkHelper.cc * src/MetalinkEntry.cc * src/ChunkChecksum.h Rewritten Base64 class for better performance. * src/Base64.{h, cc} * test/Base64Test.cc * src/HttpRequest.cc --- ChangeLog | 22 ++ TODO | 1 - src/Base64.cc | 235 +++++++----- src/Base64.h | 59 ++- src/ByteArrayDiskWriter.h | 6 + src/ChunkChecksum.h | 17 + src/FileMetalinkParserState.cc | 82 ++++ src/FileMetalinkParserState.h | 50 +++ src/FilesMetalinkParserState.cc | 59 +++ src/FilesMetalinkParserState.h | 50 +++ src/FinMetalinkParserState.cc | 45 +++ src/FinMetalinkParserState.h | 50 +++ src/HashMetalinkParserState.cc | 52 +++ src/HashMetalinkParserState.h | 50 +++ src/InitialMetalinkParserState.cc | 51 +++ src/InitialMetalinkParserState.h | 50 +++ src/LanguageMetalinkParserState.cc | 51 +++ src/LanguageMetalinkParserState.h | 50 +++ src/Makefile.am | 22 +- src/Makefile.in | 88 ++++- src/Metalink2RequestGroup.cc | 2 +- src/MetalinkEntry.cc | 1 + src/MetalinkHelper.cc | 7 +- src/MetalinkMetalinkParserState.cc | 54 +++ src/MetalinkMetalinkParserState.h | 50 +++ src/MetalinkParserController.cc | 360 +++++++++++++++++ src/MetalinkParserController.h | 137 +++++++ src/MetalinkParserState.h | 53 +++ src/MetalinkParserStateMachine.cc | 327 ++++++++++++++++ src/MetalinkParserStateMachine.h | 178 +++++++++ src/OSMetalinkParserState.cc | 51 +++ src/OSMetalinkParserState.h | 50 +++ src/PieceHashMetalinkParserState.cc | 52 +++ src/PieceHashMetalinkParserState.h | 50 +++ src/PiecesMetalinkParserState.cc | 68 ++++ src/PiecesMetalinkParserState.h | 50 +++ src/ResourcesMetalinkParserState.cc | 105 +++++ src/ResourcesMetalinkParserState.h | 50 +++ src/SizeMetalinkParserState.cc | 58 +++ src/SizeMetalinkParserState.h | 50 +++ src/SkipTagMetalinkParserState.cc | 55 +++ src/SkipTagMetalinkParserState.h | 60 +++ src/URLMetalinkParserState.cc | 53 +++ src/URLMetalinkParserState.h | 50 +++ src/VerificationMetalinkParserState.cc | 92 +++++ src/VerificationMetalinkParserState.h | 50 +++ src/VersionMetalinkParserState.cc | 51 +++ src/VersionMetalinkParserState.h | 50 +++ src/XML2SAXMetalinkProcessor.cc | 167 ++++++++ src/XML2SAXMetalinkProcessor.h | 59 +++ src/main.cc | 8 +- test/Base64Test.cc | 212 +++++++++- test/Makefile.am | 8 +- test/Makefile.in | 55 +-- test/MetalinkParserControllerTest.cc | 140 +++++++ test/XML2SAXMetalinkProcessorTest.cc | 511 +++++++++++++++++++++++++ 56 files changed, 4290 insertions(+), 174 deletions(-) create mode 100644 src/FileMetalinkParserState.cc create mode 100644 src/FileMetalinkParserState.h create mode 100644 src/FilesMetalinkParserState.cc create mode 100644 src/FilesMetalinkParserState.h create mode 100644 src/FinMetalinkParserState.cc create mode 100644 src/FinMetalinkParserState.h create mode 100644 src/HashMetalinkParserState.cc create mode 100644 src/HashMetalinkParserState.h create mode 100644 src/InitialMetalinkParserState.cc create mode 100644 src/InitialMetalinkParserState.h create mode 100644 src/LanguageMetalinkParserState.cc create mode 100644 src/LanguageMetalinkParserState.h create mode 100644 src/MetalinkMetalinkParserState.cc create mode 100644 src/MetalinkMetalinkParserState.h create mode 100644 src/MetalinkParserController.cc create mode 100644 src/MetalinkParserController.h create mode 100644 src/MetalinkParserState.h create mode 100644 src/MetalinkParserStateMachine.cc create mode 100644 src/MetalinkParserStateMachine.h create mode 100644 src/OSMetalinkParserState.cc create mode 100644 src/OSMetalinkParserState.h create mode 100644 src/PieceHashMetalinkParserState.cc create mode 100644 src/PieceHashMetalinkParserState.h create mode 100644 src/PiecesMetalinkParserState.cc create mode 100644 src/PiecesMetalinkParserState.h create mode 100644 src/ResourcesMetalinkParserState.cc create mode 100644 src/ResourcesMetalinkParserState.h create mode 100644 src/SizeMetalinkParserState.cc create mode 100644 src/SizeMetalinkParserState.h create mode 100644 src/SkipTagMetalinkParserState.cc create mode 100644 src/SkipTagMetalinkParserState.h create mode 100644 src/URLMetalinkParserState.cc create mode 100644 src/URLMetalinkParserState.h create mode 100644 src/VerificationMetalinkParserState.cc create mode 100644 src/VerificationMetalinkParserState.h create mode 100644 src/VersionMetalinkParserState.cc create mode 100644 src/VersionMetalinkParserState.h create mode 100644 src/XML2SAXMetalinkProcessor.cc create mode 100644 src/XML2SAXMetalinkProcessor.h create mode 100644 test/MetalinkParserControllerTest.cc create mode 100644 test/XML2SAXMetalinkProcessorTest.cc diff --git a/ChangeLog b/ChangeLog index 793c3148..e3437ace 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2007-12-04 Tatsuhiro Tsujikawa + + Added XML2SAXMetalinkProcessor class, which is a lot faster than + the predecessor, Xml2MetalinkParser class. + I tested them against 94KB metalink file with 1234 chunk checksums. + The new one parsed it in 22msec, while it took 6000msec with old one. + * src/XML2SAXMetalinkProcessor.{h, cc} + * test/XML2SAXMetalinkProcessorTest.cc + * src/MetalinkParserController.{h, cc} + * test/MetalinkParserControllerTest.cc + * src/MetalinkParserState.h: Also added 16 subclasses. + * src/main.cc + * src/Metalink2RequestGroup.cc + * src/MetalinkHelper.cc + * src/MetalinkEntry.cc + * src/ChunkChecksum.h + + Rewritten Base64 class for better performance. + * src/Base64.{h, cc} + * test/Base64Test.cc + * src/HttpRequest.cc + 2007-12-01 Tatsuhiro Tsujikawa Fixed the bug#1841757: aria2 will connect to server to only get diff --git a/TODO b/TODO index 531967c7..b27a76f0 100644 --- a/TODO +++ b/TODO @@ -53,7 +53,6 @@ DownloadFailureException .... RequestGroup should halt. FatalException .... Program should abort. * replace strtol with Util::parseInt -* do performance tuning against Xml2MetalinkProcessor * remove header files from Makefile.am * create MetalinkProcessorFactory and get Xml2MetalinkProcessor from it. diff --git a/src/Base64.cc b/src/Base64.cc index 97d620d0..a16bdc6e 100644 --- a/src/Base64.cc +++ b/src/Base64.cc @@ -34,7 +34,7 @@ /* copyright --> */ #include "Base64.h" -static char base64_table[64] = { +static const char CHAR_TABLE[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', @@ -45,103 +45,158 @@ static char base64_table[64] = { '4', '5', '6', '7', '8', '9', '+', '/', }; -void Base64::part_encode(const unsigned char* sub, int32_t subLength, - unsigned char* buf) +static const int INDEX_TABLE[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +void Base64::encode(unsigned char*& result, size_t& rlength, + const unsigned char* src, size_t slength) { - int32_t shift = 2; - unsigned char carry = 0; - int32_t index; - for(index = 0; index < subLength; index++) { - unsigned char cur = sub[index] >> shift | carry; - carry = (sub[index] << (6-shift)) & 0x3f; - shift += 2; - buf[index] = base64_table[(uint32_t)cur]; + if(slength == 0) { + rlength = 0; + return; } - if(subLength == 1) { - buf[index] = base64_table[(uint32_t)carry]; - buf[index+1] = buf[index+2] = '='; - } else if(subLength == 2) { - buf[index] = base64_table[(uint32_t)carry]; - buf[index+1] = '='; + size_t trituple = (slength+2)/3; + int r = slength%3; + rlength = trituple*4; + result = new unsigned char[rlength]; + + unsigned char* p = result; + const unsigned char* s = src; + const unsigned char* smax = s+slength-r; + while(s != smax) { + int n = *s++ << 16; + n += *s++ << 8; + n += *s++; + *p++ = CHAR_TABLE[n >> 18]; + *p++ = CHAR_TABLE[n >> 12&0x3f]; + *p++ = CHAR_TABLE[n >> 6&0x3f]; + *p++ = CHAR_TABLE[n&0x3f]; + } + if(r == 2) { + int n = (*s << 16)+(*(s+1) << 8); + *p++ = CHAR_TABLE[n >> 18]; + *p++ = CHAR_TABLE[n >> 12&0x3f]; + *p++ = CHAR_TABLE[n >> 6&0x3f]; + *p++ = '='; + } else if(r == 1) { + int n = (*s << 16); + *p++ = CHAR_TABLE[n >> 18]; + *p++ = CHAR_TABLE[n >> 12&0x3f]; + *p++ = '='; + *p++ = '='; + } +} + +void Base64::removeNonBase64Chars(unsigned char*& nsrc, + size_t& nlength, + const unsigned char* src, + size_t slength) +{ + unsigned char* temp = new unsigned char[slength]; + const unsigned char* end = src+slength; + size_t n = 0; + for(const unsigned char*s = src; s != end; ++s) { + if(INDEX_TABLE[*s] != -1 || *s == '=') { + *(temp+n++) = *s; + } + } + unsigned char* ret = new unsigned char[n]; + memcpy(ret, temp, n); + delete [] temp; + nlength = n; + nsrc = ret; +} + +void Base64::decode(unsigned char*& result, size_t& rlength, + const unsigned char* src, size_t slength) +{ + if(slength == 0) { + rlength = 0; + return; + } + unsigned char* nsrc; + size_t nlength; + removeNonBase64Chars(nsrc, nlength, src, slength); + + if(nlength%4 != 0) { + delete [] nsrc; + rlength = 0; + return; + } + + size_t quadtuple = nlength/4; + size_t len; + if(nsrc[nlength-1] == '=') { + if(nsrc[nlength-2] == '=') { + len = nlength-2; + } else { + len = nlength-1; + } } else { - unsigned char cur = sub[subLength-1] & 0x3f; - buf[index] = base64_table[(uint32_t)cur]; + len = nlength; } + rlength = len-quadtuple; + result = new unsigned char[rlength]; + int r = len%4; + + unsigned char* p = result; + const unsigned char* s = nsrc; + const unsigned char* smax = s+len-r; + while(s != smax) { + int n = INDEX_TABLE[*s++] << 18; + n += INDEX_TABLE[*s++] << 12; + n += INDEX_TABLE[*s++] << 6; + n += INDEX_TABLE[*s++]; + *p++ = n >> 16; + *p++ = n >> 8&0xff; + *p++ = n&0xff; + } + if(r == 2) { + int n = INDEX_TABLE[*s++] << 18; + n += INDEX_TABLE[*s++] << 12; + *p++ = n >> 16; + } else if(r == 3) { + int n = INDEX_TABLE[*s++] << 18; + n += INDEX_TABLE[*s++] << 12; + n += INDEX_TABLE[*s++] << 6; + *p++ = n >> 16; + *p++ = n >> 8&0xff; + } + delete [] nsrc; } -string Base64::encode(const string& plainSrc) +string Base64::encode(const string& s) { - unsigned char* result = 0; - int32_t resultLength = 0; - - encode((const unsigned char*)plainSrc.c_str(), plainSrc.size(), - result, resultLength); - string encoded(&result[0], &result[resultLength]); - delete [] result; - return encoded; + unsigned char* buf = 0; + size_t len; + encode(buf, len, s.c_str(), s.size()); + string r(&buf[0], &buf[len]); + delete [] buf; + return r; } -void Base64::encode(const unsigned char* src, int32_t srcLength, - unsigned char*& result, int32_t& resultLength) { - resultLength = (srcLength+(srcLength%3 == 0 ? 0 : 3-srcLength%3))/3*4; - result = new unsigned char[resultLength]; - unsigned char* tail = result; - for(int32_t index = 0; srcLength > index; index += 3) { - unsigned char temp[4]; - part_encode(&src[index], - srcLength >= index+3 ? 3 : srcLength-index, - temp); - memcpy(tail, temp, sizeof(temp)); - tail += sizeof(temp); - } -} - - -char Base64::getValue(char ch) +string Base64::decode(const string& s) { - char retch; - - if(ch >= 'A' && ch <= 'Z') { - retch = ch-'A'; - } else if(ch >= 'a' && ch <= 'z') { - retch = ch-'a'+26; - } else if(ch >= '0' && ch <= '9') { - retch = ch-'0'+52; - } else if(ch == '+') { - retch = 62; - } else if(ch == '/') { - retch = 63; - } else { - retch = 0; - } - return retch; -} - -string Base64::part_decode(const string& subCrypted) -{ - int32_t shift = 2; - string plain; - - for(uint32_t index = 0; index < subCrypted.size()-1; ++index) { - if(subCrypted.at(index) == '=') break; - char cur = getValue(subCrypted.at(index)) << shift; - char carry = getValue(subCrypted.at(index+1)) >> (6-shift); - shift += 2; - plain += cur | carry; - } - - return plain; -} - -string Base64::decode(const string& crypted) -{ - string plain; - int32_t sIndex = 0; - for(int32_t index = 0; crypted.size() > (uint32_t)index; index +=4) { - string subCrypted = crypted.substr(sIndex, 4); - string subPlain = part_decode(subCrypted); - sIndex += 4; - plain += subPlain; - } - return plain; + unsigned char* buf = 0; + size_t len; + decode(buf, len, s.c_str(), s.size()); + string r(&buf[0], &buf[len]); + delete [] buf; + return r; } diff --git a/src/Base64.h b/src/Base64.h index 4d363a66..59914b94 100644 --- a/src/Base64.h +++ b/src/Base64.h @@ -32,30 +32,57 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#ifndef _BASE64_H_ -#define _BASE64_H_ +#ifndef _D_BASE64_H_ +#define _D_BASE64_H_ #include -#include "common.h" + using namespace std; class Base64 { private: - static void part_encode(const unsigned char* sub, int32_t subLength, - unsigned char* buf); + static void removeNonBase64Chars(unsigned char*& nsrc, size_t& nlength, + const unsigned char* src, size_t slength); - static string part_encode(const string& subplain); - static string part_decode(const string& subCrypted); - static char getValue(char ch); public: - static string encode(const string& plain); - // caller must deallocate the memory used by result. - static void encode(const unsigned char* src, int32_t srcLength, - unsigned char*& result, int32_t& resultLength); - static string decode(const string& crypted); - // caller must deallocate the memory used by result. - static void decode(const unsigned char* src, int32_t srcLength, - unsigned char*& result, int32_t& resultLength); + /** + * Encods src whose length is slength into base64 encoded data + * and stores them to result. + * result is allocated in this function and the length is stored to rlength. + * If slength is equal to 0, then return with rlength set to 0 and result + * is left untouched. + * A caller must deallocate the memory used by result. + */ + static void encode(unsigned char*& result, size_t& rlength, + const unsigned char* src, size_t slength); + + static void encode(unsigned char*& result, size_t& rlength, + const char* src, size_t slength) + { + encode(result, rlength, (const unsigned char*)src, slength); + } + + static string encode(const string& s); + + /** + * Dencods base64 encoded src whose length is slength and stores them to + * result. + * result is allocated in this function and the length is stored to rlength. + * If slength is equal to 0 or is not multiple of 4, then return with rlength + * set to 0 and result is left untouched. + * The function removes non-base64 characters before decoding. + * A caller must deallocate the memory used by result. + */ + static void decode(unsigned char*& result, size_t& rlength, + const unsigned char* src, size_t slength); + + static void decode(unsigned char*& result, size_t& rlength, + const char* src, size_t slength) + { + decode(result, rlength, (const unsigned char*)src, slength); + } + + static string decode(const string& s); }; #endif // _BASE64_H_ diff --git a/src/ByteArrayDiskWriter.h b/src/ByteArrayDiskWriter.h index 47d99946..f2a646b3 100644 --- a/src/ByteArrayDiskWriter.h +++ b/src/ByteArrayDiskWriter.h @@ -69,6 +69,12 @@ public: virtual void enableDirectIO() {} virtual void disableDirectIO() {} + + void setString(const string& s) + { + buf.str(s); + } }; +typedef SharedHandle ByteArrayDiskWriterHandle; #endif // _D_BYTE_ARRAY_DISK_WRITER_H_ diff --git a/src/ChunkChecksum.h b/src/ChunkChecksum.h index e9dfbee2..c6280b4e 100644 --- a/src/ChunkChecksum.h +++ b/src/ChunkChecksum.h @@ -44,6 +44,8 @@ private: Strings _checksums; int32_t _checksumLength; public: + ChunkChecksum():_checksumLength(0) {} + ChunkChecksum(const string& algo, const Strings& checksums, int32_t checksumLength): @@ -94,6 +96,21 @@ public: { return _algo; } + + void setAlgo(const string& algo) + { + _algo = algo; + } + + void setChecksumLength(int32_t length) + { + _checksumLength = length; + } + + void setChecksums(const Strings& mds) + { + _checksums = mds; + } }; typedef SharedHandle ChunkChecksumHandle; diff --git a/src/FileMetalinkParserState.cc b/src/FileMetalinkParserState.cc new file mode 100644 index 00000000..27be505c --- /dev/null +++ b/src/FileMetalinkParserState.cc @@ -0,0 +1,82 @@ +/* */ +#include "FileMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" +#include "Util.h" +#include "RecoverableException.h" + +void FileMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + if(name == "size") { + stm->setSizeState(); + } else if(name == "version") { + stm->setVersionState(); + } else if(name == "language") { + stm->setLanguageState(); + } else if(name == "os") { + stm->setOSState(); + } else if(name == "verification") { + stm->setVerificationState(); + } else if(name == "resources") { + stm->setResourcesState(); + int32_t maxConnections; + { + map::const_iterator itr = attrs.find("maxconnections"); + if(itr == attrs.end()) { + maxConnections = -1; + } else { + try { + maxConnections = Util::parseInt((*itr).second); + } catch(RecoverableException* e) { + delete e; + maxConnections = -1; + } + } + } + stm->setMaxConnectionsOfEntry(maxConnections); + } else { + stm->setSkipTagState(this); + } +} + +void FileMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->commitEntryTransaction(); + stm->setFilesState(); +} diff --git a/src/FileMetalinkParserState.h b/src/FileMetalinkParserState.h new file mode 100644 index 00000000..22653d58 --- /dev/null +++ b/src/FileMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_FILE_METALINK_PARSER_STATE_H_ +#define _D_FILE_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class FileMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_FILE_METALINK_PARSER_STATE_H_ diff --git a/src/FilesMetalinkParserState.cc b/src/FilesMetalinkParserState.cc new file mode 100644 index 00000000..ccdbacb0 --- /dev/null +++ b/src/FilesMetalinkParserState.cc @@ -0,0 +1,59 @@ +/* */ +#include "FilesMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void FilesMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + if(name == "file") { + stm->setFileState(); + map::const_iterator itr = attrs.find("name"); + if(itr != attrs.end()) { + stm->newEntryTransaction(); + stm->setFileNameOfEntry((*itr).second); + } + } else { + stm->setSkipTagState(this); + } +} + +void FilesMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setMetalinkState(); +} diff --git a/src/FilesMetalinkParserState.h b/src/FilesMetalinkParserState.h new file mode 100644 index 00000000..176a3b89 --- /dev/null +++ b/src/FilesMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_FILES_METALINK_PARSER_STATE_H_ +#define _D_FILES_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class FilesMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_FILES_METALINK_PARSER_STATE_H_ diff --git a/src/FinMetalinkParserState.cc b/src/FinMetalinkParserState.cc new file mode 100644 index 00000000..f7de1442 --- /dev/null +++ b/src/FinMetalinkParserState.cc @@ -0,0 +1,45 @@ +/* */ +#include "FinMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void FinMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{} + +void FinMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters) +{} diff --git a/src/FinMetalinkParserState.h b/src/FinMetalinkParserState.h new file mode 100644 index 00000000..868ebbe0 --- /dev/null +++ b/src/FinMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_FIN_METALINK_PARSER_STATE_H_ +#define _D_FIN_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class FinMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_FIN_METALINK_PARSER_STATE_H_ diff --git a/src/HashMetalinkParserState.cc b/src/HashMetalinkParserState.cc new file mode 100644 index 00000000..501cc5f8 --- /dev/null +++ b/src/HashMetalinkParserState.cc @@ -0,0 +1,52 @@ +/* */ +#include "HashMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void HashMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + stm->setSkipTagState(this); +} + +void HashMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setHashOfChecksum(characters); + stm->commitChecksumTransaction(); + stm->setVerificationState(); +} diff --git a/src/HashMetalinkParserState.h b/src/HashMetalinkParserState.h new file mode 100644 index 00000000..0d23b0f0 --- /dev/null +++ b/src/HashMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_HASH_METALINK_PARSER_STATE_H_ +#define _D_HASH_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class HashMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_HASH_METALINK_PARSER_STATE_H_ diff --git a/src/InitialMetalinkParserState.cc b/src/InitialMetalinkParserState.cc new file mode 100644 index 00000000..213c25c8 --- /dev/null +++ b/src/InitialMetalinkParserState.cc @@ -0,0 +1,51 @@ +/* */ +#include "InitialMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void InitialMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + if(name == "metalink") { + stm->setMetalinkState(); + } else { + stm->setSkipTagState(this); + } +} + +void InitialMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters) +{} diff --git a/src/InitialMetalinkParserState.h b/src/InitialMetalinkParserState.h new file mode 100644 index 00000000..4864188e --- /dev/null +++ b/src/InitialMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_INITIAL_METALINK_PARSER_STATE_H_ +#define _D_INITIAL_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class InitialMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_INITIAL_METALINK_PARSER_STATE_H_ diff --git a/src/LanguageMetalinkParserState.cc b/src/LanguageMetalinkParserState.cc new file mode 100644 index 00000000..a2aafcbd --- /dev/null +++ b/src/LanguageMetalinkParserState.cc @@ -0,0 +1,51 @@ +/* */ +#include "LanguageMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void LanguageMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + stm->setSkipTagState(this); +} + +void LanguageMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setLanguageOfEntry(characters); + stm->setFileState(); +} diff --git a/src/LanguageMetalinkParserState.h b/src/LanguageMetalinkParserState.h new file mode 100644 index 00000000..dda2a39e --- /dev/null +++ b/src/LanguageMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_LANGUAGE_METALINK_PARSER_STATE_H_ +#define _D_LANGUAGE_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class LanguageMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_LANGUAGE_METALINK_PARSER_STATE_H_ diff --git a/src/Makefile.am b/src/Makefile.am index 4e6e7b0a..a2cb4e81 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,7 +46,7 @@ SRCS = Socket.h\ DefaultDiskWriter.cc DefaultDiskWriter.h\ File.cc File.h\ Option.cc Option.h\ - Base64.cc Base64.h\ + Base64.cc\ CookieBox.cc CookieBox.h\ LogFactory.cc LogFactory.h\ NullLogger.h\ @@ -255,7 +255,25 @@ SRCS += Metalinker.cc Metalinker.h\ MetalinkEntry.cc MetalinkEntry.h\ MetalinkResource.cc MetalinkResource.h\ MetalinkProcessor.h\ - Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\ + MetalinkParserController.cc\ + MetalinkParserStateMachine.cc\ + InitialMetalinkParserState.cc\ + MetalinkMetalinkParserState.cc\ + FilesMetalinkParserState.cc\ + FileMetalinkParserState.cc\ + SizeMetalinkParserState.cc\ + VersionMetalinkParserState.cc\ + LanguageMetalinkParserState.cc\ + OSMetalinkParserState.cc\ + VerificationMetalinkParserState.cc\ + HashMetalinkParserState.cc\ + PiecesMetalinkParserState.cc\ + PieceHashMetalinkParserState.cc\ + ResourcesMetalinkParserState.cc\ + URLMetalinkParserState.cc\ + FinMetalinkParserState.cc\ + SkipTagMetalinkParserState.cc\ + XML2SAXMetalinkProcessor.cc\ Metalink2RequestGroup.cc Metalink2RequestGroup.h\ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\ MetalinkHelper.cc MetalinkHelper.h diff --git a/src/Makefile.in b/src/Makefile.in index 2f36ee31..368bdb3b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -142,7 +142,25 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\ @ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\ @ENABLE_METALINK_TRUE@ MetalinkProcessor.h\ -@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\ +@ENABLE_METALINK_TRUE@ MetalinkParserController.cc\ +@ENABLE_METALINK_TRUE@ MetalinkParserStateMachine.cc\ +@ENABLE_METALINK_TRUE@ InitialMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ MetalinkMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ FilesMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ FileMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ SizeMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ VersionMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ LanguageMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ OSMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ VerificationMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ HashMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ PiecesMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ PieceHashMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ ResourcesMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ URLMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ FinMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ SkipTagMetalinkParserState.cc\ +@ENABLE_METALINK_TRUE@ XML2SAXMetalinkProcessor.cc\ @ENABLE_METALINK_TRUE@ Metalink2RequestGroup.cc Metalink2RequestGroup.h\ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\ @ENABLE_METALINK_TRUE@ MetalinkHelper.cc MetalinkHelper.h @@ -208,7 +226,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \ AbstractDiskWriter.cc AbstractDiskWriter.h \ DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \ - Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \ + Option.cc Option.h Base64.cc CookieBox.cc CookieBox.h \ LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \ SharedHandle.h HandleRegistry.h FeatureConfig.cc \ FeatureConfig.h DownloadEngineFactory.cc \ @@ -338,14 +356,22 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h Metalinker.cc \ Metalinker.h MetalinkEntry.cc MetalinkEntry.h \ MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \ - Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h \ - Metalink2RequestGroup.cc Metalink2RequestGroup.h \ - MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h \ - MetalinkHelper.cc MetalinkHelper.h libgen.c libgen.h \ - getaddrinfo.c getaddrinfo.h gai_strerror.c gai_strerror.h \ - gettimeofday.c gettimeofday.h inet_aton.c inet_aton.h \ - localtime_r.c localtime_r.h strptime.c strptime.h timegm.c \ - timegm.h + MetalinkParserController.cc MetalinkParserStateMachine.cc \ + InitialMetalinkParserState.cc MetalinkMetalinkParserState.cc \ + FilesMetalinkParserState.cc FileMetalinkParserState.cc \ + SizeMetalinkParserState.cc VersionMetalinkParserState.cc \ + LanguageMetalinkParserState.cc OSMetalinkParserState.cc \ + VerificationMetalinkParserState.cc HashMetalinkParserState.cc \ + PiecesMetalinkParserState.cc PieceHashMetalinkParserState.cc \ + ResourcesMetalinkParserState.cc URLMetalinkParserState.cc \ + FinMetalinkParserState.cc SkipTagMetalinkParserState.cc \ + XML2SAXMetalinkProcessor.cc Metalink2RequestGroup.cc \ + Metalink2RequestGroup.h MetalinkPostDownloadHandler.cc \ + MetalinkPostDownloadHandler.h MetalinkHelper.cc \ + MetalinkHelper.h libgen.c libgen.h getaddrinfo.c getaddrinfo.h \ + gai_strerror.c gai_strerror.h gettimeofday.c gettimeofday.h \ + inet_aton.c inet_aton.h localtime_r.c localtime_r.h strptime.c \ + strptime.h timegm.c timegm.h @ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = IteratableChunkChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \ @@ -409,7 +435,25 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ -@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ MetalinkParserController.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ MetalinkParserStateMachine.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ InitialMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ MetalinkMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ FilesMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ FileMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ SizeMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ VersionMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ LanguageMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ OSMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ VerificationMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ HashMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ PiecesMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ PieceHashMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ ResourcesMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ URLMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ FinMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ SkipTagMetalinkParserState.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ XML2SAXMetalinkProcessor.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ Metalink2RequestGroup.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkHelper.$(OBJEXT) @@ -708,7 +752,7 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \ ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \ AbstractDiskWriter.cc AbstractDiskWriter.h \ DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \ - Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \ + Option.cc Option.h Base64.cc CookieBox.cc CookieBox.h \ LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \ SharedHandle.h HandleRegistry.h FeatureConfig.cc \ FeatureConfig.h DownloadEngineFactory.cc \ @@ -950,7 +994,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationMan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileEntry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileMetalinkParserState.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FilesMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FillRequestGroupCommand.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FinMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpDownloadCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpInitiateConnectionCommand.Po@am__quote@ @@ -958,6 +1005,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelRequestCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelResponseCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegment.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HashMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveEraseCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpConnection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpDownloadCommand.Po@am__quote@ @@ -970,9 +1018,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpRequestCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponseCommand.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitialMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiateConnectionCommandFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LanguageMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/List.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemoryBufferPreDownloadHandler.Po@am__quote@ @@ -981,6 +1031,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalink2RequestGroup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkHelper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkMetalinkParserState.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkParserController.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkParserStateMachine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkPostDownloadHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkResource.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalinker.Po@am__quote@ @@ -990,6 +1043,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameResolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Netrc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetrcAuthResolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OSMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Option.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OptionHandlerFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OptionParser.Po@am__quote@ @@ -1007,7 +1061,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerReceiveHandshakeCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Piece.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceHashCheckIntegrityEntry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceHashMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecedSegment.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecesMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RealtimeCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Request.Po@am__quote@ @@ -1016,6 +1072,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupMan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestSlot.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ResourcesMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SeedCheckCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentMan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitor.Po@am__quote@ @@ -1023,6 +1080,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleRandomizer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SingleFileAllocationIterator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SizeMetalinkParserState.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SkipTagMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketCore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpeedCalc.Po@am__quote@ @@ -1032,10 +1091,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeBasedCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TransferStat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/URLMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnknownLengthPieceStorage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VerificationMetalinkParserState.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VersionMetalinkParserState.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XML2SAXMetalinkProcessor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gai_strerror.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getaddrinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@ diff --git a/src/Metalink2RequestGroup.cc b/src/Metalink2RequestGroup.cc index 2e36f514..4b561070 100644 --- a/src/Metalink2RequestGroup.cc +++ b/src/Metalink2RequestGroup.cc @@ -37,7 +37,6 @@ #include "Option.h" #include "LogFactory.h" #include "prefs.h" -#include "Xml2MetalinkProcessor.h" #include "Util.h" #include "message.h" #include "SingleFileDownloadContext.h" @@ -45,6 +44,7 @@ #include "BinaryStream.h" #include "MemoryBufferPreDownloadHandler.h" #include "TrueRequestGroupCriteria.h" +#include "MetalinkEntry.h" #ifdef ENABLE_BITTORRENT # include "BtDependency.h" #endif // ENABLE_BITTORRENT diff --git a/src/MetalinkEntry.cc b/src/MetalinkEntry.cc index bfd447f8..4886118b 100644 --- a/src/MetalinkEntry.cc +++ b/src/MetalinkEntry.cc @@ -37,6 +37,7 @@ #include MetalinkEntry::MetalinkEntry(): + file(0), maxConnections(-1) #ifdef ENABLE_MESSAGE_DIGEST , diff --git a/src/MetalinkHelper.cc b/src/MetalinkHelper.cc index 0f225107..fb36505c 100644 --- a/src/MetalinkHelper.cc +++ b/src/MetalinkHelper.cc @@ -35,7 +35,8 @@ #include "MetalinkHelper.h" #include "Option.h" #include "MetalinkEntry.h" -#include "Xml2MetalinkProcessor.h" +#include "XML2SAXMetalinkProcessor.h" +#include "MetalinkParserStateMachine.h" #include "Metalinker.h" #include "prefs.h" #include "DlAbortEx.h" @@ -47,7 +48,7 @@ MetalinkHelper::~MetalinkHelper() {} MetalinkEntries MetalinkHelper::parseAndQuery(const string& filename, const Option* option) { - Xml2MetalinkProcessor proc; + XML2SAXMetalinkProcessor proc; MetalinkerHandle metalinker = proc.parseFile(filename); return query(metalinker, option); @@ -55,7 +56,7 @@ MetalinkEntries MetalinkHelper::parseAndQuery(const string& filename, const Opti MetalinkEntries MetalinkHelper::parseAndQuery(const BinaryStreamHandle& binaryStream, const Option* option) { - Xml2MetalinkProcessor proc; + XML2SAXMetalinkProcessor proc; MetalinkerHandle metalinker = proc.parseFromBinaryStream(binaryStream); return query(metalinker, option); diff --git a/src/MetalinkMetalinkParserState.cc b/src/MetalinkMetalinkParserState.cc new file mode 100644 index 00000000..61a1b8e4 --- /dev/null +++ b/src/MetalinkMetalinkParserState.cc @@ -0,0 +1,54 @@ +/* */ +#include "MetalinkMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void MetalinkMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + if(name == "files") { + stm->setFilesState(); + } else { + stm->setSkipTagState(this); + } +} + +void MetalinkMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setFinState(); +} diff --git a/src/MetalinkMetalinkParserState.h b/src/MetalinkMetalinkParserState.h new file mode 100644 index 00000000..06cfe666 --- /dev/null +++ b/src/MetalinkMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_METALINK_METALINK_PARSER_STATE_H_ +#define _D_METALINK_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class MetalinkMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_METALINK_METALINK_PARSER_STATE_H_ diff --git a/src/MetalinkParserController.cc b/src/MetalinkParserController.cc new file mode 100644 index 00000000..b1a97cf0 --- /dev/null +++ b/src/MetalinkParserController.cc @@ -0,0 +1,360 @@ +/* */ +#include "MetalinkParserController.h" +#include "Metalinker.h" +#include "MetalinkEntry.h" +#include "MetalinkResource.h" +#include "Checksum.h" +#include "ChunkChecksum.h" + +MetalinkParserController::MetalinkParserController(): + _metalinker(new Metalinker()), + _tEntry(0), + _tResource(0), + _tChecksum(0), + _tChunkChecksum(0) {} + +MetalinkParserController::~MetalinkParserController() {} + +MetalinkerHandle MetalinkParserController::getResult() const +{ + return _metalinker; +} + +void MetalinkParserController::newEntryTransaction() +{ + _tEntry = new MetalinkEntry(); + _tResource = 0; + _tChecksum = 0; + _tChunkChecksum = 0; +} + +void MetalinkParserController::setFileNameOfEntry(const string& filename) +{ + if(_tEntry.isNull()) { + return; + } + if(_tEntry->file.isNull()) { + _tEntry->file = new FileEntry(filename, 0, 0); + } else { + _tEntry->file->setPath(filename); + } +} + +void MetalinkParserController::setFileLengthOfEntry(int64_t length) +{ + if(_tEntry.isNull()) { + return; + } + if(_tEntry->file.isNull()) { + _tEntry->file = new FileEntry("", length, 0); + } else { + _tEntry->file->setLength(length); + } +} + +void MetalinkParserController::setVersionOfEntry(const string& version) +{ + if(_tEntry.isNull()) { + return; + } + _tEntry->version = version; +} + +void MetalinkParserController::setLanguageOfEntry(const string& language) +{ + if(_tEntry.isNull()) { + return; + } + _tEntry->language = language; +} + +void MetalinkParserController::setOSOfEntry(const string& os) +{ + if(_tEntry.isNull()) { + return; + } + _tEntry->os = os; +} + +void MetalinkParserController::setMaxConnectionsOfEntry(int32_t maxConnections) +{ + if(_tEntry.isNull()) { + return; + } + _tEntry->maxConnections = maxConnections; +} + +void MetalinkParserController::commitEntryTransaction() +{ + if(_tEntry.isNull()) { + return; + } + commitResourceTransaction(); + commitChecksumTransaction(); + commitChunkChecksumTransaction(); + _metalinker->entries.push_back(_tEntry); + _tEntry = 0; +} + +void MetalinkParserController::cancelEntryTransaction() +{ + cancelResourceTransaction(); + cancelChecksumTransaction(); + cancelChunkChecksumTransaction(); + _tEntry = 0; +} + +void MetalinkParserController::newResourceTransaction() +{ + if(_tEntry.isNull()) { + return; + } + _tResource = new MetalinkResource(); +} + +void MetalinkParserController::setURLOfResource(const string& url) +{ + if(_tResource.isNull()) { + return; + } + _tResource->url = url; +} + +void MetalinkParserController::setTypeOfResource(const string& type) +{ + if(_tResource.isNull()) { + return; + } + if(type == "ftp") { + _tResource->type = MetalinkResource::TYPE_FTP; + } else if(type == "http") { + _tResource->type = MetalinkResource::TYPE_HTTP; + } else if(type == "https") { + _tResource->type = MetalinkResource::TYPE_HTTPS; + } else if(type == "bittorrent") { + _tResource->type = MetalinkResource::TYPE_BITTORRENT; + } else { + _tResource->type = MetalinkResource::TYPE_NOT_SUPPORTED; + } +} + +void MetalinkParserController::setLocationOfResource(const string& location) +{ + if(_tResource.isNull()) { + return; + } + _tResource->location = location; +} + +void MetalinkParserController::setPreferenceOfResource(int32_t preference) +{ + if(_tResource.isNull()) { + return; + } + _tResource->preference = preference; +} + +void MetalinkParserController::setMaxConnectionsOfResource(int32_t maxConnections) +{ + if(_tResource.isNull()) { + return; + } + _tResource->maxConnections = maxConnections; +} + +void MetalinkParserController::commitResourceTransaction() +{ + if(_tResource.isNull()) { + return; + } + _tEntry->resources.push_back(_tResource); + _tResource = 0; +} + +void MetalinkParserController::cancelResourceTransaction() +{ + _tResource = 0; +} + +void MetalinkParserController::newChecksumTransaction() +{ + if(_tEntry.isNull()) { + return; + } + _tChecksum = new Checksum(); +} + +void MetalinkParserController::setTypeOfChecksum(const string& type) +{ + if(_tChecksum.isNull()) { + return; + } + if(MessageDigestContext::supports(type)) { + _tChecksum->setAlgo(type); + } else { + cancelChecksumTransaction(); + } +} + +void MetalinkParserController::setHashOfChecksum(const string& md) +{ + if(_tChecksum.isNull()) { + return; + } + _tChecksum->setMessageDigest(md); +} + +void MetalinkParserController::commitChecksumTransaction() +{ + if(_tChecksum.isNull()) { + return; + } + if(_tEntry->checksum.isNull() || _tEntry->checksum->getAlgo() != "sha1") { + _tEntry->checksum = _tChecksum; + } + _tChecksum = 0; +} + +void MetalinkParserController::cancelChecksumTransaction() +{ + _tChecksum = 0; +} + +void MetalinkParserController::newChunkChecksumTransaction() +{ + if(_tEntry.isNull()) { + return; + } + _tChunkChecksum = new ChunkChecksum(); + _tempChunkChecksums.clear(); +} + +void MetalinkParserController::setTypeOfChunkChecksum(const string& type) +{ + if(_tChunkChecksum.isNull()) { + return; + } + if(MessageDigestContext::supports(type)) { + _tChunkChecksum->setAlgo(type); + } else { + cancelChunkChecksumTransaction(); + } +} + +void MetalinkParserController::setLengthOfChunkChecksum(int32_t length) +{ + if(_tChunkChecksum.isNull()) { + return; + } + if(length > 0) { + _tChunkChecksum->setChecksumLength(length); + } else { + cancelChunkChecksumTransaction(); + } +} + +void MetalinkParserController::addHashOfChunkChecksum(int32_t order, const string& md) +{ + if(_tChunkChecksum.isNull()) { + return; + } + _tempChunkChecksums.push_back(pair(order, md)); +} + +void MetalinkParserController::createNewHashOfChunkChecksum(int32_t order) +{ + if(_tChunkChecksum.isNull()) { + return; + } + _tempHashPair.first = order; +} + +void MetalinkParserController::setMessageDigestOfChunkChecksum(const string& md) +{ + if(_tChunkChecksum.isNull()) { + return; + } + _tempHashPair.second = md; +} + +void MetalinkParserController::addHashOfChunkChecksum() +{ + if(_tChunkChecksum.isNull()) { + return; + } + _tempChunkChecksums.push_back(_tempHashPair); +} + +bool firstAsc(const pair& p1, const pair& p2) +{ + return p1.first < p2.first; +} + +class GetSecond +{ +private: + Strings& ss; +public: + GetSecond(Strings& s):ss(s) {} + + void operator()(const pair& p) + { + ss.push_back(p.second); + } +}; + +void MetalinkParserController::commitChunkChecksumTransaction() +{ + if(_tChunkChecksum.isNull()) { + return; + } + if(_tEntry->chunkChecksum.isNull() || _tEntry->chunkChecksum->getAlgo() != "sha1") { + sort(_tempChunkChecksums.begin(), _tempChunkChecksums.end(), firstAsc); + Strings checksums; + for_each(_tempChunkChecksums.begin(), _tempChunkChecksums.end(), GetSecond(checksums)); + + _tChunkChecksum->setChecksums(checksums); + _tEntry->chunkChecksum = _tChunkChecksum; + } + _tChunkChecksum = 0; +} + +void MetalinkParserController::cancelChunkChecksumTransaction() +{ + _tChunkChecksum = 0; +} + + diff --git a/src/MetalinkParserController.h b/src/MetalinkParserController.h new file mode 100644 index 00000000..9793b1ef --- /dev/null +++ b/src/MetalinkParserController.h @@ -0,0 +1,137 @@ +/* */ +#ifndef _D_METALINK_PARSER_CONTROLLER_H_ +#define _D_METALINK_PARSER_CONTROLLER_H_ + +#include "common.h" + +class Metalinker; +typedef SharedHandle MetalinkerHandle; +class MetalinkEntry; +typedef SharedHandle MetalinkEntryHandle; +class MetalinkResource; +typedef SharedHandle MetalinkResourceHandle; +class Checksum; +typedef SharedHandle ChecksumHandle; +class ChunkChecksum; +typedef SharedHandle ChunkChecksumHandle; + +class MetalinkParserController { +private: + MetalinkerHandle _metalinker; + + MetalinkEntryHandle _tEntry; + + MetalinkResourceHandle _tResource; + + ChecksumHandle _tChecksum; + + ChunkChecksumHandle _tChunkChecksum; + + deque > _tempChunkChecksums; + + pair _tempHashPair; + +public: + MetalinkParserController(); + + ~MetalinkParserController(); + + MetalinkerHandle getResult() const; + + void newEntryTransaction(); + + void setFileNameOfEntry(const string& filename); + + void setFileLengthOfEntry(int64_t length); + + void setVersionOfEntry(const string& version); + + void setLanguageOfEntry(const string& language); + + void setOSOfEntry(const string& os); + + void setMaxConnectionsOfEntry(int32_t maxConnections); + + void commitEntryTransaction(); + + void cancelEntryTransaction(); + + void newResourceTransaction(); + + void setURLOfResource(const string& url); + + void setTypeOfResource(const string& type); + + void setLocationOfResource(const string& location); + + void setPreferenceOfResource(int32_t preference); + + void setMaxConnectionsOfResource(int32_t maxConnections); + + void commitResourceTransaction(); + + void cancelResourceTransaction(); + + void newChecksumTransaction(); + + void setTypeOfChecksum(const string& type); + + void setHashOfChecksum(const string& md); + + void commitChecksumTransaction(); + + void cancelChecksumTransaction(); + + void newChunkChecksumTransaction(); + + void setTypeOfChunkChecksum(const string& type); + + void setLengthOfChunkChecksum(int32_t length); + + void addHashOfChunkChecksum(int32_t order, const string& md); + + void createNewHashOfChunkChecksum(int32_t order); + + void setMessageDigestOfChunkChecksum(const string& md); + + void addHashOfChunkChecksum(); + + void commitChunkChecksumTransaction(); + + void cancelChunkChecksumTransaction(); +}; + +#endif // _D_METALINK_PARSER_CONTROLLER_H_ diff --git a/src/MetalinkParserState.h b/src/MetalinkParserState.h new file mode 100644 index 00000000..8ad87b93 --- /dev/null +++ b/src/MetalinkParserState.h @@ -0,0 +1,53 @@ +/* */ +#ifndef _D_METALINK_PARSER_STATE_H_ +#define _D_METALINK_PARSER_STATE_H_ + +#include "common.h" +#include + +class MetalinkParserStateMachine; + +class MetalinkParserState +{ +public: + virtual void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs) = 0; + + virtual void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters) = 0; +}; + +#endif // _D_METALINK_PARSER_STATE_H_ diff --git a/src/MetalinkParserStateMachine.cc b/src/MetalinkParserStateMachine.cc new file mode 100644 index 00000000..6d0fcbdf --- /dev/null +++ b/src/MetalinkParserStateMachine.cc @@ -0,0 +1,327 @@ +/* */ +#include "MetalinkParserStateMachine.h" +#include "MetalinkParserController.h" +#include "InitialMetalinkParserState.h" +#include "MetalinkMetalinkParserState.h" +#include "FilesMetalinkParserState.h" +#include "FileMetalinkParserState.h" +#include "SizeMetalinkParserState.h" +#include "VersionMetalinkParserState.h" +#include "LanguageMetalinkParserState.h" +#include "OSMetalinkParserState.h" +#include "VerificationMetalinkParserState.h" +#include "HashMetalinkParserState.h" +#include "PiecesMetalinkParserState.h" +#include "PieceHashMetalinkParserState.h" +#include "ResourcesMetalinkParserState.h" +#include "URLMetalinkParserState.h" +#include "FinMetalinkParserState.h" +#include "SkipTagMetalinkParserState.h" +#include "Metalinker.h" + +MetalinkParserState* MetalinkParserStateMachine::_initialState = new InitialMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_metalinkState = new MetalinkMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_filesState = new FilesMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_fileState = new FileMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_sizeState = new SizeMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_versionState = new VersionMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_languageState = new LanguageMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_osState = new OSMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_verificationState = new VerificationMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_hashState = new HashMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_piecesState = new PiecesMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_pieceHashState = new PieceHashMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_resourcesState = new ResourcesMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_urlState = new URLMetalinkParserState(); +MetalinkParserState* MetalinkParserStateMachine::_finState = new FinMetalinkParserState(); + +MetalinkParserStateMachine::MetalinkParserStateMachine(): + _ctrl(new MetalinkParserController()), + _state(_initialState), + _skipTagState(0) {} + +MetalinkParserStateMachine::~MetalinkParserStateMachine() +{ + delete _skipTagState; +} + +void MetalinkParserStateMachine::setMetalinkState() +{ + _state = _metalinkState; +} + +void MetalinkParserStateMachine::setFilesState() +{ + _state = _filesState; +} + +void MetalinkParserStateMachine::setFileState() +{ + _state = _fileState; +} + +void MetalinkParserStateMachine::setSizeState() +{ + _state = _sizeState; +} + +void MetalinkParserStateMachine::setVersionState() +{ + _state = _versionState; +} + +void MetalinkParserStateMachine::setLanguageState() +{ + _state = _languageState; +} + +void MetalinkParserStateMachine::setOSState() +{ + _state = _osState; +} + +void MetalinkParserStateMachine::setVerificationState() +{ + _state = _verificationState; +} + +void MetalinkParserStateMachine::setHashState() +{ + _state = _hashState; +} + +void MetalinkParserStateMachine::setPiecesState() +{ + _state = _piecesState; +} + +void MetalinkParserStateMachine::setPieceHashState() +{ + _state = _pieceHashState; +} + +void MetalinkParserStateMachine::setResourcesState() +{ + _state = _resourcesState; +} + +void MetalinkParserStateMachine::setURLState() +{ + _state = _urlState; +} + +void MetalinkParserStateMachine::setFinState() +{ + _state = _finState; +} + +void MetalinkParserStateMachine::setSkipTagState(MetalinkParserState* prevSate) +{ + _state = new SkipTagMetalinkParserState(prevSate); +} + +void MetalinkParserStateMachine::restoreSavedState() +{ + _state = ((SkipTagMetalinkParserState*)_state)->getPreviousState(); + delete _skipTagState; + _skipTagState = 0; +} + +bool MetalinkParserStateMachine::finished() const +{ + return _state == _finState; +} + +void MetalinkParserStateMachine::newEntryTransaction() +{ + _ctrl->newEntryTransaction(); +} + +void MetalinkParserStateMachine::setFileNameOfEntry(const string& filename) +{ + _ctrl->setFileNameOfEntry(filename); +} + +void MetalinkParserStateMachine::setFileLengthOfEntry(int64_t length) +{ + _ctrl->setFileLengthOfEntry(length); +} + +void MetalinkParserStateMachine::setVersionOfEntry(const string& version) +{ + _ctrl->setVersionOfEntry(version); +} + +void MetalinkParserStateMachine::setLanguageOfEntry(const string& language) +{ + _ctrl->setLanguageOfEntry(language); +} + +void MetalinkParserStateMachine::setOSOfEntry(const string& os) +{ + _ctrl->setOSOfEntry(os); +} + +void MetalinkParserStateMachine::setMaxConnectionsOfEntry(int32_t maxConnections) +{ + _ctrl->setMaxConnectionsOfEntry(maxConnections); +} + +void MetalinkParserStateMachine::commitEntryTransaction() +{ + _ctrl->commitEntryTransaction(); +} + +void MetalinkParserStateMachine::newResourceTransaction() +{ + _ctrl->newResourceTransaction(); +} + +void MetalinkParserStateMachine::setURLOfResource(const string& url) +{ + _ctrl->setURLOfResource(url); +} + +void MetalinkParserStateMachine::setTypeOfResource(const string& type) +{ + _ctrl->setTypeOfResource(type); +} + +void MetalinkParserStateMachine::setLocationOfResource(const string& location) +{ + _ctrl->setLocationOfResource(location); +} + +void MetalinkParserStateMachine::setPreferenceOfResource(int32_t preference) +{ + _ctrl->setPreferenceOfResource(preference); +} + +void MetalinkParserStateMachine::setMaxConnectionsOfResource(int32_t maxConnections) +{ + _ctrl->setMaxConnectionsOfResource(maxConnections); +} + +void MetalinkParserStateMachine::commitResourceTransaction() +{ + _ctrl->commitResourceTransaction(); +} + +void MetalinkParserStateMachine::cancelResourceTransaction() +{ + _ctrl->cancelResourceTransaction(); +} + +void MetalinkParserStateMachine::newChecksumTransaction() +{ + _ctrl->newChecksumTransaction(); +} + +void MetalinkParserStateMachine::setTypeOfChecksum(const string& type) +{ + _ctrl->setTypeOfChecksum(type); +} + +void MetalinkParserStateMachine::setHashOfChecksum(const string& md) +{ + _ctrl->setHashOfChecksum(md); +} + +void MetalinkParserStateMachine::commitChecksumTransaction() +{ + _ctrl->commitChecksumTransaction(); +} + +void MetalinkParserStateMachine::cancelChecksumTransaction() +{ + _ctrl->cancelChecksumTransaction(); +} + +void MetalinkParserStateMachine::newChunkChecksumTransaction() +{ + _ctrl->newChunkChecksumTransaction(); +} + +void MetalinkParserStateMachine::setLengthOfChunkChecksum(int32_t length) +{ + _ctrl->setLengthOfChunkChecksum(length); +} + +void MetalinkParserStateMachine::setTypeOfChunkChecksum(const string& type) +{ + _ctrl->setTypeOfChunkChecksum(type); +} + +void MetalinkParserStateMachine::createNewHashOfChunkChecksum(int32_t order) +{ + _ctrl->createNewHashOfChunkChecksum(order); +} + +void MetalinkParserStateMachine::setMessageDigestOfChunkChecksum(const string& md) +{ + _ctrl->setMessageDigestOfChunkChecksum(md); +} + +void MetalinkParserStateMachine::addHashOfChunkChecksum() +{ + _ctrl->addHashOfChunkChecksum(); +} + +void MetalinkParserStateMachine::commitChunkChecksumTransaction() +{ + _ctrl->commitChunkChecksumTransaction(); +} + +void MetalinkParserStateMachine::cancelChunkChecksumTransaction() +{ + _ctrl->cancelChunkChecksumTransaction(); +} + +void MetalinkParserStateMachine::beginElement(const string& name, + const map& attrs) +{ + _state->beginElement(this, name, attrs); +} + +void MetalinkParserStateMachine::endElement(const string& name, const string& characters) +{ + _state->endElement(this, name, characters); +} + +MetalinkerHandle MetalinkParserStateMachine::getResult() const +{ + return _ctrl->getResult(); +} diff --git a/src/MetalinkParserStateMachine.h b/src/MetalinkParserStateMachine.h new file mode 100644 index 00000000..0be7a352 --- /dev/null +++ b/src/MetalinkParserStateMachine.h @@ -0,0 +1,178 @@ +/* */ +#ifndef _D_METALINK_PARSER_STATE_MACHINE_H_ +#define _D_METALINK_PARSER_STATE_MACHINE_H_ + +#include "common.h" +#include + +class MetalinkParserController; +typedef SharedHandle MetalinkParserControllerHandle; +class MetalinkParserState; +class SkipTagMetalinkParserState; +class Metalinker; +typedef SharedHandle MetalinkerHandle; + +class MetalinkParserStateMachine { +private: + MetalinkParserControllerHandle _ctrl; + + MetalinkParserState* _state; + + static MetalinkParserState* _initialState; + static MetalinkParserState* _metalinkState; + static MetalinkParserState* _filesState; + static MetalinkParserState* _fileState; + static MetalinkParserState* _sizeState; + static MetalinkParserState* _versionState; + static MetalinkParserState* _languageState; + static MetalinkParserState* _osState; + static MetalinkParserState* _verificationState; + static MetalinkParserState* _hashState; + static MetalinkParserState* _piecesState; + static MetalinkParserState* _pieceHashState; + static MetalinkParserState* _resourcesState; + static MetalinkParserState* _urlState; + static MetalinkParserState* _finState; + + SkipTagMetalinkParserState* _skipTagState; +public: + MetalinkParserStateMachine(); + + ~MetalinkParserStateMachine(); + + void setMetalinkState(); + + void setFilesState(); + + void setFileState(); + + void setSizeState(); + + void setVersionState(); + + void setLanguageState(); + + void setOSState(); + + void setVerificationState(); + + void setHashState(); + + void setPiecesState(); + + void setPieceHashState(); + + void setResourcesState(); + + void setURLState(); + + void setFinState(); + + void setSkipTagState(MetalinkParserState* prevSate); + + void restoreSavedState(); + + bool finished() const; + + bool error() const; + + void beginElement(const string& name, const map& attrs); + + void endElement(const string& name, const string& characters); + + void newEntryTransaction(); + + void setFileNameOfEntry(const string& filename); + + void setFileLengthOfEntry(int64_t length); + + void setVersionOfEntry(const string& version); + + void setLanguageOfEntry(const string& language); + + void setOSOfEntry(const string& os); + + void setMaxConnectionsOfEntry(int32_t maxConnections); + + void commitEntryTransaction(); + + void newResourceTransaction(); + + void setURLOfResource(const string& url); + + void setTypeOfResource(const string& type); + + void setLocationOfResource(const string& location); + + void setPreferenceOfResource(int32_t preference); + + void setMaxConnectionsOfResource(int32_t maxConnections); + + void commitResourceTransaction(); + + void cancelResourceTransaction(); + + void newChecksumTransaction(); + + void setTypeOfChecksum(const string& type); + + void setHashOfChecksum(const string& md); + + void commitChecksumTransaction(); + + void cancelChecksumTransaction(); + + void newChunkChecksumTransaction(); + + void setLengthOfChunkChecksum(int32_t length); + + void setTypeOfChunkChecksum(const string& type); + + void createNewHashOfChunkChecksum(int32_t order); + + void setMessageDigestOfChunkChecksum(const string& md); + + void addHashOfChunkChecksum(); + + void commitChunkChecksumTransaction(); + + void cancelChunkChecksumTransaction(); + + MetalinkerHandle getResult() const; +}; + +typedef SharedHandle MetalinkParserStateMachineHandle; +#endif // _D_METALINK_PARSER_STATE_MACHINE_H_ diff --git a/src/OSMetalinkParserState.cc b/src/OSMetalinkParserState.cc new file mode 100644 index 00000000..c2c8e6e4 --- /dev/null +++ b/src/OSMetalinkParserState.cc @@ -0,0 +1,51 @@ +/* */ +#include "OSMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void OSMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + stm->setSkipTagState(this); +} + +void OSMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setOSOfEntry(characters); + stm->setFileState(); +} diff --git a/src/OSMetalinkParserState.h b/src/OSMetalinkParserState.h new file mode 100644 index 00000000..32d0d3e4 --- /dev/null +++ b/src/OSMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_OS_METALINK_PARSER_STATE_H_ +#define _D_OS_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class OSMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_OS_METALINK_PARSER_STATE_H_ diff --git a/src/PieceHashMetalinkParserState.cc b/src/PieceHashMetalinkParserState.cc new file mode 100644 index 00000000..cf64a67e --- /dev/null +++ b/src/PieceHashMetalinkParserState.cc @@ -0,0 +1,52 @@ +/* */ +#include "PieceHashMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void PieceHashMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + stm->setSkipTagState(this); +} + +void PieceHashMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setMessageDigestOfChunkChecksum(characters); + stm->addHashOfChunkChecksum(); + stm->setPiecesState(); +} diff --git a/src/PieceHashMetalinkParserState.h b/src/PieceHashMetalinkParserState.h new file mode 100644 index 00000000..d0d0e5fe --- /dev/null +++ b/src/PieceHashMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_PIECE_HASH_METALINK_PARSER_STATE_H_ +#define _D_PIECE_HASH_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class PieceHashMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_PIECE_HASH_METALINK_PARSER_STATE_H_ diff --git a/src/PiecesMetalinkParserState.cc b/src/PiecesMetalinkParserState.cc new file mode 100644 index 00000000..43dbba4d --- /dev/null +++ b/src/PiecesMetalinkParserState.cc @@ -0,0 +1,68 @@ +/* */ +#include "PiecesMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" +#include "RecoverableException.h" +#include "Util.h" + +void PiecesMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + if(name == "hash") { + stm->setPieceHashState(); + map::const_iterator itr = attrs.find("piece"); + if(itr == attrs.end()) { + stm->cancelChunkChecksumTransaction(); + } else { + try { + stm->createNewHashOfChunkChecksum(Util::parseInt((*itr).second)); + } catch(RecoverableException* e) { + delete e; + stm->cancelChunkChecksumTransaction(); + } + } + } else { + stm->setSkipTagState(this); + } +} + +void PiecesMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->commitChunkChecksumTransaction(); + stm->setVerificationState(); +} diff --git a/src/PiecesMetalinkParserState.h b/src/PiecesMetalinkParserState.h new file mode 100644 index 00000000..548275b4 --- /dev/null +++ b/src/PiecesMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_PIECES_METALINK_PARSER_STATE_H_ +#define _D_PIECES_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class PiecesMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_PIECES_METALINK_PARSER_STATE_H_ diff --git a/src/ResourcesMetalinkParserState.cc b/src/ResourcesMetalinkParserState.cc new file mode 100644 index 00000000..1a7f363d --- /dev/null +++ b/src/ResourcesMetalinkParserState.cc @@ -0,0 +1,105 @@ +/* */ +#include "ResourcesMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" +#include "Util.h" +#include "RecoverableException.h" + +void ResourcesMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + if(name == "url") { + stm->setURLState(); + string type; + { + map::const_iterator itr = attrs.find("type"); + if(itr == attrs.end()) { + return; + } else { + type = (*itr).second; + } + } + string location; + { + map::const_iterator itr = attrs.find("location"); + if(itr != attrs.end()) { + location = Util::toUpper((*itr).second); + } + } + int32_t preference; + { + map::const_iterator itr = attrs.find("preference"); + if(itr == attrs.end()) { + preference = 0; + } else { + try { + preference = Util::parseInt((*itr).second); + } catch(RecoverableException* e) { + delete e; + preference = 0; + } + } + } + int32_t maxConnections; + { + map::const_iterator itr = attrs.find("maxconnections"); + if(itr == attrs.end()) { + maxConnections = -1; + } else { + try { + maxConnections = Util::parseInt((*itr).second); + } catch(RecoverableException* e) { + delete e; + maxConnections = -1; + } + } + } + stm->newResourceTransaction(); + stm->setTypeOfResource(type); + stm->setLocationOfResource(location); + stm->setPreferenceOfResource(preference); + stm->setMaxConnectionsOfResource(maxConnections); + } else { + stm->setSkipTagState(this); + } +} + +void ResourcesMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setFileState(); +} diff --git a/src/ResourcesMetalinkParserState.h b/src/ResourcesMetalinkParserState.h new file mode 100644 index 00000000..5ed9d4eb --- /dev/null +++ b/src/ResourcesMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_RESOURCES_METALINK_PARSER_STATE_H_ +#define _D_RESOURCES_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class ResourcesMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_RESOURCES_METALINK_PARSER_STATE_H_ diff --git a/src/SizeMetalinkParserState.cc b/src/SizeMetalinkParserState.cc new file mode 100644 index 00000000..de57d031 --- /dev/null +++ b/src/SizeMetalinkParserState.cc @@ -0,0 +1,58 @@ +/* */ +#include "SizeMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" +#include "Util.h" +#include "RecoverableException.h" + +void SizeMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + stm->setSkipTagState(this); +} + +void SizeMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + try { + stm->setFileLengthOfEntry(Util::parseInt(characters)); + } catch(RecoverableException* e) { + delete e; + // current metalink specification doesn't require size element. + } + stm->setFileState(); +} diff --git a/src/SizeMetalinkParserState.h b/src/SizeMetalinkParserState.h new file mode 100644 index 00000000..83ac24fb --- /dev/null +++ b/src/SizeMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_SIZE_METALINK_PARSER_STATE_H_ +#define _D_SIZE_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class SizeMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_SIZE_METALINK_PARSER_STATE_H_ diff --git a/src/SkipTagMetalinkParserState.cc b/src/SkipTagMetalinkParserState.cc new file mode 100644 index 00000000..4552193b --- /dev/null +++ b/src/SkipTagMetalinkParserState.cc @@ -0,0 +1,55 @@ +/* */ +#include "SkipTagMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +SkipTagMetalinkParserState::SkipTagMetalinkParserState(MetalinkParserState* prevState): + _prevState(prevState), _depth(1) {} + +void SkipTagMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + ++_depth; +} + +void SkipTagMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + if(--_depth == 0) { + stm->restoreSavedState(); + } +} diff --git a/src/SkipTagMetalinkParserState.h b/src/SkipTagMetalinkParserState.h new file mode 100644 index 00000000..b3dd8d2a --- /dev/null +++ b/src/SkipTagMetalinkParserState.h @@ -0,0 +1,60 @@ +/* */ +#ifndef _D_SKIP_TAG_METALINK_PARSER_STATE_H_ +#define _D_SKIP_TAG_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class SkipTagMetalinkParserState:public MetalinkParserState +{ +private: + MetalinkParserState* _prevState; + int32_t _depth; +public: + SkipTagMetalinkParserState(MetalinkParserState* prevState); + + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); + + MetalinkParserState* getPreviousState() const + { + return _prevState; + } +}; + +#endif // _D_SKIP_TAG_METALINK_PARSER_STATE_H_ diff --git a/src/URLMetalinkParserState.cc b/src/URLMetalinkParserState.cc new file mode 100644 index 00000000..8999bd3e --- /dev/null +++ b/src/URLMetalinkParserState.cc @@ -0,0 +1,53 @@ +/* */ +#include "URLMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void URLMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + stm->setSkipTagState(this); + +} + +void URLMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setURLOfResource(characters); + stm->commitResourceTransaction(); + stm->setResourcesState(); +} diff --git a/src/URLMetalinkParserState.h b/src/URLMetalinkParserState.h new file mode 100644 index 00000000..c1c9d77c --- /dev/null +++ b/src/URLMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_URL_METALINK_PARSER_STATE_H_ +#define _D_URL_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class URLMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_URL_METALINK_PARSER_STATE_H_ diff --git a/src/VerificationMetalinkParserState.cc b/src/VerificationMetalinkParserState.cc new file mode 100644 index 00000000..a2bd0476 --- /dev/null +++ b/src/VerificationMetalinkParserState.cc @@ -0,0 +1,92 @@ +/* */ +#include "VerificationMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" +#include "DlAbortEx.h" +#include "Util.h" + +void VerificationMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + if(name == "hash") { + stm->setHashState(); + map::const_iterator itr = attrs.find("type"); + if(itr == attrs.end()) { + return; + } else { + string type = (*itr).second; + stm->newChecksumTransaction(); + stm->setTypeOfChecksum(type); + } + } else if(name == "pieces") { + stm->setPiecesState(); + try { + int32_t length; + { + map::const_iterator itr = attrs.find("length"); + if(itr == attrs.end()) { + return; + } else { + length = Util::parseInt((*itr).second); + } + } + string type; + { + map::const_iterator itr = attrs.find("type"); + if(itr == attrs.end()) { + return; + } else { + type = (*itr).second; + } + } + stm->newChunkChecksumTransaction(); + stm->setLengthOfChunkChecksum(length); + stm->setTypeOfChunkChecksum(type); + } catch(RecoverableException* e) { + delete e; + stm->cancelChunkChecksumTransaction(); + } + } else { + stm->setSkipTagState(this); + } +} + +void VerificationMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setFileState(); +} diff --git a/src/VerificationMetalinkParserState.h b/src/VerificationMetalinkParserState.h new file mode 100644 index 00000000..1ab7ce08 --- /dev/null +++ b/src/VerificationMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_VERIFICATION_METALINK_PARSER_STATE_H_ +#define _D_VERIFICATION_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class VerificationMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_VERIFICATION_METALINK_PARSER_STATE_H_ diff --git a/src/VersionMetalinkParserState.cc b/src/VersionMetalinkParserState.cc new file mode 100644 index 00000000..4ebba31a --- /dev/null +++ b/src/VersionMetalinkParserState.cc @@ -0,0 +1,51 @@ +/* */ +#include "VersionMetalinkParserState.h" +#include "MetalinkParserStateMachine.h" + +void VersionMetalinkParserState::beginElement(MetalinkParserStateMachine* stm, + const string& name, + const map& attrs) +{ + stm->setSkipTagState(this); +} + +void VersionMetalinkParserState::endElement(MetalinkParserStateMachine* stm, + const string& name, + const string& characters) +{ + stm->setVersionOfEntry(characters); + stm->setFileState(); +} diff --git a/src/VersionMetalinkParserState.h b/src/VersionMetalinkParserState.h new file mode 100644 index 00000000..d7673ea4 --- /dev/null +++ b/src/VersionMetalinkParserState.h @@ -0,0 +1,50 @@ +/* */ +#ifndef _D_VERSION_METALINK_PARSER_STATE_H_ +#define _D_VERSION_METALINK_PARSER_STATE_H_ + +#include "MetalinkParserState.h" + +class VersionMetalinkParserState:public MetalinkParserState +{ +public: + void beginElement(MetalinkParserStateMachine* stm, + const string& name, const map& attrs); + + void endElement(MetalinkParserStateMachine* stm, + const string& name, const string& characters); +}; + +#endif // _D_VERSION_METALINK_PARSER_STATE_H_ diff --git a/src/XML2SAXMetalinkProcessor.cc b/src/XML2SAXMetalinkProcessor.cc new file mode 100644 index 00000000..d905526e --- /dev/null +++ b/src/XML2SAXMetalinkProcessor.cc @@ -0,0 +1,167 @@ +/* */ +#include "XML2SAXMetalinkProcessor.h" +#include "BinaryStream.h" +#include "MetalinkParserStateMachine.h" +#include "Util.h" + +class SessionData { +public: + MetalinkParserStateMachineHandle _stm; + + Strings _charactersStack; + + SessionData(const MetalinkParserStateMachineHandle& stm):_stm(stm) {} +}; + +typedef SharedHandle SessionDataHandle; + +static void mlStartElement(void* userData, const xmlChar* name, const xmlChar** attrs) +{ + ((SessionData*)userData)->_charactersStack.push_front(string()); + map attrmap; + if(attrs) { + const xmlChar** p = attrs; + while(*p != 0) { + string name = (const char*)*p++; + if(*p == 0) { + break; + } + string value = Util::trim((const char*)*p++); + attrmap[name] = value; + } + } + ((SessionData*)userData)->_stm->beginElement((const char*)name, attrmap); +} + +static void mlEndElement(void* userData, const xmlChar* name) +{ + SessionData* sd = (SessionData*)userData; + + sd->_stm->endElement((const char*)name, Util::trim(sd->_charactersStack.front())); + sd->_charactersStack.pop_front(); +} + +static void mlCharacters(void* userData, const xmlChar* ch, int len) +{ + ((SessionData*)userData)->_charactersStack.front() += string(&ch[0], &ch[len]); +} + +static xmlSAXHandler mySAXHandler = +{ + 0, // internalSubsetSAXFunc + 0, // isStandaloneSAXFunc + 0, // hasInternalSubsetSAXFunc + 0, // hasExternalSubsetSAXFunc + 0, // resolveEntitySAXFunc + 0, // getEntitySAXFunc + 0, // entityDeclSAXFunc + 0, // notationDeclSAXFunc + 0, // attributeDeclSAXFunc + 0, // elementDeclSAXFunc + 0, // unparsedEntityDeclSAXFunc + 0, // setDocumentLocatorSAXFunc + 0, // startDocumentSAXFunc + 0, // endDocumentSAXFunc + &mlStartElement, // startElementSAXFunc + &mlEndElement, // endElementSAXFunc + 0, // referenceSAXFunc + &mlCharacters, // charactersSAXFunc + 0, // ignorableWhitespaceSAXFunc + 0, // processingInstructionSAXFunc + 0, // commentSAXFunc + 0, // warningSAXFunc + 0, // errorSAXFunc + 0, // fatalErrorSAXFunc + 0, // getParameterEntitySAXFunc + 0, // cdataBlockSAXFunc + 0, // externalSubsetSAXFunc + 0, // unsigned int initialized + 0, // void * _private + 0, // startElementNsSAX2Func + 0, // endElementNsSAX2Func + 0, // xmlStructuredErrorFunc +}; + +XML2SAXMetalinkProcessor::XML2SAXMetalinkProcessor(): + _stm(0) +{} + + +MetalinkerHandle XML2SAXMetalinkProcessor::parseFile(const string& filename) +{ + _stm = new MetalinkParserStateMachine(); + SessionDataHandle sessionData = new SessionData(_stm); + int32_t retval = xmlSAXUserParseFile(&mySAXHandler, sessionData.get(), + filename.c_str()); + if(retval != 0) { + throw new DlAbortEx("Cannot parse metalink XML file. XML may be malformed."); + } + return _stm->getResult(); +} + +MetalinkerHandle XML2SAXMetalinkProcessor::parseFromBinaryStream(const BinaryStreamHandle& binaryStream) +{ + _stm = new MetalinkParserStateMachine(); + int32_t bufSize = 4096; + unsigned char buf[bufSize]; + + int32_t res = binaryStream->readData(buf, 4, 0); + if(res != 4) { + throw new DlAbortEx("Too small data for parsing XML."); + } + + SessionDataHandle sessionData = new SessionData(_stm); + xmlParserCtxtPtr ctx = xmlCreatePushParserCtxt(&mySAXHandler, sessionData.get(), (const char*)buf, res, 0); + + int64_t readOffset = res; + while(1) { + int32_t res = binaryStream->readData(buf, bufSize, readOffset); + if(res == 0) { + break; + } + if(xmlParseChunk(ctx, (const char*)buf, res, 0) != 0) { + throw new DlAbortEx("Cannot parse metalink XML file. XML may be malformed."); + } + readOffset += res; + } + xmlParseChunk(ctx, (const char*)buf, 0, 1); + xmlFreeParserCtxt(ctx); + + if(!_stm->finished()) { + throw new DlAbortEx("Cannot parse metalink XML file. XML may be malformed."); + } + return _stm->getResult(); +} diff --git a/src/XML2SAXMetalinkProcessor.h b/src/XML2SAXMetalinkProcessor.h new file mode 100644 index 00000000..2159e331 --- /dev/null +++ b/src/XML2SAXMetalinkProcessor.h @@ -0,0 +1,59 @@ +/* */ +#ifndef _D_XML2_SAX_METALINK_PROCESSOR_H_ +#define _D_XML2_SAX_METALINK_PROCESSOR_H_ + +#include "MetalinkProcessor.h" +#include +#include + +class MetalinkParserStateMachine; +typedef SharedHandle MetalinkParserStateMachineHandle; + +class XML2SAXMetalinkProcessor:public MetalinkProcessor { +private: + MetalinkParserStateMachineHandle _stm; + +public: + XML2SAXMetalinkProcessor(); + + virtual ~XML2SAXMetalinkProcessor() {} + + virtual MetalinkerHandle parseFile(const string& filename); + + virtual MetalinkerHandle parseFromBinaryStream(const BinaryStreamHandle& binaryStream); +}; + +#endif // _D_XML2_SAX_METALINK_PROCESSOR_H_ diff --git a/src/main.cc b/src/main.cc index 295d4dbb..1518cb6c 100644 --- a/src/main.cc +++ b/src/main.cc @@ -72,9 +72,11 @@ extern int optind, opterr, optopt; #include #ifdef ENABLE_METALINK -#include "Xml2MetalinkProcessor.h" -#include "Metalink2RequestGroup.h" -#endif +# include "Metalink2RequestGroup.h" +# include "MetalinkEntry.h" +# include +# include +#endif // ENABLE_METALINK #ifdef HAVE_LIBSSL // for SSL diff --git a/test/Base64Test.cc b/test/Base64Test.cc index e7497312..77fa61bd 100644 --- a/test/Base64Test.cc +++ b/test/Base64Test.cc @@ -1,14 +1,14 @@ #include "Base64.h" -#include #include -using namespace std; - class Base64Test:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(Base64Test); CPPUNIT_TEST(testEncode); CPPUNIT_TEST(testDecode); + CPPUNIT_TEST(testEncode_string); + CPPUNIT_TEST(testDecode_string); + CPPUNIT_TEST(testLongString); CPPUNIT_TEST_SUITE_END(); private: @@ -18,25 +18,205 @@ public: void testEncode(); void testDecode(); + void testEncode_string(); + void testDecode_string(); + void testLongString(); }; CPPUNIT_TEST_SUITE_REGISTRATION( Base64Test ); void Base64Test::testEncode() { - CPPUNIT_ASSERT_EQUAL(string("SGVsbG8gV29ybGQh"), - Base64::encode("Hello World!")); - CPPUNIT_ASSERT_EQUAL(string("SGVsbG8gV29ybGQ="), - Base64::encode("Hello World")); - CPPUNIT_ASSERT_EQUAL(string("SGVsbG8gV29ybA=="), - Base64::encode("Hello Worl")); - CPPUNIT_ASSERT_EQUAL(string("YQ=="), - Base64::encode("a")); - CPPUNIT_ASSERT_EQUAL(string(""), - Base64::encode("")); + unsigned char* buf = 0; + size_t len; + string s1 = "Hello World!"; + Base64::encode(buf, len, s1.c_str(), s1.size()); + CPPUNIT_ASSERT_EQUAL(string("SGVsbG8gV29ybGQh"), string(&buf[0], &buf[len])); + delete [] buf; + + string s2 = "Hello World"; + Base64::encode(buf, len, s2.c_str(), s2.size()); + CPPUNIT_ASSERT_EQUAL(string("SGVsbG8gV29ybGQ="), string(&buf[0], &buf[len])); + delete [] buf; + + string s3 = "Hello Worl"; + Base64::encode(buf, len, s3.c_str(), s3.size()); + CPPUNIT_ASSERT_EQUAL(string("SGVsbG8gV29ybA=="), string(&buf[0], &buf[len])); + delete [] buf; + + string s4 = "Man"; + Base64::encode(buf, len, s4.c_str(), s4.size()); + CPPUNIT_ASSERT_EQUAL(string("TWFu"), string(&buf[0], &buf[len])); + delete [] buf; + + string s5 = "M"; + Base64::encode(buf, len, s5.c_str(), s5.size()); + CPPUNIT_ASSERT_EQUAL(string("TQ=="), string(&buf[0], &buf[len])); + delete [] buf; + + buf = 0; + string s6 = ""; + Base64::encode(buf, len, s6.c_str(), s6.size()); + CPPUNIT_ASSERT_EQUAL(string(""), string(&buf[0], &buf[len])); + CPPUNIT_ASSERT_EQUAL((size_t)0, len); + CPPUNIT_ASSERT(0 == buf); + + { + const char temp[] = { -1 }; + Base64::encode(buf, len, temp, 1); + CPPUNIT_ASSERT_EQUAL(string("/w=="), string(&buf[0], &buf[len])); + delete [] buf; + } } -void Base64Test::testDecode() { - CPPUNIT_ASSERT_EQUAL(string("Hello World!"), - Base64::decode("SGVsbG8gV29ybGQh")); +void Base64Test::testEncode_string() +{ + string s1 = "Hello World!"; + CPPUNIT_ASSERT_EQUAL(string("SGVsbG8gV29ybGQh"), Base64::encode(s1)); + + string s2 = ""; + CPPUNIT_ASSERT_EQUAL(string(""), Base64::encode(s2)); + + + +} + +void Base64Test::testDecode() +{ + unsigned char* buf; + size_t len; + + string s1 = "SGVsbG8gV29ybGQh"; + Base64::decode(buf, len, s1.c_str(), s1.size()); + CPPUNIT_ASSERT_EQUAL(string("Hello World!"), string(&buf[0], &buf[len])); + delete [] buf; + + string s2 = "SGVsbG8gV29ybGQ="; + Base64::decode(buf, len, s2.c_str(), s2.size()); + CPPUNIT_ASSERT_EQUAL(string("Hello World"), string(&buf[0], &buf[len])); + delete [] buf; + + string s3 = "SGVsbG8gV29ybA=="; + Base64::decode(buf, len, s3.c_str(), s3.size()); + CPPUNIT_ASSERT_EQUAL(string("Hello Worl"), string(&buf[0], &buf[len])); + delete [] buf; + + string s4 = "TWFu"; + Base64::decode(buf, len, s4.c_str(), s4.size()); + CPPUNIT_ASSERT_EQUAL(string("Man"), string(&buf[0], &buf[len])); + delete [] buf; + + string s5 = "TQ=="; + Base64::decode(buf, len, s5.c_str(), s5.size()); + CPPUNIT_ASSERT_EQUAL(string("M"), string(&buf[0], &buf[len])); + delete [] buf; + + buf = 0; + string s6 = ""; + Base64::decode(buf, len, s6.c_str(), s6.size()); + CPPUNIT_ASSERT_EQUAL(string(""), string(&buf[0], &buf[len])); + CPPUNIT_ASSERT_EQUAL((size_t)0, len); + CPPUNIT_ASSERT(!buf); + + string s7 = "SGVsbG8\ngV2*9ybGQ="; + Base64::decode(buf, len, s7.c_str(), s7.size()); + CPPUNIT_ASSERT_EQUAL(string("Hello World"), string(&buf[0], &buf[len])); + delete [] buf; + + buf = 0; + string s8 = "SGVsbG8\ngV2*9ybGQ"; + Base64::decode(buf, len, s8.c_str(), s8.size()); + CPPUNIT_ASSERT_EQUAL(string(""), string(&buf[0], &buf[len])); + CPPUNIT_ASSERT_EQUAL((size_t)0, len); + CPPUNIT_ASSERT(!buf); + + { + string s = "/w=="; + Base64::decode(buf, len, s.c_str(), s.size()); + CPPUNIT_ASSERT_EQUAL((unsigned char)-1, buf[0]); + delete [] buf; + } + +} + +void Base64Test::testDecode_string() +{ + string s1 = "SGVsbG8gV29ybGQh"; + CPPUNIT_ASSERT_EQUAL(string("Hello World!"), Base64::decode(s1)); + + string s2 = ""; + CPPUNIT_ASSERT_EQUAL(string(""), Base64::decode(s2)); +} + +void Base64Test::testLongString() +{ + string s = + "LyogPCEtLSBjb3B5cmlnaHQgKi8KLyoKICogYXJpYTIgLSBUaGUgaGlnaCBzcGVlZCBkb3dubG9h" + "ZCB1dGlsaXR5CiAqCiAqIENvcHlyaWdodCAoQykgMjAwNiBUYXRzdWhpcm8gVHN1amlrYXdhCiAq" + "CiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBp" + "dCBhbmQvb3IgbW9kaWZ5CiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwg" + "UHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5CiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5k" + "YXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCiAqIChhdCB5b3VyIG9w" + "dGlvbikgYW55IGxhdGVyIHZlcnNpb24uCiAqCiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRl" + "ZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAogKiBidXQgV0lUSE9VVCBBTlkg" + "V0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiBNRVJDSEFO" + "VEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCiAq" + "IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBz" + "aG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNl" + "bnNlCiAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVl" + "IFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGgg" + "Rmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQQogKgogKiBJbiBhZGRpdGlvbiwgYXMg" + "YSBzcGVjaWFsIGV4Y2VwdGlvbiwgdGhlIGNvcHlyaWdodCBob2xkZXJzIGdpdmUKICogcGVybWlz" + "c2lvbiB0byBsaW5rIHRoZSBjb2RlIG9mIHBvcnRpb25zIG9mIHRoaXMgcHJvZ3JhbSB3aXRoIHRo" + "ZQogKiBPcGVuU1NMIGxpYnJhcnkgdW5kZXIgY2VydGFpbiBjb25kaXRpb25zIGFzIGRlc2NyaWJl" + "ZCBpbiBlYWNoCiAqIGluZGl2aWR1YWwgc291cmNlIGZpbGUsIGFuZCBkaXN0cmlidXRlIGxpbmtl" + "ZCBjb21iaW5hdGlvbnMKICogaW5jbHVkaW5nIHRoZSB0d28uCiAqIFlvdSBtdXN0IG9iZXkgdGhl" + "IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGluIGFsbCByZXNwZWN0cwogKiBmb3IgYWxsIG9m" + "IHRoZSBjb2RlIHVzZWQgb3RoZXIgdGhhbiBPcGVuU1NMLiAgSWYgeW91IG1vZGlmeQogKiBmaWxl" + "KHMpIHdpdGggdGhpcyBleGNlcHRpb24sIHlvdSBtYXkgZXh0ZW5kIHRoaXMgZXhjZXB0aW9uIHRv" + "IHlvdXIKICogdmVyc2lvbiBvZiB0aGUgZmlsZShzKSwgYnV0IHlvdSBhcmUgbm90IG9ibGlnYXRl" + "ZCB0byBkbyBzby4gIElmIHlvdQogKiBkbyBub3Qgd2lzaCB0byBkbyBzbywgZGVsZXRlIHRoaXMg" + "ZXhjZXB0aW9uIHN0YXRlbWVudCBmcm9tIHlvdXIKICogdmVyc2lvbi4gIElmIHlvdSBkZWxldGUg" + "dGhpcyBleGNlcHRpb24gc3RhdGVtZW50IGZyb20gYWxsIHNvdXJjZQogKiBmaWxlcyBpbiB0aGUg" + "cHJvZ3JhbSwgdGhlbiBhbHNvIGRlbGV0ZSBpdCBoZXJlLgogKi8KLyogY29weXJpZ2h0IC0tPiAq" + "Lwo="; + string d = + "/* */\n"; + CPPUNIT_ASSERT_EQUAL(d, + Base64::decode(s)); + CPPUNIT_ASSERT_EQUAL(s, + Base64::encode(d)); } diff --git a/test/Makefile.am b/test/Makefile.am index 603c350f..a5f18d1d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,7 @@ TESTS = aria2c check_PROGRAMS = $(TESTS) aria2c_SOURCES = AllTest.cc\ + Base64Test.cc\ SequenceTest.cc\ a2functionalTest.cc\ FileEntryTest.cc\ @@ -38,7 +39,6 @@ aria2c_SOURCES = AllTest.cc\ ChunkedEncodingTest.cc\ FileTest.cc\ OptionTest.cc\ - Base64Test.cc\ DefaultDiskWriterTest.cc\ FeatureConfigTest.cc\ SpeedCalcTest.cc\ @@ -101,13 +101,13 @@ endif # ENABLE_BITTORRENT if ENABLE_METALINK aria2c_SOURCES += MetalinkerTest.cc\ MetalinkEntryTest.cc\ - Xml2MetalinkProcessorTest.cc\ Metalink2RequestGroupTest.cc\ MetalinkPostDownloadHandlerTest.cc\ - MetalinkHelperTest.cc + MetalinkHelperTest.cc\ + MetalinkParserControllerTest.cc\ + XML2SAXMetalinkProcessorTest.cc endif # ENABLE_METALINK - #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} diff --git a/test/Makefile.in b/test/Makefile.in index 012b343a..d2f0e1d1 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -87,10 +87,11 @@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_METALINK_TRUE@am__append_3 = MetalinkerTest.cc\ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\ -@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessorTest.cc\ @ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.cc\ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.cc\ -@ENABLE_METALINK_TRUE@ MetalinkHelperTest.cc +@ENABLE_METALINK_TRUE@ MetalinkHelperTest.cc\ +@ENABLE_METALINK_TRUE@ MetalinkParserControllerTest.cc\ +@ENABLE_METALINK_TRUE@ XML2SAXMetalinkProcessorTest.cc subdir = test DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in @@ -113,7 +114,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__EXEEXT_1 = aria2c$(EXEEXT) -am__aria2c_SOURCES_DIST = AllTest.cc SequenceTest.cc \ +am__aria2c_SOURCES_DIST = AllTest.cc Base64Test.cc SequenceTest.cc \ a2functionalTest.cc FileEntryTest.cc PieceTest.cc \ SegmentTest.cc GrowSegmentTest.cc \ SingleFileAllocationIteratorTest.cc \ @@ -129,10 +130,10 @@ am__aria2c_SOURCES_DIST = AllTest.cc SequenceTest.cc \ OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \ NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \ HttpResponseTest.cc SharedHandleTest.cc ChunkedEncodingTest.cc \ - FileTest.cc OptionTest.cc Base64Test.cc \ - DefaultDiskWriterTest.cc FeatureConfigTest.cc SpeedCalcTest.cc \ - FixedNumberRandomizer.h MultiDiskAdaptorTest.cc \ - MultiFileAllocationIteratorTest.cc MessageDigestHelperTest.cc \ + FileTest.cc OptionTest.cc DefaultDiskWriterTest.cc \ + FeatureConfigTest.cc SpeedCalcTest.cc FixedNumberRandomizer.h \ + MultiDiskAdaptorTest.cc MultiFileAllocationIteratorTest.cc \ + MessageDigestHelperTest.cc \ IteratableChunkChecksumValidatorTest.cc \ IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ BtBitfieldMessageTest.cc BtCancelMessageTest.cc \ @@ -155,8 +156,10 @@ am__aria2c_SOURCES_DIST = AllTest.cc SequenceTest.cc \ BtRegistryTest.cc BtDependencyTest.cc \ BtPostDownloadHandlerTest.cc DownloadHandlerFactoryTest.cc \ TimeSeedCriteriaTest.cc MetalinkerTest.cc MetalinkEntryTest.cc \ - Xml2MetalinkProcessorTest.cc Metalink2RequestGroupTest.cc \ - MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc + Metalink2RequestGroupTest.cc \ + MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \ + MetalinkParserControllerTest.cc \ + XML2SAXMetalinkProcessorTest.cc @ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelperTest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.$(OBJEXT) \ @@ -203,14 +206,15 @@ am__aria2c_SOURCES_DIST = AllTest.cc SequenceTest.cc \ @ENABLE_BITTORRENT_TRUE@ TimeSeedCriteriaTest.$(OBJEXT) @ENABLE_METALINK_TRUE@am__objects_3 = MetalinkerTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \ -@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessorTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \ -@ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT) -am_aria2c_OBJECTS = AllTest.$(OBJEXT) SequenceTest.$(OBJEXT) \ - a2functionalTest.$(OBJEXT) FileEntryTest.$(OBJEXT) \ - PieceTest.$(OBJEXT) SegmentTest.$(OBJEXT) \ - GrowSegmentTest.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ MetalinkParserControllerTest.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ XML2SAXMetalinkProcessorTest.$(OBJEXT) +am_aria2c_OBJECTS = AllTest.$(OBJEXT) Base64Test.$(OBJEXT) \ + SequenceTest.$(OBJEXT) a2functionalTest.$(OBJEXT) \ + FileEntryTest.$(OBJEXT) PieceTest.$(OBJEXT) \ + SegmentTest.$(OBJEXT) GrowSegmentTest.$(OBJEXT) \ SingleFileAllocationIteratorTest.$(OBJEXT) \ DefaultBtProgressInfoFileTest.$(OBJEXT) \ SingleFileDownloadContextTest.$(OBJEXT) \ @@ -229,7 +233,7 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) SequenceTest.$(OBJEXT) \ NetrcTest.$(OBJEXT) SingletonHolderTest.$(OBJEXT) \ HttpHeaderTest.$(OBJEXT) HttpResponseTest.$(OBJEXT) \ SharedHandleTest.$(OBJEXT) ChunkedEncodingTest.$(OBJEXT) \ - FileTest.$(OBJEXT) OptionTest.$(OBJEXT) Base64Test.$(OBJEXT) \ + FileTest.$(OBJEXT) OptionTest.$(OBJEXT) \ DefaultDiskWriterTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT) \ SpeedCalcTest.$(OBJEXT) MultiDiskAdaptorTest.$(OBJEXT) \ MultiFileAllocationIteratorTest.$(OBJEXT) $(am__objects_1) \ @@ -420,9 +424,10 @@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ TESTS = aria2c -aria2c_SOURCES = AllTest.cc SequenceTest.cc a2functionalTest.cc \ - FileEntryTest.cc PieceTest.cc SegmentTest.cc \ - GrowSegmentTest.cc SingleFileAllocationIteratorTest.cc \ +aria2c_SOURCES = AllTest.cc Base64Test.cc SequenceTest.cc \ + a2functionalTest.cc FileEntryTest.cc PieceTest.cc \ + SegmentTest.cc GrowSegmentTest.cc \ + SingleFileAllocationIteratorTest.cc \ DefaultBtProgressInfoFileTest.cc \ SingleFileDownloadContextTest.cc RequestGroupTest.cc \ PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \ @@ -435,11 +440,10 @@ aria2c_SOURCES = AllTest.cc SequenceTest.cc a2functionalTest.cc \ OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \ NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \ HttpResponseTest.cc SharedHandleTest.cc ChunkedEncodingTest.cc \ - FileTest.cc OptionTest.cc Base64Test.cc \ - DefaultDiskWriterTest.cc FeatureConfigTest.cc SpeedCalcTest.cc \ - FixedNumberRandomizer.h MultiDiskAdaptorTest.cc \ - MultiFileAllocationIteratorTest.cc $(am__append_1) \ - $(am__append_2) $(am__append_3) + FileTest.cc OptionTest.cc DefaultDiskWriterTest.cc \ + FeatureConfigTest.cc SpeedCalcTest.cc FixedNumberRandomizer.h \ + MultiDiskAdaptorTest.cc MultiFileAllocationIteratorTest.cc \ + $(am__append_1) $(am__append_2) $(am__append_3) #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} @@ -564,6 +568,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalink2RequestGroupTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntryTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkHelperTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkParserControllerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkPostDownloadHandlerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskAdaptorTest.Po@am__quote@ @@ -593,7 +598,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StreamUriListParserTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessorTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XML2SAXMetalinkProcessorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2functionalTest.Po@am__quote@ .cc.o: diff --git a/test/MetalinkParserControllerTest.cc b/test/MetalinkParserControllerTest.cc new file mode 100644 index 00000000..94153352 --- /dev/null +++ b/test/MetalinkParserControllerTest.cc @@ -0,0 +1,140 @@ +#include "MetalinkParserController.h" +#include "Metalinker.h" +#include "MetalinkEntry.h" +#include "MetalinkResource.h" +#include "Checksum.h" +#include "ChunkChecksum.h" +#include + +class MetalinkParserControllerTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(MetalinkParserControllerTest); + CPPUNIT_TEST(testEntryTransaction); + CPPUNIT_TEST(testResourceTransaction); + CPPUNIT_TEST(testChecksumTransaction); + CPPUNIT_TEST(testChunkChecksumTransaction); + + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() {} + + void tearDown() {} + + void testEntryTransaction(); + void testResourceTransaction(); + void testChecksumTransaction(); + void testChunkChecksumTransaction(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( MetalinkParserControllerTest ); + +void MetalinkParserControllerTest::testEntryTransaction() +{ + MetalinkParserController ctrl; + + ctrl.newEntryTransaction(); + ctrl.setFileNameOfEntry("aria2.tar.bz2"); + ctrl.setFileLengthOfEntry(1024*1024); + ctrl.setVersionOfEntry("1.0"); + ctrl.setLanguageOfEntry("ja_JP"); + ctrl.setOSOfEntry("Linux"); + ctrl.commitEntryTransaction(); + { + MetalinkerHandle m = ctrl.getResult(); + CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size()); + MetalinkEntryHandle e = m->entries.front(); + CPPUNIT_ASSERT_EQUAL(string("aria2.tar.bz2"), e->file->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)1024*1024, e->file->getLength()); + CPPUNIT_ASSERT_EQUAL((int64_t)0, e->file->getOffset()); + CPPUNIT_ASSERT_EQUAL(string("1.0"), e->version); + CPPUNIT_ASSERT_EQUAL(string("ja_JP"), e->language); + CPPUNIT_ASSERT_EQUAL(string("Linux"), e->os); + } + ctrl.newEntryTransaction(); + ctrl.cancelEntryTransaction(); + CPPUNIT_ASSERT_EQUAL((size_t)1, ctrl.getResult()->entries.size()); +} + +void MetalinkParserControllerTest::testResourceTransaction() +{ + MetalinkParserController ctrl; + ctrl.newEntryTransaction(); + ctrl.newResourceTransaction(); + ctrl.setURLOfResource("http://mirror/aria2.tar.bz2"); + ctrl.setTypeOfResource("http"); + ctrl.setLocationOfResource("US"); + ctrl.setPreferenceOfResource(100); + ctrl.setMaxConnectionsOfResource(1); + ctrl.commitEntryTransaction(); + { + MetalinkerHandle m = ctrl.getResult(); + CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.front()->resources.size()); + MetalinkResourceHandle res = m->entries.front()->resources[0]; + CPPUNIT_ASSERT_EQUAL(string("http://mirror/aria2.tar.bz2"), res->url); + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, res->type); + CPPUNIT_ASSERT_EQUAL(string("US"), res->location); + CPPUNIT_ASSERT_EQUAL(100, res->preference); + CPPUNIT_ASSERT_EQUAL(1, res->maxConnections); + } + ctrl.newEntryTransaction(); + ctrl.newResourceTransaction(); + ctrl.cancelResourceTransaction(); + ctrl.commitEntryTransaction(); + CPPUNIT_ASSERT_EQUAL((size_t)1, ctrl.getResult()->entries.front()->resources.size()); +} + +void MetalinkParserControllerTest::testChecksumTransaction() +{ + MetalinkParserController ctrl; + ctrl.newEntryTransaction(); + ctrl.newChecksumTransaction(); + ctrl.setTypeOfChecksum("md5"); + ctrl.setHashOfChecksum("hash"); + ctrl.commitEntryTransaction(); + { + MetalinkerHandle m = ctrl.getResult(); + ChecksumHandle md = m->entries.front()->checksum; + CPPUNIT_ASSERT_EQUAL(string("md5"), md->getAlgo()); + CPPUNIT_ASSERT_EQUAL(string("hash"), md->getMessageDigest()); + } + ctrl.newEntryTransaction(); + ctrl.newChecksumTransaction(); + ctrl.cancelChecksumTransaction(); + ctrl.commitEntryTransaction(); + CPPUNIT_ASSERT(ctrl.getResult()->entries[1]->checksum.isNull()); +} + +void MetalinkParserControllerTest::testChunkChecksumTransaction() +{ + MetalinkParserController ctrl; + ctrl.newEntryTransaction(); + ctrl.newChunkChecksumTransaction(); + ctrl.setTypeOfChunkChecksum("md5"); + ctrl.setLengthOfChunkChecksum(256*1024); + ctrl.addHashOfChunkChecksum(4, "hash4"); + ctrl.addHashOfChunkChecksum(1, "hash1"); + ctrl.addHashOfChunkChecksum(3, "hash3"); + ctrl.addHashOfChunkChecksum(2, "hash2"); + ctrl.addHashOfChunkChecksum(5, "hash5"); + ctrl.commitEntryTransaction(); + { + MetalinkerHandle m = ctrl.getResult(); + ChunkChecksumHandle md = m->entries.front()->chunkChecksum; + CPPUNIT_ASSERT_EQUAL(string("md5"), md->getAlgo()); + CPPUNIT_ASSERT_EQUAL(256*1024, md->getChecksumLength()); + CPPUNIT_ASSERT_EQUAL(5, md->countChecksum()); + CPPUNIT_ASSERT_EQUAL(string("hash1"), md->getChecksums()[0]); + CPPUNIT_ASSERT_EQUAL(string("hash2"), md->getChecksums()[1]); + CPPUNIT_ASSERT_EQUAL(string("hash3"), md->getChecksums()[2]); + CPPUNIT_ASSERT_EQUAL(string("hash4"), md->getChecksums()[3]); + CPPUNIT_ASSERT_EQUAL(string("hash5"), md->getChecksums()[4]); + } + ctrl.newEntryTransaction(); + ctrl.newChunkChecksumTransaction(); + ctrl.cancelChunkChecksumTransaction(); + ctrl.commitEntryTransaction(); + CPPUNIT_ASSERT(ctrl.getResult()->entries[1]->chunkChecksum.isNull()); +} diff --git a/test/XML2SAXMetalinkProcessorTest.cc b/test/XML2SAXMetalinkProcessorTest.cc new file mode 100644 index 00000000..74a123d9 --- /dev/null +++ b/test/XML2SAXMetalinkProcessorTest.cc @@ -0,0 +1,511 @@ +#include "XML2SAXMetalinkProcessor.h" +#include "MetalinkParserStateMachine.h" +#include "Exception.h" +#include "DefaultDiskWriter.h" +#include "ByteArrayDiskWriter.h" +#include + +class XML2SAXMetalinkProcessorTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(XML2SAXMetalinkProcessorTest); + CPPUNIT_TEST(testParseFile); + CPPUNIT_TEST(testParseFromBinaryStream); + CPPUNIT_TEST(testMalformedXML); + CPPUNIT_TEST(testMalformedXML2); + CPPUNIT_TEST(testBadSize); + CPPUNIT_TEST(testBadMaxConn); + CPPUNIT_TEST(testNoName); + CPPUNIT_TEST(testBadURLPrefs); + CPPUNIT_TEST(testBadURLMaxConn); + CPPUNIT_TEST(testUnsupportedType); + CPPUNIT_TEST(testMultiplePieces); + CPPUNIT_TEST(testBadPieceNo); + CPPUNIT_TEST(testBadPieceLength); + CPPUNIT_TEST(testUnsupportedType_piece); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + xmlInitParser(); + } + void tearDown() { + xmlCleanupParser(); + } + + void testParseFile(); + void testParseFromBinaryStream(); + void testMalformedXML(); + void testMalformedXML2(); + void testBadSize(); + void testBadMaxConn(); + void testNoName(); + void testBadURLPrefs(); + void testBadURLMaxConn(); + void testUnsupportedType(); + void testMultiplePieces(); + void testBadPieceNo(); + void testBadPieceLength(); + void testUnsupportedType_piece(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( XML2SAXMetalinkProcessorTest ); + +void XML2SAXMetalinkProcessorTest::testParseFile() +{ + XML2SAXMetalinkProcessor proc; + try { + MetalinkerHandle metalinker = proc.parseFile("test.xml"); + + MetalinkEntries::iterator entryItr = metalinker->entries.begin(); + + MetalinkEntryHandle entry1 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), entry1->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)0, entry1->getLength()); + CPPUNIT_ASSERT_EQUAL(string("0.5.2"), entry1->version); + CPPUNIT_ASSERT_EQUAL(string("en-US"), entry1->language); + CPPUNIT_ASSERT_EQUAL(string("Linux-x86"), entry1->os); + CPPUNIT_ASSERT_EQUAL((int32_t)1, entry1->maxConnections); +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT_EQUAL(string("a96cf3f0266b91d87d5124cf94326422800b627d"), + entry1->checksum->getMessageDigest()); + CPPUNIT_ASSERT_EQUAL(string("sha1"), entry1->checksum->getAlgo()); +#endif // ENABLE_MESSAGE_DIGEST + MetalinkResources::iterator resourceItr1 = entry1->resources.begin(); + MetalinkResourceHandle resource1 = *resourceItr1; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, resource1->type); + CPPUNIT_ASSERT_EQUAL(string("JP"), resource1->location); + CPPUNIT_ASSERT_EQUAL((int32_t)100, resource1->preference); + CPPUNIT_ASSERT_EQUAL(string("ftp://ftphost/aria2-0.5.2.tar.bz2"), + resource1->url); + CPPUNIT_ASSERT_EQUAL((int32_t)1, resource1->maxConnections); + + resourceItr1++; + MetalinkResourceHandle resource2 = *resourceItr1; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, resource2->type); + CPPUNIT_ASSERT_EQUAL(string("US"), resource2->location); + CPPUNIT_ASSERT_EQUAL((int32_t)100, resource2->preference); + CPPUNIT_ASSERT_EQUAL(string("http://httphost/aria2-0.5.2.tar.bz2"), + resource2->url); + CPPUNIT_ASSERT_EQUAL((int32_t)-1, resource2->maxConnections); + + entryItr++; + + MetalinkEntryHandle entry2 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.1.tar.bz2"), entry2->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)345689, entry2->getLength()); + CPPUNIT_ASSERT_EQUAL(string("0.5.1"), entry2->version); + CPPUNIT_ASSERT_EQUAL(string("ja-JP"), entry2->language); + CPPUNIT_ASSERT_EQUAL(string("Linux-m68k"), entry2->os); + CPPUNIT_ASSERT_EQUAL((int32_t)-1, entry2->maxConnections); +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT_EQUAL(string("4c255b0ed130f5ea880f0aa061c3da0487e251cc"), + entry2->checksum->getMessageDigest()); + CPPUNIT_ASSERT_EQUAL((int32_t)2, entry2->chunkChecksum->countChecksum()); + CPPUNIT_ASSERT_EQUAL((int32_t)262144, entry2->chunkChecksum->getChecksumLength()); + CPPUNIT_ASSERT_EQUAL(string("179463a88d79cbf0b1923991708aead914f26142"), + entry2->chunkChecksum->getChecksum(0)); + CPPUNIT_ASSERT_EQUAL(string("fecf8bc9a1647505fe16746f94e97a477597dbf3"), + entry2->chunkChecksum->getChecksum(1)); + CPPUNIT_ASSERT_EQUAL(string("sha1"), entry2->checksum->getAlgo()); +#endif // ENABLE_MESSAGE_DIGEST + + entryItr++; + + // test case: verification hash is not provided + MetalinkEntryHandle entry3 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("NoVerificationHash"), entry3->getPath()); +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT(entry3->checksum.isNull()); + CPPUNIT_ASSERT(entry3->chunkChecksum.isNull()); +#endif // ENABLE_MESSAGE_DIGEST + + entryItr++; + + // test case: unsupported verification hash is included + MetalinkEntryHandle entry4 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("UnsupportedVerificationHashTypeIncluded"), entry4->getPath()); +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT_EQUAL(string("sha1"), + entry4->checksum->getAlgo()); + CPPUNIT_ASSERT_EQUAL(string("4c255b0ed130f5ea880f0aa061c3da0487e251cc"), + entry4->checksum->getMessageDigest()); + CPPUNIT_ASSERT_EQUAL(string("sha1"), + entry4->chunkChecksum->getAlgo()); +#endif // ENABLE_MESSAGE_DIGEST + + + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testParseFromBinaryStream() +{ + XML2SAXMetalinkProcessor proc; + DefaultDiskWriterHandle dw = new DefaultDiskWriter(); + dw->openExistingFile("test.xml"); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + + MetalinkEntries::iterator entryItr = m->entries.begin(); + MetalinkEntryHandle entry1 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), entry1->getPath()); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testMalformedXML() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString(""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + CPPUNIT_FAIL("exception must be thrown."); + } catch(Exception* e) { + cerr << *e << endl; + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testMalformedXML2() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString(""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + CPPUNIT_FAIL("exception must be thrown."); + } catch(Exception* e) { + cerr << *e << endl; + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testBadSize() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " abc" + " 0.5.2" + " en-US" + " Linux-x86" + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + + MetalinkEntries::iterator entryItr = m->entries.begin(); + MetalinkEntryHandle e = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), e->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)0, e->getLength()); + CPPUNIT_ASSERT_EQUAL(string("0.5.2"), e->version); + CPPUNIT_ASSERT_EQUAL(string("en-US"), e->language); + CPPUNIT_ASSERT_EQUAL(string("Linux-x86"), e->os); + + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testBadMaxConn() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " 43743838" + " 0.5.2" + " en-US" + " Linux-x86" + " " + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + + MetalinkEntries::iterator entryItr = m->entries.begin(); + MetalinkEntryHandle e = *entryItr; + CPPUNIT_ASSERT_EQUAL((int64_t)43743838, e->getLength()); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testNoName() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " 1024" + " 0.0.1" + " GB" + " Linux-x64" + "" + "" + " 43743838" + " 0.5.2" + " en-US" + " Linux-x86" + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size()); + MetalinkEntries::iterator entryItr = m->entries.begin(); + MetalinkEntryHandle e = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), e->getPath()); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testBadURLPrefs() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " 43743838" + " 0.5.2" + " en-US" + " Linux-x86" + " " + " ftp://mirror/" + " " + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + MetalinkEntryHandle e = m->entries[0]; + MetalinkResourceHandle r = e->resources[0]; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r->type); + CPPUNIT_ASSERT_EQUAL(0, r->preference); + CPPUNIT_ASSERT_EQUAL(1, r->maxConnections); + CPPUNIT_ASSERT_EQUAL(string("JP"), r->location); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testBadURLMaxConn() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " 43743838" + " 0.5.2" + " en-US" + " Linux-x86" + " " + " ftp://mirror/" + " " + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + MetalinkEntryHandle e = m->entries[0]; + MetalinkResourceHandle r = e->resources[0]; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r->type); + CPPUNIT_ASSERT_EQUAL(100, r->preference); + CPPUNIT_ASSERT_EQUAL(-1, r->maxConnections); + CPPUNIT_ASSERT_EQUAL(string("JP"), r->location); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testUnsupportedType() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " 43743838" + " 0.5.2" + " en-US" + " Linux-x86" + " " + " ftp://mirror/" + " magnet:xt=XYZ" + " http://mirror/" + " " + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + MetalinkEntryHandle e = m->entries[0]; + CPPUNIT_ASSERT_EQUAL((size_t)3, e->resources.size()); + MetalinkResourceHandle r1 = e->resources[0]; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r1->type); + MetalinkResourceHandle r2 = e->resources[1]; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_NOT_SUPPORTED, r2->type); + MetalinkResourceHandle r3 = e->resources[2]; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, r3->type); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testMultiplePieces() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + "" + "" + ""); + + try { + // aria2 prefers sha1 + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + MetalinkEntryHandle e = m->entries[0]; + ChunkChecksumHandle c = e->chunkChecksum; + + CPPUNIT_ASSERT_EQUAL(string("sha1"), c->getAlgo()); + CPPUNIT_ASSERT_EQUAL(1024, c->getChecksumLength()); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testBadPieceNo() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " " + " " + " abc" + " xyz" + " " + " " + " abc" + " " + " " + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + MetalinkEntryHandle e = m->entries[0]; + ChunkChecksumHandle c = e->chunkChecksum; + + CPPUNIT_ASSERT_EQUAL(string("sha256"), c->getAlgo()); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testBadPieceLength() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " " + " " + " abc" + " " + " " + " abc" + " " + " " + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + MetalinkEntryHandle e = m->entries[0]; + ChunkChecksumHandle c = e->chunkChecksum; + + CPPUNIT_ASSERT_EQUAL(string("sha256"), c->getAlgo()); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +} + +void XML2SAXMetalinkProcessorTest::testUnsupportedType_piece() +{ + XML2SAXMetalinkProcessor proc; + ByteArrayDiskWriterHandle dw = new ByteArrayDiskWriter(); + dw->setString("" + "" + "" + " " + " " + " abc" + " " + " " + " abc" + " " + " " + "" + "" + ""); + + try { + MetalinkerHandle m = proc.parseFromBinaryStream(dw); + MetalinkEntryHandle e = m->entries[0]; + ChunkChecksumHandle c = e->chunkChecksum; + + CPPUNIT_ASSERT_EQUAL(string("sha256"), c->getAlgo()); + } catch(Exception* e) { + CPPUNIT_FAIL(e->getMsg()); + delete e; + } +}