1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-11 23:54:18 +00:00
JUCE/src/native/windows/juce_win32_Network.cpp
2010-03-26 18:23:54 +00:00

481 lines
16 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
// (This file gets included by juce_win32_NativeCode.cpp, rather than being
// compiled on its own).
#if JUCE_INCLUDED_FILE
#ifndef INTERNET_FLAG_NEED_FILE
#define INTERNET_FLAG_NEED_FILE 0x00000010
#endif
#ifndef INTERNET_OPTION_DISABLE_AUTODIAL
#define INTERNET_OPTION_DISABLE_AUTODIAL 70
#endif
//==============================================================================
bool juce_isOnLine()
{
DWORD connectionType;
return InternetGetConnectedState (&connectionType, 0) != 0
|| (connectionType & (INTERNET_CONNECTION_LAN | INTERNET_CONNECTION_PROXY)) != 0;
}
struct ConnectionAndRequestStruct
{
HINTERNET connection, request;
};
static HINTERNET sessionHandle = 0;
#ifndef WORKAROUND_TIMEOUT_BUG
//#define WORKAROUND_TIMEOUT_BUG 1
#endif
#if WORKAROUND_TIMEOUT_BUG
// Required because of a Microsoft bug in setting a timeout
class InternetConnectThread : public Thread
{
public:
InternetConnectThread (URL_COMPONENTS& uc_, HINTERNET& connection_, const bool isFtp_)
: Thread ("Internet"), uc (uc_), connection (connection_), isFtp (isFtp_)
{
startThread();
}
~InternetConnectThread()
{
stopThread (60000);
}
void run()
{
connection = InternetConnect (sessionHandle, uc.lpszHostName,
uc.nPort, _T(""), _T(""),
isFtp ? INTERNET_SERVICE_FTP
: INTERNET_SERVICE_HTTP,
0, 0);
notify();
}
juce_UseDebuggingNewOperator
private:
URL_COMPONENTS& uc;
HINTERNET& connection;
const bool isFtp;
InternetConnectThread (const InternetConnectThread&);
InternetConnectThread& operator= (const InternetConnectThread&);
};
#endif
void* juce_openInternetFile (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
{
if (sessionHandle == 0)
sessionHandle = InternetOpen (_T("juce"),
INTERNET_OPEN_TYPE_PRECONFIG,
0, 0, 0);
if (sessionHandle != 0)
{
// break up the url..
TCHAR file[1024], server[1024];
URL_COMPONENTS uc;
zerostruct (uc);
uc.dwStructSize = sizeof (uc);
uc.dwUrlPathLength = sizeof (file);
uc.dwHostNameLength = sizeof (server);
uc.lpszUrlPath = file;
uc.lpszHostName = server;
if (InternetCrackUrl (url, 0, 0, &uc))
{
int disable = 1;
InternetSetOption (sessionHandle, INTERNET_OPTION_DISABLE_AUTODIAL, &disable, sizeof (disable));
if (timeOutMs == 0)
timeOutMs = 30000;
else if (timeOutMs < 0)
timeOutMs = -1;
InternetSetOption (sessionHandle, INTERNET_OPTION_CONNECT_TIMEOUT, &timeOutMs, sizeof (timeOutMs));
const bool isFtp = url.startsWithIgnoreCase ("ftp:");
#if WORKAROUND_TIMEOUT_BUG
HINTERNET connection = 0;
{
InternetConnectThread connectThread (uc, connection, isFtp);
connectThread.wait (timeOutMs);
if (connection == 0)
{
InternetCloseHandle (sessionHandle);
sessionHandle = 0;
}
}
#else
HINTERNET connection = InternetConnect (sessionHandle,
uc.lpszHostName,
uc.nPort,
_T(""), _T(""),
isFtp ? INTERNET_SERVICE_FTP
: INTERNET_SERVICE_HTTP,
0, 0);
#endif
if (connection != 0)
{
if (isFtp)
{
HINTERNET request = FtpOpenFile (connection,
uc.lpszUrlPath,
GENERIC_READ,
FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_NEED_FILE,
0);
ConnectionAndRequestStruct* const result = new ConnectionAndRequestStruct();
result->connection = connection;
result->request = request;
return result;
}
else
{
const TCHAR* mimeTypes[] = { _T("*/*"), 0 };
DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE;
if (url.startsWithIgnoreCase ("https:"))
flags |= INTERNET_FLAG_SECURE; // (this flag only seems necessary if the OS is running IE6 -
// IE7 seems to automatically work out when it's https)
HINTERNET request = HttpOpenRequest (connection,
isPost ? _T("POST")
: _T("GET"),
uc.lpszUrlPath,
0, 0, mimeTypes, flags, 0);
if (request != 0)
{
INTERNET_BUFFERS buffers;
zerostruct (buffers);
buffers.dwStructSize = sizeof (INTERNET_BUFFERS);
buffers.lpcszHeader = (LPCTSTR) headers;
buffers.dwHeadersLength = headers.length();
buffers.dwBufferTotal = (DWORD) postData.getSize();
ConnectionAndRequestStruct* result = 0;
if (HttpSendRequestEx (request, &buffers, 0, HSR_INITIATE, 0))
{
int bytesSent = 0;
for (;;)
{
const int bytesToDo = jmin (1024, (int) postData.getSize() - bytesSent);
DWORD bytesDone = 0;
if (bytesToDo > 0
&& ! InternetWriteFile (request,
((const char*) postData.getData()) + bytesSent,
bytesToDo, &bytesDone))
{
break;
}
if (bytesToDo == 0 || (int) bytesDone < bytesToDo)
{
result = new ConnectionAndRequestStruct();
result->connection = connection;
result->request = request;
HttpEndRequest (request, 0, 0, 0);
return result;
}
bytesSent += bytesDone;
if (callback != 0 && ! callback (callbackContext, bytesSent, postData.getSize()))
break;
}
}
InternetCloseHandle (request);
}
InternetCloseHandle (connection);
}
}
}
}
return 0;
}
int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
{
DWORD bytesRead = 0;
const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
if (crs != 0)
InternetReadFile (crs->request,
buffer, bytesToRead,
&bytesRead);
return bytesRead;
}
int juce_seekInInternetFile (void* handle, int newPosition)
{
if (handle != 0)
{
const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
return InternetSetFilePointer (crs->request,
newPosition, 0,
FILE_BEGIN, 0);
}
else
{
return -1;
}
}
int64 juce_getInternetFileContentLength (void* handle)
{
const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
if (crs != 0)
{
DWORD index = 0;
DWORD result = 0;
DWORD size = sizeof (result);
if (HttpQueryInfo (crs->request,
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
&result,
&size,
&index))
{
return (int64) result;
}
}
return -1;
}
void juce_closeInternetFile (void* handle)
{
if (handle != 0)
{
ConnectionAndRequestStruct* const crs = (ConnectionAndRequestStruct*) handle;
InternetCloseHandle (crs->request);
InternetCloseHandle (crs->connection);
delete crs;
}
}
//==============================================================================
static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numFound = 0;
DynamicLibraryLoader dll ("iphlpapi.dll");
DynamicLibraryImport (GetAdaptersInfo, getAdaptersInfo, DWORD, dll, (PIP_ADAPTER_INFO, PULONG))
if (getAdaptersInfo != 0)
{
ULONG len = sizeof (IP_ADAPTER_INFO);
MemoryBlock mb;
PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO) mb.getData();
if (getAdaptersInfo (adapterInfo, &len) == ERROR_BUFFER_OVERFLOW)
{
mb.setSize (len);
adapterInfo = (PIP_ADAPTER_INFO) mb.getData();
}
if (getAdaptersInfo (adapterInfo, &len) == NO_ERROR)
{
PIP_ADAPTER_INFO adapter = adapterInfo;
while (adapter != 0)
{
int64 mac = 0;
for (unsigned int i = 0; i < adapter->AddressLength; ++i)
mac = (mac << 8) | adapter->Address[i];
if (littleEndian)
mac = (int64) ByteOrder::swap ((uint64) mac);
if (numFound < maxNum && mac != 0)
addresses [numFound++] = mac;
adapter = adapter->Next;
}
}
}
return numFound;
}
struct ASTAT
{
ADAPTER_STATUS adapt;
NAME_BUFFER NameBuff [30];
};
static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numFound = 0;
DynamicLibraryLoader dll ("netapi32.dll");
DynamicLibraryImport (Netbios, NetbiosCall, UCHAR, dll, (PNCB))
if (NetbiosCall != 0)
{
NCB ncb;
zerostruct (ncb);
ASTAT astat;
zerostruct (astat);
LANA_ENUM enums;
zerostruct (enums);
ncb.ncb_command = NCBENUM;
ncb.ncb_buffer = (unsigned char*) &enums;
ncb.ncb_length = sizeof (LANA_ENUM);
NetbiosCall (&ncb);
for (int i = 0; i < enums.length; ++i)
{
zerostruct (ncb);
ncb.ncb_command = NCBRESET;
ncb.ncb_lana_num = enums.lana[i];
if (NetbiosCall (&ncb) == 0)
{
zerostruct (ncb);
memcpy (ncb.ncb_callname, "* ", NCBNAMSZ);
ncb.ncb_command = NCBASTAT;
ncb.ncb_lana_num = enums.lana[i];
ncb.ncb_buffer = (unsigned char*) &astat;
ncb.ncb_length = sizeof (ASTAT);
if (NetbiosCall (&ncb) == 0)
{
if (astat.adapt.adapter_type == 0xfe)
{
uint64 mac = 0;
for (int i = 6; --i >= 0;)
mac = (mac << 8) | astat.adapt.adapter_address [littleEndian ? i : (5 - i)];
if (numFound < maxNum && mac != 0)
addresses [numFound++] = mac;
}
}
}
}
}
return numFound;
}
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian)
{
int numFound = getMACAddressViaGetAdaptersInfo (addresses, maxNum, littleEndian);
if (numFound == 0)
numFound = getMACAddressesViaNetBios (addresses, maxNum, littleEndian);
return numFound;
}
//==============================================================================
typedef ULONG (WINAPI *MAPISendMailType) (LHANDLE, ULONG, lpMapiMessage, ::FLAGS, ULONG);
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
HMODULE h = LoadLibraryA ("MAPI32.dll");
MAPISendMailType mapiSendMail = (MAPISendMailType) GetProcAddress (h, "MAPISendMail");
bool ok = false;
if (mapiSendMail != 0)
{
MapiMessage message;
zerostruct (message);
message.lpszSubject = (LPSTR) emailSubject.toCString();
message.lpszNoteText = (LPSTR) bodyText.toCString();
MapiRecipDesc recip;
zerostruct (recip);
recip.ulRecipClass = MAPI_TO;
String targetEmailAddress_ (targetEmailAddress);
if (targetEmailAddress_.isEmpty())
targetEmailAddress_ = " "; // (Windows Mail can't deal with a blank address)
recip.lpszName = (LPSTR) targetEmailAddress_.toCString();
message.nRecipCount = 1;
message.lpRecips = &recip;
MemoryBlock mb (sizeof (MapiFileDesc) * filesToAttach.size());
mb.fillWith (0);
MapiFileDesc* files = (MapiFileDesc*) mb.getData();
message.nFileCount = filesToAttach.size();
message.lpFiles = files;
for (int i = 0; i < filesToAttach.size(); ++i)
{
files[i].nPosition = (ULONG) -1;
files[i].lpszPathName = (LPSTR) filesToAttach[i].toCString();
}
ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS);
}
FreeLibrary (h);
return ok;
}
#endif