DownloadThread.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "Main.h"
  2. #pragma warning(disable:4786)
  3. #include "DownloadThread.h"
  4. #include "api__ml_wire.h"
  5. #include "api/service/waServiceFactory.h"
  6. #include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
  7. #include "errors.h"
  8. #include <strsafe.h>
  9. extern int winampVersion;
  10. #define USER_AGENT_SIZE (10 /*User-Agent*/ + 2 /*: */ + 6 /*Winamp*/ + 1 /*/*/ + 1 /*5*/ + 3/*.21*/ + 1 /*Null*/)
  11. void SetUserAgent( api_httpreceiver *http )
  12. {
  13. char user_agent[ USER_AGENT_SIZE ] = { 0 };
  14. int bigVer = ( ( winampVersion & 0x0000FF00 ) >> 12 );
  15. int smallVer = ( ( winampVersion & 0x000000FF ) );
  16. StringCchPrintfA( user_agent, USER_AGENT_SIZE, "User-Agent: Winamp/%01x.%02x", bigVer, smallVer );
  17. http->addheader( user_agent );
  18. }
  19. #define HTTP_BUFFER_SIZE 32768
  20. static int FeedXMLHTTP( api_httpreceiver *http, obj_xml *parser, bool *noData )
  21. {
  22. char downloadedData[ HTTP_BUFFER_SIZE ] = { 0 };
  23. int xmlResult = API_XML_SUCCESS;
  24. int downloadSize = http->get_bytes( downloadedData, HTTP_BUFFER_SIZE );
  25. if ( downloadSize )
  26. {
  27. xmlResult = parser->xmlreader_feed( (void *)downloadedData, downloadSize );
  28. *noData = false;
  29. }
  30. else
  31. *noData = true;
  32. return xmlResult;
  33. }
  34. DownloadThread::DownloadThread() : parser( 0 ), parserFactory( 0 )
  35. {
  36. parserFactory = plugin.service->service_getServiceByGuid( obj_xmlGUID );
  37. if ( parserFactory )
  38. parser = (obj_xml *)parserFactory->getInterface();
  39. if ( parser )
  40. {
  41. parser->xmlreader_setCaseSensitive();
  42. parser->xmlreader_registerCallback( L"*", &xmlDOM );
  43. parser->xmlreader_open();
  44. }
  45. }
  46. DownloadThread::~DownloadThread()
  47. {
  48. if ( parser )
  49. {
  50. parser->xmlreader_unregisterCallback( &xmlDOM );
  51. parser->xmlreader_close();
  52. }
  53. if ( parserFactory && parser )
  54. parserFactory->releaseInterface( parser );
  55. parserFactory = 0;
  56. parser = 0;
  57. }
  58. void URLToFileName( wchar_t *url )
  59. {
  60. while ( url && *url != 0 )
  61. {
  62. switch ( *url )
  63. {
  64. case ':':
  65. case '/':
  66. case '\\':
  67. case '*':
  68. case '?':
  69. case '"':
  70. case '<':
  71. case '>':
  72. case '|':
  73. *url = '_';
  74. }
  75. url++;
  76. }
  77. }
  78. #define FILE_BUFFER_SIZE 32768
  79. void DownloadThread::DownloadFile( const wchar_t *fileName )
  80. {
  81. if ( !parser )
  82. return; // no sense in continuing if there's no parser available
  83. HANDLE file = CreateFile( fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
  84. if ( file == INVALID_HANDLE_VALUE )
  85. return;
  86. while ( true )
  87. {
  88. char data[ FILE_BUFFER_SIZE ] = { 0 };
  89. DWORD bytesRead = 0;
  90. if ( ReadFile( file, data, FILE_BUFFER_SIZE, &bytesRead, NULL ) && bytesRead )
  91. {
  92. parser->xmlreader_feed( (void *)data, bytesRead );
  93. }
  94. else
  95. break;
  96. }
  97. CloseHandle( file );
  98. parser->xmlreader_feed( 0, 0 );
  99. ReadNodes( fileName );
  100. }
  101. #ifdef _DEBUG
  102. #include <iostream>
  103. void ShowAllHeaders( api_httpreceiver *http )
  104. {
  105. std::cout << "--------------------" << std::endl;
  106. const char *blah = http->getallheaders();
  107. while ( blah && *blah )
  108. {
  109. std::cout << blah << std::endl;
  110. blah += strlen( blah ) + 1;
  111. }
  112. }
  113. #else
  114. #define ShowAllHeaders(x)
  115. #endif
  116. int RunXMLDownload( api_httpreceiver *http, obj_xml *parser )
  117. {
  118. int ret;
  119. bool noData;
  120. do
  121. {
  122. Sleep( 50 );
  123. ret = http->run();
  124. if ( FeedXMLHTTP( http, parser, &noData ) != API_XML_SUCCESS )
  125. return DOWNLOAD_ERROR_PARSING_XML;
  126. } while ( ret == HTTPRECEIVER_RUN_OK );
  127. // finish off the data
  128. do
  129. {
  130. if ( FeedXMLHTTP( http, parser, &noData ) != API_XML_SUCCESS )
  131. return DOWNLOAD_ERROR_PARSING_XML;
  132. } while ( !noData );
  133. parser->xmlreader_feed( 0, 0 );
  134. if ( ret != HTTPRECEIVER_RUN_ERROR )
  135. return DOWNLOAD_SUCCESS;
  136. else
  137. return DOWNLOAD_CONNECTIONRESET;
  138. }
  139. int DownloadThread::DownloadURL( const wchar_t *url )
  140. {
  141. if ( !parser )
  142. return DOWNLOAD_NOPARSER; // no sense in continuing if there's no parser available
  143. api_httpreceiver *http = 0;
  144. waServiceFactory *sf = plugin.service->service_getServiceByGuid( httpreceiverGUID );
  145. if ( sf )
  146. http = (api_httpreceiver *)sf->getInterface();
  147. if ( !http )
  148. return DOWNLOAD_NOHTTP;
  149. http->AllowCompression();
  150. http->open( API_DNS_AUTODNS, HTTP_BUFFER_SIZE, mediaLibrary.GetProxy() );
  151. SetUserAgent( http );
  152. http->connect( AutoChar( url ) );
  153. int ret;
  154. do
  155. {
  156. Sleep( 50 );
  157. ret = http->run();
  158. if ( ret == -1 ) // connection failed
  159. break;
  160. // ---- check our reply code ----
  161. int status = http->get_status();
  162. switch ( status )
  163. {
  164. case HTTPRECEIVER_STATUS_CONNECTING:
  165. case HTTPRECEIVER_STATUS_READING_HEADERS:
  166. break;
  167. case HTTPRECEIVER_STATUS_READING_CONTENT:
  168. {
  169. ShowAllHeaders( http ); // benski> don't cut, only enabled in debug mode
  170. int downloadError;
  171. downloadError = RunXMLDownload( http, parser );
  172. if ( downloadError == DOWNLOAD_SUCCESS )
  173. ReadNodes( url );
  174. sf->releaseInterface( http );
  175. return downloadError;
  176. }
  177. break;
  178. case HTTPRECEIVER_STATUS_ERROR:
  179. default:
  180. sf->releaseInterface( http );
  181. return DOWNLOAD_404;
  182. }
  183. } while ( ret == HTTPRECEIVER_RUN_OK );
  184. const char *er = http->geterrorstr();
  185. sf->releaseInterface( http );
  186. return DOWNLOAD_404;
  187. }