MetalinkParserStateV4Impl.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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 <cstring>
  37. #include "MetalinkParserStateMachine.h"
  38. #include "RecoverableException.h"
  39. #include "MetalinkResource.h"
  40. #include "util.h"
  41. #include "XmlAttr.h"
  42. namespace aria2 {
  43. const char METALINK4_NAMESPACE_URI[] = "urn:ietf:params:xml:ns:metalink";
  44. namespace {
  45. bool checkNsUri(const char* nsUri)
  46. {
  47. return nsUri && strcmp(nsUri, METALINK4_NAMESPACE_URI) == 0;
  48. }
  49. } // namespace
  50. void MetalinkMetalinkParserStateV4::beginElement(
  51. MetalinkParserStateMachine* psm, const char* localname, const char* prefix,
  52. const char* nsUri, const std::vector<XmlAttr>& attrs)
  53. {
  54. if (checkNsUri(nsUri) && strcmp(localname, "file") != 0) {
  55. psm->setSkipTagState();
  56. return;
  57. }
  58. psm->setFileStateV4();
  59. auto itr = findAttr(attrs, "name", METALINK4_NAMESPACE_URI);
  60. if (itr == attrs.end() || (*itr).valueLength == 0) {
  61. psm->logError("Missing file@name");
  62. return;
  63. }
  64. std::string name((*itr).value, (*itr).valueLength);
  65. if (util::detectDirTraversal(name)) {
  66. psm->logError("Bad file@name");
  67. return;
  68. }
  69. psm->newEntryTransaction();
  70. psm->setFileNameOfEntry(name);
  71. }
  72. void FileMetalinkParserStateV4::beginElement(MetalinkParserStateMachine* psm,
  73. const char* localname,
  74. const char* prefix,
  75. const char* nsUri,
  76. const std::vector<XmlAttr>& attrs)
  77. {
  78. if (!checkNsUri(nsUri)) {
  79. psm->setSkipTagState();
  80. }
  81. else if (strcmp(localname, "size") == 0) {
  82. psm->setSizeStateV4();
  83. }
  84. else if (strcmp(localname, "version") == 0) {
  85. psm->setVersionStateV4();
  86. }
  87. else if (strcmp(localname, "language") == 0) {
  88. psm->setLanguageStateV4();
  89. }
  90. else if (strcmp(localname, "os") == 0) {
  91. psm->setOSStateV4();
  92. }
  93. else if (strcmp(localname, "metaurl") == 0) {
  94. psm->setMetaurlStateV4();
  95. std::string name;
  96. {
  97. auto itr = findAttr(attrs, "name", METALINK4_NAMESPACE_URI);
  98. if (itr != attrs.end()) {
  99. name.assign((*itr).value, (*itr).valueLength);
  100. if (name.empty() || util::detectDirTraversal(name)) {
  101. psm->logError("Bad metaurl@name");
  102. return;
  103. }
  104. }
  105. }
  106. int priority;
  107. {
  108. auto itr = findAttr(attrs, "priority", METALINK4_NAMESPACE_URI);
  109. if (itr == attrs.end()) {
  110. priority = MetalinkResource::getLowestPriority();
  111. }
  112. else if (util::parseIntNoThrow(
  113. priority, std::string((*itr).value, (*itr).valueLength))) {
  114. if (priority < 1 || MetalinkResource::getLowestPriority() < priority) {
  115. psm->logError("metaurl@priority is out of range");
  116. return;
  117. }
  118. }
  119. else {
  120. psm->logError("Bad metaurl@priority");
  121. return;
  122. }
  123. }
  124. std::string mediatype;
  125. {
  126. auto itr = findAttr(attrs, "mediatype", METALINK4_NAMESPACE_URI);
  127. if (itr == attrs.end() || (*itr).valueLength == 0) {
  128. psm->logError("Missing metaurl@mediatype");
  129. return;
  130. }
  131. mediatype.assign((*itr).value, (*itr).valueLength);
  132. }
  133. psm->newMetaurlTransaction();
  134. psm->setPriorityOfMetaurl(priority);
  135. psm->setMediatypeOfMetaurl(mediatype);
  136. psm->setNameOfMetaurl(name);
  137. }
  138. else if (strcmp(localname, "url") == 0) {
  139. psm->setURLStateV4();
  140. std::string location;
  141. {
  142. auto itr = findAttr(attrs, "location", METALINK4_NAMESPACE_URI);
  143. if (itr != attrs.end()) {
  144. location.assign((*itr).value, (*itr).valueLength);
  145. }
  146. }
  147. int priority;
  148. {
  149. auto itr = findAttr(attrs, "priority", METALINK4_NAMESPACE_URI);
  150. if (itr == attrs.end()) {
  151. priority = MetalinkResource::getLowestPriority();
  152. }
  153. else if (util::parseIntNoThrow(
  154. priority, std::string((*itr).value, (*itr).valueLength))) {
  155. if (priority < 1 || MetalinkResource::getLowestPriority() < priority) {
  156. psm->logError("url@priority is out of range");
  157. return;
  158. }
  159. }
  160. else {
  161. psm->logError("Bad url@priority");
  162. return;
  163. }
  164. }
  165. psm->newResourceTransaction();
  166. psm->setLocationOfResource(location);
  167. psm->setPriorityOfResource(priority);
  168. }
  169. else if (strcmp(localname, "hash") == 0) {
  170. psm->setHashStateV4();
  171. auto itr = findAttr(attrs, "type", METALINK4_NAMESPACE_URI);
  172. if (itr == attrs.end() || (*itr).valueLength == 0) {
  173. psm->logError("Missing hash@type");
  174. return;
  175. }
  176. psm->newChecksumTransaction();
  177. psm->setTypeOfChecksum(std::string((*itr).value, (*itr).valueLength));
  178. }
  179. else if (strcmp(localname, "pieces") == 0) {
  180. psm->setPiecesStateV4();
  181. uint32_t length;
  182. {
  183. auto itr = findAttr(attrs, "length", METALINK4_NAMESPACE_URI);
  184. if (itr == attrs.end() || (*itr).valueLength == 0) {
  185. psm->logError("Missing pieces@length");
  186. return;
  187. }
  188. if (!util::parseUIntNoThrow(
  189. length, std::string((*itr).value, (*itr).valueLength))) {
  190. psm->logError("Bad pieces@length");
  191. return;
  192. }
  193. }
  194. std::string type;
  195. {
  196. auto itr = findAttr(attrs, "type", METALINK4_NAMESPACE_URI);
  197. if (itr == attrs.end() || (*itr).valueLength == 0) {
  198. psm->logError("Missing pieces@type");
  199. return;
  200. }
  201. type.assign((*itr).value, (*itr).valueLength);
  202. }
  203. psm->newChunkChecksumTransactionV4();
  204. psm->setLengthOfChunkChecksumV4(length);
  205. psm->setTypeOfChunkChecksumV4(type);
  206. }
  207. else if (strcmp(localname, "signature") == 0) {
  208. psm->setSignatureStateV4();
  209. auto itr = findAttr(attrs, "mediatype", METALINK4_NAMESPACE_URI);
  210. if (itr == attrs.end() || (*itr).valueLength == 0) {
  211. psm->logError("Missing signature@mediatype");
  212. return;
  213. }
  214. psm->newSignatureTransaction();
  215. psm->setTypeOfSignature(std::string((*itr).value, (*itr).valueLength));
  216. }
  217. else {
  218. psm->setSkipTagState();
  219. }
  220. }
  221. void FileMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  222. const char* localname,
  223. const char* prefix,
  224. const char* nsUri,
  225. std::string characters)
  226. {
  227. psm->commitEntryTransaction();
  228. }
  229. void SizeMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  230. const char* localname,
  231. const char* prefix,
  232. const char* nsUri,
  233. std::string characters)
  234. {
  235. int64_t size;
  236. if (util::parseLLIntNoThrow(size, characters) && size >= 0 &&
  237. size <= std::numeric_limits<a2_off_t>::max()) {
  238. psm->setFileLengthOfEntry(size);
  239. }
  240. else {
  241. psm->cancelEntryTransaction();
  242. psm->logError("Bad size");
  243. }
  244. }
  245. void VersionMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  246. const char* localname,
  247. const char* prefix,
  248. const char* nsUri,
  249. std::string characters)
  250. {
  251. psm->setVersionOfEntry(std::move(characters));
  252. }
  253. void LanguageMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  254. const char* localname,
  255. const char* prefix,
  256. const char* nsUri,
  257. std::string characters)
  258. {
  259. psm->setLanguageOfEntry(std::move(characters));
  260. }
  261. void OSMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  262. const char* localname,
  263. const char* prefix, const char* nsUri,
  264. std::string characters)
  265. {
  266. psm->setOSOfEntry(std::move(characters));
  267. }
  268. void HashMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  269. const char* localname,
  270. const char* prefix,
  271. const char* nsUri,
  272. std::string characters)
  273. {
  274. psm->setHashOfChecksum(std::move(characters));
  275. psm->commitChecksumTransaction();
  276. }
  277. void PiecesMetalinkParserStateV4::beginElement(
  278. MetalinkParserStateMachine* psm, const char* localname, const char* prefix,
  279. const char* nsUri, const std::vector<XmlAttr>& attrs)
  280. {
  281. if (checkNsUri(nsUri) && strcmp(localname, "hash") == 0) {
  282. psm->setPieceHashStateV4();
  283. }
  284. else {
  285. psm->setSkipTagState();
  286. }
  287. }
  288. void PiecesMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  289. const char* localname,
  290. const char* prefix,
  291. const char* nsUri,
  292. std::string characters)
  293. {
  294. psm->commitChunkChecksumTransactionV4();
  295. }
  296. void PieceHashMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  297. const char* localname,
  298. const char* prefix,
  299. const char* nsUri,
  300. std::string characters)
  301. {
  302. psm->addHashOfChunkChecksumV4(std::move(characters));
  303. }
  304. void SignatureMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  305. const char* localname,
  306. const char* prefix,
  307. const char* nsUri,
  308. std::string characters)
  309. {
  310. psm->setBodyOfSignature(std::move(characters));
  311. psm->commitSignatureTransaction();
  312. }
  313. void URLMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  314. const char* localname,
  315. const char* prefix, const char* nsUri,
  316. std::string characters)
  317. {
  318. psm->setURLOfResource(std::move(characters));
  319. psm->commitResourceTransaction();
  320. }
  321. void MetaurlMetalinkParserStateV4::endElement(MetalinkParserStateMachine* psm,
  322. const char* localname,
  323. const char* prefix,
  324. const char* nsUri,
  325. std::string characters)
  326. {
  327. psm->setURLOfMetaurl(std::move(characters));
  328. psm->commitMetaurlTransaction();
  329. }
  330. } // namespace aria2