diff --git a/build/macosx/platform_specific_code/juce_mac_Network.mm b/build/macosx/platform_specific_code/juce_mac_Network.mm index de8df6d60b..dd0f3ab528 100644 --- a/build/macosx/platform_specific_code/juce_mac_Network.mm +++ b/build/macosx/platform_specific_code/juce_mac_Network.mm @@ -1,189 +1,446 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-7 by Raw Material Software ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the - GNU General Public License, as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - 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. - - You should have received a copy of the GNU General Public License - along with JUCE; if not, visit www.gnu.org/licenses or write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - ------------------------------------------------------------------------------ - - If you'd like to release a closed-source product which uses JUCE, commercial - licenses are also available: visit www.rawmaterialsoftware.com/juce for - more information. - - ============================================================================== -*/ - -#include "juce_mac_NativeHeaders.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -BEGIN_JUCE_NAMESPACE - -#include "../../../src/juce_core/text/juce_String.h" -#include "../../../src/juce_core/basics/juce_Time.h" -#include "../../../src/juce_core/basics/juce_SystemStats.h" -#include "../../../src/juce_core/threads/juce_ScopedLock.h" -#include "../../../src/juce_core/threads/juce_WaitableEvent.h" -#include "../../../src/juce_core/threads/juce_Thread.h" -#include "../../../src/juce_core/containers/juce_MemoryBlock.h" -#include "../../../src/juce_core/text/juce_StringArray.h" -#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" -#include "../../../src/juce_core/io/network/juce_URL.h" - -#include "juce_mac_HTTPStream.h" - -//============================================================================== -static bool GetEthernetIterator (io_iterator_t* matchingServices) throw() -{ - mach_port_t masterPort; - - if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS) - { - CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass); - - if (dict != 0) - { - CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - if (propDict != 0) - { - CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue); - - CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict); - CFRelease (propDict); - } - } - - return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS; - } - - return false; -} - -int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() -{ - int numResults = 0; - io_iterator_t it; - - if (GetEthernetIterator (&it)) - { - io_object_t i; - - while ((i = IOIteratorNext (it)) != 0) - { - io_object_t controller; - - if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS) - { - CFTypeRef data = IORegistryEntryCreateCFProperty (controller, - CFSTR (kIOMACAddress), - kCFAllocatorDefault, - 0); - if (data != 0) - { - UInt8 addr [kIOEthernetAddressSize]; - zeromem (addr, sizeof (addr)); - - CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr); - CFRelease (data); - - int64 a = 0; - for (int i = 6; --i >= 0;) - a = (a << 8) | addr[i]; - - if (! littleEndian) - a = (int64) swapByteOrder ((uint64) a); - - if (numResults < maxNum) - { - *addresses++ = a; - ++numResults; - } - } - - IOObjectRelease (controller); - } - - IOObjectRelease (i); - } - - IOObjectRelease (it); - } - - return numResults; -} - -//============================================================================== -bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, - const String& emailSubject, - const String& bodyText, - const StringArray& filesToAttach) -{ - const AutoPool pool; - - String script; - script << "tell application \"Mail\"\r\n" - "set newMessage to make new outgoing message with properties {subject:\"" - << emailSubject.replace (T("\""), T("\\\"")) - << "\", content:\"" - << bodyText.replace (T("\""), T("\\\"")) - << "\" & return & return}\r\n" - "tell newMessage\r\n" - "set visible to true\r\n" - "set sender to \"sdfsdfsdfewf\"\r\n" - "make new to recipient at end of to recipients with properties {address:\"" - << targetEmailAddress - << "\"}\r\n"; - - for (int i = 0; i < filesToAttach.size(); ++i) - { - script << "tell content\r\n" - "make new attachment with properties {file name:\"" - << filesToAttach[i].replace (T("\""), T("\\\"")) - << "\"} at after the last paragraph\r\n" - "end tell\r\n"; - } - - script << "end tell\r\n" - "end tell\r\n"; - - NSAppleScript* s = [[NSAppleScript alloc] - initWithSource: [NSString stringWithUTF8String: (const char*) script.toUTF8()]]; - NSDictionary* error = 0; - const bool ok = [s executeAndReturnError: &error] != nil; - [s release]; - - return ok; -} - - -END_JUCE_NAMESPACE +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "juce_mac_NativeHeaders.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +BEGIN_JUCE_NAMESPACE + +#include "../../../src/juce_core/text/juce_String.h" +#include "../../../src/juce_core/basics/juce_Time.h" +#include "../../../src/juce_core/basics/juce_SystemStats.h" +#include "../../../src/juce_core/basics/juce_Logger.h" +#include "../../../src/juce_core/threads/juce_ScopedLock.h" +#include "../../../src/juce_core/threads/juce_WaitableEvent.h" +#include "../../../src/juce_core/threads/juce_Thread.h" +#include "../../../src/juce_core/containers/juce_MemoryBlock.h" +#include "../../../src/juce_core/text/juce_StringArray.h" +#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" +#include "../../../src/juce_core/io/network/juce_URL.h" + +//#include "juce_mac_HTTPStream.h" + +//============================================================================== +static bool GetEthernetIterator (io_iterator_t* matchingServices) throw() +{ + mach_port_t masterPort; + + if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS) + { + CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass); + + if (dict != 0) + { + CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (propDict != 0) + { + CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue); + + CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict); + CFRelease (propDict); + } + } + + return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS; + } + + return false; +} + +int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() +{ + int numResults = 0; + io_iterator_t it; + + if (GetEthernetIterator (&it)) + { + io_object_t i; + + while ((i = IOIteratorNext (it)) != 0) + { + io_object_t controller; + + if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS) + { + CFTypeRef data = IORegistryEntryCreateCFProperty (controller, + CFSTR (kIOMACAddress), + kCFAllocatorDefault, + 0); + if (data != 0) + { + UInt8 addr [kIOEthernetAddressSize]; + zeromem (addr, sizeof (addr)); + + CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr); + CFRelease (data); + + int64 a = 0; + for (int i = 6; --i >= 0;) + a = (a << 8) | addr[i]; + + if (! littleEndian) + a = (int64) swapByteOrder ((uint64) a); + + if (numResults < maxNum) + { + *addresses++ = a; + ++numResults; + } + } + + IOObjectRelease (controller); + } + + IOObjectRelease (i); + } + + IOObjectRelease (it); + } + + return numResults; +} + +//============================================================================== +bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, + const String& emailSubject, + const String& bodyText, + const StringArray& filesToAttach) +{ + const AutoPool pool; + + String script; + script << "tell application \"Mail\"\r\n" + "set newMessage to make new outgoing message with properties {subject:\"" + << emailSubject.replace (T("\""), T("\\\"")) + << "\", content:\"" + << bodyText.replace (T("\""), T("\\\"")) + << "\" & return & return}\r\n" + "tell newMessage\r\n" + "set visible to true\r\n" + "set sender to \"sdfsdfsdfewf\"\r\n" + "make new to recipient at end of to recipients with properties {address:\"" + << targetEmailAddress + << "\"}\r\n"; + + for (int i = 0; i < filesToAttach.size(); ++i) + { + script << "tell content\r\n" + "make new attachment with properties {file name:\"" + << filesToAttach[i].replace (T("\""), T("\\\"")) + << "\"} at after the last paragraph\r\n" + "end tell\r\n"; + } + + script << "end tell\r\n" + "end tell\r\n"; + + NSAppleScript* s = [[NSAppleScript alloc] + initWithSource: [NSString stringWithUTF8String: (const char*) script.toUTF8()]]; + NSDictionary* error = 0; + const bool ok = [s executeAndReturnError: &error] != nil; + [s release]; + + return ok; +} + +//============================================================================== +END_JUCE_NAMESPACE + +using namespace JUCE_NAMESPACE; + +@interface JuceURLConnection : NSInputStream +{ + NSURLConnection* connection; + NSMutableData* data; + NSThread* runLoopThread; + NSRunLoop* runLoop; + bool initialised, hasFailed, hasFinished; + int position; + NSLock* dataLock; +} + +- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req; +- (void) dealloc; +- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response; +- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error; +- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data; +- (void) connectionDidFinishLoading: (NSURLConnection*) connection; + +- (BOOL) isOpen; +- (int) read: (char*) dest numBytes: (int) num; +- (int) readPosition; + +- (void) runThread: (id) dummyParam; + +@end + +@implementation JuceURLConnection + +- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req +{ + [super init]; + data = [[NSMutableData data] retain]; + dataLock = [[NSLock alloc] init]; + connection = 0; + initialised = false; + hasFailed = false; + hasFinished = false; + + runLoopThread = [[NSThread alloc] initWithTarget: self + selector: @selector (runThread:) + object: req]; + + [runLoopThread start]; + + while (! [runLoopThread isExecuting]) + Thread::sleep (1); + + while ([runLoopThread isExecuting] && ! initialised) + Thread::sleep (1); + + return self; +} + +- (void) dealloc +{ + [connection cancel]; + [runLoopThread cancel]; + + while ([runLoopThread isExecuting]) + [NSThread sleepForTimeInterval: 0.001]; + + [runLoopThread release]; + [connection release]; + [data release]; + [dataLock release]; + [super dealloc]; +} + +- (void) runThread: (id) request +{ + AutoPool pool; + + runLoop = [NSRunLoop currentRunLoop]; + + connection = [[NSURLConnection alloc] initWithRequest: request + delegate: self + startImmediately: YES]; + + if (connection == nil) + { + hasFailed = true; + return; + } + + initialised = true; + + while (! ([[NSThread currentThread] isCancelled] || hasFailed || hasFinished)) + { + [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; + } +} + +- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response +{ + [dataLock lock]; + [data setLength: 0]; + [dataLock unlock]; +} + +- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error +{ + NSLog ([error description]); + hasFailed = true; +} + +- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData +{ + [dataLock lock]; + [data appendData: newData]; + [dataLock unlock]; +} + +- (void) connectionDidFinishLoading: (NSURLConnection*) connection +{ + hasFinished = true; +} + +- (BOOL) isOpen +{ + return connection != 0 && ! hasFailed; +} + +- (int) readPosition +{ + return position; +} + +- (int) read: (char*) dest numBytes: (int) numNeeded +{ + int numDone = 0; + + while (numNeeded > 0) + { + int available = jmin (numNeeded, [data length]); + + if (available > 0) + { + [dataLock lock]; + [data getBytes: dest length: available]; + [data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0]; + [dataLock unlock]; + + numDone += available; + numNeeded -= available; + dest += available; + } + else + { + if (hasFailed || hasFinished) + break; + + Thread::sleep (1); + } + } + + position += numDone; + return numDone; +} + +@end +BEGIN_JUCE_NAMESPACE + + +bool juce_isOnLine() +{ + return true; +} + +void* juce_openInternetFile (const String& url, + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext, + int timeOutMs) +{ + AutoPool pool; + + NSMutableURLRequest* req = [NSMutableURLRequest + requestWithURL: [NSURL URLWithString: juceStringToNS (url)] + cachePolicy: NSURLRequestUseProtocolCachePolicy + timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)]; + + if (req == nil) + return 0; + + [req setHTTPMethod: isPost ? @"POST" : @"GET"]; + //[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData]; + + StringArray headerLines; + headerLines.addLines (headers); + headerLines.removeEmptyStrings (true); + + for (int i = 0; i < headerLines.size(); ++i) + { + const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); + const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); + + if (key.isNotEmpty() && value.isNotEmpty()) + [req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)]; + } + + if (isPost && postData.getSize() > 0) + { + [req setHTTPBody: [NSData dataWithBytes: postData.getData() + length: postData.getSize()]]; + } + + JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req]; + + if ([s isOpen]) + return s; + + delete s; + return 0; +} + +void juce_closeInternetFile (void* handle) +{ + JuceURLConnection* const s = (JuceURLConnection*) handle; + + if (s != 0) + { + AutoPool pool; + [s release]; + } +} + +int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) +{ + JuceURLConnection* const s = (JuceURLConnection*) handle; + + if (s != 0) + { + AutoPool pool; + return [s read: (char*) buffer numBytes: bytesToRead]; + } + + return 0; +} + +int juce_seekInInternetFile (void* handle, int newPosition) +{ + JuceURLConnection* const s = (JuceURLConnection*) handle; + + if (s != 0) + return [s readPosition]; + + return 0; +} + + +END_JUCE_NAMESPACE