diff --git a/uppsrc/Core/src.tpp/OutFilterStream$en-us.tpp b/uppsrc/Core/src.tpp/OutFilterStream$en-us.tpp index 0109c017a..bba8e190b 100644 --- a/uppsrc/Core/src.tpp/OutFilterStream$en-us.tpp +++ b/uppsrc/Core/src.tpp/OutFilterStream$en-us.tpp @@ -15,7 +15,9 @@ topic "OutFilterStream"; [s1;:OutFilterStream`:`:class: [@(0.0.255)3 class][3 _][*3 OutFilterStream][3 _:_][@(0.0.255)3 p ublic][3 _][*@3;3 Stream]&] [s2;%% Adapter Stream that glues an output stream with some filtering -object, typically of compression/decompression class.&] +object, typically of compression/decompression class. Output +stream can also be omitted, in that case OutFilterStream is useful +to convert anything capable of consuming data into Stream.&] [s3; &] [ {{10000F(128)G(128)@1 [s0;%% [* Public Member List]]}}&] [s3; &] @@ -26,21 +28,23 @@ call does nothing.&] [s3; &] [s4; &] [s5;:OutFilterStream`:`:out: [_^Stream^ Stream]_`*[* out]&] -[s2;%% Pointer to the output stream.&] +[s2;%% Pointer to the output stream. Can be NULL.&] [s3; &] [s4; &] [s5;:OutFilterStream`:`:Filter: [_^Callback2^ Callback2]<[@(0.0.255) const]_[@(0.0.255) voi d]_`*, [@(0.0.255) int]>_[* Filter]&] -[s2;%% Callback to filter input function.&] +[s2;%% Callback to filter input function. This is called when OutFilterStream +needs to output a chunk of buffered data.&] [s3; &] [s4; &] [s5;:OutFilterStream`:`:End: [_^Callback^ Callback]_[* End]&] -[s2;%% Callback to filter finalization.&] +[s2;%% Callback to filter finalization. Called on closing the stream.&] [s3; &] [s4; &] [s5;:OutFilterStream`:`:Out`(const void`*`,int`): [@(0.0.255) void]_[* Out]([@(0.0.255) con st]_[@(0.0.255) void]_`*[*@3 ptr], [@(0.0.255) int]_[*@3 size])&] -[s2;%% Method serving as filter output.&] +[s2;%% Method serving as filter output. Basically performs out`->Put(ptr, +size), also keeps track of output bytes written (see GetCount).&] [s3;%% &] [s4; &] [s5;:OutFilterStream`:`:GetCount`(`)const: [@(0.0.255) int64]_[* GetCount]()_[@(0.0.255) co diff --git a/uppsrc/plugin/zip/UnZip.cpp b/uppsrc/plugin/zip/UnZip.cpp index 4d9b45d89..3bddbe2e4 100644 --- a/uppsrc/plugin/zip/UnZip.cpp +++ b/uppsrc/plugin/zip/UnZip.cpp @@ -1,7 +1,5 @@ #include "zip.h" -#ifndef OLD_UNZIP - NAMESPACE_UPP void UnZip::ReadDir() @@ -68,7 +66,7 @@ void UnZip::ReadDir() error = false; } -Time UnZip::GetTime(dword dt) +Time UnZip::GetZipTime(dword dt) { Time time; time.year = int16(((dt >> 25) & 0x7f) + 1980); @@ -163,5 +161,3 @@ UnZip::UnZip() UnZip::~UnZip() {} END_UPP_NAMESPACE - -#endif \ No newline at end of file diff --git a/uppsrc/plugin/zip/UnZipOld.cpp b/uppsrc/plugin/zip/UnZipOld.cpp deleted file mode 100644 index 899f00cb1..000000000 --- a/uppsrc/plugin/zip/UnZipOld.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include "zip.h" - -#ifdef OLD_UNZIP - -NAMESPACE_UPP - -void UnZip::ReadHeader() -{ - if(zip->Get32le() != 0x04034b50) { - eof = true; - return; - } - if(zip->Get16le() > 20) { - SetError(); - return; - } - bit = zip->Get16le(); - method = zip->Get16le(); - - dword dt = zip->Get32le(); - - time.year = int16(((dt >> 25) & 0x7f) + 1980); - time.month = byte((dt >> 21) & 0x0f); - time.day = byte((dt >> 16) & 0x1f); - time.hour = byte((dt >> 11) & 0x1f); - time.minute = byte((dt >> 5) & 0x3f); - time.second = byte((dt << 1) & 0x3e); - - crc32 = zip->Get32le(); - csize = zip->Get32le(); - usize = zip->Get32le(); - - dword filelen = zip->Get16le(); - dword extralen = zip->Get16le(); - path = zip->Get(filelen); - zip->SeekCur(extralen); - - done += 5 * 2 + 5 * 4; -} - -void UnZip::SkipFile() -{ - zip->SeekCur(csize); - done += csize; - ReadHeader(); -} - -int64 zPress(Stream& out, Stream& in, int64 size, Gate2 progress, bool gzip, - bool compress, dword *crc, bool hdr); - -bool UnZip::ReadFile(Stream& out, Gate2 progress) -{ - dword crc; - int l; - if(method == 0) { - Buffer temp(65536); - int loaded; - int count = csize; - Crc32Stream crc32; - while(count > 0 && (loaded = zip->Get(temp, (int)min(count, 65536))) > 0) { - out.Put(temp, loaded); - crc32.Put(temp, loaded); - count -= loaded; - } - if(count > 0) { - SetError(); - return false; - } - l = csize; - crc = crc32; - } - else - if(method == 8) - l = (int)zPress(out, *zip, csize, AsGate64(progress), false, false, &crc, false); - else { - SetError(); - return false; - } - if(crc != crc32 || l != usize) { - SetError(); - return false; - } - done += csize; - ReadHeader(); - return true; -} - -String UnZip::ReadFile(Gate2 progress) -{ - StringStream ss; - return ReadFile(ss, progress) ? ss.GetResult() : String::GetVoid(); -} - -void UnZip::Create(Stream& _zip) -{ - eof = error = false; - zip = &_zip; - done = 0; - ReadHeader(); -} - -bool UnZip::IsEof() const -{ - return eof || !zip || error || zip->IsEof(); -} - -bool UnZip::IsFolder() const -{ - return *path.Last() == '/'; -} - -UnZip::UnZip(Stream& in) -{ - Create(in); -} - -UnZip::UnZip() -{ - error = true; - zip = NULL; -} - -UnZip::~UnZip() {} - -END_UPP_NAMESPACE - -#endif \ No newline at end of file diff --git a/uppsrc/plugin/zip/Zip.cpp b/uppsrc/plugin/zip/Zip.cpp index 0f13c5bcb..9e9340716 100644 --- a/uppsrc/plugin/zip/Zip.cpp +++ b/uppsrc/plugin/zip/Zip.cpp @@ -13,37 +13,112 @@ void Zip::WriteFolder(const char *path, Time tm) int64 zPress(Stream& out, Stream& in, int64 size, Gate2 progress, bool gzip, bool compress, dword *crc, bool hdr); -void Zip::WriteFile(const void *ptr, int size, const char *path, Gate2 progress, Time tm) + +void Zip::FileHeader(const char *path, Time tm) { - File& f = file.Add(); + File& f = file.Top(); f.path = UnixPath(path); - StringStream ss; - MemReadStream ms(ptr, size); - dword crc; - zPress(ss, ms, size, AsGate64(progress), false, true, &crc, false); - String data = ss.GetResult(); - const void *r = ~data; - int csize = data.GetLength(); zip->Put32le(0x04034b50); - zip->Put16le(20); - zip->Put16le(0); - if(data.GetLength() >= size) { - r = ptr; - csize = size; - zip->Put16le(f.method = 0); - } - else - zip->Put16le(f.method = 8); + zip->Put16le(f.version); + zip->Put16le(f.gpflag); + zip->Put16le(f.method); zip->Put32le(f.time = (tm.day << 16) | (tm.month << 21) | ((tm.year - 1980) << 25) | (tm.hour << 11) | (tm.minute << 5) | (tm.second >> 1)); - zip->Put32le(f.crc = crc); - zip->Put32le(f.csize = csize); - zip->Put32le(f.usize = size); + ASSERT((f.gpflag & 0x8) == 0 || f.crc == 0); + zip->Put32le(f.crc); + ASSERT((f.gpflag & 0x8) == 0 || f.csize == 0); + zip->Put32le(f.csize); + ASSERT((f.gpflag & 0x8) == 0 || f.usize == 0); + zip->Put32le(f.usize); zip->Put16le(strlen(f.path)); zip->Put16le(0); zip->Put(f.path); - zip->Put(r, csize); - done += 5 * 2 + 5 * 4 + csize + f.path.GetCount(); + done += 5*2 + 5*4 + f.path.GetCount(); +} + +void Zip::BeginFile(const char *path, Time tm) +{ + ASSERT(!IsFileOpened()); + pipeZLib.Create(); + pipeZLib->WhenOut = THISBACK(PutCompressed); + pipeZLib->GZip(false).CRC().NoHeader().Compress(); + File& f = file.Add(); + f.version = 21; + f.gpflag = 0x8; + f.method = 8; + f.crc = 0; + f.csize = 0; + f.usize = 0; + FileHeader(path, tm); + if (zip->IsError()) WhenError(); +} + +void Zip::BeginFile(OutFilterStream& oz, const char *path, Time tm) +{ + BeginFile(path, tm); + oz.Filter = THISBACK(Put); + oz.End = THISBACK(EndFile); +} + +void Zip::Put(const void *ptr, int size) +{ + ASSERT(IsFileOpened()); + File& f = file.Top(); + pipeZLib->Put(ptr, size); + f.usize += size; +} + +void Zip::EndFile() +{ + if(!IsFileOpened()) + return; + File& f = file.Top(); + ASSERT(f.gpflag & 0x8); + pipeZLib->End(); + zip->Put32le(f.crc = pipeZLib->GetCRC()); + zip->Put32le(f.csize); + zip->Put32le(f.usize); + done += 3*4; + pipeZLib.Clear(); + if (zip->IsError()) WhenError(); +} + +void Zip::PutCompressed(const void *ptr, int size) +{ + ASSERT(IsFileOpened()); + zip->Put(ptr, size); + if (zip->IsError()) WhenError(); + done += size; + file.Top().csize += size; +} + +void Zip::WriteFile(const void *ptr, int size, const char *path, Gate2 progress, Time tm) +{ + ASSERT(!IsFileOpened()); + File& f = file.Add(); + StringStream ss; + MemReadStream ms(ptr, size); + + f.usize = size; + zPress(ss, ms, size, AsGate64(progress), false, true, &f.crc, false); + + String data = ss.GetResult(); + const void *r = ~data; + f.csize = data.GetLength(); + + f.version = 20; + f.gpflag = 0; + if(data.GetLength() >= size) { + r = ptr; + f.csize = size; + f.method = 0; + } + else + f.method = 8; + FileHeader(path, tm); + zip->Put(r, f.csize); + done += f.csize; + if (zip->IsError()) WhenError(); } void Zip::WriteFile(const String& s, const char *path, Gate2 progress, Time tm) @@ -68,8 +143,8 @@ void Zip::Finish() File& f = file[i]; zip->Put32le(0x02014b50); zip->Put16le(20); - zip->Put16le(20); - zip->Put16le(0); // general purpose bit flag + zip->Put16le(f.version); + zip->Put16le(f.gpflag); // general purpose bit flag zip->Put16le(f.method); zip->Put32le(f.time); zip->Put32le(f.crc); @@ -82,7 +157,7 @@ void Zip::Finish() zip->Put16le(0); // internal file attributes 2 bytes zip->Put32le(0); // external file attributes 4 bytes zip->Put32le(rof); // relative offset of local header 4 bytes - rof+=5 * 2 + 5 * 4 + f.csize + f.path.GetCount(); + rof+=5 * 2 + 5 * 4 + f.csize + f.path.GetCount() + (f.gpflag & 0x8 ? 3*4 : 0); zip->Put(f.path); done += 7 * 4 + 9 * 2 + f.path.GetCount(); } @@ -94,6 +169,7 @@ void Zip::Finish() zip->Put32le(done - off); // size of the central directory zip->Put32le(off); //offset of start of central directory with respect to the starting disk number zip->Put16le(0); + if (zip->IsError()) WhenError(); zip = NULL; } diff --git a/uppsrc/plugin/zip/zip.h b/uppsrc/plugin/zip/zip.h index 99ea6a48a..399eb60bc 100644 --- a/uppsrc/plugin/zip/zip.h +++ b/uppsrc/plugin/zip/zip.h @@ -5,8 +5,6 @@ NAMESPACE_UPP -#ifndef OLD_UNZIP - class UnZip { struct File : Moveable { word bit; @@ -26,7 +24,7 @@ class UnZip { void ReadDir(); - static Time GetTime(dword time); + static Time GetZipTime(dword time); public: bool IsEof() const { return current >= file.GetCount(); } @@ -39,6 +37,7 @@ public: String GetPath(int i) const { return file[i].path; } bool IsFolder(int i) const { return *file[i].path.Last() == '/'; } int GetLength(int i) const { return file[i].usize; } + Time GetTime(int i) const { return GetZipTime(file[i].time); } void Seek(int i) { ASSERT(i >= 0 && i < file.GetCount()); current = i; } @@ -61,52 +60,6 @@ public: virtual ~UnZip(); }; -#else - -class UnZip { - Stream *zip; - - bool error; - bool eof; - String path; - word bit; - word method; - Time time; - dword crc32; - dword csize; - dword usize; - dword done; - - void Init(); - void ReadHeader(); - void SetError() { error = true; } - -public: - bool IsEof() const; - operator bool() const { return !IsEof(); } - - bool IsError() const { return error; } - - bool IsFolder() const; - String GetPath() const { return path; } - int GetLength() const { return usize; } - Time GetTime() const { return time; } - - void SkipFile(); - bool ReadFile(Stream& out, Gate2 progress = false); - String ReadFile(Gate2 progress = false); - - dword GetPos() { return done; } - - void Create(Stream& in); - - UnZip(Stream& in); - UnZip(); - virtual ~UnZip(); -}; - -#endif - class FileUnZip : public UnZip { FileIn zip; @@ -135,11 +88,15 @@ public: }; class Zip { + typedef Zip CLASSNAME; + Stream *zip; struct File { String path; dword time; + int version; + int gpflag; int method; dword crc; dword csize; @@ -149,9 +106,25 @@ class Zip { dword done; + One pipeZLib; + void WriteFile0(const void *ptr, int size, const char *path, Gate2 progress, Time tm, int method); + void FileHeader(const char *path, Time tm); + + void PutCompressed(const void *data, int size); + + typedef Zip CLASSNAME; + public: + Callback WhenError; + + void BeginFile(const char *path, Time tm = GetSysTime()); + void BeginFile(OutFilterStream& oz, const char *path, Time tm = GetSysTime()); + void Put(const void *data, int size); + void EndFile(); + bool IsFileOpened() const { return pipeZLib; } + void WriteFolder(const char *path, Time tm); void WriteFile(const void *ptr, int size, const char *path, Gate2 progress = false, Time tm = GetSysTime()); void WriteFile(const String& s, const char *path, Gate2 progress = false, Time tm = GetSysTime()); diff --git a/uppsrc/plugin/zip/zip.upp b/uppsrc/plugin/zip/zip.upp index a48261e71..00ce3225d 100644 --- a/uppsrc/plugin/zip/zip.upp +++ b/uppsrc/plugin/zip/zip.upp @@ -4,6 +4,5 @@ file zip.h, Zip.cpp, UnZip.cpp, - UnZipUtil.cpp, - UnZipOld.cpp; + UnZipUtil.cpp;