Skip to content

Commit fb0184a

Browse files
committed
support unzip password encrypted file on iOS
1 parent 070c1a7 commit fb0184a

File tree

11 files changed

+394
-759
lines changed

11 files changed

+394
-759
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,26 @@ unzip(sourcePath, targetPath)
176176
})
177177
```
178178

179+
**unzipWithPassword(source: string, target: string, passowrd: string): Promise**
180+
181+
> unzip from source to target
182+
183+
Example
184+
185+
```js
186+
const sourcePath = `${DocumentDirectoryPath}/myFile.zip`
187+
const targetPath = DocumentDirectoryPath
188+
const password = 'password'
189+
190+
unzipWithPassword(sourcePath, targetPath, password)
191+
.then((path) => {
192+
console.log(`unzip completed at ${path}`)
193+
})
194+
.catch((error) => {
195+
console.log(error)
196+
})
197+
```
198+
179199
**unzipAssets(assetPath: string, target: string): Promise**
180200

181201
> unzip file from Android `assets` folder to target path

example/UnzipApp.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import React, { Component } from 'react'
22
import {
33
StyleSheet, View,
4-
Alert, WebView
4+
Alert, WebView, Platform
55
} from 'react-native'
66
import {
77
ANIMATIONS_SLIDE,
88
CustomTabs
99
} from 'react-native-custom-tabs'
1010
import AwesomeButtonRick from 'react-native-really-awesome-button/src/themes/rick'
11-
import { DocumentPicker, DocumentPickerUtil } from 'react-native-document-picker'
11+
import { DocumentPicker } from 'react-native-document-picker'
1212
import { copyFile, DocumentDirectoryPath } from 'react-native-fs'
1313
import { subscribe, unzipWithPassword, isPasswordProtected } from 'react-native-zip-archive'
1414

@@ -40,7 +40,7 @@ export default class App extends Component {
4040
*/
4141
browseFiles () {
4242
DocumentPicker.show({
43-
filetype: [DocumentPickerUtil.allFiles()]
43+
filetype: [(Platform.OS === 'android') ? "*/*" : "public.data"]
4444
}, (err, response) => {
4545
var fileDetails = {
4646
uri: response.uri,
@@ -56,15 +56,15 @@ export default class App extends Component {
5656
}
5757

5858
componentDidMount () {
59-
this.zipProgress = subscribe(({ progress, filePath }) => {
59+
this.unzipProgress = subscribe(({ progress, filePath }) => {
6060
console.log('---- Progress update ----')
6161
console.log(filePath + ': ' + progress)
6262
console.log('-------------------------')
6363
})
6464
}
6565

6666
componentWillUnmount () {
67-
this.zipProgress.remove()
67+
this.unzipProgress.remove()
6868
}
6969

7070
extractFile () {
@@ -80,7 +80,10 @@ export default class App extends Component {
8080
var filename = fileDetails.name
8181
var filePath = DocumentDirectoryPath + '/' + filename
8282
var unzipPath = DocumentDirectoryPath
83-
copyFile(fileDetails.uri, filePath).then(() => {
83+
copyFile(fileDetails.uri, filePath).catch((err) => {
84+
console.log(err)
85+
return Promise.resolve()
86+
}).then(() => {
8487
return isPasswordProtected(filePath)
8588
}).then((isEncrypted) => {
8689
if (isEncrypted) {
@@ -108,6 +111,7 @@ export default class App extends Component {
108111
<WebView
109112
source={{uri: uri}}
110113
style={styles.webView}
114+
originWhitelist={['http://*', 'https://*', 'file://*']}
111115
startInLoadingState={true}
112116
scalesPageToFit={true}
113117
allowFileAccess={true}

example/ios/example.xcodeproj/project.pbxproj

Lines changed: 225 additions & 563 deletions
Large diffs are not rendered by default.

example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
{
22
"images" : [
3+
{
4+
"idiom" : "iphone",
5+
"size" : "20x20",
6+
"scale" : "2x"
7+
},
8+
{
9+
"idiom" : "iphone",
10+
"size" : "20x20",
11+
"scale" : "3x"
12+
},
313
{
414
"idiom" : "iphone",
515
"size" : "29x29",
@@ -29,6 +39,11 @@
2939
"idiom" : "iphone",
3040
"size" : "60x60",
3141
"scale" : "3x"
42+
},
43+
{
44+
"idiom" : "ios-marketing",
45+
"size" : "1024x1024",
46+
"scale" : "1x"
3247
}
3348
],
3449
"info" : {

example/ios/example/Info.plist

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@
2424
<string>1</string>
2525
<key>LSRequiresIPhoneOS</key>
2626
<true/>
27+
<key>NSAppTransportSecurity</key>
28+
<dict>
29+
<key>NSAllowsArbitraryLoads</key>
30+
<true/>
31+
<key>NSExceptionDomains</key>
32+
<dict>
33+
<key>localhost</key>
34+
<dict>
35+
<key>NSExceptionAllowsInsecureHTTPLoads</key>
36+
<true/>
37+
</dict>
38+
</dict>
39+
</dict>
2740
<key>NSLocationWhenInUseUsageDescription</key>
2841
<string></string>
2942
<key>UILaunchStoryboardName</key>
@@ -40,21 +53,5 @@
4053
</array>
4154
<key>UIViewControllerBasedStatusBarAppearance</key>
4255
<false/>
43-
<key>NSLocationWhenInUseUsageDescription</key>
44-
<string></string>
45-
<key>NSAppTransportSecurity</key>
46-
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
47-
<dict>
48-
<key>NSAllowsArbitraryLoads</key>
49-
<true/>
50-
<key>NSExceptionDomains</key>
51-
<dict>
52-
<key>localhost</key>
53-
<dict>
54-
<key>NSExceptionAllowsInsecureHTTPLoads</key>
55-
<true/>
56-
</dict>
57-
</dict>
58-
</dict>
5956
</dict>
6057
</plist>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.developer.icloud-container-identifiers</key>
6+
<array>
7+
<string>iCloud.$(CFBundleIdentifier)</string>
8+
</array>
9+
<key>com.apple.developer.icloud-services</key>
10+
<array>
11+
<string>CloudDocuments</string>
12+
</array>
13+
<key>com.apple.developer.ubiquity-container-identifiers</key>
14+
<array>
15+
<string>iCloud.$(CFBundleIdentifier)</string>
16+
</array>
17+
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
18+
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
19+
</dict>
20+
</plist>

example/ios/exampleTests/Info.plist

Lines changed: 0 additions & 24 deletions
This file was deleted.

example/ios/exampleTests/exampleTests.m

Lines changed: 0 additions & 68 deletions
This file was deleted.

index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const unzipWithPassword = (source, target, password) => {
1818
}
1919

2020
export const isPasswordProtected = (source) => {
21-
return RNZipArchive.isPasswordProtected(source)
21+
return RNZipArchive.isPasswordProtected(source).then(isEncrypted => !!isEncrypted)
2222
}
2323

2424
export const zip = (source, target) => {

ios/RNZipArchive.m

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,23 @@ @implementation RNZipArchive
2121

2222
RCT_EXPORT_MODULE();
2323

24+
RCT_EXPORT_METHOD(isPasswordProtected:(NSString *)file
25+
resolver:(RCTPromiseResolveBlock)resolve
26+
rejecter:(RCTPromiseRejectBlock)reject) {
27+
28+
BOOL isPasswordProtected = [RNZASSZipArchive isFilePasswordProtectedAtPath:file];
29+
resolve([NSNumber numberWithBool:isPasswordProtected]);
30+
}
31+
2432
RCT_EXPORT_METHOD(unzip:(NSString *)from
2533
destinationPath:(NSString *)destinationPath
34+
password:(NSString *)password
2635
resolver:(RCTPromiseResolveBlock)resolve
2736
rejecter:(RCTPromiseRejectBlock)reject) {
2837

2938
[self zipArchiveProgressEvent:0 total:1 filePath:from]; // force 0%
3039

31-
BOOL success = [RNZASSZipArchive unzipFileAtPath:from toDestination:destinationPath delegate:self];
40+
BOOL success = [RNZASSZipArchive unzipFileAtPath:from toDestination:destinationPath overwrite:YES password:password error:nil delegate:self];
3241

3342
[self zipArchiveProgressEvent:1 total:1 filePath:from]; // force 100%
3443

@@ -73,9 +82,9 @@ - (dispatch_queue_t)methodQueue {
7382

7483
- (void)zipArchiveProgressEvent:(unsigned long long)loaded total:(unsigned long long)total filePath:(NSString *)filePath {
7584
[self.bridge.eventDispatcher sendAppEventWithName:@"zipArchiveProgressEvent" body:@{
76-
@"progress": @((float)loaded / (float)total),
77-
@"filePath": filePath
78-
}];
85+
@"progress": @((float)loaded / (float)total),
86+
@"filePath": filePath
87+
}];
7988
}
8089

8190
@end

0 commit comments

Comments
 (0)