MetalinkParserStateV4Impl.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2010 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "MetalinkParserStateV4Impl.h"
  36. #include "MetalinkParserStateMachine.h"
  37. #include "RecoverableException.h"
  38. #include "MetalinkResource.h"
  39. #include "util.h"
  40. namespace aria2 {
  41. namespace {
  42. const std::string FILE("file");
  43. const std::string HASH("hash");
  44. const std::string LANGUAGE("language");
  45. const std::string LENGTH("length");
  46. const std::string LOCATION("location");
  47. const std::string METALINK("metalink");
  48. // Can't use name VERSION because it is used as a macro.
  49. const std::string METALINK_VERSION("version");
  50. const std::string METAURL("metaurl");
  51. const std::string NAME("name");
  52. const std::string OS("os");
  53. const std::string PIECE("piece");
  54. const std::string PIECES("pieces");
  55. const std::string PRIORITY("priority");
  56. const std::string SIGNATURE("signature");
  57. const std::string SIZE("size");
  58. const std::string TYPE("type");
  59. const std::string MEDIATYPE("mediatype");
  60. const std::string URL("url");
  61. } // namespace
  62. const std::string METALINK4_NAMESPACE_URI("urn:ietf:params:xml:ns:metalink");
  63. namespace {
  64. class FindAttr {
  65. private:
  66. const std::string& localname_;
  67. public:
  68. FindAttr(const std::string& localname):localname_(localname) {}
  69. bool operator()(const XmlAttr& attr) const
  70. {
  71. return attr.localname == localname_ &&
  72. (attr.nsUri.empty() || attr.nsUri == METALINK4_NAMESPACE_URI);
  73. }
  74. };
  75. } // namespace
  76. namespace {
  77. template<typename Container>
  78. typename Container::const_iterator findAttr
  79. (const Container& attrs, const std::string& localname)
  80. {
  81. return std::find_if(attrs.begin(), attrs.end(), FindAttr(localname));
  82. }
  83. } // namespace
  84. void MetalinkMetalinkParserStateV4::beginElement
  85. (MetalinkParserStateMachine* stm,
  86. const std::string& localname,
  87. const std::string& prefix,
  88. const std::string& nsUri,
  89. const std::vector<XmlAttr>& attrs)
  90. {
  91. if(nsUri == METALINK4_NAMESPACE_URI && localname == FILE) {
  92. stm->setFileStateV4();
  93. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
  94. if(itr == attrs.end() || (*itr).value.empty()) {
  95. stm->logError("Missing file@name");
  96. return;
  97. } else if(util::detectDirTraversal((*itr).value)) {
  98. stm->logError("Bad file@name");
  99. return;
  100. }
  101. stm->newEntryTransaction();
  102. stm->setFileNameOfEntry((*itr).value);
  103. } else {
  104. stm->setSkipTagState();
  105. }
  106. }
  107. void FileMetalinkParserStateV4::beginElement
  108. (MetalinkParserStateMachine* stm,
  109. const std::string& localname,
  110. const std::string& prefix,
  111. const std::string& nsUri,
  112. const std::vector<XmlAttr>& attrs)
  113. {
  114. if(nsUri != METALINK4_NAMESPACE_URI) {
  115. stm->setSkipTagState();
  116. } else if(localname == SIZE) {
  117. stm->setSizeStateV4();
  118. } else if(localname == METALINK_VERSION) {
  119. stm->setVersionStateV4();
  120. } else if(localname == LANGUAGE) {
  121. stm->setLanguageStateV4();
  122. } else if(localname == OS) {
  123. stm->setOSStateV4();
  124. } else if(localname == METAURL) {
  125. stm->setMetaurlStateV4();
  126. std::string name;
  127. {
  128. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
  129. if(itr != attrs.end()) {
  130. if((*itr).value.empty() || util::detectDirTraversal((*itr).value)) {
  131. stm->logError("Bad metaurl@name");
  132. return;
  133. } else {
  134. name = (*itr).value;
  135. }
  136. }
  137. }
  138. int priority;
  139. {
  140. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PRIORITY);
  141. if(itr == attrs.end()) {
  142. priority = MetalinkResource::getLowestPriority();
  143. } else {
  144. try {
  145. priority = util::parseInt((*itr).value.begin(), (*itr).value.end());
  146. if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
  147. stm->logError("metaurl@priority is out of range");
  148. return;
  149. }
  150. } catch(RecoverableException& e) {
  151. stm->logError("Bad metaurl@priority");
  152. return;
  153. }
  154. }
  155. }
  156. std::string mediatype;
  157. {
  158. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, MEDIATYPE);
  159. if(itr == attrs.end() || (*itr).value.empty()) {
  160. stm->logError("Missing metaurl@mediatype");
  161. return;
  162. } else {
  163. mediatype = (*itr).value;
  164. }
  165. }
  166. stm->newMetaurlTransaction();
  167. stm->setPriorityOfMetaurl(priority);
  168. stm->setMediatypeOfMetaurl(mediatype);
  169. stm->setNameOfMetaurl(name);
  170. } else if(localname == URL) {
  171. stm->setURLStateV4();
  172. std::string location;
  173. {
  174. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LOCATION);
  175. if(itr != attrs.end()) {
  176. location = (*itr).value;
  177. }
  178. }
  179. int priority;
  180. {
  181. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PRIORITY);
  182. if(itr == attrs.end()) {
  183. priority = MetalinkResource::getLowestPriority();
  184. } else {
  185. try {
  186. priority = util::parseInt((*itr).value.begin(), (*itr).value.end());
  187. if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
  188. stm->logError("url@priority is out of range");
  189. return;
  190. }
  191. } catch(RecoverableException& e) {
  192. stm->logError("Bad url@priority");
  193. return;
  194. }
  195. }
  196. }
  197. stm->newResourceTransaction();
  198. stm->setLocationOfResource(location);
  199. stm->setPriorityOfResource(priority);
  200. }
  201. #ifdef ENABLE_MESSAGE_DIGEST
  202. else if(localname == HASH) {
  203. stm->setHashStateV4();
  204. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
  205. if(itr == attrs.end() || (*itr).value.empty()) {
  206. stm->logError("Missing hash@type");
  207. return;
  208. } else {
  209. std::string type = (*itr).value;
  210. stm->newChecksumTransaction();
  211. stm->setTypeOfChecksum(type);
  212. }
  213. } else if(localname == PIECES) {
  214. stm->setPiecesStateV4();
  215. size_t length;
  216. {
  217. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LENGTH);
  218. if(itr == attrs.end() || (*itr).value.empty()) {
  219. stm->logError("Missing pieces@length");
  220. return;
  221. } else {
  222. try {
  223. length = util::parseInt((*itr).value.begin(), (*itr).value.end());
  224. } catch(RecoverableException& e) {
  225. stm->logError("Bad pieces@length");
  226. return;
  227. }
  228. }
  229. }
  230. std::string type;
  231. {
  232. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
  233. if(itr == attrs.end() || (*itr).value.empty()) {
  234. stm->logError("Missing pieces@type");
  235. return;
  236. } else {
  237. type = (*itr).value;
  238. }
  239. }
  240. stm->newChunkChecksumTransactionV4();
  241. stm->setLengthOfChunkChecksumV4(length);
  242. stm->setTypeOfChunkChecksumV4(type);
  243. }
  244. #endif // ENABLE_MESSAGE_DIGEST
  245. else if(localname == SIGNATURE) {
  246. stm->setSignatureStateV4();
  247. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, MEDIATYPE);
  248. if(itr == attrs.end() || (*itr).value.empty()) {
  249. stm->logError("Missing signature@mediatype");
  250. return;
  251. }
  252. stm->newSignatureTransaction();
  253. stm->setTypeOfSignature((*itr).value);
  254. } else {
  255. stm->setSkipTagState();
  256. }
  257. }
  258. void FileMetalinkParserStateV4::endElement
  259. (MetalinkParserStateMachine* stm,
  260. const std::string& localname,
  261. const std::string& prefix,
  262. const std::string& nsUri,
  263. const std::string& characters)
  264. {
  265. stm->commitEntryTransaction();
  266. }
  267. void SizeMetalinkParserStateV4::endElement
  268. (MetalinkParserStateMachine* stm,
  269. const std::string& localname,
  270. const std::string& prefix,
  271. const std::string& nsUri,
  272. const std::string& characters)
  273. {
  274. try {
  275. stm->setFileLengthOfEntry
  276. (util::parseULLInt(characters.begin(), characters.end()));
  277. } catch(RecoverableException& e) {
  278. stm->cancelEntryTransaction();
  279. stm->logError("Bad size");
  280. }
  281. }
  282. void VersionMetalinkParserStateV4::endElement
  283. (MetalinkParserStateMachine* stm,
  284. const std::string& localname,
  285. const std::string& prefix,
  286. const std::string& nsUri,
  287. const std::string& characters)
  288. {
  289. stm->setVersionOfEntry(characters);
  290. }
  291. void LanguageMetalinkParserStateV4::endElement
  292. (MetalinkParserStateMachine* stm,
  293. const std::string& localname,
  294. const std::string& prefix,
  295. const std::string& nsUri,
  296. const std::string& characters)
  297. {
  298. stm->setLanguageOfEntry(characters);
  299. }
  300. void OSMetalinkParserStateV4::endElement
  301. (MetalinkParserStateMachine* stm,
  302. const std::string& localname,
  303. const std::string& prefix,
  304. const std::string& nsUri,
  305. const std::string& characters)
  306. {
  307. stm->setOSOfEntry(characters);
  308. }
  309. void HashMetalinkParserStateV4::endElement
  310. (MetalinkParserStateMachine* stm,
  311. const std::string& localname,
  312. const std::string& prefix,
  313. const std::string& nsUri,
  314. const std::string& characters)
  315. {
  316. stm->setHashOfChecksum(characters);
  317. stm->commitChecksumTransaction();
  318. }
  319. void PiecesMetalinkParserStateV4::beginElement
  320. (MetalinkParserStateMachine* stm,
  321. const std::string& localname,
  322. const std::string& prefix,
  323. const std::string& nsUri,
  324. const std::vector<XmlAttr>& attrs)
  325. {
  326. if(nsUri == METALINK4_NAMESPACE_URI && localname == HASH) {
  327. stm->setPieceHashStateV4();
  328. } else {
  329. stm->setSkipTagState();
  330. }
  331. }
  332. void PiecesMetalinkParserStateV4::endElement
  333. (MetalinkParserStateMachine* stm,
  334. const std::string& localname,
  335. const std::string& prefix,
  336. const std::string& nsUri,
  337. const std::string& characters)
  338. {
  339. stm->commitChunkChecksumTransactionV4();
  340. }
  341. void PieceHashMetalinkParserStateV4::endElement
  342. (MetalinkParserStateMachine* stm,
  343. const std::string& localname,
  344. const std::string& prefix,
  345. const std::string& nsUri,
  346. const std::string& characters)
  347. {
  348. stm->addHashOfChunkChecksumV4(characters);
  349. }
  350. void SignatureMetalinkParserStateV4::endElement
  351. (MetalinkParserStateMachine* stm,
  352. const std::string& localname,
  353. const std::string& prefix,
  354. const std::string& nsUri,
  355. const std::string& characters)
  356. {
  357. stm->setBodyOfSignature(characters);
  358. stm->commitSignatureTransaction();
  359. }
  360. void URLMetalinkParserStateV4::endElement
  361. (MetalinkParserStateMachine* stm,
  362. const std::string& localname,
  363. const std::string& prefix,
  364. const std::string& nsUri,
  365. const std::string& characters)
  366. {
  367. stm->setURLOfResource(characters);
  368. stm->commitResourceTransaction();
  369. }
  370. void MetaurlMetalinkParserStateV4::endElement
  371. (MetalinkParserStateMachine* stm,
  372. const std::string& localname,
  373. const std::string& prefix,
  374. const std::string& nsUri,
  375. const std::string& characters)
  376. {
  377. stm->setURLOfMetaurl(characters);
  378. stm->commitMetaurlTransaction();
  379. }
  380. } // namespace aria2