123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- #include "main.h"
- #include "api.h"
- #include "resource.h"
- #include "../xml/obj_xml.h"
- #include "nu/AutoChar.h"
- #include "../nu/AutoUrl.h"
- #include "../nu/AutoHeader.h"
- #include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
- #include "../agave/albumart/svc_albumartprovider.h"
- #include <api/service/waservicefactory.h>
- #include <shlwapi.h>
- #include <strsafe.h>
- static const GUID internetConfigGroupGUID =
- {
- 0xc0a565dc, 0xcfe, 0x405a, { 0xa2, 0x7c, 0x46, 0x8b, 0xc, 0x8a, 0x3a, 0x5c }
- };
- #define USER_AGENT_SIZE (10 /*User-Agent*/ + 2 /*: */ + 6 /*Winamp*/ + 1 /*/*/ + 1 /*5*/ + 3/*.21*/ + 1 /*Null*/)
- static void SetUserAgent(api_httpreceiver *http)
- {
- char user_agent[USER_AGENT_SIZE] = {0};
- int bigVer = ((winampVersion & 0x0000FF00) >> 12);
- int smallVer = ((winampVersion & 0x000000FF));
- StringCchPrintfA(user_agent, USER_AGENT_SIZE, "User-Agent: Winamp/%01x.%02x", bigVer, smallVer);
- http->addheader(user_agent);
- }
- #define HTTP_BUFFER_SIZE 8192
- #define POST_BUFFER_SIZE (128*1024)
- int PostFile(const char *base_url, const wchar_t *filename, const itemRecordW *track, obj_xml *parser, int *killswitch,
- void (*callback)(void *callbackContext, wchar_t *status), void *context, char *new_item_id, size_t new_item_id_len)
- {
- //if (!parser)
- // return 1;
- bool first=true;
- char url[2048] = {0};
- char *p_url=url;
- size_t url_cch=sizeof(url)/sizeof(*url);
- FILE *f = _wfopen(filename, L"rb");
- if (!f)
- return 1;
- api_httpreceiver *http = 0;
- waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
- if (sf)
- http = (api_httpreceiver *)sf->getInterface();
- if (!http)
- return 1;
- int use_proxy = 1;
- bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
- if (proxy80 && strstr(url, ":") && (!strstr(url, ":80/") && strstr(url, ":80") != (url + strlen(url) - 3)))
- use_proxy = 0;
- const wchar_t *proxy = use_proxy?AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0):0;
- fseek(f, 0, SEEK_END);
-
- size_t clen = ftell(f);
- size_t transferred=0;
- size_t total_clen = clen;
- fseek(f, 0, SEEK_SET);
- http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, (proxy && proxy[0]) ? (const char *)AutoChar(proxy) : NULL);
- http->set_sendbufsize(POST_BUFFER_SIZE);
- SetUserAgent(http);
- char data[POST_BUFFER_SIZE] = {0};
- StringCbCopyExA(p_url, url_cch, base_url, &p_url, &url_cch, 0);
-
- StringCbPrintfA(data, sizeof(data), "Content-Length: %u", clen);
- http->addheader(data);
- // http->addheader("Content-Type: application/octet-stream");
- /* send metadata */
- if (track->artist && track->artist[0])
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?artist=%s", AutoUrl(track->artist));
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&artist=%s", AutoUrl(track->artist));
- first=false;
- }
- if (track->title && track->title[0])
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?title=%s", AutoUrl(track->title));
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&title=%s", AutoUrl(track->title));
- first=false;
- }
- if (track->album && track->album[0])
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?album=%s", AutoUrl(track->album));
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&album=%s", AutoUrl(track->album));
- first=false;
- }
- if (track->composer && track->composer[0])
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?composer=%s", AutoUrl(track->composer));
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&composer=%s", AutoUrl(track->composer));
- first=false;
- }
- if (track->albumartist && track->albumartist[0])
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?albumartist=%s", AutoUrl(track->albumartist));
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&albumartist=%s", AutoUrl(track->albumartist));
- first=false;
- }
- if (track->genre && track->genre[0])
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?genre=%s", AutoUrl(track->genre));
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&genre=%s", AutoUrl(track->genre));
- first=false;
- }
- if (track->track > 0)
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?track=%d", track->track);
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&track=%d", track->track);
- first=false;
- }
- const wchar_t *ext = PathFindExtension(filename);
- if (ext && ext[0])
- {
- if (ext[0] == '.') ext++;
- if (ext[0])
- {
- if (first)
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?extension=%s", AutoUrl(ext));
- else
- StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&extension=%s", AutoUrl(ext));
- first=false;
- }
- }
- wchar_t mime_type[128] = {0};
- if (AGAVE_API_METADATA->GetExtendedFileInfo(filename, L"mime", mime_type, 128) == 1 && mime_type[0])
- {
- http->AddHeaderValue("Content-Type", AutoHeader(mime_type));
- }
- http->AddHeaderValue("X-Winamp-ID", winamp_id_str);
- http->AddHeaderValue("X-Winamp-Name", winamp_name);
- http->AddHeaderValue("Expect", "100-continue");
- /* connect */
- callback(context, WASABI_API_LNGSTRINGW(IDS_CONNECTING));
- http->connect(url, 0, "POST");
- // spin and wait for a 100 response
- for (;;)
- {
- Sleep(55);
- if (*killswitch)
- goto connection_failed;
- int ret = http->run();
- if (ret != HTTPRECEIVER_RUN_OK) // connection failed or closed
- goto connection_failed;
- int reply_code = http->getreplycode();
- if (reply_code == 100)
- break;
- else if (reply_code)
- goto connection_failed;
- }
-
- /* POST the data */
- api_connection *connection = http->GetConnection();
- if (connection)
- {
- if (http->run() == -1)
- goto connection_failed;
- while (clen)
- {
- int percent = MulDiv(100, (int)transferred, (int)total_clen);
- wchar_t msg[128] = {0};
- StringCbPrintfW(msg, sizeof(msg), WASABI_API_LNGSTRINGW(IDS_UPLOADING), percent);
- callback(context, msg);
- if (*killswitch)
- goto connection_failed;
- if (http->run() == -1)
- goto connection_failed;
- int connection_state = connection->get_state();
- if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
- goto connection_failed;
- size_t lengthToSend = min(clen, connection->GetSendBytesAvailable());
- lengthToSend = min(lengthToSend, sizeof(data));
- if (lengthToSend)
- {
- int bytes_read = (int)fread(data, 1, lengthToSend, f);
- connection->send(data, bytes_read);
- clen-=bytes_read;
- transferred+=bytes_read;
- }
- else
- {
- Sleep(10);
- }
- }
- int x;
- while (x = (int)connection->GetSendBytesInQueue())
- {
- int connection_state = connection->get_state();
- if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
- goto connection_failed;
- Sleep(10);
- if (*killswitch)
- goto connection_failed;
- if (http->run() == -1)
- goto connection_failed;
- }
- }
- fclose(f);
- f=0;
- /* retrieve reply */
- int ret;
- do
- {
- Sleep(55);
- ret = http->run();
- if (ret == -1) // connection failed
- break;
- // ---- check our reply code ----
- int status = http->get_status();
- switch (status)
- {
- case HTTPRECEIVER_STATUS_CONNECTING:
- case HTTPRECEIVER_STATUS_READING_HEADERS:
- break;
- case HTTPRECEIVER_STATUS_READING_CONTENT:
- {
- const char *location = http->getheader("Location");
- if (location)
- StringCchCopyA(new_item_id, new_item_id_len, location);
- else
- new_item_id[0]=0;
- sf->releaseInterface(http);
- return 0;
- }
- break;
- case HTTPRECEIVER_STATUS_ERROR:
- default:
- sf->releaseInterface(http);
- return 1;
- }
- }
- while (ret == HTTPRECEIVER_RUN_OK);
- connection_failed:
- if (f)
- fclose(f);
- sf->releaseInterface(http);
- return 1;
- }
- int PostAlbumArt(const char *url, const itemRecordW *track, obj_xml *parser, int *killswitch, void (*callback)(void *callbackContext, wchar_t *status), void *context)
- {
- void *artData=0;
- size_t datalen=0;
- wchar_t *mimeType=0;
- if (AGAVE_API_ALBUMART->GetAlbumArtData(track->filename, L"cover", &artData, &datalen, &mimeType) != ALBUMART_SUCCESS)
- return 1;
- api_httpreceiver *http = 0;
- waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
- if (sf)
- http = (api_httpreceiver *)sf->getInterface();
- if (!http)
- return 1;
- int use_proxy = 1;
- bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
- if (proxy80 && strstr(url, ":") && (!strstr(url, ":80/") && strstr(url, ":80") != (url + strlen(url) - 3)))
- use_proxy = 0;
- const wchar_t *proxy = use_proxy?AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0):0;
- uint8_t *artDataPtr=(uint8_t *)artData;
- size_t clen = datalen;
- size_t transferred=0;
- size_t total_clen = datalen;
- http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, (proxy && proxy[0]) ? (const char *)AutoChar(proxy) : NULL);
- http->set_sendbufsize(POST_BUFFER_SIZE);
- SetUserAgent(http);
- char data[POST_BUFFER_SIZE] = {0};
-
- StringCbPrintfA(data, sizeof(data), "Content-Length: %u", datalen);
- http->addheader(data);
- if (mimeType)
- {
- StringCbPrintfA(data, sizeof(data), "Content-Type: %s", AutoHeader(mimeType));
- http->addheader(data);
- }
- http->AddHeaderValue("X-Winamp-ID", winamp_id_str);
- http->AddHeaderValue("X-Winamp-Name", winamp_name);
- /* connect */
- http->AddHeaderValue("Expect", "100-continue");
- callback(context, WASABI_API_LNGSTRINGW(IDS_CONNECTING));
- http->connect(url, 0, "POST");
-
- // spin and wait for a 100 response
- for (;;)
- {
- Sleep(55);
- int ret = http->run();
- if (ret != HTTPRECEIVER_RUN_OK) // connection failed or closed
- goto connection_failed;
- if (*killswitch)
- goto connection_failed;
- int reply_code = http->getreplycode();
- if (reply_code == 100)
- break;
- else if (reply_code)
- goto connection_failed;
- }
- /* POST the data */
- api_connection *connection = http->GetConnection();
- if (connection)
- {
- if (http->run() == -1)
- goto connection_failed;
- while (clen)
- {
- int percent = MulDiv(100, (int)transferred, (int)total_clen);
- wchar_t msg[128] = {0};
- StringCbPrintfW(msg, sizeof(msg), L"Uploading Album Art (%d%%)", percent);
- callback(context, msg);
- if (*killswitch)
- goto connection_failed;
- if (http->run() == -1)
- goto connection_failed;
- int connection_state = connection->get_state();
- if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
- goto connection_failed;
- size_t lengthToSend = min(clen, connection->GetSendBytesAvailable());
- if (lengthToSend)
- {
- connection->send(artDataPtr, (int)lengthToSend);
- artDataPtr += lengthToSend;
- clen-=lengthToSend;
- transferred+=lengthToSend;
- }
- else
- {
- Sleep(10);
- }
- }
- int x;
- while (x = (int)connection->GetSendBytesInQueue())
- {
- int connection_state = connection->get_state();
- if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
- goto connection_failed;
- Sleep(10);
- if (*killswitch)
- goto connection_failed;
- if (http->run() == -1)
- goto connection_failed;
- }
- }
- /* retrieve reply */
- int ret;
- do
- {
- Sleep(55);
- ret = http->run();
- if (ret == -1) // connection failed
- break;
- // ---- check our reply code ----
- int status = http->get_status();
- switch (status)
- {
- case HTTPRECEIVER_STATUS_CONNECTING:
- case HTTPRECEIVER_STATUS_READING_HEADERS:
- break;
- case HTTPRECEIVER_STATUS_READING_CONTENT:
- {
- sf->releaseInterface(http);
- WASABI_API_MEMMGR->sysFree(artData);
- WASABI_API_MEMMGR->sysFree(mimeType);
- return 0;
- }
- break;
- case HTTPRECEIVER_STATUS_ERROR:
- default:
- sf->releaseInterface(http);
- WASABI_API_MEMMGR->sysFree(artData);
- WASABI_API_MEMMGR->sysFree(mimeType);
- return 1;
- }
- }
- while (ret == HTTPRECEIVER_RUN_OK);
- connection_failed:
- WASABI_API_MEMMGR->sysFree(artData);
- WASABI_API_MEMMGR->sysFree(mimeType);
- sf->releaseInterface(http);
- return 1;
- }
- int HTTP_Delete(const char *url)
- {
- api_httpreceiver *http = 0;
- waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
- if (sf)
- http = (api_httpreceiver *)sf->getInterface();
- if (!http)
- return 1;
- int use_proxy = 1;
- bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
- if (proxy80 && strstr(url, ":") && (!strstr(url, ":80/") && strstr(url, ":80") != (url + strlen(url) - 3)))
- use_proxy = 0;
- const wchar_t *proxy = use_proxy?AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0):0;
- http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, (proxy && proxy[0]) ? (const char *)AutoChar(proxy) : NULL);
- SetUserAgent(http);
- http->AddHeaderValue("X-Winamp-ID", winamp_id_str);
- http->AddHeaderValue("X-Winamp-Name", winamp_name);
- /* connect */
- http->connect(url, 0, "DELETE");
-
- /* retrieve reply */
- int ret;
- do
- {
- Sleep(55);
- ret = http->run();
- if (ret == -1) // connection failed
- break;
- // ---- check our reply code ----
- int status = http->get_status();
- switch (status)
- {
- case HTTPRECEIVER_STATUS_CONNECTING:
- case HTTPRECEIVER_STATUS_READING_HEADERS:
- break;
- case HTTPRECEIVER_STATUS_READING_CONTENT:
- {
- sf->releaseInterface(http);
- return 0;
- }
- break;
- case HTTPRECEIVER_STATUS_ERROR:
- default:
- sf->releaseInterface(http);
- return 1;
- }
- }
- while (ret == HTTPRECEIVER_RUN_OK);
- sf->releaseInterface(http);
- return 1;
- }
|