Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Minizip 1.2 #5

Merged
merged 17 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Zip/minizip/* linguist-vendored
Sources/Minizip/* linguist-vendored
20 changes: 4 additions & 16 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# MacOS
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
Expand All @@ -18,23 +18,11 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Pods/

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build
/*.xcodeproj
xcuserdata/

# Swift Package Manager
.build/
.swiftpm/
Packages/
Package.resolved
12 changes: 9 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ let package = Package(
targets: [
.target(
name: "Minizip",
path: "Zip/minizip",
exclude: ["module"],
swiftSettings: [
.enableUpcomingFeature("ConciseMagicFile"),
],
linkerSettings: [
.linkedLibrary("z")
]
Expand All @@ -20,8 +22,9 @@ let package = Package(
dependencies: [
.target(name: "Minizip"),
],
path: "Zip",
exclude: ["minizip", "zlib"]
swiftSettings: [
.enableUpcomingFeature("ConciseMagicFile"),
]
),
.testTarget(
name: "ZipTests",
Expand All @@ -30,6 +33,9 @@ let package = Package(
],
resources: [
.copy("Resources"),
],
swiftSettings: [
.enableUpcomingFeature("ConciseMagicFile"),
]
),
]
Expand Down
33 changes: 25 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@
A framework for zipping and unzipping files in Swift.

Simple and quick to use.
Built on top of [minizip](https://github.com/nmoinvaz/minizip).
Built on top of [Minizip 1.2](https://github.com/zlib-ng/minizip-ng/tree/1.2).

Use the SPM string to easily include the dependendency in your `Package.swift` file.

```swift
.package(url: "https://github.com/vapor-community/Zip.git", from: "2.1.3")
.package(url: "https://github.com/vapor-community/Zip.git", from: "2.2.0")
```

## Usage

### Quick functions
### Quick Functions

The easiest way to use Zip is through quick functions. Both take local file paths as `URL`s, throw if an error is encountered and return an `URL` to the destination if successful.

Expand All @@ -48,22 +48,39 @@ do {

### Advanced Zip

For more advanced usage, Zip has functions that let you set custom destination paths, work with password protected zips and use a progress handling closure. These functions throw if there is an error but don't return.
For more advanced usage, Zip has functions that let you set custom destination paths, work with password protected zips and use a progress handling closure. These functions throw if there is an error, but don't return.

```swift
import Zip

do {
let filePath = Bundle.main.url(forResource: "file", withExtension: "zip")!
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
try Zip.unzipFile(filePath, destination: documentsDirectory, overwrite: true,password: "password", progress: { (progress) -> () in
try Zip.unzipFile(filePath, destination: documentsDirectory, overwrite: true, password: "password") { progress in
print(progress)
})
}

let zipFilePath = documentsFolder.appendingPathComponent("archive.zip")
try Zip.zipFiles([filePath], zipFilePath: zipFilePath, password: "password", progress: { (progress) -> () in
try Zip.zipFiles([filePath], zipFilePath: zipFilePath, password: "password") { progress in
print(progress)
})
}
} catch {
print("Something went wrong")
}
```

# Archive Data saved in memory

Zip provides a way to archive data saved in memory.
This is useful when you want to create a zip archive without having the source files saved to disk.

```swift
import Zip

do {
let archiveFile = ArchiveFile(filename: "file.txt", data: "Hello, World!".data(using: .utf8)!)
let zipFilePath = FileManager.default.temporaryDirectory.appendingPathComponent("archive.zip")
try Zip.zipData(archiveFiles: [archiveFile], zipFilePath: zipFilePath)
} catch {
print("Something went wrong")
}
Expand Down
155 changes: 155 additions & 0 deletions Sources/Minizip/crypt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/* crypt.c -- base code for traditional PKWARE encryption
Version 1.2.0, September 16th, 2017

Copyright (C) 2012-2017 Nathan Moinvaziri
https://github.com/nmoinvaz/minizip
Copyright (C) 1998-2005 Gilles Vollant
Modifications for Info-ZIP crypting
http://www.winimage.com/zLibDll/minizip.html
Copyright (C) 2003 Terry Thorsen

This code is a modified version of crypting code in Info-ZIP distribution

Copyright (C) 1990-2000 Info-ZIP. All rights reserved.

This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.

This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).

If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT.
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>

#ifdef _WIN32
# include <windows.h>
# include <wincrypt.h>
#else
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
#endif

#include "zlib.h"

#include "crypt.h"

// Fix for Linux which doesn't have `arc4random_buf` function
#if defined(__APPLE__)
#define get_random_bytes(buf, len) arc4random_buf(buf, len)
#elif defined(__linux__)
#include <sys/syscall.h>
#include <linux/random.h>
#define get_random_bytes(buf, len) syscall(SYS_getrandom, buf, len, 0)
#endif

/***************************************************************************/

#define CRC32(c, b) ((*(pcrc_32_tab+(((uint32_t)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))

