MetalinkParserStateV4Impl.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  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. }
  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. }
  76. template<typename Container>
  77. static typename Container::const_iterator findAttr
  78. (const Container& attrs, const std::string& localname)
  79. {
  80. return std::find_if(attrs.begin(), attrs.end(), FindAttr(localname));
  81. }
  82. void MetalinkMetalinkParserStateV4::beginElement
  83. (MetalinkParserStateMachine* stm,
  84. const std::string& localname,
  85. const std::string& prefix,
  86. const std::string& nsUri,
  87. const std::vector<XmlAttr>& attrs)
  88. {
  89. if(nsUri == METALINK4_NAMESPACE_URI && localname == FILE) {
  90. stm->setFileStateV4();
  91. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
  92. if(itr == attrs.end() || (*itr).value.empty()) {
  93. stm->logError("Missing file@name");
  94. return;
  95. } else if(util::detectDirTraversal((*itr).value)) {
  96. stm->logError("Bad file@name");
  97. return;
  98. }
  99. stm->newEntryTransaction();
  100. stm->setFileNameOfEntry((*itr).value);
  101. } else {
  102. stm->setSkipTagState();
  103. }
  104. }
  105. void FileMetalinkParserStateV4::beginElement
  106. (MetalinkParserStateMachine* stm,
  107. const std::string& localname,
  108. const std::string& prefix,
  109. const std::string& nsUri,
  110. const std::vector<XmlAttr>& attrs)
  111. {
  112. if(nsUri != METALINK4_NAMESPACE_URI) {
  113. stm->setSkipTagState();
  114. } else if(localname == SIZE) {
  115. stm->setSizeStateV4();
  116. } else if(localname == METALINK_VERSION) {
  117. stm->setVersionStateV4();
  118. } else if(localname == LANGUAGE) {
  119. stm->setLanguageStateV4();
  120. } else if(localname == OS) {
  121. stm->setOSStateV4();
  122. } else if(localname == METAURL) {
  123. stm->setMetaurlStateV4();
  124. std::string name;
  125. {
  126. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME);
  127. if(itr != attrs.end()) {
  128. if((*itr).value.empty() || util::detectDirTraversal((*itr).value)) {
  129. stm->logError("Bad metaurl@name");
  130. return;
  131. } else {
  132. name = (*itr).value;
  133. }
  134. }
  135. }
  136. int priority;
  137. {
  138. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PRIORITY);
  139. if(itr == attrs.end()) {
  140. priority = MetalinkResource::getLowestPriority();
  141. } else {
  142. try {
  143. priority = util::parseInt((*itr).value);
  144. if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
  145. stm->logError("metaurl@priority is out of range");
  146. return;
  147. }
  148. } catch(RecoverableException& e) {
  149. stm->logError("Bad metaurl@priority");
  150. return;
  151. }
  152. }
  153. }
  154. std::string mediatype;
  155. {
  156. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, MEDIATYPE);
  157. if(itr == attrs.end() || (*itr).value.empty()) {
  158. stm->logError("Missing metaurl@mediatype");
  159. return;
  160. } else {
  161. mediatype = (*itr).value;
  162. }
  163. }
  164. stm->newMetaurlTransaction();
  165. stm->setPriorityOfMetaurl(priority);
  166. stm->setMediatypeOfMetaurl(mediatype);
  167. stm->setNameOfMetaurl(name);
  168. } else if(localname == URL) {
  169. stm->setURLStateV4();
  170. std::string location;
  171. {
  172. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LOCATION);
  173. if(itr != attrs.end()) {
  174. location = (*itr).value;
  175. }
  176. }
  177. int priority;
  178. {
  179. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, PRIORITY);
  180. if(itr == attrs.end()) {
  181. priority = MetalinkResource::getLowestPriority();
  182. } else {
  183. try {
  184. priority = util::parseInt((*itr).value);
  185. if(priority < 1 || MetalinkResource::getLowestPriority() < priority) {
  186. stm->logError("url@priority is out of range");
  187. return;
  188. }
  189. } catch(RecoverableException& e) {
  190. stm->logError("Bad url@priority");
  191. return;
  192. }
  193. }
  194. }
  195. stm->newResourceTransaction();
  196. stm->setLocationOfResource(location);
  197. stm->setPriorityOfResource(priority);
  198. }
  199. #ifdef ENABLE_MESSAGE_DIGEST
  200. else if(localname == HASH) {
  201. stm->setHashStateV4();
  202. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
  203. if(itr == attrs.end() || (*itr).value.empty()) {
  204. stm->logError("Missing hash@type");
  205. return;
  206. } else {
  207. std::string type = (*itr).value;
  208. stm->newChecksumTransaction();
  209. stm->setTypeOfChecksum(type);
  210. }
  211. } else if(localname == PIECES) {
  212. stm->setPiecesStateV4();
  213. size_t length;
  214. {
  215. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, LENGTH);
  216. if(itr == attrs.end() || (*itr).value.empty()) {
  217. stm->logError("Missing pieces@length");
  218. return;
  219. } else {
  220. try {
  221. length = util::parseInt((*itr).value);
  222. } catch(RecoverableException& e) {
  223. stm->logError("Bad pieces@length");
  224. return;
  225. }
  226. }
  227. }
  228. std::string type;
  229. {
  230. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, TYPE);
  231. if(itr == attrs.end() || (*itr).value.empty()) {
  232. stm->logError("Missing pieces@type");
  233. return;
  234. } else {
  235. type = (*itr).value;
  236. }
  237. }
  238. stm->newChunkChecksumTransactionV4();
  239. stm->setLengthOfChunkChecksumV4(length);
  240. stm->setTypeOfChunkChecksumV4(type);
  241. }
  242. #endif // ENABLE_MESSAGE_DIGEST
  243. else if(localname == SIGNATURE) {
  244. stm->setSignatureStateV4();
  245. std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, MEDIATYPE);
  246. if(itr == attrs.end() || (*itr).value.empty()) {
  247. stm->logError("Missing signature@mediatype");
  248. return;
  249. }
  250. stm->newSignatureTransaction();
  251. stm->setTypeOfSignature((*itr).value);
  252. } else {
  253. stm->setSkipTagState();
  254. }
  255. }
  256. void FileMetalinkParserStateV4::endElement
  257. (MetalinkParserStateMachine* stm,
  258. const std::string& localname,
  259. const std::string& prefix,
  260. const std::string& nsUri,
  261. const std::string& characters)
  262. {
  263. stm->commitEntryTransaction();
  264. }
  265. void SizeMetalinkParserStateV4::endElement
  266. (MetalinkParserStateMachine* stm,
  267. const std::string& localname,
  268. const std::string& prefix,
  269. const std::string& nsUri,
  270. const std::string& characters)
  271. {
  272. try {
  273. stm->setFileLengthOfEntry(util::parseULLInt(characters));
  274. } catch(RecoverableException& e) {
  275. stm->cancelEntryTransaction();
  276. stm->logError("Bad size");
  277. }
  278. }
  279. void VersionMetalinkParserStateV4::endElement
  280. (MetalinkParserStateMachine* stm,
  281. const std::string& localname,
  282. const std::string& prefix,
  283. const std::string& nsUri,
  284. const std::string& characters)
  285. {
  286. stm->setVersionOfEntry(characters);
  287. }
  288. void LanguageMetalinkParserStateV4::endElement
  289. (MetalinkParserStateMachine* stm,
  290. const std::string& localname,
  291. const std::string& prefix,
  292. const std::string& nsUri,
  293. const std::string& characters)
  294. {
  295. stm->setLanguageOfEntry(characters);
  296. }
  297. void OSMetalinkParserStateV4::endElement
  298. (MetalinkParserStateMachine* stm,
  299. const std::string& localname,
  300. const std::string& prefix,
  301. const std::string& nsUri,
  302. const std::string& characters)
  303. {
  304. stm->setOSOfEntry(characters);
  305. }
  306. void HashMetalinkParserStateV4::endElement
  307. (MetalinkParserStateMachine* stm,
  308. const std::string& localname,
  309. const std::string& prefix,
  310. const std::string& nsUri,
  311. const std::string& characters)
  312. {
  313. stm->setHashOfChecksum(characters);
  314. stm->commitChecksumTransaction();
  315. }
  316. void PiecesMetalinkParserStateV4::beginElement
  317. (MetalinkParserStateMachine* stm,
  318. const std::string& localname,
  319. const std::string& prefix,
  320. const std::string& nsUri,
  321. const std::vector<XmlAttr>& attrs)
  322. {
  323. if(nsUri == METALINK4_NAMESPACE_URI && localname == HASH) {
  324. stm->setPieceHashStateV4();
  325. } else {
  326. stm->setSkipTagState();
  327. }
  328. }
  329. void PiecesMetalinkParserStateV4::endElement
  330. (MetalinkParserStateMachine* stm,
  331. const std::string& localname,
  332. const std::string& prefix,
  333. const std::string& nsUri,
  334. const std::string& characters)
  335. {
  336. stm->commitChunkChecksumTransactionV4();
  337. }
  338. void PieceHashMetalinkParserStateV4::endElement
  339. (MetalinkParserStateMachine* stm,
  340. const std::string& localname,
  341. const std::string& prefix,
  342. const std::string& nsUri,
  343. const std::string& characters)
  344. {
  345. stm->addHashOfChunkChecksumV4(characters);
  346. }
  347. void SignatureMetalinkParserStateV4::endElement
  348. (MetalinkParserStateMachine* stm,
  349. const std::string& localname,
  350. const std::string& prefix,
  351. const std::string& nsUri,
  352. const std::string& characters)
  353. {
  354. stm->setBodyOfSignature(characters);
  355. stm->commitSignatureTransaction();
  356. }
  357. void URLMetalinkParserStateV4::endElement
  358. (MetalinkParserStateMachine* stm,
  359. const std::string& localname,
  360. const std::string& prefix,
  361. const std::string& nsUri,
  362. const std::string& characters)
  363. {
  364. stm->setURLOfResource(characters);
  365. stm->commitResourceTransaction();
  366. }
  367. void MetaurlMetalinkParserStateV4::endElement
  368. (MetalinkParserStateMachine* stm,
  369. const std::string& localname,
  370. const std::string& prefix,
  371. const std::string& nsUri,
  372. const std::string& characters)
  373. {
  374. stm->setURLOfMetaurl(characters);
  375. stm->commitMetaurlTransaction();
  376. }
  377. } // namespace aria2