Browse Source

A few minor tweaks to ZipFile. Handling for aliased folders in OSX file chooser.

tags/2021-05-28
Julian Storer 13 years ago
parent
commit
24d40bdbb0
7 changed files with 180 additions and 150 deletions
  1. +9
    -6
      modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  2. +1
    -3
      modules/juce_core/network/juce_URL.cpp
  3. +132
    -126
      modules/juce_core/zip/juce_ZipFile.cpp
  4. +20
    -10
      modules/juce_core/zip/juce_ZipFile.h
  5. +0
    -2
      modules/juce_graphics/image_formats/juce_JPEGLoader.cpp
  6. +0
    -2
      modules/juce_graphics/image_formats/juce_PNGLoader.cpp
  7. +18
    -1
      modules/juce_gui_basics/native/juce_mac_FileChooser.mm

+ 9
- 6
modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm View File

@@ -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 <EditorCompHolder*> (windowComp->getChildComponent(0));
if (editorCompHolder != nullptr)
{
AudioProcessorEditor* audioProcessEditor = dynamic_cast <AudioProcessorEditor*> (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;


+ 1
- 3
modules/juce_core/network/juce_URL.cpp View File

@@ -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";
}
}


+ 132
- 126
modules/juce_core/zip/juce_ZipFile.cpp View File

@@ -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 (InputStream& stream)
: inputStream (&stream)
{
init();
}
ZipFile::ZipFile (const File& file)
: inputStream (nullptr)
#if JUCE_DEBUG
, numOpenStreams (0)
#endif
: 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<InputStream> in (createStreamForEntry (index));
if (in == nullptr)
return Result::fail ("Failed to open the zip file for reading");
if (targetFile.exists())
{
if (! shouldOverwriteFiles)
return Result::ok();
ScopedPointer<InputStream> in (createStreamForEntry (index));
if (! targetFile.deleteFile())
return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName());
}
if (in == nullptr)
return Result::fail ("Failed to open the zip file for reading");
if (! targetFile.getParentDirectory().createDirectory())
return Result::fail ("Failed to create target folder: " + targetFile.getParentDirectory().getFullPathName());
if (targetFile.exists())
{
if (! shouldOverwriteFiles)
return Result::ok();
{
FileOutputStream out (targetFile);
if (! targetFile.deleteFile())
return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName());
}
if (out.failedToOpen())
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());
out << *in;
}
{
FileOutputStream out (targetFile);
targetFile.setCreationTime (zei->entry.fileTime);
targetFile.setLastModificationTime (zei->entry.fileTime);
targetFile.setLastAccessTime (zei->entry.fileTime);
if (out.failedToOpen())
return Result::fail ("Failed to write to target file: " + targetFile.getFullPathName());
return Result::ok();
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;
}


+ 20
- 10
modules/juce_core/zip/juce_ZipFile.h View File

@@ -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 <ZipEntryInfo> entries;
OwnedArray <ZipEntryHolder> entries;
CriticalSection lock;
InputStream* inputStream;
ScopedPointer <InputStream> streamToDelete;
ScopedPointer <InputSource> 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);
};


+ 0
- 2
modules/juce_graphics/image_formats/juce_JPEGLoader.cpp View File

@@ -413,8 +413,6 @@ bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
jpeg_finish_compress (&jpegCompStruct);
jpeg_destroy_compress (&jpegCompStruct);
out.flush();
return true;
}


+ 0
- 2
modules/juce_graphics/image_formats/juce_PNGLoader.cpp View File

@@ -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;
}


+ 18
- 1
modules/juce_gui_basics/native/juce_mac_FileChooser.mm View File

@@ -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


Loading…
Cancel
Save