/***************************************************************************/

uint8_t decrypt_byte(uint32_t *pkeys)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */

temp = ((uint32_t)(*(pkeys+2)) & 0xffff) | 2;
return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff);
}

uint8_t update_keys(uint32_t *pkeys, const z_crc_t *pcrc_32_tab, int32_t c)
{
(*(pkeys+0)) = (uint32_t)CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
register int32_t keyshift = (int32_t)((*(pkeys + 1)) >> 24);
(*(pkeys+2)) = (uint32_t)CRC32((*(pkeys+2)), keyshift);
}
return c;
}

void init_keys(const char *passwd, uint32_t *pkeys, const z_crc_t *pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L;
while (*passwd != 0)
{
update_keys(pkeys, pcrc_32_tab, *passwd);
passwd += 1;
}
}

/***************************************************************************/

#ifndef NOCRYPT
int cryptrand(unsigned char *buf, unsigned int len)
{
#ifdef _WIN32
HCRYPTPROV provider;
unsigned __int64 pentium_tsc[1];
int rlen = 0;
int result = 0;


if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
{
result = CryptGenRandom(provider, len, buf);
CryptReleaseContext(provider, 0);
if (result)
return len;
}

for (rlen = 0; rlen < (int)len; ++rlen)
{
if (rlen % 8 == 0)
QueryPerformanceCounter((LARGE_INTEGER *)pentium_tsc);
buf[rlen] = ((unsigned char*)pentium_tsc)[rlen % 8];
}

return rlen;
#else
get_random_bytes(buf, len); // Originally was `arc4random_buf`
return len;
#endif
}

int crypthead(const char *passwd, uint8_t *buf, int buf_size, uint32_t *pkeys,
const z_crc_t *pcrc_32_tab, uint8_t verify1, uint8_t verify2)
{
uint8_t n = 0; /* index in random header */
uint8_t header[RAND_HEAD_LEN-2]; /* random header */
uint16_t t = 0; /* temporary */

if (buf_size < RAND_HEAD_LEN)
return 0;

init_keys(passwd, pkeys, pcrc_32_tab);

/* First generate RAND_HEAD_LEN-2 random bytes. */
cryptrand(header, RAND_HEAD_LEN-2);

/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);

for (n = 0; n < RAND_HEAD_LEN-2; n++)
buf[n] = (uint8_t)zencode(pkeys, pcrc_32_tab, header[n], t);

buf[n++] = (uint8_t)zencode(pkeys, pcrc_32_tab, verify1, t);
buf[n++] = (uint8_t)zencode(pkeys, pcrc_32_tab, verify2, t);
return n;
}
#endif

/***************************************************************************/
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef Minizip_h
#define Minizip_h

#import "ioapi.h"
#import "crypt.h"
#import "unzip.h"
#import "zip.h"
Expand Down
66 changes: 66 additions & 0 deletions Sources/Minizip/include/crypt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* crypt.h -- base code for traditional PKWARE encryption
Version 1.2.0, September 16th, 2017

Copyright (C) 2012-2017 Nathan Moinvaziri
https://github.com/nmoinvaz/minizip
Copyright (C) 1998-2005 Gilles Vollant
Modifications for Info-ZIP crypting
http://www.winimage.com/zLibDll/minizip.html
Copyright (C) 2003 Terry Thorsen

This code is a modified version of crypting code in Info-ZIP distribution

Copyright (C) 1990-2000 Info-ZIP. All rights reserved.

This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/

#ifndef _MINICRYPT_H
#define _MINICRYPT_H

#if ZLIB_VERNUM < 0x1270
typedef unsigned long z_crc_t;
#endif

#ifdef __cplusplus
extern "C" {
#endif

#define RAND_HEAD_LEN 12

/***************************************************************************/

#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab, c ^= decrypt_byte(pkeys)))

#define zencode(pkeys,pcrc_32_tab,c,t) \
(t = decrypt_byte(pkeys), update_keys(pkeys,pcrc_32_tab,c), t^(c))

/***************************************************************************/

/* Return the next byte in the pseudo-random sequence */
uint8_t decrypt_byte(uint32_t *pkeys);

/* Update the encryption keys with the next byte of plain text */
uint8_t update_keys(uint32_t *pkeys, const z_crc_t *pcrc_32_tab, int32_t c);

/* Initialize the encryption keys and the random header according to the given password. */
void init_keys(const char *passwd, uint32_t *pkeys, const z_crc_t *pcrc_32_tab);

#ifndef NOCRYPT
/* Generate cryptographically secure random numbers */
int cryptrand(unsigned char *buf, unsigned int len);

/* Create encryption header */
int crypthead(const char *passwd, uint8_t *buf, int buf_size, uint32_t *pkeys,
const z_crc_t *pcrc_32_tab, uint8_t verify1, uint8_t verify2);
#endif

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
Loading