-
Notifications
You must be signed in to change notification settings - Fork 95
/
Copy pathURKArchive.h
526 lines (452 loc) · 19.2 KB
/
URKArchive.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
//
// URKArchive.h
// UnrarKit
//
//
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
#import "UnrarKitMacros.h"
RarosHppIgnore
#import "raros.hpp"
#pragma clang diagnostic pop
DllHppIgnore
#import "dll.hpp"
#pragma clang diagnostic pop
@class URKFileInfo;
/**
* Defines the various error codes that the listing and extraction methods return.
* These are returned in NSError's [code]([NSError code]) field.
*/
typedef NS_ENUM(NSInteger, URKErrorCode) {
/**
* The last file of the archive has been read
*/
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
/**
* The library ran out of memory while reading the archive
*/
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
/**
* The header's CRC doesn't match the decompressed data's CRC
*/
URKErrorCodeBadData = ERAR_BAD_DATA,
/**
* The archive is not a valid RAR file
*/
URKErrorCodeBadArchive = ERAR_BAD_ARCHIVE,
/**
* The archive is an unsupported RAR format or version
*/
URKErrorCodeUnknownFormat = ERAR_UNKNOWN_FORMAT,
/**
* Failed to open a reference to the file
*/
URKErrorCodeOpen = ERAR_EOPEN,
/**
* Failed to create the target directory for extraction
*/
URKErrorCodeCreate = ERAR_ECREATE,
/**
* Failed to close the archive
*/
URKErrorCodeClose = ERAR_ECLOSE,
/**
* Failed to read the archive
*/
URKErrorCodeRead = ERAR_EREAD,
/**
* Failed to write a file to disk
*/
URKErrorCodeWrite = ERAR_EWRITE,
/**
* The archive header's comments are larger than the buffer size
*/
URKErrorCodeSmall = ERAR_SMALL_BUF,
/**
* The cause of the error is unspecified
*/
URKErrorCodeUnknown = ERAR_UNKNOWN,
/**
* A password was not given for a password-protected archive
*/
URKErrorCodeMissingPassword = ERAR_MISSING_PASSWORD,
/**
* No data was returned from the archive
*/
URKErrorCodeArchiveNotFound = 101,
/**
* User cancelled the operation
*/
URKErrorCodeUserCancelled = 102,
/**
* Error converting string to UTF-8
*/
URKErrorCodeStringConversion = 103,
};
typedef NSString *const URKProgressInfoKey;
/**
* Defines the keys passed in `-[NSProgress userInfo]` for certain methods
*/
static URKProgressInfoKey _Nonnull
/**
* For `extractFilesTo:overwrite:error:`, this key contains an instance of URKFileInfo with the file currently being extracted
*/
URKProgressInfoKeyFileInfoExtracting = @"URKProgressInfoKeyFileInfoExtracting";
NS_ASSUME_NONNULL_BEGIN
extern NSString *URKErrorDomain;
/**
* An Objective-C/Cocoa wrapper around the unrar library
*/
@interface URKArchive : NSObject
// Minimum of iOS 9, macOS 10.11 SDKs
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED > 90000) || (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED > 101100)
<NSProgressReporting>
#endif
/**
* The URL of the archive
*/
@property(nullable, weak, atomic, readonly) NSURL *fileURL;
/**
* The filename of the archive
*/
@property(nullable, weak, atomic, readonly) NSString *filename;
/**
* The password of the archive
*/
@property(nullable, nonatomic, strong) NSString *password;
/**
* The total uncompressed size (in bytes) of all files in the archive. Returns nil on errors
*/
@property(nullable, atomic, readonly) NSNumber *uncompressedSize;
/**
* The total compressed size (in bytes) of the archive. Returns nil on errors
*/
@property(nullable, atomic, readonly) NSNumber *compressedSize;
/**
* True if the file is one volume of a multi-part archive
*/
@property(atomic, readonly) BOOL hasMultipleVolumes;
/**
* Can be used for progress reporting, but it's not necessary. You can also use
* implicit progress reporting. If you don't use it, one will still be created,
* which will become a child progress of whichever one is the current NSProgress
* instance.
*
* To use this, assign it before beginning an operation that reports progress. Once
* the method you're calling has a reference to it, it will nil it out. Please check
* for nil before assigning it to avoid concurrency conflicts.
*/
@property(nullable, strong) NSProgress *progress;
/**
* When performing operations on a RAR archive, the contents of compressed files are checked
* against the record of what they were when the archive was created. If there's a mismatch,
* either the metadata (header) or archive contents have become corrupted. You can defeat this check by
* setting this property to YES, though there may be security implications to turning the
* warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability.
*
* It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user
*/
@property (assign) BOOL ignoreCRCMismatches;
/**
* **DEPRECATED:** Creates and returns an archive at the given path
*
* @param filePath A path to the archive file
*/
+ (nullable instancetype)rarArchiveAtPath:(NSString *)filePath __deprecated_msg("Use -initWithPath:error: instead");
/**
* **DEPRECATED:** Creates and returns an archive at the given URL
*
* @param fileURL The URL of the archive file
*/
+ (nullable instancetype)rarArchiveAtURL:(NSURL *)fileURL __deprecated_msg("Use -initWithURL:error: instead");
/**
* **DEPRECATED:** Creates and returns an archive at the given path, with a given password
*
* @param filePath A path to the archive file
* @param password The passowrd of the given archive
*/
+ (nullable instancetype)rarArchiveAtPath:(NSString *)filePath password:(NSString *)password __deprecated_msg("Use -initWithPath:password:error: instead");
/**
* **DEPRECATED:** Creates and returns an archive at the given URL, with a given password
*
* @param fileURL The URL of the archive file
* @param password The passowrd of the given archive
*/
+ (nullable instancetype)rarArchiveAtURL:(NSURL *)fileURL password:(NSString *)password __deprecated_msg("Use -initWithURL:password:error: instead");
/**
* Do not use the default initializer
*/
- (instancetype)init NS_UNAVAILABLE;
/**
* Creates and returns an archive at the given path
*
* @param filePath A path to the archive file
* @param error Contains any error during initialization
*
* @return Returns an initialized URKArchive, unless there's a problem creating a bookmark to the path
*/
- (nullable instancetype)initWithPath:(NSString *)filePath error:(NSError **)error;
/**
* Creates and returns an archive at the given URL
*
* @param fileURL The URL of the archive file
* @param error Contains any error during initialization
*
* @return Returns an initialized URKArchive, unless there's a problem creating a bookmark to the URL
*/
- (nullable instancetype)initWithURL:(NSURL *)fileURL error:(NSError **)error;
/**
* Creates and returns an archive at the given path, with a given password
*
* @param filePath A path to the archive file
* @param password The passowrd of the given archive
* @param error Contains any error during initialization
*
* @return Returns an initialized URKArchive, unless there's a problem creating a bookmark to the path
*/
- (nullable instancetype)initWithPath:(NSString *)filePath password:(NSString *)password error:(NSError **)error;
/**
* Creates and returns an archive at the given URL, with a given password
*
* @param fileURL The URL of the archive file
* @param password The passowrd of the given archive
* @param error Contains any error during initialization
*
* @return Returns an initialized URKArchive, unless there's a problem creating a bookmark to the URL
*/
- (nullable instancetype)initWithURL:(NSURL *)fileURL password:(NSString *)password error:(NSError **)error;
/**
* Determines whether a file is a RAR archive by reading the signature
*
* @param filePath Path to the file being checked
*
* @return YES if the file exists and contains a signature indicating it is a RAR archive
*/
+ (BOOL)pathIsARAR:(NSString *)filePath;
/**
* Determines whether a file is a RAR archive by reading the signature
*
* @param fileURL URL of the file being checked
*
* @return YES if the file exists and contains a signature indicating it is a RAR archive
*/
+ (BOOL)urlIsARAR:(NSURL *)fileURL;
/**
* Lists the names of the files in the archive
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return Returns a list of NSString containing the paths within the archive's contents, or nil if an error was encountered
*/
- (nullable NSArray<NSString*> *)listFilenames:(NSError **)error;
/**
* Lists the various attributes of each file in the archive
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return Returns a list of URKFileInfo objects, which contain metadata about the archive's files, or nil if an error was encountered
*/
- (nullable NSArray<URKFileInfo*> *)listFileInfo:(NSError **)error;
/**
* Iterates the header of the archive, calling the block with each archived file's info.
*
* WARNING: There is no filtering of duplicate header entries. If a file is listed twice, `action`
* will be called twice with that file's path
*
* @param action The action to perform using the data. Must be non-nil
*
* - *fileInfo* The metadata of the file within the archive
* - *stop* Set to YES to stop reading the archive
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return Returns NO if an error was encountered
*/
- (BOOL) iterateFileInfo:(void(^)(URKFileInfo *fileInfo, BOOL *stop))action
error:(NSError **)error;
/**
* Lists the URLs of volumes in a single- or multi-volume archive
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return Returns the list of URLs of all volumes of the archive
*/
- (nullable NSArray<NSURL*> *)listVolumeURLs:(NSError **)error;
/**
* Writes all files in the archive to the given path. Supports NSProgress for progress reporting, which also
* allows cancellation in the middle of extraction. Use the progress property (as explained in the README) to
* retrieve more detailed information, such as the current file being extracted, number of files extracted,
* and the URKFileInfo instance being extracted
*
* @param filePath The destination path of the unarchived files
* @param overwrite YES to overwrite files in the destination directory, NO otherwise
* @param error Contains an NSError object when there was an error reading the archive
*
* @return YES on successful extraction, NO if an error was encountered
*/
- (BOOL)extractFilesTo:(NSString *)filePath
overwrite:(BOOL)overwrite
error:(NSError **)error;
/**
* **DEPRECATED:** Writes all files in the archive to the given path
*
* @param filePath The destination path of the unarchived files
* @param overwrite YES to overwrite files in the destination directory, NO otherwise
* @param progressBlock Called every so often to report the progress of the extraction
*
* - *currentFile* The info about the file that's being extracted
* - *percentArchiveDecompressed* The percentage of the archive that has been decompressed
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return YES on successful extraction, NO if an error was encountered
*/
- (BOOL)extractFilesTo:(NSString *)filePath
overwrite:(BOOL)overwrite
progress:(nullable void (^)(URKFileInfo *currentFile, CGFloat percentArchiveDecompressed))progressBlock
error:(NSError **)error __deprecated_msg("Use -extractFilesTo:overwrite:error: instead, and if using the progress block, replace with NSProgress as described in the README");
/**
* Unarchive a single file from the archive into memory. Supports NSProgress for progress reporting, which also
* allows cancellation in the middle of extraction
*
* @param fileInfo The info of the file within the archive to be expanded. Only the filename property is used
* @param error Contains an NSError object when there was an error reading the archive
*
* @return An NSData object containing the bytes of the file, or nil if an error was encountered
*/
- (nullable NSData *)extractData:(URKFileInfo *)fileInfo
error:(NSError **)error;
/**
* **DEPRECATED:** Unarchive a single file from the archive into memory
*
* @param fileInfo The info of the file within the archive to be expanded. Only the filename property is used
* @param progressBlock Called every so often to report the progress of the extraction
*
* - *percentDecompressed* The percentage of the archive that has been decompressed
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return An NSData object containing the bytes of the file, or nil if an error was encountered
*/
- (nullable NSData *)extractData:(URKFileInfo *)fileInfo
progress:(nullable void (^)(CGFloat percentDecompressed))progressBlock
error:(NSError **)error __deprecated_msg("Use -extractData:error: instead, and if using the progress block, replace with NSProgress as described in the README");
/**
* Unarchive a single file from the archive into memory. Supports NSProgress for progress reporting, which also
* allows cancellation in the middle of extraction
*
* @param filePath The path of the file within the archive to be expanded
*
* - *percentDecompressed* The percentage of the file that has been decompressed
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return An NSData object containing the bytes of the file, or nil if an error was encountered
*/
- (nullable NSData *)extractDataFromFile:(NSString *)filePath
error:(NSError **)error;
/**
* **DEPRECATED:** Unarchive a single file from the archive into memory
*
* @param filePath The path of the file within the archive to be expanded
* @param progressBlock Called every so often to report the progress of the extraction
*
* - *percentDecompressed* The percentage of the file that has been decompressed
*
* @param error Contains an NSError object when there was an error reading the archive
*
* @return An NSData object containing the bytes of the file, or nil if an error was encountered
*/
- (nullable NSData *)extractDataFromFile:(NSString *)filePath
progress:(nullable void (^)(CGFloat percentDecompressed))progressBlock
error:(NSError **)error __deprecated_msg("Use -extractDataFromFile:error: instead, and if using the progress block, replace with NSProgress as described in the README");
/**
* Loops through each file in the archive in alphabetical order, allowing you to perform an
* action using its info. Supports NSProgress for progress reporting, which also allows
* cancellation of the operation in the middle
*
* @param action The action to perform using the data
*
* - *fileInfo* The metadata of the file within the archive
* - *stop* Set to YES to stop reading the archive
*
* @param error Contains an error if any was returned
*
* @return YES if no errors were encountered, NO otherwise
*/
- (BOOL)performOnFilesInArchive:(void(^)(URKFileInfo *fileInfo, BOOL *stop))action
error:(NSError **)error;
/**
* Extracts each file in the archive into memory, allowing you to perform an action
* on it (not sorted). Supports NSProgress for progress reporting, which also allows
* cancellation of the operation in the middle
*
* @param action The action to perform using the data
*
* - *fileInfo* The metadata of the file within the archive
* - *fileData* The full data of the file in the archive
* - *stop* Set to YES to stop reading the archive
*
* @param error Contains an error if any was returned
*
* @return YES if no errors were encountered, NO otherwise
*/
- (BOOL)performOnDataInArchive:(void(^)(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop))action
error:(NSError **)error;
/**
* Unarchive a single file from the archive into memory. Supports NSProgress for progress reporting, which also
* allows cancellation in the middle of extraction
*
* @param filePath The path of the file within the archive to be expanded
* @param error Contains an NSError object when there was an error reading the archive
* @param action The block to run for each chunk of data, each of size <= bufferSize
*
* - *dataChunk* The data read from the archived file. Read bytes and length to write the data
* - *percentDecompressed* The percentage of the file that has been decompressed
*
* @return YES if all data was read successfully, NO if an error was encountered
*/
- (BOOL)extractBufferedDataFromFile:(NSString *)filePath
error:(NSError **)error
action:(void(^)(NSData *dataChunk, CGFloat percentDecompressed))action;
/**
* YES if archive protected with a password, NO otherwise
*/
- (BOOL)isPasswordProtected;
/**
* Tests whether the provided password unlocks the archive
*
* @return YES if correct password or archive is not password protected, NO if password is wrong
*/
- (BOOL)validatePassword;
/**
Iterate through the archive, checking for any errors, including CRC mismatches between
the archived file and its header
@return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_)
*/
- (BOOL)checkDataIntegrity;
/**
Iterate through the archive, checking for any errors, including CRC mismatches between
the archived file and its header. If any file's CRC doesn't match, run the given block
to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a
security risk. The block is intended to prompt the user, which is why it's forced onto
the main thread, rather than making a design-time decision
@param ignoreCRCMismatches This block, called on the main thread, allows a consuming API to
prompt the user whether or not he'd like to ignore CRC mismatches.
This block is called the first time a CRC mismatch is detected, if
at all. It won't be called if all CRCs match. If this returns YES,
then all further CRC mismatches will be ignored for the
archive instance
@return YES if the data is all correct and/or the block returns YES; returns false if
any check failed and the given block also returns NO
*/
- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches;
/**
Check a particular file, to determine if its data matches the CRC
checksum stored at the time it written
@param filePath The file in the archive to check
@return YES if the data is correct, false if any check failed
*/
- (BOOL)checkDataIntegrityOfFile:(NSString *)filePath;
@end
NS_ASSUME_NONNULL_END