diff --git a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm index 20549b9ddf..965dd86ced 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm @@ -1219,8 +1219,13 @@ private: aren't so careful) */ jassert (Component::getCurrentlyModalComponent() == nullptr); - if (windowComp != nullptr && windowComp->getChildComponent(0) != nullptr) - juceFilter->editorBeingDeleted ((AudioProcessorEditor*) windowComp->getChildComponent(0)); + EditorCompHolder* editorCompHolder = dynamic_cast (windowComp->getChildComponent(0)); + if (editorCompHolder != nullptr) + { + AudioProcessorEditor* audioProcessEditor = dynamic_cast (editorCompHolder->getChildComponent(0)); + if (audioProcessEditor != nullptr) + juceFilter->editorBeingDeleted (audioProcessEditor); + } windowComp = nullptr; } @@ -1231,7 +1236,6 @@ private: class ComponentInHIView : public Component { public: - //============================================================================== ComponentInHIView (AudioProcessorEditor* const editor_, HIViewRef parentHIView) : parentView (parentHIView), editor (editor_), @@ -1263,7 +1267,7 @@ private: #else addToDesktop (ComponentPeer::windowIsTemporary); setWantsKeyboardFocus (true); - #endif + #endif setVisible (true); toFront (false); @@ -1287,7 +1291,7 @@ private: removeFromDesktop(); [hostWindow release]; - hostWindow = 0; + hostWindow = nil; } void updateWindowPos() @@ -1362,7 +1366,6 @@ private: } private: - //============================================================================== HIViewRef parentView; NSWindow* hostWindow; EditorCompHolder editor; diff --git a/modules/juce_core/network/juce_URL.cpp b/modules/juce_core/network/juce_URL.cpp index 90de257ccd..f4dbe4a51d 100644 --- a/modules/juce_core/network/juce_URL.cpp +++ b/modules/juce_core/network/juce_URL.cpp @@ -175,16 +175,14 @@ namespace URLHelpers } data << "--\r\n"; - data.flush(); } else { data << getMangledParameters (url.getParameters()) << url.getPostData(); - data.flush(); // just a short text attachment, so use simple url encoding.. headers << "Content-Type: application/x-www-form-urlencoded\r\nContent-length: " - << (int) postData.getSize() << "\r\n"; + << (int) data.getDataSize() << "\r\n"; } } diff --git a/modules/juce_core/zip/juce_ZipFile.cpp b/modules/juce_core/zip/juce_ZipFile.cpp index 46b59e0730..556c77ddca 100644 --- a/modules/juce_core/zip/juce_ZipFile.cpp +++ b/modules/juce_core/zip/juce_ZipFile.cpp @@ -26,22 +26,97 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -class ZipFile::ZipEntryInfo +class ZipFile::ZipEntryHolder { public: - ZipFile::ZipEntry entry; + ZipEntryHolder (const char* const buffer, const int fileNameLen) + { + entry.filename = String::fromUTF8 (buffer + 46, fileNameLen); + + const int time = ByteOrder::littleEndianShort (buffer + 12); + const int date = ByteOrder::littleEndianShort (buffer + 14); + entry.fileTime = getFileTimeFromRawEncodings (time, date); + + compressed = ByteOrder::littleEndianShort (buffer + 10) != 0; + compressedSize = (size_t) ByteOrder::littleEndianInt (buffer + 20); + entry.uncompressedSize = ByteOrder::littleEndianInt (buffer + 24); + + streamOffset = ByteOrder::littleEndianInt (buffer + 42); + } + + struct FileNameComparator + { + static int compareElements (const ZipEntryHolder* first, const ZipEntryHolder* second) + { + return first->entry.filename.compare (second->entry.filename); + } + }; + + ZipEntry entry; size_t streamOffset; size_t compressedSize; bool compressed; + +private: + static Time getFileTimeFromRawEncodings (int time, int date) + { + const int year = 1980 + (date >> 9); + const int month = ((date >> 5) & 15) - 1; + const int day = date & 31; + const int hours = time >> 11; + const int minutes = (time >> 5) & 63; + const int seconds = (time & 31) << 1; + + return Time (year, month, day, hours, minutes, seconds); + } }; +//============================================================================== +namespace +{ + int findEndOfZipEntryTable (InputStream& input, int& numEntries) + { + BufferedInputStream in (input, 8192); + + in.setPosition (in.getTotalLength()); + int64 pos = in.getPosition(); + const int64 lowestPos = jmax ((int64) 0, pos - 1024); + + char buffer [32] = { 0 }; + + while (pos > lowestPos) + { + in.setPosition (pos - 22); + pos = in.getPosition(); + memcpy (buffer + 22, buffer, 4); + + if (in.read (buffer, 22) != 22) + return 0; + + for (int i = 0; i < 22; ++i) + { + if (ByteOrder::littleEndianInt (buffer + i) == 0x06054b50) + { + in.setPosition (pos + i); + in.read (buffer, 22); + numEntries = ByteOrder::littleEndianShort (buffer + 10); + + return (int) ByteOrder::littleEndianInt (buffer + 16); + } + } + } + + return 0; + } +} + //============================================================================== class ZipFile::ZipInputStream : public InputStream { public: - ZipInputStream (ZipFile& file_, ZipFile::ZipEntryInfo& zei) + ZipInputStream (ZipFile& file_, ZipFile::ZipEntryHolder& zei) : file (file_), - zipEntryInfo (zei), + zipEntryHolder (zei), pos (0), headerSize (0), inputStream (file_.inputStream) @@ -53,7 +128,7 @@ public: else { #if JUCE_DEBUG - file_.numOpenStreams++; + file_.streamCounter.numOpenStreams++; #endif } @@ -73,13 +148,13 @@ public: { #if JUCE_DEBUG if (inputStream != nullptr && inputStream == file.inputStream) - file.numOpenStreams--; + file.streamCounter.numOpenStreams--; #endif } int64 getTotalLength() { - return zipEntryInfo.compressedSize; + return zipEntryHolder.compressedSize; } int read (void* buffer, int howMany) @@ -87,7 +162,7 @@ public: if (headerSize <= 0) return 0; - howMany = (int) jmin ((int64) howMany, (int64) (zipEntryInfo.compressedSize - pos)); + howMany = (int) jmin ((int64) howMany, (int64) (zipEntryHolder.compressedSize - pos)); if (inputStream == nullptr) return 0; @@ -97,12 +172,12 @@ public: if (inputStream == file.inputStream) { const ScopedLock sl (file.lock); - inputStream->setPosition (pos + zipEntryInfo.streamOffset + headerSize); + inputStream->setPosition (pos + zipEntryHolder.streamOffset + headerSize); num = inputStream->read (buffer, howMany); } else { - inputStream->setPosition (pos + zipEntryInfo.streamOffset + headerSize); + inputStream->setPosition (pos + zipEntryHolder.streamOffset + headerSize); num = inputStream->read (buffer, howMany); } @@ -112,7 +187,7 @@ public: bool isExhausted() { - return headerSize <= 0 || pos >= (int64) zipEntryInfo.compressedSize; + return headerSize <= 0 || pos >= (int64) zipEntryHolder.compressedSize; } int64 getPosition() @@ -122,13 +197,13 @@ public: bool setPosition (int64 newPos) { - pos = jlimit ((int64) 0, (int64) zipEntryInfo.compressedSize, newPos); + pos = jlimit ((int64) 0, (int64) zipEntryHolder.compressedSize, newPos); return true; } private: ZipFile& file; - ZipEntryInfo zipEntryInfo; + ZipEntryHolder zipEntryHolder; int64 pos; int headerSize; InputStream* inputStream; @@ -139,11 +214,8 @@ private: //============================================================================== -ZipFile::ZipFile (InputStream* const source_, const bool deleteStreamWhenDestroyed) - : inputStream (source_) - #if JUCE_DEBUG - , numOpenStreams (0) - #endif +ZipFile::ZipFile (InputStream* const stream, const bool deleteStreamWhenDestroyed) + : inputStream (stream) { if (deleteStreamWhenDestroyed) streamToDelete = inputStream; @@ -151,39 +223,42 @@ ZipFile::ZipFile (InputStream* const source_, const bool deleteStreamWhenDestroy init(); } -ZipFile::ZipFile (const File& file) - : inputStream (nullptr) - #if JUCE_DEBUG - , numOpenStreams (0) - #endif +ZipFile::ZipFile (InputStream& stream) + : inputStream (&stream) +{ + init(); +} + +ZipFile::ZipFile (const File& file) + : inputStream (nullptr), + inputSource (new FileInputSource (file)) { - inputSource = new FileInputSource (file); init(); } ZipFile::ZipFile (InputSource* const inputSource_) : inputStream (nullptr), inputSource (inputSource_) - #if JUCE_DEBUG - , numOpenStreams (0) - #endif { init(); } ZipFile::~ZipFile() { - #if JUCE_DEBUG entries.clear(); +} +#if JUCE_DEBUG +ZipFile::OpenStreamCounter::~OpenStreamCounter() +{ /* If you hit this assertion, it means you've created a stream to read one of the items in the zipfile, but you've forgotten to delete that stream object before deleting the file.. Streams can't be kept open after the file is deleted because they need to share the input - stream that the file uses to read itself. + stream that is managed by the ZipFile object. */ jassert (numOpenStreams == 0); - #endif } +#endif //============================================================================== int ZipFile::getNumEntries() const noexcept @@ -193,7 +268,7 @@ int ZipFile::getNumEntries() const noexcept const ZipFile::ZipEntry* ZipFile::getEntry (const int index) const noexcept { - ZipEntryInfo* const zei = entries [index]; + ZipEntryHolder* const zei = entries [index]; return zei != nullptr ? &(zei->entry) : nullptr; } @@ -213,7 +288,7 @@ const ZipFile::ZipEntry* ZipFile::getEntry (const String& fileName) const noexce InputStream* ZipFile::createStreamForEntry (const int index) { - ZipEntryInfo* const zei = entries[index]; + ZipEntryHolder* const zei = entries[index]; InputStream* stream = nullptr; if (zei != nullptr) @@ -233,18 +308,9 @@ InputStream* ZipFile::createStreamForEntry (const int index) return stream; } -class ZipFile::ZipFilenameComparator -{ -public: - int compareElements (const ZipFile::ZipEntryInfo* first, const ZipFile::ZipEntryInfo* second) - { - return first->entry.filename.compare (second->entry.filename); - } -}; - void ZipFile::sortEntriesByFilename() { - ZipFilenameComparator sorter; + ZipEntryHolder::FileNameComparator sorter; entries.sort (sorter); } @@ -288,27 +354,7 @@ void ZipFile::init() if (pos + 46 + fileNameLen > size) break; - ZipEntryInfo* const zei = new ZipEntryInfo(); - zei->entry.filename = String::fromUTF8 (buffer + 46, fileNameLen); - - const int time = ByteOrder::littleEndianShort (buffer + 12); - const int date = ByteOrder::littleEndianShort (buffer + 14); - - const int year = 1980 + (date >> 9); - const int month = ((date >> 5) & 15) - 1; - const int day = date & 31; - const int hours = time >> 11; - const int minutes = (time >> 5) & 63; - const int seconds = (time & 31) << 1; - - zei->entry.fileTime = Time (year, month, day, hours, minutes, seconds); - - zei->compressed = ByteOrder::littleEndianShort (buffer + 10) != 0; - zei->compressedSize = (size_t) ByteOrder::littleEndianInt (buffer + 20); - zei->entry.uncompressedSize = ByteOrder::littleEndianInt (buffer + 24); - - zei->streamOffset = ByteOrder::littleEndianInt (buffer + 42); - entries.add (zei); + entries.add (new ZipEntryHolder (buffer, fileNameLen)); pos += 46 + fileNameLen + ByteOrder::littleEndianShort (buffer + 30) @@ -319,41 +365,6 @@ void ZipFile::init() } } -int ZipFile::findEndOfZipEntryTable (InputStream& input, int& numEntries) -{ - BufferedInputStream in (input, 8192); - - in.setPosition (in.getTotalLength()); - int64 pos = in.getPosition(); - const int64 lowestPos = jmax ((int64) 0, pos - 1024); - - char buffer [32] = { 0 }; - - while (pos > lowestPos) - { - in.setPosition (pos - 22); - pos = in.getPosition(); - memcpy (buffer + 22, buffer, 4); - - if (in.read (buffer, 22) != 22) - return 0; - - for (int i = 0; i < 22; ++i) - { - if (ByteOrder::littleEndianInt (buffer + i) == 0x06054b50) - { - in.setPosition (pos + i); - in.read (buffer, 22); - numEntries = ByteOrder::littleEndianShort (buffer + 10); - - return (int) ByteOrder::littleEndianInt (buffer + 16); - } - } - } - - return 0; -} - Result ZipFile::uncompressTo (const File& targetDirectory, const bool shouldOverwriteFiles) { @@ -371,48 +382,44 @@ Result ZipFile::uncompressEntry (const int index, const File& targetDirectory, bool shouldOverwriteFiles) { - const ZipEntryInfo* zei = entries.getUnchecked (index); + const ZipEntryHolder* zei = entries.getUnchecked (index); const File targetFile (targetDirectory.getChildFile (zei->entry.filename)); if (zei->entry.filename.endsWithChar ('/')) - { return targetFile.createDirectory(); // (entry is a directory, not a file) - } - else + + ScopedPointer in (createStreamForEntry (index)); + + if (in == nullptr) + return Result::fail ("Failed to open the zip file for reading"); + + if (targetFile.exists()) { - ScopedPointer in (createStreamForEntry (index)); + if (! shouldOverwriteFiles) + return Result::ok(); - if (in == nullptr) - return Result::fail ("Failed to open the zip file for reading"); - - if (targetFile.exists()) - { - if (! shouldOverwriteFiles) - return Result::ok(); - - if (! targetFile.deleteFile()) - return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName()); - } - - if (! targetFile.getParentDirectory().createDirectory()) - return Result::fail ("Failed to create target folder: " + targetFile.getParentDirectory().getFullPathName()); - - { - FileOutputStream out (targetFile); - - if (out.failedToOpen()) - return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName()); - - out << *in; - } - - targetFile.setCreationTime (zei->entry.fileTime); - targetFile.setLastModificationTime (zei->entry.fileTime); - targetFile.setLastAccessTime (zei->entry.fileTime); - - return Result::ok(); + if (! targetFile.deleteFile()) + return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName()); } + + if (! targetFile.getParentDirectory().createDirectory()) + return Result::fail ("Failed to create target folder: " + targetFile.getParentDirectory().getFullPathName()); + + { + FileOutputStream out (targetFile); + + if (out.failedToOpen()) + return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName()); + + out << *in; + } + + targetFile.setCreationTime (zei->entry.fileTime); + targetFile.setLastModificationTime (zei->entry.fileTime); + targetFile.setLastAccessTime (zei->entry.fileTime); + + return Result::ok(); } @@ -562,7 +569,6 @@ bool ZipFile::Builder::writeToStream (OutputStream& target) const target.writeInt ((int) (directoryEnd - directoryStart)); target.writeInt ((int) (directoryStart - fileStart)); target.writeShort (0); - target.flush(); return true; } diff --git a/modules/juce_core/zip/juce_ZipFile.h b/modules/juce_core/zip/juce_ZipFile.h index e3131cf764..b2156d2748 100644 --- a/modules/juce_core/zip/juce_ZipFile.h +++ b/modules/juce_core/zip/juce_ZipFile.h @@ -42,6 +42,9 @@ class JUCE_API ZipFile { public: + /** Creates a ZipFile based for a file. */ + ZipFile (const File& file); + //============================================================================== /** Creates a ZipFile for a given stream. @@ -51,8 +54,11 @@ public: */ ZipFile (InputStream* inputStream, bool deleteStreamWhenDestroyed); - /** Creates a ZipFile based for a file. */ - ZipFile (const File& file); + /** Creates a ZipFile for a given stream. + The stream will not be owned or deleted by this class - if you want the ZipFile to + manage the stream's lifetime, use the other constructor. + */ + ZipFile (InputStream& inputStream); /** Creates a ZipFile for an input source. @@ -207,25 +213,29 @@ public: private: //============================================================================== class ZipInputStream; - class ZipFilenameComparator; - class ZipEntryInfo; + class ZipEntryHolder; friend class ZipInputStream; - friend class ZipFilenameComparator; - friend class ZipEntryInfo; + friend class ZipEntryHolder; - OwnedArray entries; + OwnedArray entries; CriticalSection lock; InputStream* inputStream; ScopedPointer streamToDelete; ScopedPointer inputSource; #if JUCE_DEBUG - int numOpenStreams; + struct OpenStreamCounter + { + OpenStreamCounter() : numOpenStreams (0) {} + ~OpenStreamCounter(); + + int numOpenStreams; + }; + + OpenStreamCounter streamCounter; #endif void init(); - int findEndOfZipEntryTable (InputStream& input, int& numEntries); - static int compareElements (const ZipEntryInfo* first, const ZipEntryInfo* second); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ZipFile); }; diff --git a/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp b/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp index 0733ddb34b..8381a1dd5e 100644 --- a/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp +++ b/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp @@ -413,8 +413,6 @@ bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) jpeg_finish_compress (&jpegCompStruct); jpeg_destroy_compress (&jpegCompStruct); - out.flush(); - return true; } diff --git a/modules/juce_graphics/image_formats/juce_PNGLoader.cpp b/modules/juce_graphics/image_formats/juce_PNGLoader.cpp index 9c7106ffca..cb3330267e 100644 --- a/modules/juce_graphics/image_formats/juce_PNGLoader.cpp +++ b/modules/juce_graphics/image_formats/juce_PNGLoader.cpp @@ -352,8 +352,6 @@ bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) png_write_end (pngWriteStruct, pngInfoStruct); png_destroy_write_struct (&pngWriteStruct, &pngInfoStruct); - out.flush(); - return true; } diff --git a/modules/juce_gui_basics/native/juce_mac_FileChooser.mm b/modules/juce_gui_basics/native/juce_mac_FileChooser.mm index 951c9cdac2..6841c843c6 100644 --- a/modules/juce_gui_basics/native/juce_mac_FileChooser.mm +++ b/modules/juce_gui_basics/native/juce_mac_FileChooser.mm @@ -69,7 +69,24 @@ using namespace juce; if (f.getFileName().matchesWildcard ((*filters)[i], true)) return true; - return f.isDirectory() && ! [[NSWorkspace sharedWorkspace] isFilePackageAtPath: filename]; + #if (! defined (MAC_OS_X_VERSION_10_7)) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + NSError* error; + NSString* name = [[NSWorkspace sharedWorkspace] typeOfFile: filename error: &error]; + + if ([name isEqualToString: nsStringLiteral ("com.apple.alias-file")]) + { + FSRef ref; + FSPathMakeRef ((const UInt8*) [filename fileSystemRepresentation], &ref, nullptr); + + Boolean targetIsFolder = false, wasAliased = false; + FSResolveAliasFileWithMountFlags (&ref, true, &targetIsFolder, &wasAliased, 0); + + return wasAliased && targetIsFolder; + } + #endif + + return f.isDirectory() + && ! [[NSWorkspace sharedWorkspace] isFilePackageAtPath: filename]; } @end