MetalinkParserStateV3Impl.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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 "MetalinkParserStateV3Impl.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 METALINK3_NAMESPACE_URI[] = "http://www.metalinker.org/";
  44. namespace {
  45. bool checkNsUri(const char* nsUri)
  46. {
  47. return nsUri && strcmp(nsUri, METALINK3_NAMESPACE_URI) == 0;
  48. }
  49. } // namespace
  50. void MetalinkMetalinkParserState::beginElement
  51. (MetalinkParserStateMachine* psm,
  52. const char* localname,
  53. const char* prefix,
  54. const char* nsUri,
  55. const std::vector<XmlAttr>& attrs)
  56. {
  57. if(checkNsUri(nsUri) && strcmp(localname, "files") == 0) {
  58. psm->setFilesState();
  59. } else {
  60. psm->setSkipTagState();
  61. }
  62. }
  63. void FilesMetalinkParserState::beginElement
  64. (MetalinkParserStateMachine* psm,
  65. const char* localname,
  66. const char* prefix,
  67. const char* nsUri,
  68. const std::vector<XmlAttr>& attrs)
  69. {
  70. if(checkNsUri(nsUri) && strcmp(localname, "file") == 0) {
  71. psm->setFileState();
  72. std::vector<XmlAttr>::const_iterator itr =
  73. findAttr(attrs, "name", METALINK3_NAMESPACE_URI);
  74. if(itr != attrs.end()) {
  75. std::string name((*itr).value, (*itr).valueLength);
  76. if(name.empty() || util::detectDirTraversal(name)) {
  77. return;
  78. }
  79. psm->newEntryTransaction();
  80. psm->setFileNameOfEntry(name);
  81. }
  82. } else {
  83. psm->setSkipTagState();
  84. }
  85. }
  86. void FileMetalinkParserState::beginElement
  87. (MetalinkParserStateMachine* psm,
  88. const char* localname,
  89. const char* prefix,
  90. const char* nsUri,
  91. const std::vector<XmlAttr>& attrs)
  92. {
  93. if(!checkNsUri(nsUri)) {
  94. psm->setSkipTagState();
  95. } else if(strcmp(localname, "size") == 0) {
  96. psm->setSizeState();
  97. } else if(strcmp(localname, "version") == 0) {
  98. psm->setVersionState();
  99. } else if(strcmp(localname, "language") == 0) {
  100. psm->setLanguageState();
  101. } else if(strcmp(localname, "os") == 0) {
  102. psm->setOSState();
  103. } else if(strcmp(localname, "verification") == 0) {
  104. psm->setVerificationState();
  105. } else if(strcmp(localname, "resources") == 0) {
  106. psm->setResourcesState();
  107. int maxConnections;
  108. std::vector<XmlAttr>::const_iterator itr =
  109. findAttr(attrs, "maxconnections", METALINK3_NAMESPACE_URI);
  110. if(itr == attrs.end()) {
  111. maxConnections = -1;
  112. } else {
  113. if(!util::parseIntNoThrow
  114. (maxConnections, std::string((*itr).value, (*itr).valueLength)) ||
  115. maxConnections <= 0) {
  116. maxConnections = -1;
  117. }
  118. }
  119. psm->setMaxConnectionsOfEntry(maxConnections);
  120. } else {
  121. psm->setSkipTagState();
  122. }
  123. }
  124. void FileMetalinkParserState::endElement
  125. (MetalinkParserStateMachine* psm,
  126. const char* localname,
  127. const char* prefix,
  128. const char* nsUri,
  129. const std::string& characters)
  130. {
  131. psm->commitEntryTransaction();
  132. }
  133. void SizeMetalinkParserState::endElement
  134. (MetalinkParserStateMachine* psm,
  135. const char* localname,
  136. const char* prefix,
  137. const char* nsUri,
  138. const std::string& characters)
  139. {
  140. // current metalink specification doesn't require size element.
  141. off_t size;
  142. if(util::parseLLIntNoThrow(size, characters) && size >= 0) {
  143. psm->setFileLengthOfEntry(size);
  144. }
  145. }
  146. void VersionMetalinkParserState::endElement
  147. (MetalinkParserStateMachine* psm,
  148. const char* localname,
  149. const char* prefix,
  150. const char* nsUri,
  151. const std::string& characters)
  152. {
  153. psm->setVersionOfEntry(characters);
  154. }
  155. void LanguageMetalinkParserState::endElement
  156. (MetalinkParserStateMachine* psm,
  157. const char* localname,
  158. const char* prefix,
  159. const char* nsUri,
  160. const std::string& characters)
  161. {
  162. psm->setLanguageOfEntry(characters);
  163. }
  164. void OSMetalinkParserState::endElement
  165. (MetalinkParserStateMachine* psm,
  166. const char* localname,
  167. const char* prefix,
  168. const char* nsUri,
  169. const std::string& characters)
  170. {
  171. psm->setOSOfEntry(characters);
  172. }
  173. void VerificationMetalinkParserState::beginElement
  174. (MetalinkParserStateMachine* psm,
  175. const char* localname,
  176. const char* prefix,
  177. const char* nsUri,
  178. const std::vector<XmlAttr>& attrs)
  179. {
  180. if(!checkNsUri(nsUri)) {
  181. psm->setSkipTagState();
  182. } else
  183. #ifdef ENABLE_MESSAGE_DIGEST
  184. if(strcmp(localname, "hash") == 0) {
  185. psm->setHashState();
  186. std::vector<XmlAttr>::const_iterator itr =
  187. findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
  188. if(itr == attrs.end()) {
  189. return;
  190. } else {
  191. psm->newChecksumTransaction();
  192. psm->setTypeOfChecksum(std::string((*itr).value, (*itr).valueLength));
  193. }
  194. } else if(strcmp(localname, "pieces") == 0) {
  195. psm->setPiecesState();
  196. uint32_t length;
  197. {
  198. std::vector<XmlAttr>::const_iterator itr =
  199. findAttr(attrs, "length", METALINK3_NAMESPACE_URI);
  200. if(itr == attrs.end()) {
  201. return;
  202. } else {
  203. if(!util::parseUIntNoThrow
  204. (length, std::string((*itr).value, (*itr).valueLength))) {
  205. return;
  206. }
  207. }
  208. }
  209. std::string type;
  210. {
  211. std::vector<XmlAttr>::const_iterator itr =
  212. findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
  213. if(itr == attrs.end()) {
  214. return;
  215. } else {
  216. type.assign((*itr).value, (*itr).valueLength);
  217. }
  218. }
  219. psm->newChunkChecksumTransaction();
  220. psm->setLengthOfChunkChecksum(length);
  221. psm->setTypeOfChunkChecksum(type);
  222. } else
  223. #endif // ENABLE_MESSAGE_DIGEST
  224. if(strcmp(localname, "signature") == 0) {
  225. psm->setSignatureState();
  226. std::vector<XmlAttr>::const_iterator itr =
  227. findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
  228. if(itr == attrs.end()) {
  229. return;
  230. } else {
  231. psm->newSignatureTransaction();
  232. psm->setTypeOfSignature
  233. (std::string((*itr).value, (*itr).valueLength));
  234. std::vector<XmlAttr>::const_iterator itr =
  235. findAttr(attrs, "file", METALINK3_NAMESPACE_URI);
  236. if(itr != attrs.end()) {
  237. std::string file((*itr).value, (*itr).valueLength);
  238. if(!util::detectDirTraversal(file)) {
  239. psm->setFileOfSignature(file);
  240. }
  241. }
  242. }
  243. } else {
  244. psm->setSkipTagState();
  245. }
  246. }
  247. void HashMetalinkParserState::endElement
  248. (MetalinkParserStateMachine* psm,
  249. const char* localname,
  250. const char* prefix,
  251. const char* nsUri,
  252. const std::string& characters)
  253. {
  254. psm->setHashOfChecksum(characters);
  255. psm->commitChecksumTransaction();
  256. }
  257. void PiecesMetalinkParserState::beginElement
  258. (MetalinkParserStateMachine* psm,
  259. const char* localname,
  260. const char* prefix,
  261. const char* nsUri,
  262. const std::vector<XmlAttr>& attrs)
  263. {
  264. if(checkNsUri(nsUri) && strcmp(localname, "hash") == 0) {
  265. psm->setPieceHashState();
  266. std::vector<XmlAttr>::const_iterator itr =
  267. findAttr(attrs, "piece", METALINK3_NAMESPACE_URI);
  268. if(itr == attrs.end()) {
  269. psm->cancelChunkChecksumTransaction();
  270. } else {
  271. uint32_t idx;
  272. if(util::parseUIntNoThrow
  273. (idx, std::string((*itr).value, (*itr).valueLength))) {
  274. psm->createNewHashOfChunkChecksum(idx);
  275. } else {
  276. psm->cancelChunkChecksumTransaction();
  277. }
  278. }
  279. } else {
  280. psm->setSkipTagState();
  281. }
  282. }
  283. void PiecesMetalinkParserState::endElement
  284. (MetalinkParserStateMachine* psm,
  285. const char* localname,
  286. const char* prefix,
  287. const char* nsUri,
  288. const std::string& characters)
  289. {
  290. psm->commitChunkChecksumTransaction();
  291. }
  292. void PieceHashMetalinkParserState::endElement
  293. (MetalinkParserStateMachine* psm,
  294. const char* localname,
  295. const char* prefix,
  296. const char* nsUri,
  297. const std::string& characters)
  298. {
  299. psm->setMessageDigestOfChunkChecksum(characters);
  300. psm->addHashOfChunkChecksum();
  301. }
  302. void SignatureMetalinkParserState::endElement
  303. (MetalinkParserStateMachine* psm,
  304. const char* localname,
  305. const char* prefix,
  306. const char* nsUri,
  307. const std::string& characters)
  308. {
  309. psm->setBodyOfSignature(characters);
  310. psm->commitSignatureTransaction();
  311. }
  312. void ResourcesMetalinkParserState::beginElement
  313. (MetalinkParserStateMachine* psm,
  314. const char* localname,
  315. const char* prefix,
  316. const char* nsUri,
  317. const std::vector<XmlAttr>& attrs)
  318. {
  319. if(!checkNsUri(nsUri)) {
  320. psm->setSkipTagState();
  321. } else if(strcmp(localname, "url") == 0) {
  322. psm->setURLState();
  323. std::string type;
  324. {
  325. std::vector<XmlAttr>::const_iterator itr =
  326. findAttr(attrs, "type", METALINK3_NAMESPACE_URI);
  327. if(itr == attrs.end()) {
  328. return;
  329. } else {
  330. type.assign((*itr).value, (*itr).valueLength);
  331. }
  332. }
  333. std::string location;
  334. {
  335. std::vector<XmlAttr>::const_iterator itr =
  336. findAttr(attrs, "location", METALINK3_NAMESPACE_URI);
  337. if(itr != attrs.end()) {
  338. location.assign((*itr).value, (*itr).valueLength);
  339. }
  340. }
  341. int preference;
  342. {
  343. std::vector<XmlAttr>::const_iterator itr =
  344. findAttr(attrs, "preference", METALINK3_NAMESPACE_URI);
  345. if(itr == attrs.end()) {
  346. preference = MetalinkResource::getLowestPriority();
  347. } else {
  348. if(util::parseIntNoThrow
  349. (preference, std::string((*itr).value, (*itr).valueLength)) &&
  350. preference >= 0) {
  351. // In Metalink3Spec, highest prefernce value is 100. We
  352. // use Metalink4Spec priority unit system in which 1 is
  353. // higest.
  354. preference = 101-preference;
  355. } else {
  356. preference = MetalinkResource::getLowestPriority();
  357. }
  358. }
  359. }
  360. int maxConnections;
  361. {
  362. std::vector<XmlAttr>::const_iterator itr =
  363. findAttr(attrs, "maxconnections", METALINK3_NAMESPACE_URI);
  364. if(itr == attrs.end()) {
  365. maxConnections = -1;
  366. } else {
  367. if(!util::parseIntNoThrow
  368. (maxConnections, std::string((*itr).value, (*itr).valueLength)) ||
  369. maxConnections <= 0) {
  370. maxConnections = -1;
  371. }
  372. }
  373. }
  374. psm->newResourceTransaction();
  375. psm->setTypeOfResource(type);
  376. psm->setLocationOfResource(location);
  377. psm->setPriorityOfResource(preference);
  378. psm->setMaxConnectionsOfResource(maxConnections);
  379. } else {
  380. psm->setSkipTagState();
  381. }
  382. }
  383. void URLMetalinkParserState::endElement
  384. (MetalinkParserStateMachine* psm,
  385. const char* localname,
  386. const char* prefix,
  387. const char* nsUri,
  388. const std::string& characters)
  389. {
  390. psm->setURLOfResource(characters);
  391. psm->commitResourceTransaction();
  392. }
  393. } // namespace aria2