winamp/Src/Winamp/HTTPRetrieveFile.cpp
2024-09-24 14:54:57 +02:00

305 lines
6.5 KiB
C++

/** (c) Nullsoft, Inc. C O N F I D E N T I A L
** Filename:
** Project:
** Description:
** Author: Ben Allison benski@nullsoft.com
** Created:
**/
#include "Main.h"
#include "api.h"
#include "..\Components\wac_network\wac_network_http_receiver_api.h"
#include "api/service/waServiceFactory.h"
void GetMIMEType(const char *url, char *mimeType, int mimeTypeCch)
{
api_httpreceiver *http = 0;
waServiceFactory *sf = 0;
if (WASABI_API_SVC)
{
sf = WASABI_API_SVC->service_getServiceByGuid(httpreceiverGUID);
if (sf)
http = (api_httpreceiver *)sf->getInterface();
}
if (!http)
return ;
int ret;
http->open(API_DNS_AUTODNS, 2048, config_proxy);
http->connect(url, 0, "HEAD");
do
{
Sleep(10);
ret = http->run();
if (ret == -1) // connection failed
break;
// ---- check our reply code ----
int replycode = http->getreplycode();
switch (replycode)
{
case 0:
case 100:
break;
case 200:
{
const char *contentType = http->getheader("Content-Type");
if (contentType)
lstrcpynA(mimeType, contentType, mimeTypeCch);
else
mimeType[0] = 0;
sf->releaseInterface(http);
return ;
}
break;
default:
sf->releaseInterface(http);
return ;
}
}
while (ret == HTTPRECEIVER_RUN_OK);
sf->releaseInterface(http);
}
#if 0
#define WM_HRF_READINGHTTP WM_USER
#define WM_HRF_DOWNLOADING (WM_USER+1)
struct RFData
{
public:
char *url, *file;
HWND hwnd;
};
bool killswitch;
static DWORD WINAPI rf_ThreadProc(void *p)
{
RFData *rfData = (RFData *)p;
char *url = rfData->url, *file = rfData->file;
waServiceFactory *sf = 0;
api_httpreceiver *http = 0;
if (WASABI_API_SVC)
{
sf = WASABI_API_SVC->service_getServiceByGuid(httpreceiverGUID);
if (sf)
http = (api_httpreceiver *)sf->getInterface();
}
if (!http)
return 1;
HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
sf->releaseInterface(http);
return 1;
}
http->Open(API_DNS_AUTODNS, 16384);
http->AddHeader("User-Agent: Winamp/" APP_VERSION);
http->Connect(url);
int ret;
do
{
Sleep(50);
http->Run();
ret = http->GetStatus();
if (ret == HTTPRECEIVER_STATUS_ERROR)
killswitch = true;
if (killswitch)
break;
}
while (ret == HTTPRECEIVER_STATUS_CONNECTING);
if (ret == HTTPRECEIVER_STATUS_READING_HEADERS || ret == HTTPRECEIVER_STATUS_READING_CONTENT)
{
PostMessageW(rfData->hwnd, WM_HRF_READINGHTTP, 0, 0);
int replycode = http->GetReplyCode();
switch (replycode)
{
case 0: case 100: // shouldn't really get here
break;
case 200:
break;
default:
killswitch = true;
break;
}
}
bool error = false;
char block[16384] = {0};
size_t downloadSize;
size_t currentSize = 0, totalSize = 0;
do
{
if (killswitch)
{
error = true;
break;
}
// ---- Pause a bit and then run the http downloader ----
Sleep(50);
ret = http->Run();
if (ret == -1) // connection failed
{
error = true;
break;
}
// ---- download ----
downloadSize = http->GetBytesAvailable();
if (downloadSize)
{
totalSize = http->GetContentLength();
downloadSize = http->GetBytes(block, downloadSize);
currentSize += downloadSize;
PostMessageW(rfData->hwnd, WM_HRF_DOWNLOADING, currentSize, totalSize);
// ---- write to disk ----
if (downloadSize) // WriteFile doesn't like 0 byte writes
{
DWORD numWritten = 0;
WriteFile(hFile, block, downloadSize, &numWritten, FALSE);
if (numWritten != downloadSize) // make sure that the block was actually written
{
error = true;
break; // failed writing
}
}
}
}
while (ret != 1 || downloadSize); // http may be closed, but make sure we get all the data.
CloseHandle(hFile);
if (error)
DeleteFile(file);
sf->releaseInterface(http);
return 0;
}
static LRESULT CALLBACK rf_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
SetDlgItemText(hwndDlg, IDC_STATUS, getString(IDS_HTTP_INIT,NULL,0));
return FALSE;
case WM_HRF_READINGHTTP:
SetDlgItemText(hwndDlg, IDC_STATUS, getString(IDS_HTTP_READ_REQUEST,NULL,0));
return TRUE;
case WM_HRF_DOWNLOADING:
{
char temp[128] = {0};
if (!lParam)
StringCchPrintf(temp, 128, getString(IDS_HTTP_RET_FILE,NULL,0), wParam);
else
StringCchPrintf(temp, 128, getString(IDS_HTTP_RET_FILE_PERCENT,NULL,0), (100*wParam) / lParam, wParam, lParam);
SetDlgItemText(hwndDlg, IDC_STATUS, temp);
}
return TRUE;
case WM_DESTROY:
if (GetParent(hwndDlg) == hMainWindow)
{
if (hMainWindow) EnableWindow(hMainWindow, 1);
if (hPLWindow) EnableWindow(hPLWindow, 1);
if (hEQWindow) EnableWindow(hEQWindow, 1);
//if (hMBWindow) EnableWindow(hMBWindow,1);
}
else
EnableWindow(GetParent(hwndDlg), 1);
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
DestroyWindow(hwndDlg);
return 0;
}
return 0;
}
return 0;
}
int httpRetrieveFile(HWND hwnd, char *url, char *file, char *dlgtitle)
{
killswitch = false;
RECT r;
HANDLE hThread = 0;
if (!hwnd) hwnd = hMainWindow;
if (hwnd == hMainWindow && g_dialog_box_parent) hwnd = g_dialog_box_parent;
GetWindowRect(hwnd, &r);
HWND dlgWnd = LPCreateDialog(IDD_HTTPGET, hwnd, rf_DlgProc);
SetWindowText(dlgWnd, dlgtitle);
SetDlgItemText(dlgWnd, IDC_URL, url);
RFData data = {url, file, dlgWnd};
DWORD id;
hThread = CreateThread(NULL, 0, rf_ThreadProc, (void *) & data, CREATE_SUSPENDED, &id);
if (NULL)
return 1;
ResumeThread(hThread);
if (r.bottom > GetSystemMetrics(SM_CXSCREEN) / 2 && r.bottom - r.top < 100)
{
RECT r2;
GetWindowRect(dlgWnd, &r2);
r.top = r.bottom - (r2.bottom - r2.top);
}
SetWindowPos(dlgWnd, NULL, r.left, r.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
if (GetForegroundWindow() == hwnd)
ShowWindow(dlgWnd, SW_SHOW);
else
ShowWindow(dlgWnd, SW_SHOWNA);
if (hwnd == hMainWindow)
{
if (hMainWindow) EnableWindow(hMainWindow, 0);
if (hPLWindow) EnableWindow(hPLWindow, 0);
if (hEQWindow) EnableWindow(hEQWindow, 0);
//if (hMBWindow) EnableWindow(hMBWindow,0);
}
else
EnableWindow(hwnd, 0);
while (1)
{
MSG msg;
if (!IsWindow(dlgWnd))
{
killswitch = true;
break;
}
if (WaitForSingleObject(hThread, 0) == WAIT_OBJECT_0)
{
DestroyWindow(dlgWnd);
break;
}
GetMessage(&msg, NULL, 0, 0);
DispatchMessage(&msg);
}
WaitForSingleObject(hThread, 5000);
DWORD exitCode;
if (GetExitCodeThread(hThread, &exitCode))
return exitCode;
else
{
// CUT: TerminateThread(hThread, 0);
return 1;
}
}
#endif