├── ArtworkDetailViewController.xib ├── ArtworkViewController.xib ├── Classes ├── AppDelegate.h ├── AppDelegate.m ├── ArtworkDetailViewController.h ├── ArtworkDetailViewController.m ├── ArtworkViewController.h ├── ArtworkViewController.m ├── EmojiImageView.h ├── EmojiImageView.m ├── FindSymbol.c ├── FindSymbol.h ├── GlossyButtonViewController.h ├── GlossyButtonViewController.m ├── IPAArchive.h ├── IPAArchive.m ├── IPAViewController.h ├── IPAViewController.m ├── NSString+IPAArchive.h └── NSString+IPAArchive.m ├── Default-568h@2x.png ├── External └── ZipKit │ ├── COPYING.TXT │ ├── Credits.html │ ├── GMAppleDouble+ZKAdditions.h │ ├── GMAppleDouble+ZKAdditions.m │ ├── MacFUSE │ ├── COPYING.TXT │ ├── GMAppleDouble.h │ └── GMAppleDouble.m │ ├── NSData+ZKAdditions.h │ ├── NSData+ZKAdditions.m │ ├── NSDate+ZKAdditions.h │ ├── NSDate+ZKAdditions.m │ ├── NSDictionary+ZKAdditions.h │ ├── NSDictionary+ZKAdditions.m │ ├── NSFileHandle+ZKAdditions.h │ ├── NSFileHandle+ZKAdditions.m │ ├── NSFileManager+ZKAdditions.h │ ├── NSFileManager+ZKAdditions.m │ ├── NSString+ZKAdditions.h │ ├── NSString+ZKAdditions.m │ ├── ZKArchive.h │ ├── ZKArchive.m │ ├── ZKCDHeader.h │ ├── ZKCDHeader.m │ ├── ZKCDTrailer.h │ ├── ZKCDTrailer.m │ ├── ZKCDTrailer64.h │ ├── ZKCDTrailer64.m │ ├── ZKCDTrailer64Locator.h │ ├── ZKCDTrailer64Locator.m │ ├── ZKDataArchive.h │ ├── ZKDataArchive.m │ ├── ZKDefs.h │ ├── ZKDefs.m │ ├── ZKFileArchive.h │ ├── ZKFileArchive.m │ ├── ZKLFHeader.h │ ├── ZKLFHeader.m │ ├── ZKLog.h │ └── ZKLog.m ├── IPAViewController.xib ├── MainWindow.xib ├── README.md ├── Resources ├── Artwork.png ├── Artwork@2x.png ├── Checkerboard.png ├── Emoji.png ├── Emoji@2x.png ├── GlossyButton.png ├── GlossyButton@2x.png ├── IPA.png ├── IPA@2x.png ├── Icon.png ├── Icon@2x.png ├── Shared │ ├── UITintedGlassButtonHighlight@2x.png │ ├── UITintedGlassButtonMask@2x.png │ └── UITintedGlassButtonShadow@2x.png ├── Unknown.png └── Unknown@2x.png ├── Screenshots ├── Artwork.png ├── Emoji.png ├── GlossyButton.png ├── IPA.png └── UISwitch.png ├── iOS Artwork Extractor.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── iOS_Artwork_Extractor-Info.plist ├── iOS_Artwork_Extractor_Prefix.pch └── main.m /ArtworkDetailViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1024 5 | 9L30 6 | 680 7 | 949.54 8 | 353.00 9 | 10 | YES 11 | 12 | 13 | YES 14 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 15 | 16 | 17 | YES 18 | 19 | YES 20 | 21 | 22 | YES 23 | 24 | 25 | 26 | YES 27 | 28 | IBFilesOwner 29 | 30 | 31 | IBFirstResponder 32 | 33 | 34 | 35 | 274 36 | 37 | YES 38 | 39 | 40 | 301 41 | {{20, 20}, {200, 230}} 42 | 43 | 44 | 3 45 | MCAwAA 46 | 47 | 2 48 | 49 | 50 | NO 51 | NO 52 | 4 53 | NO 54 | 55 | 56 | {{40, -84}, {320, 460}} 57 | 58 | 3 59 | MC43NQA 60 | 61 | 62 | NO 63 | 64 | 65 | Save 66 | 1 67 | 68 | 69 | 70 | 71 | YES 72 | 73 | 74 | saveButton 75 | 76 | 77 | 78 | 5 79 | 80 | 81 | 82 | save 83 | 84 | 85 | 86 | 7 87 | 88 | 89 | 90 | view 91 | 92 | 93 | 94 | 9 95 | 96 | 97 | 98 | imageView 99 | 100 | 101 | 102 | 10 103 | 104 | 105 | 106 | 107 | YES 108 | 109 | 0 110 | 111 | YES 112 | 113 | 114 | 115 | 116 | 117 | -1 118 | 119 | 120 | RmlsZSdzIE93bmVyA 121 | 122 | 123 | -2 124 | 125 | 126 | 127 | 128 | 4 129 | 130 | 131 | 132 | 133 | 8 134 | 135 | 136 | YES 137 | 138 | 139 | 140 | 141 | 142 | 3 143 | 144 | 145 | 146 | 147 | 148 | 149 | YES 150 | 151 | YES 152 | -1.CustomClassName 153 | -2.CustomClassName 154 | 3.IBEditorWindowLastContentRect 155 | 3.IBPluginDependency 156 | 4.IBPluginDependency 157 | 8.IBEditorWindowLastContentRect 158 | 8.IBPluginDependency 159 | 160 | 161 | YES 162 | ArtworkDetailViewController 163 | UIResponder 164 | {{0, 274}, {320, 460}} 165 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 166 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 167 | {{0, 285}, {320, 460}} 168 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 169 | 170 | 171 | 172 | YES 173 | 174 | YES 175 | 176 | 177 | YES 178 | 179 | 180 | 181 | 182 | YES 183 | 184 | YES 185 | 186 | 187 | YES 188 | 189 | 190 | 191 | 10 192 | 193 | 194 | 195 | YES 196 | 197 | ArtworkDetailViewController 198 | UIViewController 199 | 200 | save 201 | id 202 | 203 | 204 | YES 205 | 206 | YES 207 | imageView 208 | saveButton 209 | 210 | 211 | YES 212 | UIImageView 213 | UIBarButtonItem 214 | 215 | 216 | 217 | IBProjectSource 218 | Classes/ArtworkDetailViewController.h 219 | 220 | 221 | 222 | ArtworkDetailViewController 223 | UIViewController 224 | 225 | IBUserSource 226 | 227 | 228 | 229 | 230 | 231 | 0 232 | iOS Artwork Extractor.xcodeproj 233 | 3 234 | 3.1 235 | 236 | 237 | -------------------------------------------------------------------------------- /ArtworkViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 10K549 6 | 1938 7 | 1038.36 8 | 461.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 933 12 | 13 | 14 | IBUISearchDisplayController 15 | IBUIProgressView 16 | IBUITableView 17 | IBUIBarButtonItem 18 | IBUISearchBar 19 | IBProxyObject 20 | 21 | 22 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 23 | 24 | 25 | PluginDependencyRecalculationVersion 26 | 27 | 28 | 29 | 30 | IBFilesOwner 31 | IBCocoaTouchFramework 32 | 33 | 34 | IBFirstResponder 35 | IBCocoaTouchFramework 36 | 37 | 38 | 39 | 274 40 | 41 | 42 | 43 | 290 44 | {320, 44} 45 | 46 | 47 | 3 48 | IBCocoaTouchFramework 49 | 50 | IBCocoaTouchFramework 51 | 52 | 53 | 54 | {{0, 64}, {320, 367}} 55 | 56 | 57 | 58 | 59 | 3 60 | MC43NQA 61 | 62 | 2 63 | 64 | 65 | NO 66 | YES 67 | NO 68 | 69 | 70 | NO 71 | 72 | 73 | IBCocoaTouchFramework 74 | NO 75 | 1 76 | 0 77 | YES 78 | 44 79 | 22 80 | 22 81 | 82 | 83 | 84 | IBCocoaTouchFramework 85 | 86 | 87 | 88 | 292 89 | {100, 11} 90 | 91 | 92 | NO 93 | YES 94 | YES 95 | IBCocoaTouchFramework 96 | 1 97 | 98 | 99 | Save All 100 | IBCocoaTouchFramework 101 | 1 102 | 103 | 104 | 105 | 106 | 107 | 108 | view 109 | 110 | 111 | 112 | 9 113 | 114 | 115 | 116 | searchDisplayController 117 | 118 | 119 | 120 | 22 121 | 122 | 123 | 124 | progressView 125 | 126 | 127 | 128 | 33 129 | 130 | 131 | 132 | saveAllButton 133 | 134 | 135 | 136 | 34 137 | 138 | 139 | 140 | dataSource 141 | 142 | 143 | 144 | 29 145 | 146 | 147 | 148 | delegate 149 | 150 | 151 | 152 | 30 153 | 154 | 155 | 156 | delegate 157 | 158 | 159 | 160 | 27 161 | 162 | 163 | 164 | searchContentsController 165 | 166 | 167 | 168 | 23 169 | 170 | 171 | 172 | searchResultsDataSource 173 | 174 | 175 | 176 | 24 177 | 178 | 179 | 180 | searchResultsDelegate 181 | 182 | 183 | 184 | 25 185 | 186 | 187 | 188 | delegate 189 | 190 | 191 | 192 | 26 193 | 194 | 195 | 196 | searchBar 197 | 198 | 199 | 200 | 21 201 | 202 | 203 | 204 | saveAll 205 | 206 | 207 | 208 | 35 209 | 210 | 211 | 212 | 213 | 214 | 0 215 | 216 | 217 | 218 | 219 | 220 | -1 221 | 222 | 223 | File's Owner 224 | 225 | 226 | -2 227 | 228 | 229 | 230 | 231 | 3 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 20 240 | 241 | 242 | 243 | 244 | 19 245 | 246 | 247 | 248 | 249 | 31 250 | 251 | 252 | 253 | 254 | 32 255 | 256 | 257 | 258 | 259 | 260 | 261 | ArtworkViewController 262 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 263 | UIResponder 264 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 265 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 266 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 267 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 268 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 269 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 270 | 271 | 272 | 273 | 274 | 275 | 35 276 | 277 | 278 | 279 | 280 | ArtworkViewController 281 | UITableViewController 282 | 283 | saveAll 284 | id 285 | 286 | 287 | saveAll 288 | 289 | saveAll 290 | id 291 | 292 | 293 | 294 | UIProgressView 295 | UIBarButtonItem 296 | 297 | 298 | 299 | progressView 300 | UIProgressView 301 | 302 | 303 | saveAllButton 304 | UIBarButtonItem 305 | 306 | 307 | 308 | IBProjectSource 309 | ./Classes/ArtworkViewController.h 310 | 311 | 312 | 313 | 314 | 0 315 | IBCocoaTouchFramework 316 | YES 317 | 3 318 | 933 319 | 320 | 321 | -------------------------------------------------------------------------------- /Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 19.02.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | { 13 | UIWindow *window; 14 | UITabBarController *tabBarController; 15 | } 16 | 17 | @property (nonatomic, retain) IBOutlet UIWindow *window; 18 | @property (nonatomic, retain) IBOutlet UITabBarController *tabBarController; 19 | 20 | - (NSString *) saveDirectory:(NSString *)subDirectory; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 19.02.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import 12 | #import "IPAViewController.h" 13 | 14 | @implementation AppDelegate 15 | 16 | @synthesize window; 17 | @synthesize tabBarController; 18 | 19 | - (void) applicationDidFinishLaunching:(UIApplication *)application 20 | { 21 | self.window.frame = [[UIScreen mainScreen] bounds]; 22 | 23 | NSString *mobileApplicationsPath = NSProcessInfo.processInfo.environment[@"MOBILE_APPLICATIONS_DIRECTORY"]; 24 | if (!mobileApplicationsPath) 25 | { 26 | NSString *homeDirectory = [self homeDirectory]; 27 | for (NSString *path in @[ @"Music/iTunes/Mobile Applications", @"Music/iTunes/iTunes Media/Mobile Applications" ]) 28 | { 29 | NSString *fullPath = [homeDirectory stringByAppendingPathComponent:path]; 30 | if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath]) 31 | mobileApplicationsPath = fullPath; 32 | } 33 | } 34 | if (!mobileApplicationsPath) 35 | NSLog(@"'Mobile Applications' directory not found."); 36 | 37 | NSArray *mobileApplications = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mobileApplicationsPath error:NULL]; 38 | NSMutableArray *archives = [NSMutableArray array]; 39 | for (NSString *ipaFile in mobileApplications) 40 | { 41 | NSString *ipaPath = [mobileApplicationsPath stringByAppendingPathComponent:ipaFile]; 42 | [archives addObject:ipaPath]; 43 | } 44 | 45 | NSUInteger ipaViewControllerIndex = 2; 46 | if ([archives count] == 0) 47 | { 48 | NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers]; 49 | [viewControllers removeObjectAtIndex:ipaViewControllerIndex]; 50 | self.tabBarController.viewControllers = viewControllers; 51 | } 52 | else 53 | { 54 | IPAViewController *ipaViewController = (IPAViewController *)[[self.tabBarController.viewControllers objectAtIndex:ipaViewControllerIndex] topViewController]; 55 | ipaViewController.archives = archives; 56 | } 57 | 58 | if (!NSClassFromString(@"UIGlassButton")) 59 | { 60 | NSLog(@"The UIGlassButton class is not available, use the iOS 5.0 simulator to generate glossy buttons."); 61 | NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers]; 62 | [viewControllers removeLastObject]; 63 | self.tabBarController.viewControllers = viewControllers; 64 | } 65 | 66 | if ([self.window respondsToSelector:@selector(setRootViewController:)]) 67 | self.window.rootViewController = self.tabBarController; 68 | else 69 | [self.window addSubview:self.tabBarController.view]; 70 | } 71 | 72 | - (NSString *) homeDirectory 73 | { 74 | for (NSString *simulatorHostHomeVariable in @[ @"IPHONE_SIMULATOR_HOST_HOME", @"SIMULATOR_HOST_HOME" ]) 75 | { 76 | char *simulatorHostHome = getenv([simulatorHostHomeVariable UTF8String]); 77 | if (simulatorHostHome) 78 | return @(simulatorHostHome); 79 | } 80 | 81 | char *lognameEnv = getenv("LOGNAME"); 82 | if (lognameEnv) 83 | { 84 | struct passwd *pw = getpwnam(lognameEnv); 85 | return pw ? [NSString stringWithCString:pw->pw_dir encoding:NSUTF8StringEncoding] : [@"/Users" stringByAppendingPathComponent:@(lognameEnv)]; 86 | } 87 | else 88 | { 89 | return @"/Users/Shared"; 90 | } 91 | } 92 | 93 | - (NSString *) saveDirectory:(NSString *)subDirectory 94 | { 95 | NSString *saveDirectory = NSProcessInfo.processInfo.environment[@"ARTWORK_DIRECTORY"]; 96 | 97 | if (!saveDirectory) 98 | { 99 | #if TARGET_IPHONE_SIMULATOR 100 | saveDirectory = [NSString stringWithFormat:@"%@/Desktop/%@ %@ artwork", [self homeDirectory], [UIDevice currentDevice].model, [UIDevice currentDevice].systemVersion]; 101 | #else 102 | saveDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 103 | #endif 104 | } 105 | if (subDirectory) 106 | saveDirectory = [saveDirectory stringByAppendingPathComponent:subDirectory]; 107 | 108 | if (![[NSFileManager defaultManager] fileExistsAtPath:saveDirectory]) 109 | { 110 | NSError *error = nil; 111 | BOOL created = [[NSFileManager defaultManager] createDirectoryAtPath:saveDirectory withIntermediateDirectories:YES attributes:nil error:&error]; 112 | if (!created) 113 | NSLog(@"%@\n%@", error, error.userInfo); 114 | } 115 | 116 | return saveDirectory; 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /Classes/ArtworkDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArtworkDetailViewController.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 05.03.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ArtworkDetailViewController : UIViewController 12 | { 13 | IBOutlet UIBarButtonItem *saveButton; 14 | IBOutlet UIImageView *imageView; 15 | 16 | NSDictionary *imageInfo; 17 | } 18 | 19 | - (id) initWithImageInfo:(NSDictionary *)anImageInfo; 20 | 21 | @property (nonatomic, retain) IBOutlet UIBarButtonItem *saveButton; 22 | @property (nonatomic, retain) IBOutlet UIImageView *imageView; 23 | 24 | - (IBAction) save; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/ArtworkDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArtworkDetailViewController.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 05.03.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import "ArtworkDetailViewController.h" 10 | 11 | 12 | @interface ArtworkDetailViewController () 13 | @property (nonatomic, retain) NSDictionary *imageInfo; 14 | @property (nonatomic, readonly) UIImage *image; 15 | @property (nonatomic, readonly) NSString *name; 16 | @end 17 | 18 | 19 | @implementation ArtworkDetailViewController 20 | 21 | @synthesize saveButton, imageView; 22 | @synthesize imageInfo; 23 | 24 | - (id) initWithImageInfo:(NSDictionary *)anImageInfo 25 | { 26 | if (!(self = [super initWithNibName:@"ArtworkDetailViewController" bundle:nil])) 27 | return nil; 28 | 29 | self.imageInfo = anImageInfo; 30 | 31 | return self; 32 | } 33 | 34 | - (void) dealloc 35 | { 36 | self.saveButton = nil; 37 | self.imageView = nil; 38 | self.imageInfo = nil; 39 | [super dealloc]; 40 | } 41 | 42 | - (UIImage *) image 43 | { 44 | return [self.imageInfo objectForKey:@"image"]; 45 | } 46 | 47 | - (NSString *) name 48 | { 49 | return [self.imageInfo objectForKey:@"name"]; 50 | } 51 | 52 | - (void) viewWillAppear:(BOOL)animated 53 | { 54 | self.title = [self.name stringByDeletingPathExtension]; 55 | 56 | self.imageView.image = self.image; 57 | [self.imageView sizeToFit]; 58 | CGFloat posX = roundf((CGRectGetWidth(self.view.frame) - CGRectGetWidth(self.imageView.frame)) / 2.0f); 59 | CGFloat posY = roundf((CGRectGetHeight(self.view.frame) - CGRectGetHeight(self.imageView.frame)) / 2.0f); 60 | self.imageView.frame = CGRectMake(posX, posY, CGRectGetWidth(self.imageView.frame), CGRectGetHeight(self.imageView.frame)); 61 | 62 | [self.navigationItem setRightBarButtonItem:self.saveButton animated:animated]; 63 | } 64 | 65 | - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 66 | { 67 | static UIColor *originalColor = nil; 68 | if (originalColor == nil) 69 | originalColor = [self.view.backgroundColor retain]; 70 | 71 | if ([self.view.backgroundColor isEqual:originalColor]) 72 | self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Checkerboard.png"]]; 73 | else 74 | self.view.backgroundColor = originalColor; 75 | } 76 | 77 | - (IBAction) save 78 | { 79 | NSUInteger artworkViewControllerIndex = [self.navigationController.viewControllers count] - 2; 80 | id artworkViewController = [self.navigationController.viewControllers objectAtIndex:artworkViewControllerIndex]; 81 | [artworkViewController performSelector:@selector(saveImage:) withObject:imageInfo]; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /Classes/ArtworkViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArtworkViewController.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 19.02.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class IPAArchive; 12 | 13 | @interface ArtworkViewController : UITableViewController 14 | { 15 | IBOutlet UIProgressView *progressView; 16 | IBOutlet UIBarButtonItem *saveAllButton; 17 | 18 | NSMutableDictionary *artwork; 19 | NSMutableDictionary *bundles; // dictionary of array of cells, keys are section titles (bundle names) 20 | 21 | NSIndexPath *firstCellIndexPath; 22 | 23 | NSUInteger saveCounter; 24 | } 25 | 26 | @property (nonatomic, retain) IBOutlet UIProgressView *progressView; 27 | @property (nonatomic, retain) IBOutlet UIBarButtonItem *saveAllButton; 28 | @property (nonatomic, readonly) NSDictionary *artwork; 29 | @property (nonatomic, retain) NSMutableDictionary *bundles; 30 | @property (nonatomic, retain) NSIndexPath *firstCellIndexPath; 31 | @property (nonatomic, assign) NSUInteger saveCounter; 32 | 33 | - (id) initWithArchive:(IPAArchive *)archive; 34 | @property (nonatomic, retain) IPAArchive *archive; 35 | 36 | - (IBAction) saveAll; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Classes/EmojiImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // EmojiImageView.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 09.03.12. 6 | // Copyright (c) 2012 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | @interface EmojiImageView : UIView 10 | 11 | - (id) initWithFrame:(CGRect)frame emoji:(id)emoji; 12 | 13 | - (UIImage *) image; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/EmojiImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // EmojiImageView.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 09.03.12. 6 | // Copyright (c) 2012 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | #import "EmojiImageView.h" 10 | 11 | @interface EmojiImageView () 12 | @property (nonatomic, retain) id emoji; 13 | @end 14 | 15 | @implementation EmojiImageView 16 | 17 | @synthesize emoji = _emoji; 18 | 19 | - (id) initWithFrame:(CGRect)frame emoji:(id)emoji 20 | { 21 | if (!(self = [super initWithFrame:frame])) 22 | return nil; 23 | 24 | self.backgroundColor = [UIColor clearColor]; 25 | self.emoji = emoji; 26 | 27 | return self; 28 | } 29 | 30 | - (void) dealloc 31 | { 32 | self.emoji = nil; 33 | [super dealloc]; 34 | } 35 | 36 | - (void) drawRect:(CGRect)rect 37 | { 38 | UIFont *emojiFont = [UIFont fontWithName:@"AppleColorEmoji" size:CGRectGetHeight(self.frame)]; 39 | NSString *emojiString = [self.emoji valueForKey:@"emojiString"]; 40 | [emojiString drawAtPoint:CGPointZero withFont:emojiFont]; 41 | } 42 | 43 | - (UIImage *) image 44 | { 45 | UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0f); 46 | CGContextRef context = UIGraphicsGetCurrentContext(); 47 | [self.layer renderInContext:context]; 48 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 49 | UIGraphicsEndImageContext(); 50 | 51 | return image; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Classes/FindSymbol.c: -------------------------------------------------------------------------------- 1 | #import "FindSymbol.h" 2 | 3 | #import 4 | #import 5 | 6 | // Adapted from MoreAddrToSym / GetFunctionName() 7 | // http://www.opensource.apple.com/source/openmpi/openmpi-8/openmpi/opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreAddrToSym.c 8 | void *FindSymbol(struct mach_header *image, const char *symbol) 9 | { 10 | if ((image == NULL) || (symbol == NULL)) 11 | return NULL; 12 | 13 | struct segment_command *seg_linkedit = NULL; 14 | struct segment_command *seg_text = NULL; 15 | struct symtab_command *symtab = NULL; 16 | unsigned int index; 17 | 18 | struct load_command *cmd = (struct load_command*)((char*)image + sizeof(struct mach_header)); 19 | for (index = 0; index < image->ncmds; index += 1, cmd = (struct load_command*)((char*)cmd + cmd->cmdsize)) 20 | { 21 | switch(cmd->cmd) 22 | { 23 | case LC_SEGMENT: 24 | if (!strcmp(((struct segment_command*)cmd)->segname, SEG_TEXT)) 25 | seg_text = (struct segment_command*)cmd; 26 | else if (!strcmp(((struct segment_command*)cmd)->segname, SEG_LINKEDIT)) 27 | seg_linkedit = (struct segment_command*)cmd; 28 | break; 29 | 30 | case LC_SYMTAB: 31 | symtab = (struct symtab_command*)cmd; 32 | break; 33 | } 34 | } 35 | 36 | if ((seg_text == NULL) || (seg_linkedit == NULL) || (symtab == NULL)) 37 | return NULL; 38 | 39 | unsigned int vm_slide = (unsigned long)image - (unsigned long)seg_text->vmaddr; 40 | unsigned int file_slide = ((unsigned long)seg_linkedit->vmaddr - (unsigned long)seg_text->vmaddr) - seg_linkedit->fileoff; 41 | struct nlist *symbase = (struct nlist*)((unsigned long)image + (symtab->symoff + file_slide)); 42 | char *strings = (char*)((unsigned long)image + (symtab->stroff + file_slide)); 43 | struct nlist *sym; 44 | 45 | for (index = 0, sym = symbase; index < symtab->nsyms; index += 1, sym += 1) 46 | { 47 | if (sym->n_un.n_strx != 0 && !strcmp(symbol, strings + sym->n_un.n_strx)) 48 | { 49 | unsigned int address = vm_slide + sym->n_value; 50 | if (sym->n_desc & N_ARM_THUMB_DEF) 51 | return (void*)(address | 1); 52 | else 53 | return (void*)(address); 54 | } 55 | } 56 | 57 | return NULL; 58 | } 59 | -------------------------------------------------------------------------------- /Classes/FindSymbol.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | void *FindSymbol(struct mach_header *image, const char *symbol); 4 | -------------------------------------------------------------------------------- /Classes/GlossyButtonViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GlossyButtonViewController.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 19.02.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GlossyButtonViewController : UIViewController 12 | { 13 | IBOutlet UITextField *titleTextField; 14 | IBOutlet UISlider *fontSizeSlider; 15 | IBOutlet UILabel *fontSizeLabel; 16 | IBOutlet UISlider *widthSlider; 17 | IBOutlet UILabel *widthLabel; 18 | IBOutlet UISlider *heightSlider; 19 | IBOutlet UILabel *heightLabel; 20 | IBOutlet UISlider *redSlider; 21 | IBOutlet UILabel *redLabel; 22 | IBOutlet UISlider *greenSlider; 23 | IBOutlet UILabel *greenLabel; 24 | IBOutlet UISlider *blueSlider; 25 | IBOutlet UILabel *blueLabel; 26 | IBOutlet UISlider *alphaSlider; 27 | IBOutlet UILabel *alphaLabel; 28 | 29 | UIButton *glossyButton; 30 | } 31 | 32 | @property (nonatomic, retain) IBOutlet UITextField *titleTextField; 33 | @property (nonatomic, retain) IBOutlet UISlider *fontSizeSlider; 34 | @property (nonatomic, retain) IBOutlet UILabel *fontSizeLabel; 35 | @property (nonatomic, retain) IBOutlet UISlider *widthSlider; 36 | @property (nonatomic, retain) IBOutlet UILabel *widthLabel; 37 | @property (nonatomic, retain) IBOutlet UISlider *heightSlider; 38 | @property (nonatomic, retain) IBOutlet UILabel *heightLabel; 39 | @property (nonatomic, retain) IBOutlet UISlider *redSlider; 40 | @property (nonatomic, retain) IBOutlet UILabel *redLabel; 41 | @property (nonatomic, retain) IBOutlet UISlider *greenSlider; 42 | @property (nonatomic, retain) IBOutlet UILabel *greenLabel; 43 | @property (nonatomic, retain) IBOutlet UISlider *blueSlider; 44 | @property (nonatomic, retain) IBOutlet UILabel *blueLabel; 45 | @property (nonatomic, retain) IBOutlet UISlider *alphaSlider; 46 | @property (nonatomic, retain) IBOutlet UILabel *alphaLabel; 47 | 48 | @property (nonatomic, retain) UIButton *glossyButton; 49 | 50 | - (IBAction) changeColor:(UISlider *)slider; 51 | - (IBAction) changeSize:(UISlider *)slider; 52 | - (IBAction) changeFontSize:(UISlider *)slider; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Classes/GlossyButtonViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 19.02.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import "GlossyButtonViewController.h" 10 | #import "AppDelegate.h" 11 | 12 | #import 13 | #import "FindSymbol.h" 14 | #import 15 | #import 16 | 17 | @implementation GlossyButtonViewController 18 | 19 | static UIImage*(*GetTintedGlassButtonImage)(UIColor*, UIControlState) = NULL; 20 | 21 | @synthesize titleTextField; 22 | @synthesize fontSizeSlider, fontSizeLabel; 23 | @synthesize widthSlider, widthLabel; 24 | @synthesize heightSlider, heightLabel; 25 | @synthesize redSlider, redLabel; 26 | @synthesize greenSlider, greenLabel; 27 | @synthesize blueSlider, blueLabel; 28 | @synthesize alphaSlider, alphaLabel; 29 | @synthesize glossyButton; 30 | 31 | + (void) initialize 32 | { 33 | if (self != [GlossyButtonViewController class]) 34 | return; 35 | 36 | for(uint32_t i = 0; i < _dyld_image_count(); i++) 37 | { 38 | if (strstr(_dyld_get_image_name(i), "UIKit.framework")) 39 | { 40 | struct mach_header* header = (struct mach_header*)_dyld_get_image_header(i); 41 | GetTintedGlassButtonImage = FindSymbol(header, "_GetTintedGlassButtonImage"); 42 | 43 | NSMutableDictionary **__images = FindSymbol(header, "___images"); 44 | if (__images && [[UIScreen mainScreen] scale] > 1) 45 | { 46 | for (NSString *glassButtonImageName in [NSArray arrayWithObjects:/*@"UITintedGlassButtonGradient.png",*/ @"UITintedGlassButtonHighlight.png", @"UITintedGlassButtonMask.png", @"UITintedGlassButtonShadow.png", nil]) 47 | [*__images setObject:[UIImage imageNamed:glassButtonImageName] forKey:glassButtonImageName]; 48 | } 49 | break; 50 | } 51 | } 52 | } 53 | 54 | - (void) sizeToFit 55 | { 56 | CGSize fitSize = [self.glossyButton sizeThatFits:self.glossyButton.bounds.size]; 57 | if ((int)fitSize.width % 2 == 1) 58 | fitSize.width++; 59 | self.widthSlider.value = fitSize.width; 60 | self.heightSlider.value = fitSize.height; 61 | [self.glossyButton sizeToFit]; 62 | 63 | [self changeSize:nil]; 64 | } 65 | 66 | - (void) viewDidLoad 67 | { 68 | self.redSlider.value = 0.25f; 69 | self.greenSlider.value = 0.5f; 70 | self.blueSlider.value = 0.75f; 71 | self.alphaSlider.value = 1.0f; 72 | 73 | self.glossyButton = [[[NSClassFromString(@"UIGlassButton") alloc] initWithFrame:CGRectZero] autorelease]; 74 | [self.glossyButton setTitle:self.titleTextField.text forState:UIControlStateNormal]; 75 | [self.glossyButton addTarget:self action:@selector(save) forControlEvents:UIControlEventTouchUpInside]; 76 | 77 | self.fontSizeSlider.value = self.glossyButton.titleLabel.font.pointSize; 78 | 79 | [self changeColor:nil]; 80 | [self sizeToFit]; 81 | [self changeFontSize:nil]; 82 | 83 | [self.view addSubview:self.glossyButton]; 84 | } 85 | 86 | - (void) viewDidUnload 87 | { 88 | self.titleTextField = nil; 89 | self.widthSlider = nil; 90 | self.widthLabel = nil; 91 | self.heightSlider = nil; 92 | self.heightLabel = nil; 93 | self.redSlider = nil; 94 | self.redLabel = nil; 95 | self.greenSlider = nil; 96 | self.greenLabel = nil; 97 | self.blueSlider = nil; 98 | self.blueLabel = nil; 99 | self.alphaSlider = nil; 100 | self.alphaLabel = nil; 101 | self.glossyButton = nil; 102 | } 103 | 104 | - (IBAction) changeColor:(UISlider *)slider 105 | { 106 | CGFloat red = self.redSlider.value; 107 | CGFloat green = self.greenSlider.value; 108 | CGFloat blue = self.blueSlider.value; 109 | CGFloat alpha = self.alphaSlider.value; 110 | 111 | [self.glossyButton setValue:[UIColor colorWithRed:red green:green blue:blue alpha:alpha] forKey:@"tintColor"]; 112 | 113 | NSString *colorFormat = @"%1$ld\n#%1$02lX"; 114 | self.redLabel.text = [NSString stringWithFormat:colorFormat, lroundf(red * 255)]; 115 | self.greenLabel.text = [NSString stringWithFormat:colorFormat, lroundf(green * 255)]; 116 | self.blueLabel.text = [NSString stringWithFormat:colorFormat, lroundf(blue * 255)]; 117 | self.alphaLabel.text = [NSString stringWithFormat:colorFormat, lroundf(alpha * 255)]; 118 | } 119 | 120 | - (IBAction) changeSize:(UISlider *)slider 121 | { 122 | CGFloat width = roundf(self.widthSlider.value); 123 | CGFloat height = roundf(self.heightSlider.value); 124 | 125 | self.glossyButton.frame = CGRectMake((320 - self.widthSlider.value) / 2.0f, 20, width, height); 126 | 127 | self.widthLabel.text = [NSString stringWithFormat:@"%g", width]; 128 | self.heightLabel.text = [NSString stringWithFormat:@"%g", height]; 129 | } 130 | 131 | - (IBAction) changeFontSize:(UISlider *)slider 132 | { 133 | CGFloat fontSize = roundf(self.fontSizeSlider.value); 134 | UIFont *font = self.glossyButton.titleLabel.font; 135 | self.glossyButton.titleLabel.font = [UIFont fontWithName:font.fontName size:fontSize]; 136 | self.fontSizeLabel.text = [NSString stringWithFormat:@"%g", fontSize]; 137 | } 138 | 139 | - (void) saveButtonInState:(UIControlState)state scale:(CGFloat)scale 140 | { 141 | if (!GetTintedGlassButtonImage) 142 | { 143 | NSLog(@"GetTintedGlassButtonImage function not found"); 144 | return; 145 | } 146 | 147 | NSString *buttonName = @"glossyButton"; 148 | NSString *xSuffix = scale > 1 ? [NSString stringWithFormat:@"@%gx", scale] : @""; 149 | switch (state) 150 | { 151 | case UIControlStateNormal: 152 | buttonName = [NSString stringWithFormat:@"glossyButton-normal%@.png", xSuffix]; 153 | break; 154 | case UIControlStateHighlighted: 155 | buttonName = [NSString stringWithFormat:@"glossyButton-highlighted%@.png", xSuffix]; 156 | break; 157 | case UIControlStateDisabled: 158 | buttonName = [NSString stringWithFormat:@"glossyButton-disabled%@.png", xSuffix]; 159 | break; 160 | default: 161 | break; 162 | } 163 | 164 | // Use dlsym so that it still compiles with the 3.1.3 SDK, could aslo use #if __IPHONE_OS_VERSION_MAX_ALLOWED < 40000 165 | void (*UIGraphicsBeginImageContextWithOptions)(CGSize, BOOL, CGFloat) = dlsym(RTLD_DEFAULT, "UIGraphicsBeginImageContextWithOptions"); 166 | if (UIGraphicsBeginImageContextWithOptions) 167 | UIGraphicsBeginImageContextWithOptions(self.glossyButton.frame.size, NO, scale); 168 | else 169 | UIGraphicsBeginImageContext(self.glossyButton.frame.size); 170 | 171 | UIImage *stretchableImage = GetTintedGlassButtonImage([self.glossyButton valueForKey:@"tintColor"], state); 172 | CGFloat alpha = state == UIControlStateDisabled ? 0.5 : 1.0; 173 | [stretchableImage drawInRect:self.glossyButton.bounds blendMode:kCGBlendModeNormal alpha:alpha]; 174 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 175 | NSData *data = UIImagePNGRepresentation(image); 176 | AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; 177 | [data writeToFile:[[appDelegate saveDirectory:@"UIGlassButton"] stringByAppendingPathComponent:buttonName] atomically:YES]; 178 | 179 | UIGraphicsEndImageContext(); 180 | } 181 | 182 | - (IBAction) save 183 | { 184 | [self saveButtonInState:UIControlStateDisabled scale:1]; 185 | [self saveButtonInState:UIControlStateHighlighted scale:1]; 186 | [self saveButtonInState:UIControlStateNormal scale:1]; 187 | 188 | CGFloat scale = [[UIScreen mainScreen] scale]; 189 | if (scale > 1) 190 | { 191 | [self saveButtonInState:UIControlStateDisabled scale:scale]; 192 | [self saveButtonInState:UIControlStateHighlighted scale:scale]; 193 | [self saveButtonInState:UIControlStateNormal scale:scale]; 194 | } 195 | } 196 | 197 | // MARK: Text Field Delegate 198 | 199 | - (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 200 | { 201 | NSMutableString *fullString = [NSMutableString stringWithString:titleTextField.text]; 202 | [fullString replaceCharactersInRange:range withString:string]; 203 | 204 | [self.glossyButton setTitle:[[fullString copy] autorelease] forState:UIControlStateNormal]; 205 | 206 | [self sizeToFit]; 207 | 208 | return YES; 209 | } 210 | 211 | - (BOOL) textFieldShouldClear:(UITextField *)textField 212 | { 213 | [self.glossyButton setTitle:nil forState:UIControlStateNormal]; 214 | 215 | return YES; 216 | } 217 | 218 | - (void) textFieldDidEndEditing:(UITextField *)textField 219 | { 220 | [self.glossyButton setTitle:[[textField.text copy] autorelease] forState:UIControlStateNormal]; 221 | } 222 | 223 | - (BOOL) textFieldShouldReturn:(UITextField *)textField 224 | { 225 | return [self.view endEditing:YES]; 226 | } 227 | 228 | @end 229 | -------------------------------------------------------------------------------- /Classes/IPAArchive.h: -------------------------------------------------------------------------------- 1 | // 2 | // IPAArchive.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 30.12.11. 6 | // Copyright (c) 2011 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IPAArchive : NSObject 12 | 13 | - (id) initWithPath:(NSString *)ipaPath; 14 | @property (nonatomic, readonly, retain) NSString *path; 15 | 16 | @property (nonatomic, readonly, retain) NSString *appName; 17 | @property (nonatomic, readonly, retain) UIImage *appIcon; 18 | @property (nonatomic, readonly, retain) NSArray *imageNames; 19 | 20 | @property (nonatomic, readonly) BOOL iPhone; 21 | @property (nonatomic, readonly) BOOL iPad; 22 | 23 | - (UIImage *) imageNamed:(NSString *)imageName; 24 | 25 | - (void) unload; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Classes/IPAArchive.m: -------------------------------------------------------------------------------- 1 | // 2 | // IPAArchive.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 30.12.11. 6 | // Copyright (c) 2011 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | #import "IPAArchive.h" 10 | 11 | #import 12 | #import "ZKCDHeader.h" 13 | #import "ZKDataArchive.h" 14 | 15 | static CGImageRef (*LICreateIconForImage)(CGImageRef image, NSUInteger variant, NSUInteger flags) = NULL; 16 | 17 | 18 | @interface IPAArchive () 19 | @property (nonatomic, readwrite, retain) UIImage *appIcon; 20 | @property (nonatomic, readwrite, retain) NSArray *imageNames; 21 | 22 | @property (nonatomic, readwrite, retain) NSString *path; 23 | @property (nonatomic, retain) ZKDataArchive *ipa; 24 | @property (nonatomic, retain) NSDictionary *metadata; 25 | @property (nonatomic, retain) NSDictionary *infoPlist; 26 | @end 27 | 28 | 29 | @implementation IPAArchive 30 | 31 | @synthesize path = _path; 32 | @synthesize ipa = _ipa; 33 | @synthesize metadata = _metadata; 34 | @synthesize infoPlist = _infoPlist; 35 | @synthesize appIcon = _appIcon; 36 | @synthesize imageNames = _imageNames; 37 | 38 | + (void) initialize 39 | { 40 | if (self != [IPAArchive class]) 41 | return; 42 | 43 | NSString *root = [[[NSProcessInfo processInfo] environment] objectForKey:@"IPHONE_SIMULATOR_ROOT"] ?: @""; 44 | void *MobileIcons = dlopen([[root stringByAppendingPathComponent:@"/System/Library/PrivateFrameworks/MobileIcons.framework/MobileIcons"] fileSystemRepresentation], RTLD_NOW); 45 | LICreateIconForImage = dlsym(MobileIcons, "LICreateIconForImage"); 46 | } 47 | 48 | - (id) initWithPath:(NSString *)ipaPath; 49 | { 50 | if (!(self = [super init])) 51 | return nil; 52 | 53 | self.path = ipaPath; 54 | 55 | return self; 56 | } 57 | 58 | - (void) dealloc 59 | { 60 | self.path = nil; 61 | self.imageNames = nil; 62 | self.appIcon = nil; 63 | self.ipa = nil; 64 | self.metadata = nil; 65 | self.infoPlist = nil; 66 | 67 | [super dealloc]; 68 | } 69 | 70 | - (NSDictionary *) metadata 71 | { 72 | if (_metadata) 73 | return _metadata; 74 | 75 | for (ZKCDHeader *header in self.ipa.centralDirectory) 76 | { 77 | if ([header.filename isEqualToString:@"iTunesMetadata.plist"]) 78 | { 79 | NSDictionary *attributes = nil; 80 | NSData *iTunesMetadata = [self.ipa inflateFile:header attributes:&attributes]; 81 | _metadata = [[NSPropertyListSerialization propertyListWithData:iTunesMetadata options:0 format:NULL error:NULL] retain]; 82 | } 83 | } 84 | 85 | return _metadata; 86 | } 87 | 88 | - (NSDictionary *) infoPlist 89 | { 90 | if (_infoPlist) 91 | return _infoPlist; 92 | 93 | for (ZKCDHeader *header in self.ipa.centralDirectory) 94 | { 95 | if ([header.filename hasSuffix:@"/Info.plist"] && [[header.filename componentsSeparatedByString:@"/"] count] == 3) 96 | { 97 | NSDictionary *attributes = nil; 98 | NSData *infoData = [self.ipa inflateFile:header attributes:&attributes]; 99 | _infoPlist = [[NSPropertyListSerialization propertyListWithData:infoData options:0 format:NULL error:NULL] retain]; 100 | break; 101 | } 102 | } 103 | 104 | return _infoPlist; 105 | } 106 | 107 | - (NSString *) appName 108 | { 109 | return [self.metadata objectForKey:@"itemName"]; 110 | } 111 | 112 | - (UIImage *) appIcon 113 | { 114 | if (_appIcon) 115 | return _appIcon; 116 | 117 | NSDictionary *bundleIcons = [self.infoPlist objectForKey:@"CFBundleIcons"]; 118 | NSArray *bundleIconFiles = [[bundleIcons objectForKey:@"CFBundlePrimaryIcon"] objectForKey:@"CFBundleIconFiles"]; 119 | if (!bundleIconFiles) 120 | bundleIconFiles = [self.infoPlist objectForKey:@"CFBundleIconFiles"]; 121 | if (!bundleIconFiles) 122 | { 123 | NSString *bundleIconFile = [self.infoPlist objectForKey:@"CFBundleIconFile"]; 124 | if ([bundleIconFile length] > 0) 125 | bundleIconFiles = [NSArray arrayWithObject:bundleIconFile]; 126 | } 127 | if ([bundleIconFiles count] == 0) 128 | { 129 | bundleIconFiles = [NSArray arrayWithObjects:@"Icon.png", @"Icon@2x.png", nil]; 130 | } 131 | 132 | NSMutableArray *icons = [NSMutableArray array]; 133 | for (NSString *iconFile in bundleIconFiles) 134 | { 135 | if ([iconFile length] > 0 && [[iconFile stringByDeletingPathExtension] isEqualToString:iconFile]) 136 | iconFile = [iconFile stringByAppendingPathExtension:@"png"]; 137 | 138 | for (ZKCDHeader *header in self.ipa.centralDirectory) 139 | { 140 | NSArray *pathComponents = [header.filename componentsSeparatedByString:@"/"]; 141 | if ([pathComponents count] == 3) 142 | { 143 | NSString *iconName = [[pathComponents objectAtIndex:2] uppercaseString]; 144 | if ([[iconFile uppercaseString] isEqualToString:iconName]) 145 | { 146 | NSDictionary *attributes = nil; 147 | NSData *iconData = [self.ipa inflateFile:header attributes:&attributes]; 148 | UIImage *icon = [UIImage imageWithData:iconData]; 149 | if (icon) 150 | [icons addObject:icon]; 151 | } 152 | } 153 | } 154 | } 155 | 156 | CGFloat screenScale = [UIScreen mainScreen].scale; 157 | for (NSNumber *scale in [NSArray arrayWithObjects:[NSNumber numberWithFloat:screenScale], [NSNumber numberWithFloat:screenScale > 1 ? 1 : 2], nil]) 158 | { 159 | for (UIImage *icon in icons) 160 | { 161 | CGFloat iconSize = (self.iPhone ? 57 : 72) * [scale floatValue]; 162 | if (CGSizeEqualToSize(icon.size, CGSizeMake(iconSize, iconSize))) 163 | { 164 | _appIcon = [icon retain]; 165 | break; 166 | } 167 | } 168 | if (_appIcon) 169 | break; 170 | } 171 | 172 | if (LICreateIconForImage && _appIcon) 173 | { 174 | CGFloat scale = _appIcon.scale; 175 | CGImageRef icon = LICreateIconForImage(_appIcon.CGImage, 15, [[self.infoPlist objectForKey:@"UIPrerenderedIcon"] boolValue] ? 2 : 0); 176 | [_appIcon release]; 177 | _appIcon = [[UIImage alloc] initWithCGImage:icon scale:scale orientation:UIImageOrientationUp]; 178 | CGImageRelease(icon); 179 | } 180 | 181 | if (!_appIcon) 182 | _appIcon = [[UIImage imageNamed:@"Unknown.png"] retain]; 183 | 184 | return _appIcon; 185 | } 186 | 187 | - (NSArray *) imageNames 188 | { 189 | if (_imageNames) 190 | return _imageNames; 191 | 192 | _imageNames = [[NSMutableArray alloc] init]; 193 | for (ZKCDHeader *header in self.ipa.centralDirectory) 194 | { 195 | if ([header.filename hasSuffix:@"png"]) 196 | [(NSMutableArray*)_imageNames addObject:header.filename]; 197 | } 198 | 199 | return _imageNames; 200 | } 201 | 202 | - (UIImage *) imageNamed:(NSString *)imageName 203 | { 204 | UIImage *image = nil; 205 | 206 | for (ZKCDHeader *header in self.ipa.centralDirectory) 207 | { 208 | if ([header.filename isEqualToString:imageName]) 209 | { 210 | NSDictionary *attributes = nil; 211 | NSData *imageData = [self.ipa inflateFile:header attributes:&attributes]; 212 | CGDataProviderRef source = CGDataProviderCreateWithCFData((CFDataRef)imageData); 213 | CGImageRef imageRef = CGImageCreateWithPNGDataProvider(source, NULL, false, kCGRenderingIntentDefault); 214 | CGFloat scale = [imageName rangeOfString:@"@2x"].location != NSNotFound || [imageName rangeOfString:@"@2X"].location != NSNotFound ? 2 : 1; 215 | image = [UIImage imageWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp]; 216 | CGImageRelease(imageRef); 217 | CGDataProviderRelease(source); 218 | break; 219 | } 220 | } 221 | 222 | return image; 223 | } 224 | 225 | - (BOOL) iPhone 226 | { 227 | NSArray *deviceFamily = [[self infoPlist] objectForKey:@"UIDeviceFamily"]; 228 | return [deviceFamily containsObject:[NSNumber numberWithInteger:1]] || deviceFamily == nil; 229 | } 230 | 231 | - (BOOL) iPad 232 | { 233 | return [[[self infoPlist] objectForKey:@"UIDeviceFamily"] containsObject:[NSNumber numberWithInteger:2]]; 234 | } 235 | 236 | - (ZKDataArchive *) ipa 237 | { 238 | if (!_ipa) 239 | _ipa = [[ZKDataArchive archiveWithArchivePath:self.path] retain]; 240 | 241 | return _ipa; 242 | } 243 | 244 | - (void) unload 245 | { 246 | [self appIcon]; 247 | [self metadata]; 248 | [self infoPlist]; 249 | self.ipa = nil; 250 | } 251 | 252 | @end 253 | -------------------------------------------------------------------------------- /Classes/IPAViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IPAViewController.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 30.12.11. 6 | // Copyright (c) 2011 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IPAViewController : UITableViewController 12 | 13 | @property (nonatomic, retain) NSMutableArray *archives; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/IPAViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // IPAViewController.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 30.12.11. 6 | // Copyright (c) 2011 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | #import "IPAViewController.h" 10 | 11 | #import "AppDelegate.h" 12 | #import "ArtworkViewController.h" 13 | #import "IPAArchive.h" 14 | #import "NSString+IPAArchive.h" 15 | 16 | @implementation IPAViewController 17 | 18 | @synthesize archives = _archives; 19 | 20 | - (void) reloadRowsAtIndexPaths:(NSArray *)indexPaths 21 | { 22 | if ([NSThread isMainThread]) 23 | { 24 | [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; 25 | [self.searchDisplayController.searchResultsTableView reloadData]; 26 | } 27 | else 28 | [self performSelectorOnMainThread:_cmd withObject:indexPaths waitUntilDone:NO]; 29 | } 30 | 31 | - (void) loadArchives 32 | { 33 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 34 | 35 | NSUInteger i = 0; 36 | for (NSString *ipaPath in [[self.archives copy] autorelease]) 37 | { 38 | NSAutoreleasePool *archivePool = [[NSAutoreleasePool alloc] init]; 39 | NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:ipaPath error:NULL]; 40 | if ([attributes fileSize] > 500 * 1024 * 1024) 41 | { 42 | NSLog(@"Skipped %@ (too big)", [ipaPath lastPathComponent]); 43 | i++; 44 | continue; 45 | } 46 | IPAArchive *archive = [[[IPAArchive alloc] initWithPath:ipaPath] autorelease]; 47 | if ([archive.imageNames count] == 0) 48 | { 49 | NSLog(@"Skipped %@ (no images)", [ipaPath lastPathComponent]); 50 | i++; 51 | continue; 52 | } 53 | [archive unload]; 54 | [self.archives replaceObjectAtIndex:i withObject:archive]; 55 | 56 | NSArray *indexPaths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:i++ inSection:0]]; 57 | [self reloadRowsAtIndexPaths:indexPaths]; 58 | 59 | [archivePool drain]; 60 | } 61 | 62 | [pool drain]; 63 | } 64 | 65 | - (void) viewDidLoad 66 | { 67 | self.title = self.tabBarItem.title; 68 | self.tableView.rowHeight = [UIImage imageNamed:@"Unknown.png"].size.height; 69 | 70 | [self performSelectorInBackground:@selector(loadArchives) withObject:nil]; 71 | } 72 | 73 | - (void) viewDidUnload 74 | { 75 | self.archives = nil; 76 | } 77 | 78 | // MARK: - UITableView data source 79 | 80 | - (NSMutableArray *) archivesForTableView:(UITableView *)tableView 81 | { 82 | NSMutableArray *archives = self.archives; 83 | if (tableView == self.searchDisplayController.searchResultsTableView) 84 | { 85 | NSString *searchText = [NSString stringWithFormat:@"*%@*", self.searchDisplayController.searchBar.text]; 86 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"appName LIKE[c] %@", searchText]; 87 | archives = [NSMutableArray arrayWithArray:[archives filteredArrayUsingPredicate:predicate]]; 88 | } 89 | 90 | return archives; 91 | } 92 | 93 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 94 | { 95 | return [[self archivesForTableView:tableView] count]; 96 | } 97 | 98 | - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 99 | { 100 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"IPACell"]; 101 | if (!cell) 102 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"IPACell"] autorelease]; 103 | 104 | return cell; 105 | } 106 | 107 | // MARK: - UITableView delegate 108 | 109 | - (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 110 | { 111 | IPAArchive *archive = [[self archivesForTableView:tableView] objectAtIndex:indexPath.row]; 112 | NSString *path = [archive isKindOfClass:[IPAArchive class]] ? archive.path : (NSString *)archive; 113 | UIImage *icon = [archive isKindOfClass:[IPAArchive class]] ? archive.appIcon : [UIImage imageNamed:@"Unknown.png"]; 114 | 115 | cell.textLabel.text = [path appName]; 116 | cell.imageView.image = icon; 117 | } 118 | 119 | - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 120 | { 121 | NSMutableArray *archives = [self archivesForTableView:tableView]; 122 | IPAArchive *archive = [archives objectAtIndex:indexPath.row]; 123 | if (![archive isKindOfClass:[IPAArchive class]]) 124 | { 125 | NSString *path = (NSString *)archive; 126 | archive = [[[IPAArchive alloc] initWithPath:path] autorelease]; 127 | [archives replaceObjectAtIndex:indexPath.row withObject:archive]; 128 | } 129 | ArtworkViewController *artworkViewController = [[[ArtworkViewController alloc] initWithArchive:archive] autorelease]; 130 | [self.navigationController pushViewController:artworkViewController animated:YES]; 131 | } 132 | 133 | // MARK: - Search Display Delegate 134 | 135 | - (void) searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView 136 | { 137 | tableView.backgroundColor = self.tableView.backgroundColor; 138 | tableView.rowHeight = self.tableView.rowHeight; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Classes/NSString+IPAArchive.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IPAArchive.h 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 09.01.12. 6 | // Copyright (c) 2012 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (IPAArchive) 12 | 13 | - (NSString *) appName; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/NSString+IPAArchive.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IPAArchive.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 09.01.12. 6 | // Copyright (c) 2012 Cédric Luthi. All rights reserved. 7 | // 8 | 9 | #import "NSString+IPAArchive.h" 10 | 11 | @implementation NSString (IPAArchive) 12 | 13 | - (NSString *) appName 14 | { 15 | return [[self lastPathComponent] stringByDeletingPathExtension]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Default-568h@2x.png -------------------------------------------------------------------------------- /External/ZipKit/COPYING.TXT: -------------------------------------------------------------------------------- 1 | ZipKit is covered under the following BSD-style license: 2 | ================================================================ 3 | Copyright (c) 2009, Karl Moskowski 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following disclaimer 14 | in the documentation and/or other materials provided with the 15 | distribution. 16 | * Neither the name of Karl Moskowski nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ================================================================ 32 | 33 | Acknowledgement using this text is appreciated: 34 | ZipKit developed by Karl Moskowski. 35 | http://bitbucket.org/kolpanic/zipkit/ 36 | 37 | ------------------------------------------------------------------------------------------------ 38 | 39 | The GMAppleDouble class used in this project is part of the MacFUSE project by Google Inc. 40 | 41 | 42 | See the file COPYING.TXT in the MacFUSE folder for license details. 43 | -------------------------------------------------------------------------------- /External/ZipKit/Credits.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | ZipKit Credits 12 | 13 | 14 |

15 | Thanks to Jaka Jančar for manual memory management & iPhoneOS support. 16 |

17 |

18 | Portions of MacFUSE used with appreciation. 19 |

20 | 21 | -------------------------------------------------------------------------------- /External/ZipKit/GMAppleDouble+ZKAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // GMAppleDouble+ZKAdditions.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "GMAppleDouble.h" 9 | 10 | @interface GMAppleDouble (ZKAdditions) 11 | 12 | + (NSData *) zk_appleDoubleDataForPath:(NSString *)path; 13 | + (void) zk_restoreAppleDoubleData:(NSData *)appleDoubleData toPath:(NSString *)path; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /External/ZipKit/GMAppleDouble+ZKAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // GMAppleDouble+ZKAdditions.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "GMAppleDouble+ZKAdditions.h" 9 | #include 10 | 11 | @implementation GMAppleDouble (ZKAdditions) 12 | 13 | + (NSData *) zk_appleDoubleDataForPath:(NSString *)path { 14 | // extract a file's Finder info metadata and resource fork to a NSData object suitable for writing to a ._ file 15 | NSData *appleDoubleData = nil; 16 | if ([[[NSFileManager new] autorelease] fileExistsAtPath:path]) { 17 | GMAppleDouble *appleDouble = [GMAppleDouble appleDouble]; 18 | NSMutableData *data; 19 | 20 | ssize_t finderInfoSize = getxattr([path fileSystemRepresentation], XATTR_FINDERINFO_NAME, NULL, ULONG_MAX, 0, XATTR_NOFOLLOW); 21 | if (finderInfoSize > 0) { 22 | data = [NSMutableData dataWithLength:finderInfoSize]; 23 | if (getxattr([path fileSystemRepresentation], XATTR_FINDERINFO_NAME, [data mutableBytes], [data length], 0, XATTR_NOFOLLOW) > 0) 24 | [appleDouble addEntryWithID:DoubleEntryFinderInfo data:data]; 25 | } 26 | 27 | ssize_t resourceForkSize = getxattr([path fileSystemRepresentation], XATTR_RESOURCEFORK_NAME, NULL, ULONG_MAX, 0, XATTR_NOFOLLOW); 28 | if (resourceForkSize > 0) { 29 | data = [NSMutableData dataWithLength:resourceForkSize]; 30 | if (getxattr([path fileSystemRepresentation], XATTR_RESOURCEFORK_NAME, [data mutableBytes], [data length], 0, XATTR_NOFOLLOW) > 0) 31 | [appleDouble addEntryWithID:DoubleEntryResourceFork data:data]; 32 | } 33 | 34 | if ([[appleDouble entries] count]) 35 | appleDoubleData = [appleDouble data]; 36 | } 37 | return appleDoubleData; 38 | } 39 | 40 | + (void) zk_restoreAppleDoubleData:(NSData *)appleDoubleData toPath:(NSString *)path { 41 | // retsore AppleDouble NSData to a file's Finder info metadata and resource fork 42 | if ([[[NSFileManager new] autorelease] fileExistsAtPath:path]) { 43 | GMAppleDouble *appleDouble = [GMAppleDouble appleDoubleWithData:appleDoubleData]; 44 | if ([appleDouble entries] && [[appleDouble entries] count] > 0) { 45 | for (GMAppleDoubleEntry *entry in [appleDouble entries]) { 46 | char *key = NULL; 47 | if ([entry entryID] == DoubleEntryFinderInfo) 48 | key = XATTR_FINDERINFO_NAME; 49 | else if ([entry entryID] == DoubleEntryResourceFork) 50 | key = XATTR_RESOURCEFORK_NAME; 51 | if (key != NULL) 52 | setxattr([path fileSystemRepresentation], key, [[entry data] bytes], [[entry data] length], 0, XATTR_NOFOLLOW); 53 | } 54 | } 55 | } 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /External/ZipKit/MacFUSE/COPYING.TXT: -------------------------------------------------------------------------------- 1 | MacFUSE is a package developed by Google and is covered under the following 2 | BSD-style license: 3 | 4 | ================================================================ 5 | Copyright (c) 2007-2009 Google Inc. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are 10 | met: 11 | 12 | * Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | * Redistributions in binary form must reproduce the above 15 | copyright notice, this list of conditions and the following disclaimer 16 | in the documentation and/or other materials provided with the 17 | distribution. 18 | * Neither the name of Google Inc. nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | ================================================================ 34 | 35 | Note that Google's patches to the FUSE library (libfuse/*.patch) (and to 36 | the SSHFS user-space program (filesystems/sshfs/*.patch) are also released 37 | under the BSD license. 38 | 39 | Portions of this package were derived from code developed by other authors. 40 | Please read further for specific details. 41 | 42 | * fusefs/fuse_kernel.h is an unmodified copy of the interface header from 43 | the Linux FUSE distribution (http://fuse.sourceforge.net). fuse_kernel.h 44 | can be redistributed either under the GPL or under the BSD license. It 45 | is being redistributed here under the BSD license. 46 | 47 | * Unless otherwise noted, parts of MacFUSE (multiple files in fusefs/) contain 48 | code derived from the FreeBSD version of FUSE (http://fuse4bsd.creo.hu), 49 | which is covered by the following BSD-style license: 50 | 51 | ================================================================ 52 | Copyright (C) 2005 Csaba Henk. All rights reserved. 53 | 54 | Redistribution and use in source and binary forms, with or without 55 | modification, are permitted provided that the following conditions 56 | are met: 57 | 1. Redistributions of source code must retain the above copyright 58 | notice, this list of conditions and the following disclaimer. 59 | 2. Redistributions in binary form must reproduce the above copyright 60 | notice, this list of conditions and the following disclaimer in the 61 | documentation and/or other materials provided with the distribution. 62 | 63 | THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 64 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 | ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 67 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 | SUCH DAMAGE. 74 | ================================================================ 75 | 76 | * fusefs/fuse_nodehash.c is a modified version of HashNode.c from an 77 | Apple Developer Technical Support (DTS) sample code example. The original 78 | source, which is available on http://developer.apple.com/samplecode/, has 79 | the following disclaimer: 80 | 81 | ================================================================ 82 | Disclaimer: IMPORTANT: This Apple software is supplied to you by 83 | Apple Computer, Inc. Apple") in consideration of your agreement 84 | to the following terms, and your use, installation, modification 85 | or redistribution of this Apple software constitutes acceptance 86 | of these terms. If you do not agree with these terms, please do 87 | not use, install, modify or redistribute this Apple software. 88 | 89 | In consideration of your agreement to abide by the following terms, 90 | and subject to these terms, Apple grants you a personal, non-exclusive 91 | license, under Apple's copyrights in this original Apple software 92 | (the "Apple Software"), to use, reproduce, modify and redistribute 93 | the Apple Software, with or without modifications, in source and/or 94 | binary forms; provided that if you redistribute the Apple Software 95 | in its entirety and without modifications, you must retain this 96 | notice and the following text and disclaimers in all such 97 | redistributions of the Apple Software. Neither the name, 98 | trademarks, service marks or logos of Apple Computer, Inc. may be 99 | used to endorse or promote products derived from the Apple Software 100 | without specific prior written permission from Apple. Except as 101 | expressly stated in this notice, no other rights or licenses, 102 | express or implied, are granted by Apple herein, including but 103 | not limited to any patent rights that may be infringed by your 104 | derivative works or by other works in which the Apple Software 105 | may be incorporated. 106 | 107 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 108 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 109 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND 110 | FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR 111 | ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 112 | 113 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, 114 | INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 115 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 116 | PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 117 | REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, 118 | HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING 119 | NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN 120 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 121 | ================================================================ 122 | 123 | * Parts of the mount_fusefs and the load_fusefs command-line programs 124 | (implemented in fusefs/mount_fusefs/ and fusefs/load_fusefs/, respectively) 125 | come from Apple's Darwin sources and are covered under the Apple Public 126 | Source License (APSL). You can read the APSL at: 127 | 128 | http://www.publicsource.apple.com/apsl/ -------------------------------------------------------------------------------- /External/ZipKit/MacFUSE/GMAppleDouble.h: -------------------------------------------------------------------------------- 1 | // ================================================================ 2 | // Copyright (c) 2007, Google Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // ================================================================ 31 | // 32 | // GMAppleDouble.h 33 | // MacFUSE 34 | // 35 | // Created by ted on 12/29/07. 36 | // 37 | 38 | /*! 39 | * @header GMAppleDouble 40 | * 41 | * A utility class to construct an AppleDouble (._) file. 42 | * 43 | * AppleDouble files contain information about a corresponding file and are 44 | * typically used on file systems that do not support extended attributes. 45 | */ 46 | 47 | #import 48 | 49 | #define GM_EXPORT __attribute__((visibility("default"))) 50 | 51 | /*! 52 | *
 53 |  * Based on "AppleSingle/AppleDouble Formats for Foreign Files Developer's Note"
 54 |  *
 55 |  * Notes:
 56 |  * DoubleEntryFileDatesInfo
 57 |  *    File creation, modification, backup, and access times as number of seconds 
 58 |  *    before or after 12:00 AM Jan 1 2000 GMT as SInt32.
 59 |  *  DoubleEntryFinderInfo
 60 |  *    16 bytes of FinderInfo followed by 16 bytes of extended FinderInfo.
 61 |  *    New FinderInfo should be zero'd out. For a directory, when the Finder 
 62 |  *    encounters an entry with the init'd bit cleared, it will initialize the 
 63 |  *    frView field of the to a value indicating how the contents of the
 64 |  *    directory should be shown. Recommend to set frView to value of 256.
 65 |  *  DoubleEntryMacFileInfo
 66 |  *    This is a 32 bit flag that stores locked (bit 0) and protected (bit 1).
 67 |  * 
68 | */ 69 | typedef enum { 70 | DoubleEntryInvalid = 0, 71 | DoubleEntryDataFork = 1, 72 | DoubleEntryResourceFork = 2, 73 | DoubleEntryRealName = 3, 74 | DoubleEntryComment = 4, 75 | DoubleEntryBlackAndWhiteIcon = 5, 76 | DoubleEntryColorIcon = 6, 77 | DoubleEntryFileDatesInfo = 8, // See notes 78 | DoubleEntryFinderInfo = 9, // See notes 79 | DoubleEntryMacFileInfo = 10, // See notes 80 | DoubleEntryProDosFileInfo = 11, 81 | DoubleEntryMSDosFileinfo = 12, 82 | DoubleEntryShortName = 13, 83 | DoubleEntryAFPFileInfo = 14, 84 | DoubleEntryDirectoryID = 15, 85 | } GMAppleDoubleEntryID; 86 | 87 | /*! 88 | * @class 89 | * @discussion This class represents a single entry in an AppleDouble file. 90 | */ 91 | GM_EXPORT @interface GMAppleDoubleEntry : NSObject { 92 | @private 93 | GMAppleDoubleEntryID entryID_; 94 | NSData* data_; // Format depends on entryID_ 95 | } 96 | /*! 97 | * @abstract Initializes an AppleDouble entry with ID and data. 98 | * @param entryID A valid entry identifier 99 | * @param data Raw data for the entry 100 | */ 101 | - (id)initWithEntryID:(GMAppleDoubleEntryID)entryID data:(NSData *)data; 102 | 103 | /*! @abstract The entry ID */ 104 | - (GMAppleDoubleEntryID)entryID; 105 | 106 | /*! @abstract The entry data */ 107 | - (NSData *)data; 108 | @end 109 | 110 | /*! 111 | * @class 112 | * @discussion This class can be used to construct raw AppleDouble data. 113 | */ 114 | GM_EXPORT @interface GMAppleDouble : NSObject { 115 | @private 116 | NSMutableArray* entries_; 117 | } 118 | 119 | /*! @abstract An autoreleased empty GMAppleDouble file */ 120 | + (GMAppleDouble *)appleDouble; 121 | 122 | /*! 123 | * @abstract An autoreleased GMAppleDouble file. 124 | * @discussion The GMAppleDouble is pre-filled with entries from the raw 125 | * AppleDouble file data. 126 | * @param data Raw AppleDouble file data. 127 | */ 128 | + (GMAppleDouble *)appleDoubleWithData:(NSData *)data; 129 | 130 | /*! 131 | * @abstract Adds an entry to the AppleDouble file. 132 | * @param entry The entry to add 133 | */ 134 | - (void)addEntry:(GMAppleDoubleEntry *)entry; 135 | 136 | /*! 137 | * @abstract Adds an entry to the AppleDouble file with ID and data. 138 | * @param entryID The ID of the entry to add 139 | * @param data The raw data for the entry to add (retained) 140 | */ 141 | - (void)addEntryWithID:(GMAppleDoubleEntryID)entryID data:(NSData *)data; 142 | 143 | /*! 144 | * @abstract Adds entries based on the provided raw AppleDouble file data. 145 | * @discussion This will attempt to parse the given data as an AppleDouble file 146 | * and add all entries found. 147 | * @param data Raw AppleDouble file data 148 | * @param data The raw data for the entry to add (retained) 149 | * @result YES if the provided data was parsed correctly. 150 | */ 151 | - (BOOL)addEntriesFromAppleDoubleData:(NSData *)data; 152 | 153 | /*! 154 | * @abstract The set of GMAppleDoubleEntry present in this GMAppleDouble. 155 | * @result An array of GMAppleDoubleEntry. 156 | */ 157 | - (NSArray *)entries; 158 | 159 | /*! 160 | * @abstract Constructs raw data for the AppleDouble file. 161 | * @result The raw data for an AppleDouble file represented by this GMAppleDouble. 162 | */ 163 | - (NSData *)data; 164 | 165 | @end 166 | 167 | #undef GM_EXPORT -------------------------------------------------------------------------------- /External/ZipKit/MacFUSE/GMAppleDouble.m: -------------------------------------------------------------------------------- 1 | // ================================================================ 2 | // Copyright (c) 2007, Google Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // ================================================================ 31 | // 32 | // GMAppleDouble.m 33 | // MacFUSE 34 | // 35 | // Created by ted on 12/29/07. 36 | // 37 | #import "GMAppleDouble.h" 38 | #import "libkern/OSByteOrder.h" 39 | 40 | #define GM_APPLE_DOUBLE_HEADER_MAGIC 0x00051607 41 | #define GM_APPLE_DOUBLE_HEADER_VERSION 0x00020000 42 | 43 | typedef struct { 44 | UInt32 magicNumber; // Should be 0x00051607 45 | UInt32 versionNumber; // Should be 0x00020000 46 | char filler[16]; // Zero-filled bytes. 47 | UInt16 numberOfEntries; // Number of entries. 48 | } __attribute__((packed)) DoubleHeader; 49 | 50 | typedef struct { 51 | UInt32 entryID; // Defines what entry is (0 is invalid) 52 | UInt32 offset; // Offset from beginning of file to entry data. 53 | UInt32 length; // Length of entry data in bytes. 54 | } __attribute__((packed)) DoubleEntryHeader; 55 | 56 | @implementation GMAppleDoubleEntry 57 | 58 | + (GMAppleDoubleEntry *)entryWithID:(GMAppleDoubleEntryID)entryID 59 | data:(NSData *)data { 60 | return [[[GMAppleDoubleEntry alloc] 61 | initWithEntryID:entryID data:data] autorelease]; 62 | } 63 | 64 | - (id)initWithEntryID:(GMAppleDoubleEntryID)entryID 65 | data:(NSData *)data { 66 | if ((self = [super init])) { 67 | if (entryID == DoubleEntryInvalid || data == nil) { 68 | [self release]; 69 | return nil; 70 | } 71 | entryID_ = entryID; 72 | data_ = [data retain]; 73 | } 74 | return self; 75 | } 76 | 77 | - (void)dealloc { 78 | [data_ release]; 79 | [super dealloc]; 80 | } 81 | 82 | - (GMAppleDoubleEntryID)entryID { 83 | return entryID_; 84 | } 85 | - (NSData *)data { 86 | return data_; 87 | } 88 | 89 | @end 90 | 91 | @implementation GMAppleDouble 92 | 93 | + (GMAppleDouble *)appleDouble { 94 | return [[[GMAppleDouble alloc] init] autorelease]; 95 | } 96 | 97 | + (GMAppleDouble *)appleDoubleWithData:(NSData *)data { 98 | GMAppleDouble* appleDouble = [[[GMAppleDouble alloc] init] autorelease]; 99 | if ([appleDouble addEntriesFromAppleDoubleData:data]) { 100 | return appleDouble; 101 | } 102 | return nil; 103 | } 104 | 105 | - (id)init { 106 | if ((self = [super init])) { 107 | entries_ = [[NSMutableArray alloc] init]; 108 | } 109 | return self; 110 | } 111 | 112 | - (void)dealloc { 113 | [entries_ release]; 114 | [super dealloc]; 115 | } 116 | 117 | - (void)addEntry:(GMAppleDoubleEntry *)entry { 118 | [entries_ addObject:entry]; 119 | } 120 | 121 | - (void)addEntryWithID:(GMAppleDoubleEntryID)entryID data:(NSData *)data { 122 | GMAppleDoubleEntry* entry = [GMAppleDoubleEntry entryWithID:entryID data:data]; 123 | [self addEntry:entry]; 124 | } 125 | 126 | - (BOOL)addEntriesFromAppleDoubleData:(NSData *)data { 127 | const int len = [data length]; 128 | DoubleHeader header; 129 | if (len < sizeof(header)) { 130 | return NO; // To small to even fit our header. 131 | } 132 | [data getBytes:&header length:sizeof(header)]; 133 | if (OSSwapBigToHostInt32(header.magicNumber) != GM_APPLE_DOUBLE_HEADER_MAGIC || 134 | OSSwapBigToHostInt32(header.versionNumber) != GM_APPLE_DOUBLE_HEADER_VERSION) { 135 | return NO; // Invalid header. 136 | } 137 | int count = OSSwapBigToHostInt16(header.numberOfEntries); 138 | int offset = sizeof(DoubleHeader); 139 | if (len < (offset + (count * sizeof(DoubleEntryHeader)))) { 140 | return NO; // Not enough data to hold all the DoubleEntryHeader. 141 | } 142 | for (int i = 0; i < count; ++i, offset += sizeof(DoubleEntryHeader)) { 143 | // Extract header 144 | DoubleEntryHeader entryHeader; 145 | NSRange range = NSMakeRange(offset, sizeof(entryHeader)); 146 | [data getBytes:&entryHeader range:range]; 147 | 148 | // Extract data 149 | range = NSMakeRange(OSSwapBigToHostInt32(entryHeader.offset), 150 | OSSwapBigToHostInt32(entryHeader.length)); 151 | if (len < (range.location + range.length)) { 152 | return NO; // Given data too small to contain this entry. 153 | } 154 | NSData* entryData = [data subdataWithRange:range]; 155 | [self addEntryWithID:OSSwapBigToHostInt32(entryHeader.entryID) data:entryData]; 156 | } 157 | 158 | return YES; 159 | } 160 | 161 | - (NSArray *)entries { 162 | return entries_; 163 | } 164 | 165 | - (NSData *)data { 166 | NSMutableData* entryListData = [NSMutableData data]; 167 | NSMutableData* entryData = [NSMutableData data]; 168 | int dataStartOffset = 169 | sizeof(DoubleHeader) + [entries_ count] * sizeof(DoubleEntryHeader); 170 | for (int i = 0; i < [entries_ count]; ++i) { 171 | GMAppleDoubleEntry* entry = [entries_ objectAtIndex:i]; 172 | 173 | DoubleEntryHeader entryHeader; 174 | memset(&entryHeader, 0, sizeof(entryHeader)); 175 | entryHeader.entryID = OSSwapHostToBigInt32((UInt32)[entry entryID]); 176 | entryHeader.offset = 177 | OSSwapHostToBigInt32((UInt32)(dataStartOffset + [entryData length])); 178 | entryHeader.length = OSSwapHostToBigInt32((UInt32)[[entry data] length]); 179 | [entryListData appendBytes:&entryHeader length:sizeof(entryHeader)]; 180 | [entryData appendData:[entry data]]; 181 | } 182 | 183 | NSMutableData* data = [NSMutableData data]; 184 | 185 | DoubleHeader header; 186 | memset(&header, 0, sizeof(header)); 187 | header.magicNumber = OSSwapHostToBigConstInt32(GM_APPLE_DOUBLE_HEADER_MAGIC); 188 | header.versionNumber = OSSwapHostToBigConstInt32(GM_APPLE_DOUBLE_HEADER_VERSION); 189 | header.numberOfEntries = OSSwapHostToBigInt16((UInt16)[entries_ count]); 190 | [data appendBytes:&header length:sizeof(header)]; 191 | [data appendData:entryListData]; 192 | [data appendData:entryData]; 193 | return data; 194 | } 195 | 196 | @end 197 | -------------------------------------------------------------------------------- /External/ZipKit/NSData+ZKAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+ZKAdditions.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface NSData (ZKAdditions) 11 | 12 | - (UInt16) zk_hostInt16OffsetBy:(NSUInteger *)offset; 13 | - (UInt32) zk_hostInt32OffsetBy:(NSUInteger *)offset; 14 | - (UInt64) zk_hostInt64OffsetBy:(NSUInteger *)offset; 15 | - (BOOL) zk_hostBoolOffsetBy:(NSUInteger *) offset; 16 | - (NSString *) zk_stringOffsetBy:(NSUInteger *)offset length:(NSUInteger)length; 17 | - (NSUInteger) zk_crc32; 18 | - (NSUInteger) zk_crc32:(NSUInteger)crc; 19 | - (NSData *) zk_inflate; 20 | - (NSData *) zk_deflate; 21 | 22 | @end 23 | 24 | @interface NSMutableData (ZKAdditions) 25 | 26 | + (NSMutableData *) zk_dataWithLittleInt16:(UInt16)value; 27 | + (NSMutableData *) zk_dataWithLittleInt32:(UInt32)value; 28 | + (NSMutableData *) zk_dataWithLittleInt64:(UInt64)value; 29 | 30 | - (void) zk_appendLittleInt16:(UInt16)value; 31 | - (void) zk_appendLittleInt32:(UInt32)value; 32 | - (void) zk_appendLittleInt64:(UInt64)value; 33 | - (void) zk_appendLittleBool:(BOOL) value; 34 | - (void) zk_appendPrecomposedUTF8String:(NSString *)value; 35 | 36 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSData+ZKAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+ZKAdditions.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "NSData+ZKAdditions.h" 9 | #import "NSFileManager+ZKAdditions.h" 10 | #import "ZKCDHeader.h" 11 | #import "ZKCDTrailer.h" 12 | #import "ZKLFHeader.h" 13 | #import "zlib.h" 14 | 15 | @implementation NSData (ZKAdditions) 16 | 17 | - (UInt16) zk_hostInt16OffsetBy:(NSUInteger *)offset { 18 | UInt16 value; 19 | NSUInteger length = sizeof(value); 20 | [self getBytes:&value range:NSMakeRange(*offset, length)]; 21 | *offset += length; 22 | return CFSwapInt16LittleToHost(value); 23 | } 24 | 25 | - (UInt32) zk_hostInt32OffsetBy:(NSUInteger *)offset { 26 | UInt32 value; 27 | NSUInteger length = sizeof(value); 28 | [self getBytes:&value range:NSMakeRange(*offset, length)]; 29 | *offset += length; 30 | return CFSwapInt32LittleToHost(value); 31 | } 32 | 33 | - (UInt64) zk_hostInt64OffsetBy:(NSUInteger *)offset { 34 | UInt64 value; 35 | NSUInteger length = sizeof(value); 36 | [self getBytes:&value range:NSMakeRange(*offset, length)]; 37 | *offset += length; 38 | return CFSwapInt64LittleToHost(value); 39 | } 40 | 41 | - (BOOL) zk_hostBoolOffsetBy:(NSUInteger *)offset { 42 | UInt32 value = [self zk_hostInt32OffsetBy:offset]; 43 | return value != 0; 44 | } 45 | 46 | - (NSString *) zk_stringOffsetBy:(NSUInteger *)offset length:(NSUInteger)length { 47 | NSString *value = nil; 48 | NSData *subData = [self subdataWithRange:NSMakeRange(*offset, length)]; 49 | if (length > 0) 50 | value = [[[NSString alloc] initWithData:subData encoding:NSUTF8StringEncoding] autorelease]; 51 | if (!value) { 52 | // No valid utf8 encoding, replace everything non-ascii with '?' 53 | NSMutableData *md = [subData mutableCopyWithZone:nil]; 54 | unsigned char *mdd = [md mutableBytes]; 55 | if ([md length] > 0) { 56 | for (unsigned int i = 0; i < [md length]; i++) 57 | if (mdd[i] > 127) 58 | mdd[i] = '?'; 59 | value = [[[NSString alloc] initWithData:md encoding:NSUTF8StringEncoding] autorelease]; 60 | } 61 | [md release]; 62 | } 63 | *offset += length; 64 | return value; 65 | } 66 | 67 | - (NSUInteger) zk_crc32 { 68 | return [self zk_crc32:0]; 69 | } 70 | 71 | - (NSUInteger) zk_crc32:(NSUInteger)crc { 72 | return crc32(crc, [self bytes], [self length]); 73 | } 74 | 75 | - (NSData *) zk_inflate { 76 | NSUInteger full_length = [self length]; 77 | NSUInteger half_length = full_length / 2; 78 | 79 | NSMutableData *inflatedData = [NSMutableData dataWithLength:full_length + half_length]; 80 | BOOL done = NO; 81 | int status; 82 | 83 | z_stream strm; 84 | 85 | strm.next_in = (Bytef *)[self bytes]; 86 | strm.avail_in = [self length]; 87 | strm.total_out = 0; 88 | strm.zalloc = Z_NULL; 89 | strm.zfree = Z_NULL; 90 | 91 | if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) return nil; 92 | while (!done) { 93 | if (strm.total_out >= [inflatedData length]) 94 | [inflatedData increaseLengthBy:half_length]; 95 | strm.next_out = [inflatedData mutableBytes] + strm.total_out; 96 | strm.avail_out = [inflatedData length] - strm.total_out; 97 | status = inflate(&strm, Z_SYNC_FLUSH); 98 | if (status == Z_STREAM_END) done = YES; 99 | else if (status != Z_OK) break; 100 | } 101 | if (inflateEnd(&strm) == Z_OK && done) 102 | [inflatedData setLength:strm.total_out]; 103 | else 104 | inflatedData = nil; 105 | return inflatedData; 106 | } 107 | 108 | - (NSData *) zk_deflate { 109 | z_stream strm; 110 | 111 | strm.zalloc = Z_NULL; 112 | strm.zfree = Z_NULL; 113 | strm.opaque = Z_NULL; 114 | strm.total_out = 0; 115 | strm.next_in = (Bytef *)[self bytes]; 116 | strm.avail_in = [self length]; 117 | 118 | NSMutableData *deflatedData = [NSMutableData dataWithLength:16384]; 119 | if (deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil; 120 | do { 121 | if (strm.total_out >= [deflatedData length]) 122 | [deflatedData increaseLengthBy:16384]; 123 | strm.next_out = [deflatedData mutableBytes] + strm.total_out; 124 | strm.avail_out = [deflatedData length] - strm.total_out; 125 | deflate(&strm, Z_FINISH); 126 | } while (strm.avail_out == 0); 127 | deflateEnd(&strm); 128 | [deflatedData setLength:strm.total_out]; 129 | 130 | return deflatedData; 131 | } 132 | 133 | @end 134 | 135 | @implementation NSMutableData (ZKAdditions) 136 | 137 | + (NSMutableData *) zk_dataWithLittleInt16:(UInt16)value { 138 | NSMutableData *data = [self data]; 139 | [data zk_appendLittleInt16:value]; 140 | return data; 141 | } 142 | 143 | + (NSMutableData *) zk_dataWithLittleInt32:(UInt32)value { 144 | NSMutableData *data = [self data]; 145 | [data zk_appendLittleInt32:value]; 146 | return data; 147 | } 148 | 149 | + (NSMutableData *) zk_dataWithLittleInt64:(UInt64)value { 150 | NSMutableData *data = [self data]; 151 | [data zk_appendLittleInt64:value]; 152 | return data; 153 | } 154 | 155 | - (void) zk_appendLittleInt16:(UInt16)value { 156 | UInt16 swappedValue = CFSwapInt16HostToLittle(value); 157 | [self appendBytes:&swappedValue length:sizeof(swappedValue)]; 158 | } 159 | 160 | - (void) zk_appendLittleInt32:(UInt32)value { 161 | UInt32 swappedValue = CFSwapInt32HostToLittle(value); 162 | [self appendBytes:&swappedValue length:sizeof(swappedValue)]; 163 | } 164 | 165 | - (void) zk_appendLittleInt64:(UInt64)value { 166 | UInt64 swappedValue = CFSwapInt64HostToLittle(value); 167 | [self appendBytes:&swappedValue length:sizeof(swappedValue)]; 168 | } 169 | 170 | - (void) zk_appendLittleBool:(BOOL)value { 171 | return [self zk_appendLittleInt32:(value ? 1:0)]; 172 | } 173 | 174 | - (void) zk_appendPrecomposedUTF8String:(NSString *)value { 175 | return [self appendData:[[value precomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF8StringEncoding]]; 176 | } 177 | 178 | @end 179 | -------------------------------------------------------------------------------- /External/ZipKit/NSDate+ZKAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+ZKAdditions.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface NSDate (ZKAdditions) 11 | 12 | + (NSDate *) zk_dateWithDosDate:(NSUInteger) dosDate; 13 | - (NSUInteger) zk_dosDate; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /External/ZipKit/NSDate+ZKAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+ZKAdditions.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "NSDate+ZKAdditions.h" 9 | 10 | @implementation NSDate (ZKAdditions) 11 | 12 | + (NSDate *)zk_dateWithDosDate : (NSUInteger)dosDate { 13 | NSUInteger date = (NSUInteger)(dosDate >> 16); 14 | NSDateComponents *comps = [[NSDateComponents new] autorelease]; 15 | comps.year = ((date & 0x0FE00) / 0x0200) + 1980; 16 | comps.month = (date & 0x1E0) / 0x20; 17 | comps.day = date & 0x1f; 18 | comps.hour = (dosDate & 0xF800) / 0x800; 19 | comps.minute = (dosDate & 0x7E0) / 0x20; 20 | comps.second = 2 * (dosDate & 0x1f); 21 | return [[NSCalendar currentCalendar] dateFromComponents:comps]; 22 | } 23 | 24 | - (NSUInteger) zk_dosDate { 25 | NSUInteger options = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | 26 | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; 27 | NSDateComponents *comps = [[NSCalendar currentCalendar] components:options fromDate:self]; 28 | return ((comps.day + 32 * comps.month + 512 * (comps.year - 1980)) << 16) | (comps.second / 2 + 32 * comps.minute + 2048 * comps.hour); 29 | } 30 | 31 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSDictionary+ZKAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+ZKAdditions.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface NSDictionary (ZKAdditions) 11 | 12 | + (NSDictionary *) zk_totalSizeAndCountDictionaryWithSize:(unsigned long long) size andItemCount:(unsigned long long) count; 13 | - (unsigned long long) zk_totalFileSize; 14 | - (unsigned long long) zk_itemCount; 15 | 16 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSDictionary+ZKAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+ZKAdditions.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "NSDictionary+ZKAdditions.h" 9 | 10 | NSString* const ZKTotalFileSize = @"ZKTotalFileSize"; 11 | NSString* const ZKItemCount = @"ZKItemCount"; 12 | 13 | @implementation NSDictionary (ZKAdditions) 14 | 15 | + (NSDictionary *) zk_totalSizeAndCountDictionaryWithSize:(unsigned long long) size andItemCount:(unsigned long long) count { 16 | return [NSDictionary dictionaryWithObjectsAndKeys: 17 | [NSNumber numberWithUnsignedLongLong:size], ZKTotalFileSize, 18 | [NSNumber numberWithUnsignedLongLong:count], ZKItemCount, nil]; 19 | } 20 | 21 | - (unsigned long long) zk_totalFileSize { 22 | return [[self objectForKey:ZKTotalFileSize] unsignedLongLongValue]; 23 | } 24 | 25 | - (unsigned long long) zk_itemCount { 26 | return [[self objectForKey:ZKItemCount] unsignedLongLongValue]; 27 | } 28 | 29 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSFileHandle+ZKAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileHandle+ZKAdditions.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface NSFileHandle (ZKAdditions) 11 | 12 | + (NSFileHandle *) zk_newFileHandleForWritingAtPath:(NSString *)path; 13 | 14 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSFileHandle+ZKAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileHandle+ZKAdditions.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "NSFileHandle+ZKAdditions.h" 9 | 10 | @implementation NSFileHandle (ZKAdditions) 11 | 12 | + (NSFileHandle *)zk_newFileHandleForWritingAtPath:(NSString *)path { 13 | NSFileManager *fm = [NSFileManager new]; 14 | if (![fm fileExistsAtPath:path]) { 15 | [fm createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; 16 | [fm createFileAtPath:path contents:nil attributes:nil]; 17 | } 18 | NSFileHandle *fileHandle = [self fileHandleForWritingAtPath:path]; 19 | [fm release]; 20 | return fileHandle; 21 | } 22 | 23 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSFileManager+ZKAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+ZKAdditions.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | #import "ZKDefs.h" 10 | 11 | @interface NSFileManager (ZKAdditions) 12 | 13 | - (BOOL) zk_isSymLinkAtPath:(NSString *) path; 14 | - (BOOL) zk_isDirAtPath:(NSString *) path; 15 | 16 | - (unsigned long long) zk_dataSizeAtFilePath:(NSString *) path; 17 | - (NSDictionary *) zkTotalSizeAndItemCountAtPath:(NSString *) path usingResourceFork:(BOOL) rfFlag; 18 | #if ZK_TARGET_OS_MAC 19 | - (void) zk_combineAppleDoubleInDirectory:(NSString *) path; 20 | #endif 21 | 22 | - (NSDate *) zk_modificationDateForPath:(NSString *) path; 23 | - (NSUInteger) zk_posixPermissionsAtPath:(NSString *) path; 24 | - (NSUInteger) zk_externalFileAttributesAtPath:(NSString *) path; 25 | - (NSUInteger) zk_externalFileAttributesFor:(NSDictionary *) fileAttributes; 26 | 27 | - (NSUInteger) zk_crcForPath:(NSString *) path; 28 | - (NSUInteger) zk_crcForPath:(NSString *) path invoker:(id) invoker; 29 | - (NSUInteger) zk_crcForPath:(NSString *) path invoker:(id)invoker; 30 | - (NSUInteger) zk_crcForPath:(NSString *)path invoker:(id)invoker throttleThreadSleepTime:(NSTimeInterval) throttleThreadSleepTime; 31 | 32 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSFileManager+ZKAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+ZKAdditions.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "NSFileManager+ZKAdditions.h" 9 | #import "NSData+ZKAdditions.h" 10 | #import "NSDictionary+ZKAdditions.h" 11 | 12 | #if ZK_TARGET_OS_MAC 13 | #import "GMAppleDouble+ZKAdditions.h" 14 | #endif 15 | 16 | const NSUInteger ZKMaxEntriesPerFetch = 40; 17 | 18 | @implementation NSFileManager (ZKAdditions) 19 | 20 | - (BOOL) zk_isSymLinkAtPath:(NSString *) path { 21 | return [[[self attributesOfItemAtPath:path error:nil] fileType] isEqualToString:NSFileTypeSymbolicLink]; 22 | } 23 | 24 | - (BOOL) zk_isDirAtPath:(NSString *) path { 25 | BOOL isDir; 26 | BOOL pathExists = [self fileExistsAtPath:path isDirectory:&isDir]; 27 | return pathExists && isDir; 28 | } 29 | 30 | - (unsigned long long) zk_dataSizeAtFilePath:(NSString *) path { 31 | return [[self attributesOfItemAtPath:path error:nil] fileSize]; 32 | } 33 | 34 | #if ZK_TARGET_OS_MAC 35 | - (void) totalsAtDirectoryFSRef:(FSRef*) fsRef usingResourceFork:(BOOL) rfFlag 36 | totalSize:(unsigned long long *) size 37 | itemCount:(unsigned long long *) count { 38 | FSIterator iterator; 39 | OSErr fsErr = FSOpenIterator(fsRef, kFSIterateFlat, &iterator); 40 | if (fsErr == noErr) { 41 | ItemCount actualFetched; 42 | FSRef fetchedRefs[ZKMaxEntriesPerFetch]; 43 | FSCatalogInfo fetchedInfos[ZKMaxEntriesPerFetch]; 44 | while (fsErr == noErr) { 45 | fsErr = FSGetCatalogInfoBulk(iterator, ZKMaxEntriesPerFetch, &actualFetched, NULL, 46 | kFSCatInfoDataSizes | kFSCatInfoRsrcSizes | kFSCatInfoNodeFlags, 47 | fetchedInfos, fetchedRefs, NULL, NULL); 48 | if ((fsErr == noErr) || (fsErr == errFSNoMoreItems)) { 49 | (*count) += actualFetched; 50 | for (ItemCount i = 0; i < actualFetched; i++) { 51 | if (fetchedInfos[i].nodeFlags & kFSNodeIsDirectoryMask) 52 | [self totalsAtDirectoryFSRef:&fetchedRefs[i] usingResourceFork:rfFlag totalSize:size itemCount:count]; 53 | else 54 | (*size) += fetchedInfos [i].dataLogicalSize + (rfFlag ? fetchedInfos [i].rsrcLogicalSize : 0); 55 | } 56 | } 57 | } 58 | FSCloseIterator(iterator); 59 | } 60 | return ; 61 | } 62 | #endif 63 | 64 | - (NSDictionary *) zkTotalSizeAndItemCountAtPath:(NSString *) path usingResourceFork:(BOOL) rfFlag { 65 | unsigned long long size = 0; 66 | unsigned long long count = 0; 67 | #if ZK_TARGET_OS_MAC 68 | FSRef fsRef; 69 | Boolean isDirectory; 70 | OSStatus status = FSPathMakeRef((const unsigned char*)[path fileSystemRepresentation], &fsRef, &isDirectory); 71 | if (status != noErr) 72 | return nil; 73 | if (isDirectory) { 74 | [self totalsAtDirectoryFSRef:&fsRef usingResourceFork:rfFlag totalSize:&size itemCount:&count]; 75 | } else { 76 | count = 1; 77 | FSCatalogInfo info; 78 | OSErr fsErr = FSGetCatalogInfo(&fsRef, kFSCatInfoDataSizes | kFSCatInfoRsrcSizes, &info, NULL, NULL, NULL); 79 | if (fsErr == noErr) 80 | size = info.dataLogicalSize + (rfFlag ? info.rsrcLogicalSize : 0); 81 | } 82 | #else 83 | // TODO: maybe fix this for non-Mac targets 84 | size = 0; 85 | count = 0; 86 | #endif 87 | return [NSDictionary zk_totalSizeAndCountDictionaryWithSize:size andItemCount:count]; 88 | } 89 | 90 | #if ZK_TARGET_OS_MAC 91 | - (void) zk_combineAppleDoubleInDirectory:(NSString *) path { 92 | if (![self zk_isDirAtPath:path]) 93 | return; 94 | NSArray *dirContents = [self contentsOfDirectoryAtPath:path error:nil]; 95 | for (NSString *entry in dirContents) { 96 | NSString *subPath = [path stringByAppendingPathComponent:entry]; 97 | if (![self zk_isSymLinkAtPath:subPath]) { 98 | if ([self zk_isDirAtPath:subPath]) 99 | [self zk_combineAppleDoubleInDirectory:subPath]; 100 | else { 101 | // if the file is an AppleDouble file (i.e., it begins with "._") in the __MACOSX hierarchy, 102 | // find its corresponding data fork and combine them 103 | if ([subPath rangeOfString:ZKMacOSXDirectory].location != NSNotFound) { 104 | NSString *fileName = [subPath lastPathComponent]; 105 | NSRange ZKDotUnderscoreRange = [fileName rangeOfString:ZKDotUnderscore]; 106 | if (ZKDotUnderscoreRange.location == 0 && ZKDotUnderscoreRange.length == 2) { 107 | NSMutableArray *pathComponents = 108 | (NSMutableArray *)[[[subPath stringByDeletingLastPathComponent] stringByAppendingPathComponent: 109 | [fileName substringFromIndex:2]] pathComponents]; 110 | for (NSString *pathComponent in pathComponents) { 111 | if ([ZKMacOSXDirectory isEqualToString:pathComponent]) { 112 | [pathComponents removeObject:pathComponent]; 113 | break; 114 | } 115 | } 116 | NSData *appleDoubleData = [NSData dataWithContentsOfFile:subPath]; 117 | [GMAppleDouble zk_restoreAppleDoubleData:appleDoubleData toPath:[NSString pathWithComponents:pathComponents]]; 118 | } 119 | } 120 | } 121 | } 122 | } 123 | } 124 | #endif 125 | 126 | - (NSDate *) zk_modificationDateForPath:(NSString *) path { 127 | return [[self attributesOfItemAtPath:path error:nil] fileModificationDate]; 128 | } 129 | 130 | - (NSUInteger) zk_posixPermissionsAtPath:(NSString *) path { 131 | return [[self attributesOfItemAtPath:path error:nil] filePosixPermissions]; 132 | } 133 | 134 | - (NSUInteger) zk_externalFileAttributesAtPath:(NSString *) path { 135 | return [self zk_externalFileAttributesFor:[self attributesOfItemAtPath:path error:nil]]; 136 | } 137 | 138 | - (NSUInteger) zk_externalFileAttributesFor:(NSDictionary *) fileAttributes { 139 | NSUInteger externalFileAttributes = 0; 140 | @try { 141 | BOOL isSymLink = [[fileAttributes fileType] isEqualToString:NSFileTypeSymbolicLink]; 142 | BOOL isDir = [[fileAttributes fileType] isEqualToString:NSFileTypeDirectory]; 143 | NSUInteger posixPermissions = [fileAttributes filePosixPermissions]; 144 | externalFileAttributes = posixPermissions << 16 | (isSymLink ? 0xA0004000 : (isDir ? 0x40004000 : 0x80004000)); 145 | } @catch(NSException * e) { 146 | externalFileAttributes = 0; 147 | } 148 | return externalFileAttributes; 149 | } 150 | 151 | - (NSUInteger) zk_crcForPath:(NSString *) path { 152 | return [self zk_crcForPath:path invoker:nil throttleThreadSleepTime:0.0]; 153 | } 154 | 155 | - (NSUInteger) zk_crcForPath:(NSString *) path invoker:(id)invoker { 156 | return [self zk_crcForPath:path invoker:invoker throttleThreadSleepTime:0.0]; 157 | } 158 | 159 | - (NSUInteger) zk_crcForPath:(NSString *)path invoker:(id)invoker throttleThreadSleepTime:(NSTimeInterval) throttleThreadSleepTime { 160 | NSUInteger crc32 = 0; 161 | path = [path stringByExpandingTildeInPath]; 162 | BOOL isDirectory; 163 | if ([self fileExistsAtPath:path isDirectory:&isDirectory] && !isDirectory) { 164 | BOOL irtsIsCancelled = [invoker respondsToSelector:@selector(isCancelled)]; 165 | const NSUInteger crcBlockSize = 1048576; 166 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path]; 167 | NSData *block = [fileHandle readDataOfLength:crcBlockSize] ; 168 | while ([block length] > 0) { 169 | crc32 = [block zk_crc32:crc32]; 170 | if (irtsIsCancelled) { 171 | if ([invoker isCancelled]) { 172 | [fileHandle closeFile]; 173 | return 0; 174 | } 175 | } 176 | block = [fileHandle readDataOfLength:crcBlockSize]; 177 | [NSThread sleepForTimeInterval:throttleThreadSleepTime]; 178 | } 179 | [fileHandle closeFile]; 180 | } else 181 | crc32 = 0; 182 | return crc32; 183 | } 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /External/ZipKit/NSString+ZKAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+ZKAdditions.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface NSString (ZKAdditions) 11 | 12 | - (NSUInteger) zk_precomposedUTF8Length; 13 | - (BOOL) zk_isResourceForkPath; 14 | 15 | @end -------------------------------------------------------------------------------- /External/ZipKit/NSString+ZKAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+ZKAdditions.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "NSString+ZKAdditions.h" 9 | #import "ZKDefs.h" 10 | 11 | @implementation NSString (ZKAdditions) 12 | 13 | - (NSUInteger) zk_precomposedUTF8Length { 14 | return [[self precomposedStringWithCanonicalMapping] lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 15 | } 16 | 17 | - (BOOL) zk_isResourceForkPath { 18 | return [[[self pathComponents] objectAtIndex:0] isEqualToString:ZKMacOSXDirectory]; 19 | } 20 | 21 | 22 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKArchive.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKArchive.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 08/05/09. 6 | // 7 | 8 | #import 9 | 10 | @class ZKCDTrailer; 11 | 12 | @interface ZKArchive : NSObject { 13 | @private 14 | // invoker should be an NSOperation or NSThread; if [invoker isCancelled], inflation or deflation will be aborted 15 | id __weak _invoker; 16 | id __weak _delegate; 17 | NSString *_archivePath; 18 | NSMutableArray *_centralDirectory; 19 | NSFileManager *_fileManager; 20 | ZKCDTrailer *_cdTrailer; 21 | NSTimeInterval _throttleThreadSleepTime; 22 | 23 | @protected 24 | // cached respondsToSelector: checks 25 | BOOL drtsDelegateWantsSizes; 26 | BOOL drtsDidBeginZip; 27 | BOOL drtsDidBeginUnzip; 28 | BOOL drtsWillZipPath; 29 | BOOL drtsWillUnzipPath; 30 | BOOL drtsDidEndZip; 31 | BOOL drtsDidEndUnzip; 32 | BOOL drtsDidCancel; 33 | BOOL drtsDidFail; 34 | BOOL drtsDidUpdateTotalSize; 35 | BOOL drtsDidUpdateTotalCount; 36 | BOOL drtsDidUpdateBytesWritten; 37 | 38 | BOOL irtsIsCancelled; 39 | } 40 | 41 | + (BOOL) validArchiveAtPath:(NSString *) path; 42 | + (NSString *) uniquify:(NSString *) path; 43 | - (void) calculateSizeAndItemCount:(NSDictionary *) userInfo; 44 | - (NSString *) uniqueExpansionDirectoryIn:(NSString *) enclosingFolder; 45 | - (void) cleanUpExpansionDirectory:(NSString *) expansionDirectory; 46 | 47 | - (BOOL) delegateWantsSizes; 48 | 49 | - (void) didBeginZip; 50 | - (void) didBeginUnzip; 51 | - (void) willZipPath:(NSString *)path; 52 | - (void) willUnzipPath:(NSString *)path; 53 | - (void) didEndZip; 54 | - (void) didEndUnzip; 55 | - (void) didCancel; 56 | - (void) didFail; 57 | - (void) didUpdateTotalSize:(NSNumber *) size; 58 | - (void) didUpdateTotalCount:(NSNumber *) count; 59 | - (void) didUpdateBytesWritten:(NSNumber *) byteCount; 60 | 61 | @property (assign, nonatomic) id __weak invoker; 62 | @property (assign, nonatomic) id __weak delegate; 63 | @property (copy) NSString *archivePath; 64 | @property (retain) NSMutableArray *centralDirectory; 65 | @property (retain) NSFileManager *fileManager; 66 | @property (retain) ZKCDTrailer *cdTrailer; 67 | @property (assign) NSTimeInterval throttleThreadSleepTime; 68 | @property (copy) NSString *comment; 69 | 70 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKArchive.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKArchive.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 08/05/09. 6 | // 7 | 8 | #import "ZKArchive.h" 9 | #import "NSDictionary+ZKAdditions.h" 10 | #import "NSFileManager+ZKAdditions.h" 11 | #import "ZKCDTrailer.h" 12 | #import "ZKDefs.h" 13 | 14 | @interface NSObject (ZipKitDelegate) 15 | - (void) onZKArchiveDidBeginZip:(ZKArchive *) archive; 16 | - (void) onZKArchiveDidBeginUnzip:(ZKArchive *) archive; 17 | - (void) onZKArchive:(ZKArchive *) archive willZipPath:(NSString *) path; 18 | - (void) onZKArchive:(ZKArchive *) archive willUnzipPath:(NSString *) path; 19 | - (void) onZKArchive:(ZKArchive *) archive didUpdateTotalSize:(unsigned long long) size; 20 | - (void) onZKArchive:(ZKArchive *) archive didUpdateTotalCount:(unsigned long long) count; 21 | - (void) onZKArchive:(ZKArchive *) archive didUpdateBytesWritten:(unsigned long long) byteCount; 22 | - (void) onZKArchiveDidEndZip:(ZKArchive *) archive; 23 | - (void) onZKArchiveDidEndUnzip:(ZKArchive *) archive; 24 | - (void) onZKArchiveDidCancel:(ZKArchive *) archive; 25 | - (void) onZKArchiveDidFail:(ZKArchive *) archive; 26 | - (BOOL) zkDelegateWantsSizes; 27 | @end 28 | 29 | #pragma mark - 30 | 31 | @implementation ZKArchive 32 | 33 | #pragma mark - 34 | #pragma mark Utility 35 | 36 | + (BOOL) validArchiveAtPath:(NSString *) path { 37 | // check that the first few bytes of the file are a local file header 38 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path]; 39 | NSData *fileHeader = [fileHandle readDataOfLength:4]; 40 | [fileHandle closeFile]; 41 | UInt32 headerValue; 42 | [fileHeader getBytes:&headerValue]; 43 | return (CFSwapInt32LittleToHost(headerValue) == ZKLFHeaderMagicNumber); 44 | } 45 | 46 | + (NSString *) uniquify:(NSString *) path { 47 | // avoid name collisions by adding a sequence number if needed 48 | NSString * uniquePath = [NSString stringWithString:path]; 49 | NSString *dir = [path stringByDeletingLastPathComponent]; 50 | NSString *fileNameBase = [[path lastPathComponent] stringByDeletingPathExtension]; 51 | NSString *ext = [path pathExtension]; 52 | NSUInteger i = 2; 53 | NSFileManager *fm = [[NSFileManager new] autorelease]; 54 | while ([fm fileExistsAtPath:uniquePath]) { 55 | uniquePath = [dir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %u", fileNameBase, i++]]; 56 | if (ext && [ext length] > 0) 57 | uniquePath = [uniquePath stringByAppendingPathExtension:ext]; 58 | } 59 | return uniquePath; 60 | } 61 | 62 | - (void) calculateSizeAndItemCount:(NSDictionary *) userInfo { 63 | NSArray *paths = [userInfo objectForKey:ZKPathsKey]; 64 | BOOL rfFlag = [[userInfo objectForKey:ZKusingResourceForkKey] boolValue]; 65 | unsigned long long size = 0; 66 | unsigned long long count = 0; 67 | NSFileManager *fmgr = [[NSFileManager new] autorelease]; 68 | NSDictionary *dict = nil; 69 | for (NSString *path in paths) { 70 | dict = [fmgr zkTotalSizeAndItemCountAtPath:path usingResourceFork:rfFlag]; 71 | size += [dict zk_totalFileSize]; 72 | count += [dict zk_itemCount]; 73 | } 74 | [self performSelectorOnMainThread:@selector(didUpdateTotalSize:) 75 | withObject:[NSNumber numberWithUnsignedLongLong:size] waitUntilDone:NO]; 76 | [self performSelectorOnMainThread:@selector(didUpdateTotalCount:) 77 | withObject:[NSNumber numberWithUnsignedLongLong:count] waitUntilDone:NO]; 78 | } 79 | 80 | - (NSString *) uniqueExpansionDirectoryIn:(NSString *) enclosingFolder { 81 | NSString *expansionDirectory = [enclosingFolder stringByAppendingPathComponent:ZKExpansionDirectoryName]; 82 | NSUInteger i = 1; 83 | while ([self.fileManager fileExistsAtPath:expansionDirectory]) { 84 | expansionDirectory = [enclosingFolder stringByAppendingPathComponent: 85 | [NSString stringWithFormat:@"%@ %u", ZKExpansionDirectoryName, i++]]; 86 | } 87 | return expansionDirectory; 88 | } 89 | 90 | - (void) cleanUpExpansionDirectory:(NSString *) expansionDirectory { 91 | NSString *enclosingFolder = [expansionDirectory stringByDeletingLastPathComponent]; 92 | NSArray *dirContents = [self.fileManager contentsOfDirectoryAtPath:expansionDirectory error:nil]; 93 | for (NSString *item in dirContents) { 94 | if (![item isEqualToString:ZKMacOSXDirectory]) { 95 | NSString *subPath = [expansionDirectory stringByAppendingPathComponent:item]; 96 | NSString *dest = [enclosingFolder stringByAppendingPathComponent:item]; 97 | NSUInteger i = 2; 98 | while ([self.fileManager fileExistsAtPath:dest]) { 99 | NSString *ext = [item pathExtension]; 100 | dest = [enclosingFolder stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %u", 101 | [item stringByDeletingPathExtension], i++]]; 102 | if (ext && [ext length] > 0) 103 | dest = [dest stringByAppendingPathExtension:ext]; 104 | } 105 | [self.fileManager moveItemAtPath:subPath toPath:dest error:nil]; 106 | } 107 | } 108 | [self.fileManager removeItemAtPath:expansionDirectory error:nil]; 109 | 110 | } 111 | 112 | #pragma mark - 113 | #pragma mark Accessors 114 | 115 | - (NSString *) comment { 116 | return self.cdTrailer.comment; 117 | } 118 | - (void) setComment:(NSString *)comment { 119 | self.cdTrailer.comment = comment; 120 | } 121 | 122 | #pragma mark - 123 | #pragma mark Delegate 124 | 125 | - (void) setInvoker:(id)i { 126 | _invoker = i; 127 | if (_invoker) { 128 | irtsIsCancelled = [self.invoker respondsToSelector:@selector(isCancelled)]; 129 | } else { 130 | irtsIsCancelled = NO; 131 | } 132 | } 133 | 134 | - (void) setDelegate:(id)d { 135 | _delegate = d; 136 | if (_delegate) { 137 | drtsDelegateWantsSizes = [_delegate respondsToSelector:@selector(zkDelegateWantsSizes)]; 138 | drtsDidBeginZip = [_delegate respondsToSelector:@selector(onZKArchiveDidBeginZip:)]; 139 | drtsDidBeginUnzip = [_delegate respondsToSelector:@selector(onZKArchiveDidBeginUnzip:)]; 140 | drtsWillZipPath = [_delegate respondsToSelector:@selector(onZKArchive:willZipPath:)]; 141 | drtsWillUnzipPath = [_delegate respondsToSelector:@selector(onZKArchive:willUnzipPath:)]; 142 | drtsDidEndZip = [_delegate respondsToSelector:@selector(onZKArchiveDidEndZip:)]; 143 | drtsDidEndUnzip = [_delegate respondsToSelector:@selector(onZKArchiveDidEndUnzip:)]; 144 | drtsDidCancel = [_delegate respondsToSelector:@selector(onZKArchiveDidCancel:)]; 145 | drtsDidFail = [_delegate respondsToSelector:@selector(onZKArchiveDidFail:)]; 146 | drtsDidUpdateTotalSize = [_delegate respondsToSelector:@selector(onZKArchive:didUpdateTotalSize:)]; 147 | drtsDidUpdateTotalCount = [_delegate respondsToSelector:@selector(onZKArchive:didUpdateTotalCount:)]; 148 | drtsDidUpdateBytesWritten = [_delegate respondsToSelector:@selector(onZKArchive:didUpdateBytesWritten:)]; 149 | } else { 150 | drtsDelegateWantsSizes = NO; 151 | drtsDidBeginZip = NO; 152 | drtsDidBeginUnzip = NO; 153 | drtsWillZipPath = NO; 154 | drtsWillUnzipPath = NO; 155 | drtsDidEndZip = NO; 156 | drtsDidEndUnzip = NO; 157 | drtsDidCancel = NO; 158 | drtsDidFail = NO; 159 | drtsDidUpdateTotalSize = NO; 160 | drtsDidUpdateTotalCount = NO; 161 | drtsDidUpdateBytesWritten = NO; 162 | } 163 | } 164 | 165 | - (BOOL) delegateWantsSizes { 166 | BOOL delegateWantsSizes = NO; 167 | if (drtsDelegateWantsSizes) { 168 | delegateWantsSizes = [self.delegate zkDelegateWantsSizes]; 169 | } 170 | return delegateWantsSizes; 171 | } 172 | 173 | - (void) didBeginZip { 174 | if (drtsDidBeginZip) 175 | [self.delegate onZKArchiveDidBeginZip:self]; 176 | } 177 | 178 | - (void) didBeginUnzip { 179 | if (drtsDidBeginUnzip) 180 | [self.delegate onZKArchiveDidBeginUnzip:self]; 181 | } 182 | 183 | - (void) willZipPath:(NSString *) path { 184 | if (drtsWillZipPath) 185 | [self.delegate onZKArchive:self willZipPath:path]; 186 | } 187 | 188 | - (void) willUnzipPath:(NSString *) path { 189 | if (drtsWillUnzipPath) 190 | [self.delegate onZKArchive:self willUnzipPath:path]; 191 | } 192 | 193 | - (void) didEndZip { 194 | if (drtsDidEndZip) 195 | [self.delegate onZKArchiveDidEndZip:self]; 196 | } 197 | 198 | - (void) didEndUnzip { 199 | if (drtsDidEndUnzip) 200 | [self.delegate onZKArchiveDidEndUnzip:self]; 201 | } 202 | 203 | - (void) didCancel { 204 | if (drtsDidCancel) 205 | [self.delegate onZKArchiveDidCancel:self]; 206 | } 207 | 208 | - (void) didFail { 209 | if (drtsDidFail) 210 | [self.delegate onZKArchiveDidFail:self]; 211 | } 212 | 213 | - (void) didUpdateTotalSize:(NSNumber *) size { 214 | if (drtsDidUpdateTotalSize) 215 | [self.delegate onZKArchive:self didUpdateTotalSize:[size unsignedLongLongValue]]; 216 | } 217 | 218 | - (void) didUpdateTotalCount:(NSNumber *) count { 219 | if (drtsDidUpdateTotalCount) 220 | [self.delegate onZKArchive:self didUpdateTotalCount:[count unsignedLongLongValue]]; 221 | } 222 | 223 | - (void) didUpdateBytesWritten:(NSNumber *) byteCount { 224 | if (drtsDidUpdateBytesWritten) 225 | [self.delegate onZKArchive:self didUpdateBytesWritten:[byteCount unsignedLongLongValue]]; 226 | } 227 | 228 | #pragma mark - 229 | #pragma mark Setup 230 | 231 | - (id) init { 232 | if (self = [super init]) { 233 | self.invoker = nil; 234 | self.delegate = nil; 235 | self.archivePath = nil; 236 | self.centralDirectory = [NSMutableArray array]; 237 | self.fileManager = [[NSFileManager new] autorelease]; 238 | self.cdTrailer = [[ZKCDTrailer new] autorelease]; 239 | self.throttleThreadSleepTime = 0.0; 240 | } 241 | return self; 242 | } 243 | 244 | - (void) dealloc { 245 | self.invoker = nil; 246 | self.delegate = nil; 247 | self.archivePath = nil; 248 | self.centralDirectory = nil; 249 | self.fileManager = nil; 250 | self.cdTrailer = nil; 251 | [super dealloc]; 252 | } 253 | 254 | - (NSString *) description { 255 | return [NSString stringWithFormat: @"%@\n\ttrailer:%@\n\tcentral directory:%@", self.archivePath, self.cdTrailer, self.centralDirectory]; 256 | } 257 | 258 | @synthesize invoker = _invoker, delegate = _delegate, archivePath = _archivePath, centralDirectory = _centralDirectory, fileManager = _fileManager, cdTrailer = _cdTrailer, throttleThreadSleepTime = _throttleThreadSleepTime; 259 | @dynamic comment; 260 | 261 | @end 262 | -------------------------------------------------------------------------------- /External/ZipKit/ZKCDHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDHeader.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface ZKCDHeader : NSObject { 11 | @private 12 | NSUInteger magicNumber; 13 | NSUInteger versionMadeBy; 14 | NSUInteger versionNeededToExtract; 15 | NSUInteger generalPurposeBitFlag; 16 | NSUInteger compressionMethod; 17 | NSDate *lastModDate; 18 | NSUInteger crc; 19 | unsigned long long compressedSize; 20 | unsigned long long uncompressedSize; 21 | NSUInteger filenameLength; 22 | NSUInteger extraFieldLength; 23 | NSUInteger commentLength; 24 | NSUInteger diskNumberStart; 25 | NSUInteger internalFileAttributes; 26 | NSUInteger externalFileAttributes; 27 | unsigned long long localHeaderOffset; 28 | NSString *filename; 29 | NSData *extraField; 30 | NSString *comment; 31 | NSMutableData *cachedData; 32 | } 33 | 34 | + (ZKCDHeader *) recordWithData:(NSData *)data atOffset:(NSUInteger)offset; 35 | + (ZKCDHeader *) recordWithArchivePath:(NSString *)path atOffset:(unsigned long long)offset; 36 | - (void) parseZip64ExtraField; 37 | - (NSData *) zip64ExtraField; 38 | - (NSData *) data; 39 | - (NSUInteger) length; 40 | - (BOOL) useZip64Extensions; 41 | - (NSNumber *) posixPermissions; 42 | - (BOOL) isDirectory; 43 | - (BOOL) isSymLink; 44 | - (BOOL) isResourceFork; 45 | 46 | @property (assign) NSUInteger magicNumber; 47 | @property (assign) NSUInteger versionMadeBy; 48 | @property (assign) NSUInteger versionNeededToExtract; 49 | @property (assign) NSUInteger generalPurposeBitFlag; 50 | @property (assign) NSUInteger compressionMethod; 51 | @property (retain) NSDate *lastModDate; 52 | @property (assign) NSUInteger crc; 53 | @property (assign) unsigned long long compressedSize; 54 | @property (assign) unsigned long long uncompressedSize; 55 | @property (assign) NSUInteger filenameLength; 56 | @property (assign) NSUInteger extraFieldLength; 57 | @property (assign) NSUInteger commentLength; 58 | @property (assign) NSUInteger diskNumberStart; 59 | @property (assign) NSUInteger internalFileAttributes; 60 | @property (assign) NSUInteger externalFileAttributes; 61 | @property (assign) unsigned long long localHeaderOffset; 62 | @property (copy) NSString *filename; 63 | @property (retain) NSData *extraField; 64 | @property (copy) NSString *comment; 65 | @property (retain) NSMutableData *cachedData; 66 | 67 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKCDHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDHeader.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "ZKCDHeader.h" 9 | #import "NSDate+ZKAdditions.h" 10 | #import "NSData+ZKAdditions.h" 11 | #import "NSString+ZKAdditions.h" 12 | #import "ZKDefs.h" 13 | #import "zlib.h" 14 | 15 | @implementation ZKCDHeader 16 | 17 | - (id) init { 18 | if (self = [super init]) { 19 | self.magicNumber = ZKCDHeaderMagicNumber; 20 | self.versionNeededToExtract = 20; 21 | self.versionMadeBy = 789; 22 | self.generalPurposeBitFlag = 0; 23 | self.compressionMethod = Z_DEFLATED; 24 | self.lastModDate = [NSDate date]; 25 | self.crc = 0; 26 | self.compressedSize = 0; 27 | self.uncompressedSize = 0; 28 | self.filenameLength = 0; 29 | self.extraFieldLength = 0; 30 | self.commentLength = 0; 31 | self.diskNumberStart = 0; 32 | self.internalFileAttributes = 0; 33 | self.externalFileAttributes = 0; 34 | self.localHeaderOffset = 0; 35 | self.extraField = nil; 36 | self.comment = nil; 37 | 38 | [self addObserver:self forKeyPath:@"compressedSize" options:NSKeyValueObservingOptionNew context:nil]; 39 | [self addObserver:self forKeyPath:@"uncompressedSize" options:NSKeyValueObservingOptionNew context:nil]; 40 | [self addObserver:self forKeyPath:@"localHeaderOffset" options:NSKeyValueObservingOptionNew context:nil]; 41 | [self addObserver:self forKeyPath:@"extraField" options:NSKeyValueObservingOptionNew context:nil]; 42 | [self addObserver:self forKeyPath:@"filename" options:NSKeyValueObservingOptionNew context:nil]; 43 | [self addObserver:self forKeyPath:@"comment" options:NSKeyValueObservingOptionNew context:nil]; 44 | } 45 | return self; 46 | } 47 | 48 | - (void) removeObservers { 49 | [self removeObserver:self forKeyPath:@"compressedSize"]; 50 | [self removeObserver:self forKeyPath:@"uncompressedSize"]; 51 | [self removeObserver:self forKeyPath:@"localHeaderOffset"]; 52 | [self removeObserver:self forKeyPath:@"extraField"]; 53 | [self removeObserver:self forKeyPath:@"filename"]; 54 | [self removeObserver:self forKeyPath:@"comment"]; 55 | } 56 | 57 | - (void) dealloc { 58 | [self removeObservers]; 59 | self.cachedData = nil; 60 | self.lastModDate = nil; 61 | self.filename = nil; 62 | self.extraField = nil; 63 | self.comment = nil; 64 | [super dealloc]; 65 | } 66 | 67 | - (void) finalize { 68 | self.cachedData = nil; 69 | [self removeObservers]; 70 | [super finalize]; 71 | } 72 | 73 | - (void) observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context { 74 | if ([keyPath isEqualToString:@"compressedSize"] 75 | || [keyPath isEqualToString:@"uncompressedSize"] 76 | || [keyPath isEqualToString:@"localHeaderOffset"]) { 77 | self.versionNeededToExtract = ([self useZip64Extensions] ? 45 : 20); 78 | } else if ([keyPath isEqualToString:@"extraField"] && self.extraFieldLength < 1) { 79 | self.extraFieldLength = [self.extraField length]; 80 | } else if ([keyPath isEqualToString:@"filename"] && self.filenameLength < 1) { 81 | self.filenameLength = [self.filename zk_precomposedUTF8Length]; 82 | } else if ([keyPath isEqualToString:@"comment"] && self.commentLength < 1) { 83 | self.commentLength = [self.comment zk_precomposedUTF8Length]; 84 | } 85 | } 86 | 87 | + (ZKCDHeader *) recordWithData:(NSData *)data atOffset:(NSUInteger)offset { 88 | if (!data) return nil; 89 | NSUInteger mn = [data zk_hostInt32OffsetBy:&offset]; 90 | if (mn != ZKCDHeaderMagicNumber) return nil; 91 | ZKCDHeader *record = [[ZKCDHeader new] autorelease]; 92 | record.magicNumber = mn; 93 | record.versionMadeBy = [data zk_hostInt16OffsetBy:&offset]; 94 | record.versionNeededToExtract = [data zk_hostInt16OffsetBy:&offset]; 95 | record.generalPurposeBitFlag = [data zk_hostInt16OffsetBy:&offset]; 96 | record.compressionMethod = [data zk_hostInt16OffsetBy:&offset]; 97 | record.lastModDate = [NSDate zk_dateWithDosDate:[data zk_hostInt32OffsetBy:&offset]]; 98 | record.crc = [data zk_hostInt32OffsetBy:&offset]; 99 | record.compressedSize = [data zk_hostInt32OffsetBy:&offset]; 100 | record.uncompressedSize = [data zk_hostInt32OffsetBy:&offset]; 101 | record.filenameLength = [data zk_hostInt16OffsetBy:&offset]; 102 | record.extraFieldLength = [data zk_hostInt16OffsetBy:&offset]; 103 | record.commentLength = [data zk_hostInt16OffsetBy:&offset]; 104 | record.diskNumberStart = [data zk_hostInt16OffsetBy:&offset]; 105 | record.internalFileAttributes = [data zk_hostInt16OffsetBy:&offset]; 106 | record.externalFileAttributes = [data zk_hostInt32OffsetBy:&offset]; 107 | record.localHeaderOffset = [data zk_hostInt32OffsetBy:&offset]; 108 | if ([data length] > ZKCDHeaderFixedDataLength) { 109 | if (record.filenameLength) 110 | record.filename = [data zk_stringOffsetBy:&offset length:record.filenameLength]; 111 | if (record.extraFieldLength) { 112 | record.extraField = [data subdataWithRange:NSMakeRange(offset, record.extraFieldLength)]; 113 | offset += record.extraFieldLength; 114 | [record parseZip64ExtraField]; 115 | } 116 | if (record.commentLength) 117 | record.comment = [data zk_stringOffsetBy:&offset length:record.commentLength]; 118 | } 119 | return record; 120 | } 121 | 122 | + (ZKCDHeader *) recordWithArchivePath:(NSString *)path atOffset:(unsigned long long)offset { 123 | NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; 124 | [file seekToFileOffset:offset]; 125 | NSData *fixedData = [file readDataOfLength:ZKCDHeaderFixedDataLength]; 126 | ZKCDHeader *record = [self recordWithData:fixedData atOffset:0]; 127 | if (record.filenameLength > 0) { 128 | NSData *data = [file readDataOfLength:record.filenameLength]; 129 | record.filename = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; 130 | } 131 | if (record.extraFieldLength > 0) { 132 | record.extraField = [file readDataOfLength:record.extraFieldLength]; 133 | [record parseZip64ExtraField]; 134 | } 135 | if (record.commentLength > 0) { 136 | NSData *data = [file readDataOfLength:record.commentLength]; 137 | record.comment = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; 138 | } else 139 | record.comment = nil; 140 | 141 | [file closeFile]; 142 | return record; 143 | } 144 | 145 | - (NSData *) data { 146 | if (!self.cachedData || ([self.cachedData length] < ZKCDHeaderFixedDataLength)) { 147 | self.extraField = [self zip64ExtraField]; 148 | 149 | self.cachedData = [NSMutableData zk_dataWithLittleInt32:self.magicNumber]; 150 | [self.cachedData zk_appendLittleInt16:self.versionMadeBy]; 151 | [self.cachedData zk_appendLittleInt16:self.versionNeededToExtract]; 152 | [self.cachedData zk_appendLittleInt16:self.generalPurposeBitFlag]; 153 | [self.cachedData zk_appendLittleInt16:self.compressionMethod]; 154 | [self.cachedData zk_appendLittleInt32:[self.lastModDate zk_dosDate]]; 155 | [self.cachedData zk_appendLittleInt32:self.crc]; 156 | if ([self useZip64Extensions]) { 157 | [self.cachedData zk_appendLittleInt32:0xFFFFFFFF]; 158 | [self.cachedData zk_appendLittleInt32:0xFFFFFFFF]; 159 | } else { 160 | [self.cachedData zk_appendLittleInt32:self.compressedSize]; 161 | [self.cachedData zk_appendLittleInt32:self.uncompressedSize]; 162 | } 163 | [self.cachedData zk_appendLittleInt16:[self.filename zk_precomposedUTF8Length]]; 164 | [self.cachedData zk_appendLittleInt16:[self.extraField length]]; 165 | [self.cachedData zk_appendLittleInt16:[self.comment zk_precomposedUTF8Length]]; 166 | [self.cachedData zk_appendLittleInt16:self.diskNumberStart]; 167 | [self.cachedData zk_appendLittleInt16:self.internalFileAttributes]; 168 | [self.cachedData zk_appendLittleInt32:self.externalFileAttributes]; 169 | if ([self useZip64Extensions]) 170 | [self.cachedData zk_appendLittleInt32:0xFFFFFFFF]; 171 | else 172 | [self.cachedData zk_appendLittleInt32:self.localHeaderOffset]; 173 | [self.cachedData zk_appendPrecomposedUTF8String:self.filename]; 174 | [self.cachedData appendData:self.extraField]; 175 | [self.cachedData zk_appendPrecomposedUTF8String:self.comment]; 176 | } 177 | return self.cachedData; 178 | } 179 | 180 | - (void) parseZip64ExtraField { 181 | NSUInteger offset = 0, tag, length; 182 | while (offset < self.extraFieldLength) { 183 | tag = [self.extraField zk_hostInt16OffsetBy:&offset]; 184 | length = [self.extraField zk_hostInt16OffsetBy:&offset]; 185 | if (tag == 0x0001) { 186 | if (length >= 8) 187 | self.uncompressedSize = [self.extraField zk_hostInt64OffsetBy:&offset]; 188 | if (length >= 16) 189 | self.compressedSize = [self.extraField zk_hostInt64OffsetBy:&offset]; 190 | if (length >= 24) 191 | self.localHeaderOffset = [self.extraField zk_hostInt64OffsetBy:&offset]; 192 | break; 193 | } else { 194 | offset += length; 195 | } 196 | } 197 | } 198 | 199 | - (NSData *) zip64ExtraField { 200 | NSMutableData *zip64ExtraField = nil; 201 | if ([self useZip64Extensions]) { 202 | zip64ExtraField = [NSMutableData zk_dataWithLittleInt16:0x0001]; 203 | [zip64ExtraField zk_appendLittleInt16:24]; 204 | [zip64ExtraField zk_appendLittleInt64:self.uncompressedSize]; 205 | [zip64ExtraField zk_appendLittleInt64:self.compressedSize]; 206 | [zip64ExtraField zk_appendLittleInt64:self.localHeaderOffset]; 207 | } 208 | return zip64ExtraField; 209 | } 210 | 211 | - (NSUInteger) length { 212 | if (!self.extraField || [self.extraField length] == 0) 213 | self.extraField = [self zip64ExtraField]; 214 | return ZKCDHeaderFixedDataLength + self.filenameLength + self.commentLength + [self.extraField length]; 215 | } 216 | 217 | - (BOOL) useZip64Extensions { 218 | return (self.uncompressedSize >= 0xFFFFFFFF) || (self.compressedSize >= 0xFFFFFFFF) || (self.localHeaderOffset >= 0xFFFFFFFF); 219 | } 220 | 221 | - (NSString *) description { 222 | return [NSString stringWithFormat:@"%@ modified %@, %qu bytes (%qu compressed), @ %qu", 223 | self.filename, self.lastModDate, self.uncompressedSize, self.compressedSize, self.localHeaderOffset]; 224 | } 225 | 226 | - (NSNumber *) posixPermissions { 227 | // if posixPermissions are 0, e.g. on Windows-produced archives, then default them to rwxr-wr-w a la Archive Utility 228 | return [NSNumber numberWithUnsignedInteger:(self.externalFileAttributes >> 16 & 0x1FF) ?: 0755U]; 229 | } 230 | 231 | - (BOOL) isDirectory { 232 | uLong type = self.externalFileAttributes >> 29 & 0x1F; 233 | return (0x02 == type) && ![self isSymLink]; 234 | } 235 | 236 | - (BOOL) isSymLink { 237 | uLong type = self.externalFileAttributes >> 29 & 0x1F; 238 | return (0x05 == type); 239 | } 240 | 241 | - (BOOL) isResourceFork { 242 | return [self.filename zk_isResourceForkPath]; 243 | } 244 | 245 | @synthesize magicNumber, versionNeededToExtract, versionMadeBy, generalPurposeBitFlag, compressionMethod, lastModDate, crc, compressedSize, uncompressedSize, filenameLength, extraFieldLength, commentLength, diskNumberStart, internalFileAttributes, externalFileAttributes, localHeaderOffset, filename, extraField, comment, cachedData; 246 | 247 | @end 248 | -------------------------------------------------------------------------------- /External/ZipKit/ZKCDTrailer.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDTrailer.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface ZKCDTrailer : NSObject { 11 | @private 12 | NSUInteger magicNumber; 13 | NSUInteger thisDiskNumber; 14 | NSUInteger diskNumberWithStartOfCentralDirectory; 15 | NSUInteger numberOfCentralDirectoryEntriesOnThisDisk; 16 | NSUInteger totalNumberOfCentralDirectoryEntries; 17 | unsigned long long sizeOfCentralDirectory; 18 | unsigned long long offsetOfStartOfCentralDirectory; 19 | NSUInteger commentLength; 20 | NSString *comment; 21 | } 22 | 23 | + (ZKCDTrailer *) recordWithData:(NSData *)data atOffset:(NSUInteger) offset; 24 | + (ZKCDTrailer *) recordWithData:(NSData *)data; 25 | + (ZKCDTrailer *) recordWithArchivePath:(NSString *) path; 26 | - (NSData *) data; 27 | - (NSUInteger) length; 28 | - (BOOL) useZip64Extensions; 29 | 30 | @property (assign) NSUInteger magicNumber; 31 | @property (assign) NSUInteger thisDiskNumber; 32 | @property (assign) NSUInteger diskNumberWithStartOfCentralDirectory; 33 | @property (assign) NSUInteger numberOfCentralDirectoryEntriesOnThisDisk; 34 | @property (assign) NSUInteger totalNumberOfCentralDirectoryEntries; 35 | @property (assign) unsigned long long sizeOfCentralDirectory; 36 | @property (assign) unsigned long long offsetOfStartOfCentralDirectory; 37 | @property (assign) NSUInteger commentLength; 38 | @property (copy) NSString *comment; 39 | 40 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKCDTrailer.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDTrailer.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "ZKCDTrailer.h" 9 | #import "NSData+ZKAdditions.h" 10 | #import "NSString+ZKAdditions.h" 11 | #import "ZKDefs.h" 12 | #import "zlib.h" 13 | 14 | @implementation ZKCDTrailer 15 | 16 | - (id) init { 17 | if (self = [super init]) { 18 | [self addObserver:self forKeyPath:@"comment" options:NSKeyValueObservingOptionNew context:nil]; 19 | 20 | self.magicNumber = ZKCDTrailerMagicNumber; 21 | self.thisDiskNumber = 0; 22 | self.diskNumberWithStartOfCentralDirectory = 0; 23 | self.numberOfCentralDirectoryEntriesOnThisDisk = 0; 24 | self.totalNumberOfCentralDirectoryEntries = 0; 25 | self.sizeOfCentralDirectory = 0; 26 | self.offsetOfStartOfCentralDirectory = 0; 27 | self.comment = @"Archive created with ZipKit"; 28 | } 29 | return self; 30 | } 31 | 32 | - (void) removeObservers { 33 | [self removeObserver:self forKeyPath:@"comment"]; 34 | } 35 | 36 | - (void) finalize { 37 | [self removeObservers]; 38 | [super finalize]; 39 | } 40 | 41 | - (void) dealloc { 42 | [self removeObservers]; 43 | self.comment = nil; 44 | [super dealloc]; 45 | } 46 | 47 | 48 | - (void) observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context { 49 | if ([keyPath isEqualToString:@"comment"] && self.commentLength < 1) { 50 | self.commentLength = [self.comment zk_precomposedUTF8Length]; 51 | } 52 | } 53 | 54 | + (ZKCDTrailer *) recordWithData:(NSData *)data atOffset:(NSUInteger) offset { 55 | NSUInteger mn = [data zk_hostInt32OffsetBy:&offset]; 56 | if (mn != ZKCDTrailerMagicNumber) return nil; 57 | ZKCDTrailer *record = [[ZKCDTrailer new] autorelease]; 58 | record.magicNumber = mn; 59 | record.thisDiskNumber = [data zk_hostInt16OffsetBy:&offset]; 60 | record.diskNumberWithStartOfCentralDirectory = [data zk_hostInt16OffsetBy:&offset]; 61 | record.numberOfCentralDirectoryEntriesOnThisDisk = [data zk_hostInt16OffsetBy:&offset]; 62 | record.totalNumberOfCentralDirectoryEntries = [data zk_hostInt16OffsetBy:&offset]; 63 | record.sizeOfCentralDirectory = [data zk_hostInt32OffsetBy:&offset]; 64 | record.offsetOfStartOfCentralDirectory = [data zk_hostInt32OffsetBy:&offset]; 65 | record.commentLength = [data zk_hostInt16OffsetBy:&offset]; 66 | if (record.commentLength > 0) 67 | record.comment = [data zk_stringOffsetBy:&offset length:record.commentLength]; 68 | else 69 | record.comment = nil; 70 | return record; 71 | } 72 | 73 | + (ZKCDTrailer *) recordWithData:(NSData *)data { 74 | UInt32 trailerCheck = 0; 75 | NSInteger offset = [data length] - sizeof(trailerCheck); 76 | while (trailerCheck != ZKCDTrailerMagicNumber && offset > 0) { 77 | NSUInteger o = offset; 78 | trailerCheck = [data zk_hostInt32OffsetBy:&o]; 79 | offset--; 80 | } 81 | if (offset < 1) 82 | return nil; 83 | ZKCDTrailer *record = [self recordWithData:data atOffset:++offset]; 84 | return record; 85 | } 86 | 87 | + (ZKCDTrailer *) recordWithArchivePath:(NSString *)path { 88 | NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; 89 | unsigned long long fileOffset = [file seekToEndOfFile]; 90 | for (UInt32 trailerCheck = 0; trailerCheck != ZKCDTrailerMagicNumber && fileOffset > 0; fileOffset--) { 91 | [file seekToFileOffset:fileOffset]; 92 | NSData *data = [file readDataOfLength:sizeof(UInt32)]; 93 | [data getBytes:&trailerCheck length:sizeof(UInt32)]; 94 | } 95 | if (fileOffset < 1) { 96 | [file closeFile]; 97 | return nil; 98 | } 99 | fileOffset++; 100 | [file seekToFileOffset:fileOffset]; 101 | NSData *data = [file readDataToEndOfFile]; 102 | [file closeFile]; 103 | ZKCDTrailer *record = [self recordWithData:data atOffset:(NSUInteger) 0]; 104 | return record; 105 | } 106 | 107 | - (NSData *) data { 108 | NSMutableData *data = [NSMutableData zk_dataWithLittleInt32:self.magicNumber]; 109 | [data zk_appendLittleInt16:self.thisDiskNumber]; 110 | [data zk_appendLittleInt16:self.diskNumberWithStartOfCentralDirectory]; 111 | [data zk_appendLittleInt16:self.numberOfCentralDirectoryEntriesOnThisDisk]; 112 | [data zk_appendLittleInt16:self.totalNumberOfCentralDirectoryEntries]; 113 | if ([self useZip64Extensions]) { 114 | [data zk_appendLittleInt32:0xFFFFFFFF]; 115 | [data zk_appendLittleInt32:0xFFFFFFFF]; 116 | } else { 117 | [data zk_appendLittleInt32:self.sizeOfCentralDirectory]; 118 | [data zk_appendLittleInt32:self.offsetOfStartOfCentralDirectory]; 119 | } 120 | [data zk_appendLittleInt16:[self.comment zk_precomposedUTF8Length]]; 121 | [data zk_appendPrecomposedUTF8String:self.comment]; 122 | return data; 123 | } 124 | 125 | - (NSUInteger) length { 126 | return ZKCDTrailerFixedDataLength + [self.comment length]; 127 | } 128 | 129 | - (BOOL) useZip64Extensions { 130 | return (self.sizeOfCentralDirectory >= 0xFFFFFFFF) || (self.offsetOfStartOfCentralDirectory >= 0xFFFFFFFF); 131 | } 132 | 133 | - (NSString *) description { 134 | return [NSString stringWithFormat:@"%u entries (%qu bytes) @: %qu", 135 | self.totalNumberOfCentralDirectoryEntries, 136 | self.sizeOfCentralDirectory, 137 | self.offsetOfStartOfCentralDirectory]; 138 | } 139 | 140 | @synthesize magicNumber, thisDiskNumber, diskNumberWithStartOfCentralDirectory, numberOfCentralDirectoryEntriesOnThisDisk, totalNumberOfCentralDirectoryEntries, sizeOfCentralDirectory, offsetOfStartOfCentralDirectory, commentLength, comment; 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /External/ZipKit/ZKCDTrailer64.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDTrailer64.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface ZKCDTrailer64 : NSObject { 11 | @private 12 | NSUInteger magicNumber; 13 | unsigned long long sizeOfTrailer; 14 | NSUInteger versionMadeBy; 15 | NSUInteger versionNeededToExtract; 16 | NSUInteger thisDiskNumber; 17 | NSUInteger diskNumberWithStartOfCentralDirectory; 18 | unsigned long long numberOfCentralDirectoryEntriesOnThisDisk; 19 | unsigned long long totalNumberOfCentralDirectoryEntries; 20 | unsigned long long sizeOfCentralDirectory; 21 | unsigned long long offsetOfStartOfCentralDirectory; 22 | } 23 | 24 | + (ZKCDTrailer64 *) recordWithData:(NSData *)data atOffset:(NSUInteger)offset; 25 | + (ZKCDTrailer64 *) recordWithArchivePath:(NSString *)path atOffset:(unsigned long long)offset; 26 | 27 | - (NSData *) data; 28 | - (NSUInteger) length; 29 | 30 | @property (assign) NSUInteger magicNumber; 31 | @property (assign) unsigned long long sizeOfTrailer; 32 | @property (assign) NSUInteger versionMadeBy; 33 | @property (assign) NSUInteger versionNeededToExtract; 34 | @property (assign) NSUInteger thisDiskNumber; 35 | @property (assign) NSUInteger diskNumberWithStartOfCentralDirectory; 36 | @property (assign) unsigned long long numberOfCentralDirectoryEntriesOnThisDisk; 37 | @property (assign) unsigned long long totalNumberOfCentralDirectoryEntries; 38 | @property (assign) unsigned long long sizeOfCentralDirectory; 39 | @property (assign) unsigned long long offsetOfStartOfCentralDirectory; 40 | 41 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKCDTrailer64.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDTrailer64.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "ZKCDTrailer64.h" 9 | #import "NSData+ZKAdditions.h" 10 | #import "ZKDefs.h" 11 | 12 | @implementation ZKCDTrailer64 13 | 14 | - (id) init { 15 | if (self = [super init]) { 16 | self.magicNumber = ZKCDTrailer64MagicNumber; 17 | self.sizeOfTrailer = 44; 18 | self.versionMadeBy = 789; 19 | self.versionNeededToExtract = 45; 20 | self.thisDiskNumber = 0; 21 | self.diskNumberWithStartOfCentralDirectory = 0; 22 | } 23 | return self; 24 | } 25 | 26 | + (ZKCDTrailer64 *) recordWithData:(NSData *)data atOffset:(NSUInteger)offset { 27 | if (!data) return nil; 28 | NSUInteger mn = [data zk_hostInt32OffsetBy:&offset]; 29 | if (mn != ZKCDTrailer64MagicNumber) return nil; 30 | ZKCDTrailer64 *record = [[ZKCDTrailer64 new] autorelease]; 31 | record.magicNumber = mn; 32 | record.sizeOfTrailer = [data zk_hostInt64OffsetBy:&offset]; 33 | record.versionMadeBy = [data zk_hostInt16OffsetBy:&offset]; 34 | record.versionNeededToExtract = [data zk_hostInt16OffsetBy:&offset]; 35 | record.thisDiskNumber = [data zk_hostInt32OffsetBy:&offset]; 36 | record.diskNumberWithStartOfCentralDirectory = [data zk_hostInt32OffsetBy:&offset]; 37 | record.numberOfCentralDirectoryEntriesOnThisDisk = [data zk_hostInt64OffsetBy:&offset]; 38 | record.totalNumberOfCentralDirectoryEntries = [data zk_hostInt64OffsetBy:&offset]; 39 | record.sizeOfCentralDirectory = [data zk_hostInt64OffsetBy:&offset]; 40 | record.offsetOfStartOfCentralDirectory = [data zk_hostInt64OffsetBy:&offset]; 41 | return record; 42 | } 43 | 44 | + (ZKCDTrailer64 *) recordWithArchivePath:(NSString *)path atOffset:(unsigned long long)offset { 45 | NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; 46 | [file seekToFileOffset:offset]; 47 | NSData *data = [file readDataOfLength:ZKCDTrailer64FixedDataLength]; 48 | [file closeFile]; 49 | ZKCDTrailer64 *record = [self recordWithData:data atOffset:0]; 50 | return record; 51 | } 52 | 53 | - (NSData *) data { 54 | NSMutableData *data = [NSMutableData zk_dataWithLittleInt32:self.magicNumber]; 55 | [data zk_appendLittleInt64:self.sizeOfTrailer]; 56 | [data zk_appendLittleInt16:self.versionMadeBy]; 57 | [data zk_appendLittleInt16:self.versionNeededToExtract]; 58 | [data zk_appendLittleInt32:self.thisDiskNumber]; 59 | [data zk_appendLittleInt32:self.diskNumberWithStartOfCentralDirectory]; 60 | [data zk_appendLittleInt64:self.numberOfCentralDirectoryEntriesOnThisDisk]; 61 | [data zk_appendLittleInt64:self.totalNumberOfCentralDirectoryEntries]; 62 | [data zk_appendLittleInt64:self.sizeOfCentralDirectory]; 63 | [data zk_appendLittleInt64:self.offsetOfStartOfCentralDirectory]; 64 | return data; 65 | } 66 | 67 | - (NSUInteger) length { 68 | return ZKCDTrailer64FixedDataLength; 69 | } 70 | 71 | - (NSString *) description { 72 | return [NSString stringWithFormat:@"%qu entries @ offset of CD: %qu (%qu bytes)", 73 | self.numberOfCentralDirectoryEntriesOnThisDisk, 74 | self.offsetOfStartOfCentralDirectory, 75 | self.sizeOfCentralDirectory]; 76 | } 77 | 78 | @synthesize magicNumber, sizeOfTrailer, versionMadeBy, versionNeededToExtract, thisDiskNumber, diskNumberWithStartOfCentralDirectory, numberOfCentralDirectoryEntriesOnThisDisk, totalNumberOfCentralDirectoryEntries, sizeOfCentralDirectory, offsetOfStartOfCentralDirectory; 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /External/ZipKit/ZKCDTrailer64Locator.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDTrailer64Locator.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface ZKCDTrailer64Locator : NSObject { 11 | @private 12 | NSUInteger magicNumber; 13 | NSUInteger diskNumberWithStartOfCentralDirectory; 14 | unsigned long long offsetOfStartOfCentralDirectoryTrailer64; 15 | NSUInteger numberOfDisks; 16 | } 17 | 18 | + (ZKCDTrailer64Locator *) recordWithData:(NSData *)data atOffset:(NSUInteger) offset; 19 | + (ZKCDTrailer64Locator *) recordWithArchivePath:(NSString *)path andCDTrailerLength:(NSUInteger)cdTrailerLength; 20 | 21 | - (NSData *) data; 22 | - (NSUInteger) length; 23 | 24 | @property (assign) NSUInteger magicNumber; 25 | @property (assign) NSUInteger diskNumberWithStartOfCentralDirectory; 26 | @property (assign) unsigned long long offsetOfStartOfCentralDirectoryTrailer64; 27 | @property (assign) NSUInteger numberOfDisks; 28 | 29 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKCDTrailer64Locator.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKCDTrailer64Locator.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "ZKCDTrailer64Locator.h" 9 | #import "NSData+ZKAdditions.h" 10 | #import "ZKDefs.h" 11 | 12 | @implementation ZKCDTrailer64Locator 13 | 14 | - (id) init { 15 | if (self = [super init]) { 16 | self.magicNumber = ZKCDTrailer64LocatorMagicNumber; 17 | self.diskNumberWithStartOfCentralDirectory = 0; 18 | self.numberOfDisks = 1; 19 | } 20 | return self; 21 | } 22 | 23 | + (ZKCDTrailer64Locator *) recordWithData:(NSData *)data atOffset:(NSUInteger) offset { 24 | NSUInteger mn = [data zk_hostInt32OffsetBy:&offset]; 25 | if (mn != ZKCDTrailer64LocatorMagicNumber) return nil; 26 | ZKCDTrailer64Locator *record = [[ZKCDTrailer64Locator new] autorelease]; 27 | record.magicNumber = mn; 28 | record.diskNumberWithStartOfCentralDirectory = [data zk_hostInt32OffsetBy:&offset]; 29 | record.offsetOfStartOfCentralDirectoryTrailer64 = [data zk_hostInt64OffsetBy:&offset]; 30 | record.numberOfDisks = [data zk_hostInt32OffsetBy:&offset]; 31 | return record; 32 | } 33 | 34 | + (ZKCDTrailer64Locator *) recordWithArchivePath:(NSString *)path andCDTrailerLength:(NSUInteger)cdTrailerLength { 35 | NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; 36 | unsigned long long fileOffset = [file seekToEndOfFile] - cdTrailerLength - ZKCDTrailer64LocatorFixedDataLength; 37 | [file seekToFileOffset:fileOffset]; 38 | NSData *data = [file readDataOfLength:ZKCDTrailer64LocatorFixedDataLength]; 39 | [file closeFile]; 40 | ZKCDTrailer64Locator *record = [self recordWithData:data atOffset:0]; 41 | return record; 42 | } 43 | 44 | - (NSData *) data { 45 | NSMutableData *data = [NSMutableData zk_dataWithLittleInt32:self.magicNumber]; 46 | [data zk_appendLittleInt32:self.diskNumberWithStartOfCentralDirectory]; 47 | [data zk_appendLittleInt64:self.offsetOfStartOfCentralDirectoryTrailer64]; 48 | [data zk_appendLittleInt32:self.numberOfDisks]; 49 | return data; 50 | } 51 | 52 | - (NSUInteger) length { 53 | return ZKCDTrailer64LocatorFixedDataLength; 54 | } 55 | 56 | - (NSString *) description { 57 | return [NSString stringWithFormat:@"offset of CD64: %qu", self.offsetOfStartOfCentralDirectoryTrailer64]; 58 | } 59 | 60 | @synthesize magicNumber, diskNumberWithStartOfCentralDirectory, offsetOfStartOfCentralDirectoryTrailer64, numberOfDisks; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /External/ZipKit/ZKDataArchive.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKDataArchive.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 07/05/09. 6 | // 7 | 8 | #import 9 | #import "ZKArchive.h" 10 | 11 | @class ZKCDHeader; 12 | 13 | @interface ZKDataArchive : ZKArchive { 14 | NSMutableData *_data; 15 | NSMutableArray *_inflatedFiles; 16 | } 17 | 18 | + (ZKDataArchive *) archiveWithArchivePath:(NSString *) path; 19 | + (ZKDataArchive *) archiveWithArchiveData:(NSMutableData *) archiveData; 20 | - (NSUInteger) inflateAll; 21 | - (NSData *) inflateFile:(ZKCDHeader *) cdHeader attributes:(NSDictionary **) fileAttributes; 22 | - (NSUInteger) inflateInFolder:(NSString *)enclosingFolder withFolderName:(NSString *)folderName usingResourceFork:(BOOL) rfFlag; 23 | 24 | - (NSInteger) deflateFiles:(NSArray *) paths relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) flag; 25 | - (NSInteger) deflateDirectory:(NSString *) dirPath relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) flag; 26 | - (NSInteger) deflateFile:(NSString *) path relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) rfFlag; 27 | - (NSInteger) deflateData:(NSData *)data withFilename:(NSString *) filename andAttributes:(NSDictionary *) fileAttributes; 28 | 29 | @property (retain) NSMutableData *data; 30 | @property (retain) NSMutableArray *inflatedFiles; 31 | 32 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKDataArchive.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKDataArchive.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 07/05/09. 6 | // 7 | 8 | #import "ZKDataArchive.h" 9 | #import "ZKCDHeader.h" 10 | #import "ZKCDTrailer.h" 11 | #import "ZKLFHeader.h" 12 | #import "NSData+ZKAdditions.h" 13 | #import "NSFileManager+ZKAdditions.h" 14 | #import "NSString+ZKAdditions.h" 15 | #import "ZKDefs.h" 16 | #import "zlib.h" 17 | 18 | #if ZK_TARGET_OS_MAC 19 | #import "GMAppleDouble+ZKAdditions.h" 20 | #endif 21 | 22 | @implementation ZKDataArchive 23 | 24 | + (ZKDataArchive *) archiveWithArchivePath:(NSString *) path { 25 | return [self archiveWithArchiveData:[NSMutableData dataWithContentsOfFile:path]]; 26 | } 27 | 28 | + (ZKDataArchive *) archiveWithArchiveData:(NSMutableData *) archiveData { 29 | ZKDataArchive *archive = [[ZKDataArchive new] autorelease]; 30 | archive.data = archiveData; 31 | archive.cdTrailer = [ZKCDTrailer recordWithData:archive.data]; 32 | if (archive.cdTrailer) { 33 | unsigned long long offset = archive.cdTrailer.offsetOfStartOfCentralDirectory; 34 | for (NSUInteger i = 0; i < archive.cdTrailer.totalNumberOfCentralDirectoryEntries; i++) { 35 | ZKCDHeader *cdHeader = [ZKCDHeader recordWithData:archive.data atOffset:offset]; 36 | [archive.centralDirectory addObject:cdHeader]; 37 | offset += [cdHeader length]; 38 | } 39 | } else { 40 | archive = nil; 41 | } 42 | return archive; 43 | } 44 | 45 | #pragma mark - 46 | #pragma mark Inflation 47 | 48 | - (NSUInteger) inflateAll { 49 | [self.inflatedFiles removeAllObjects]; 50 | NSDictionary *fileAttributes = nil; 51 | NSData *inflatedData = nil; 52 | for (ZKCDHeader *cdHeader in self.centralDirectory) { 53 | inflatedData = [self inflateFile:cdHeader attributes:&fileAttributes]; 54 | if (!inflatedData) 55 | return zkFailed; 56 | 57 | if ([cdHeader isSymLink] || [cdHeader isDirectory]) { 58 | [self.inflatedFiles addObject:[NSDictionary dictionaryWithObjectsAndKeys: 59 | fileAttributes, ZKFileAttributesKey, 60 | [[[NSString alloc] initWithData:inflatedData encoding:NSUTF8StringEncoding] autorelease], ZKPathKey, 61 | nil]]; 62 | } else { 63 | [self.inflatedFiles addObject:[NSDictionary dictionaryWithObjectsAndKeys: 64 | inflatedData, ZKFileDataKey, 65 | fileAttributes, ZKFileAttributesKey, 66 | cdHeader.filename, ZKPathKey, 67 | nil]]; 68 | } 69 | } 70 | return zkSucceeded; 71 | } 72 | 73 | - (NSData *) inflateFile:(ZKCDHeader *) cdHeader attributes:(NSDictionary **) fileAttributes { 74 | // if (self.delegate) { 75 | // if ([NSThread isMainThread]) 76 | // [self willUnzipPath:cdHeader.filename]; 77 | // else 78 | // [self performSelectorOnMainThread:@selector(willUnzipPath:) withObject:cdHeader.filename waitUntilDone:NO]; 79 | // } 80 | BOOL isDirectory = [cdHeader isDirectory]; 81 | 82 | ZKLFHeader *lfHeader = [ZKLFHeader recordWithData:self.data atOffset:cdHeader.localHeaderOffset]; 83 | 84 | NSData *deflatedData = nil; 85 | if (!isDirectory) 86 | deflatedData = [self.data subdataWithRange: 87 | NSMakeRange(cdHeader.localHeaderOffset + [lfHeader length], cdHeader.compressedSize)]; 88 | 89 | NSData *inflatedData = nil; 90 | NSString *fileType = nil; 91 | if ([cdHeader isSymLink]) { 92 | inflatedData = deflatedData; // UTF-8 encoded symlink destination path 93 | fileType = NSFileTypeSymbolicLink; 94 | } else if (isDirectory) { 95 | inflatedData = [cdHeader.filename dataUsingEncoding:NSUTF8StringEncoding]; 96 | fileType = NSFileTypeDirectory; 97 | } else { 98 | if (cdHeader.compressionMethod == Z_NO_COMPRESSION) 99 | inflatedData = deflatedData; 100 | else 101 | inflatedData = [deflatedData zk_inflate]; 102 | fileType = NSFileTypeRegular; 103 | } 104 | 105 | if (inflatedData) 106 | *fileAttributes = [NSDictionary dictionaryWithObjectsAndKeys: 107 | [cdHeader posixPermissions], NSFilePosixPermissions, 108 | [cdHeader lastModDate], NSFileCreationDate, 109 | [cdHeader lastModDate], NSFileModificationDate, 110 | fileType, NSFileType, nil]; 111 | else 112 | *fileAttributes = nil; 113 | 114 | return inflatedData; 115 | } 116 | 117 | - (NSUInteger) inflateInFolder:(NSString *)enclosingFolder withFolderName:(NSString *)folderName usingResourceFork:(BOOL) rfFlag { 118 | if ([self inflateAll] != zkSucceeded) 119 | return zkFailed; 120 | if ([self.inflatedFiles count] < 1) 121 | return zkSucceeded; 122 | 123 | if (![self.fileManager fileExistsAtPath:enclosingFolder]) 124 | return zkFailed; 125 | 126 | NSString *expansionDirectory = [self uniqueExpansionDirectoryIn:enclosingFolder]; 127 | [self.fileManager createDirectoryAtPath:expansionDirectory withIntermediateDirectories:YES attributes:nil error:nil]; 128 | for (NSDictionary *file in self.inflatedFiles) { 129 | NSDictionary *fileAttributes = [file objectForKey:ZKFileAttributesKey]; 130 | NSData *inflatedData = [file objectForKey:ZKFileDataKey]; 131 | NSString *path = [expansionDirectory stringByAppendingPathComponent:[file objectForKey:ZKPathKey]]; 132 | [self.fileManager createDirectoryAtPath:[path stringByDeletingLastPathComponent] 133 | withIntermediateDirectories:YES attributes:nil error:nil]; 134 | if ([[fileAttributes fileType] isEqualToString:NSFileTypeRegular]) 135 | [inflatedData writeToFile:path atomically:YES]; 136 | else if ([[fileAttributes fileType] isEqualToString:NSFileTypeDirectory]) 137 | [self.fileManager createDirectoryAtPath:path 138 | withIntermediateDirectories:YES attributes:nil error:nil]; 139 | else if ([[fileAttributes fileType] isEqualToString:NSFileTypeSymbolicLink]) { 140 | NSString *symLinkDestinationPath = [[[NSString alloc] initWithData:inflatedData 141 | encoding:NSUTF8StringEncoding] autorelease]; 142 | [self.fileManager createSymbolicLinkAtPath:path 143 | withDestinationPath:symLinkDestinationPath error:nil]; 144 | } 145 | [self.fileManager setAttributes:fileAttributes ofItemAtPath:path error:nil]; 146 | } 147 | 148 | #if ZK_TARGET_OS_MAC 149 | if (rfFlag) 150 | [self.fileManager zk_combineAppleDoubleInDirectory:expansionDirectory]; 151 | #endif 152 | [self cleanUpExpansionDirectory:expansionDirectory]; 153 | 154 | return zkSucceeded; 155 | } 156 | 157 | 158 | 159 | #pragma mark - 160 | #pragma mark Deflation 161 | 162 | - (NSInteger) deflateFiles:(NSArray *) paths relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) rfFlag { 163 | NSInteger rc = zkSucceeded; 164 | for (NSString *path in paths) { 165 | if ([self.fileManager zk_isDirAtPath:path] && ![self.fileManager zk_isSymLinkAtPath:path]) { 166 | rc = [self deflateDirectory:path relativeToPath:basePath usingResourceFork:rfFlag]; 167 | if (rc != zkSucceeded) 168 | break; 169 | } else { 170 | rc = [self deflateFile:path relativeToPath:basePath usingResourceFork:rfFlag]; 171 | if (rc != zkSucceeded) 172 | break; 173 | } 174 | } 175 | return rc; 176 | } 177 | 178 | - (NSInteger) deflateDirectory:(NSString *) dirPath relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) rfFlag { 179 | NSInteger rc = [self deflateFile:dirPath relativeToPath:basePath usingResourceFork:rfFlag]; 180 | if (rc == zkSucceeded) { 181 | NSDirectoryEnumerator *e = [self.fileManager enumeratorAtPath:dirPath]; 182 | for (NSString *path in e) { 183 | rc = [self deflateFile:[dirPath stringByAppendingPathComponent:path] relativeToPath:basePath usingResourceFork:rfFlag]; 184 | if (rc != zkSucceeded) 185 | break; 186 | } 187 | } 188 | return rc; 189 | } 190 | 191 | - (NSInteger) deflateFile:(NSString *) path relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) rfFlag { 192 | BOOL isDir = [self.fileManager zk_isDirAtPath:path]; 193 | BOOL isSymlink = [self.fileManager zk_isSymLinkAtPath:path]; 194 | BOOL isFile = (!isSymlink && !isDir); 195 | 196 | // if (self.delegate) { 197 | // if ([NSThread isMainThread]) 198 | // [self willZipPath:path]; 199 | // else 200 | // [self performSelectorOnMainThread:@selector(willZipPath:) withObject:path waitUntilDone:NO]; 201 | // } 202 | 203 | // append a trailing slash to directory paths 204 | if (isDir && !isSymlink && ![[path substringFromIndex:([path length] - 1)] isEqualToString:@"/"]) 205 | path = [path stringByAppendingString:@"/"]; 206 | 207 | // construct a relative path for storage in the archive directory by removing basePath from the beginning of path 208 | NSString *relativePath = path; 209 | if (basePath && [basePath length] > 0) { 210 | if (![basePath hasSuffix:@"/"]) 211 | basePath = [basePath stringByAppendingString:@"/"]; 212 | NSRange r = [path rangeOfString:basePath]; 213 | if (r.location != NSNotFound) 214 | relativePath = [path substringFromIndex:r.length]; 215 | } 216 | 217 | if (isFile) { 218 | NSData *fileData = [NSData dataWithContentsOfFile:path]; 219 | NSDictionary *fileAttributes = [self.fileManager attributesOfItemAtPath:path error:nil]; 220 | NSInteger rc = [self deflateData:fileData withFilename:relativePath andAttributes:fileAttributes]; 221 | #if ZK_TARGET_OS_MAC 222 | if (rc == zkSucceeded && rfFlag) { 223 | NSData *appleDoubleData = [GMAppleDouble zk_appleDoubleDataForPath:path]; 224 | if (appleDoubleData) { 225 | NSString *appleDoublePath = [[ZKMacOSXDirectory stringByAppendingPathComponent: 226 | [relativePath stringByDeletingLastPathComponent]] 227 | stringByAppendingPathComponent: 228 | [ZKDotUnderscore stringByAppendingString:[relativePath lastPathComponent]]]; 229 | rc = [self deflateData:appleDoubleData withFilename:appleDoublePath andAttributes:fileAttributes]; 230 | } 231 | } 232 | #endif 233 | return rc; 234 | } 235 | 236 | // create the local file header for the file 237 | ZKLFHeader *lfHeaderData = [[ZKLFHeader new] autorelease]; 238 | lfHeaderData.uncompressedSize = 0; 239 | lfHeaderData.lastModDate = [self.fileManager zk_modificationDateForPath:path]; 240 | lfHeaderData.filename = relativePath; 241 | lfHeaderData.filenameLength = [lfHeaderData.filename zk_precomposedUTF8Length]; 242 | lfHeaderData.crc = 0; 243 | lfHeaderData.compressedSize = 0; 244 | 245 | // remove the existing central directory from the data 246 | unsigned long long lfHeaderDataOffset = self.cdTrailer.offsetOfStartOfCentralDirectory; 247 | [self.data setLength:lfHeaderDataOffset]; 248 | 249 | if (isSymlink) { 250 | NSString *symlinkPath = [self.fileManager destinationOfSymbolicLinkAtPath:path error:nil]; 251 | NSData *symlinkData = [symlinkPath dataUsingEncoding:NSUTF8StringEncoding]; 252 | lfHeaderData.crc = [symlinkData zk_crc32]; 253 | lfHeaderData.compressedSize = [symlinkData length]; 254 | lfHeaderData.uncompressedSize = [symlinkData length]; 255 | lfHeaderData.compressionMethod = Z_NO_COMPRESSION; 256 | lfHeaderData.versionNeededToExtract = 10; 257 | [self.data appendData:[lfHeaderData data]]; 258 | [self.data appendData:symlinkData]; 259 | } else if (isDir) { 260 | lfHeaderData.crc = 0; 261 | lfHeaderData.compressedSize = 0; 262 | lfHeaderData.uncompressedSize = 0; 263 | lfHeaderData.compressionMethod = Z_NO_COMPRESSION; 264 | lfHeaderData.versionNeededToExtract = 10; 265 | [self.data appendData:[lfHeaderData data]]; 266 | } 267 | 268 | // create the central directory header and add it to central directory 269 | ZKCDHeader *cdHeaderData = [[ZKCDHeader new] autorelease]; 270 | cdHeaderData.uncompressedSize = lfHeaderData.uncompressedSize; 271 | cdHeaderData.lastModDate = lfHeaderData.lastModDate; 272 | cdHeaderData.crc = lfHeaderData.crc; 273 | cdHeaderData.compressedSize = lfHeaderData.compressedSize; 274 | cdHeaderData.filename = lfHeaderData.filename; 275 | cdHeaderData.filenameLength = lfHeaderData.filenameLength; 276 | cdHeaderData.localHeaderOffset = lfHeaderDataOffset; 277 | cdHeaderData.compressionMethod = lfHeaderData.compressionMethod; 278 | cdHeaderData.generalPurposeBitFlag = lfHeaderData.generalPurposeBitFlag; 279 | cdHeaderData.versionNeededToExtract = lfHeaderData.versionNeededToExtract; 280 | cdHeaderData.externalFileAttributes = [self.fileManager zk_externalFileAttributesAtPath:path]; 281 | [self.centralDirectory addObject:cdHeaderData]; 282 | 283 | // update the central directory trailer 284 | self.cdTrailer.numberOfCentralDirectoryEntriesOnThisDisk++; 285 | self.cdTrailer.totalNumberOfCentralDirectoryEntries++; 286 | self.cdTrailer.sizeOfCentralDirectory += [cdHeaderData length]; 287 | 288 | self.cdTrailer.offsetOfStartOfCentralDirectory = [self.data length]; 289 | for (ZKCDHeader *cdHeader in self.centralDirectory) 290 | [self.data appendData:[cdHeader data]]; 291 | 292 | [self.data appendData:[self.cdTrailer data]]; 293 | 294 | return zkSucceeded; 295 | } 296 | 297 | - (NSInteger) deflateData:(NSData *)data withFilename:(NSString *) filename andAttributes:(NSDictionary *) fileAttributes { 298 | if (!filename || [filename length] < 1) 299 | return zkFailed; 300 | 301 | NSData *deflatedData = [data zk_deflate]; 302 | if (!deflatedData) 303 | return zkFailed; 304 | 305 | unsigned long long lfHeaderDataOffset = self.cdTrailer.offsetOfStartOfCentralDirectory; 306 | [self.data setLength:lfHeaderDataOffset]; 307 | 308 | ZKLFHeader *lfHeaderData = [[ZKLFHeader new] autorelease]; 309 | lfHeaderData.uncompressedSize = [data length]; 310 | lfHeaderData.filename = filename; 311 | lfHeaderData.filenameLength = [lfHeaderData.filename zk_precomposedUTF8Length]; 312 | lfHeaderData.crc = [data zk_crc32]; 313 | lfHeaderData.compressedSize = [deflatedData length]; 314 | 315 | ZKCDHeader *cdHeaderData = [[ZKCDHeader new] autorelease]; 316 | cdHeaderData.uncompressedSize = lfHeaderData.uncompressedSize; 317 | cdHeaderData.crc = lfHeaderData.crc; 318 | cdHeaderData.compressedSize = lfHeaderData.compressedSize; 319 | cdHeaderData.filename = lfHeaderData.filename; 320 | cdHeaderData.filenameLength = lfHeaderData.filenameLength; 321 | cdHeaderData.localHeaderOffset = lfHeaderDataOffset; 322 | cdHeaderData.compressionMethod = lfHeaderData.compressionMethod; 323 | cdHeaderData.generalPurposeBitFlag = lfHeaderData.generalPurposeBitFlag; 324 | cdHeaderData.versionNeededToExtract = lfHeaderData.versionNeededToExtract; 325 | [self.centralDirectory addObject:cdHeaderData]; 326 | 327 | self.cdTrailer.numberOfCentralDirectoryEntriesOnThisDisk++; 328 | self.cdTrailer.totalNumberOfCentralDirectoryEntries++; 329 | self.cdTrailer.sizeOfCentralDirectory += [cdHeaderData length]; 330 | 331 | if (fileAttributes) { 332 | if ([[fileAttributes allKeys] containsObject:NSFileModificationDate]) { 333 | lfHeaderData.lastModDate = [fileAttributes objectForKey:NSFileModificationDate]; 334 | cdHeaderData.lastModDate = lfHeaderData.lastModDate; 335 | } 336 | cdHeaderData.externalFileAttributes = [self.fileManager zk_externalFileAttributesFor:fileAttributes]; 337 | } 338 | 339 | [self.data appendData:[lfHeaderData data]]; 340 | [self.data appendData:deflatedData]; 341 | 342 | self.cdTrailer.offsetOfStartOfCentralDirectory = [self.data length]; 343 | for (ZKCDHeader *cdHeader in self.centralDirectory) 344 | [self.data appendData:[cdHeader data]]; 345 | 346 | [self.data appendData:[self.cdTrailer data]]; 347 | 348 | return zkSucceeded; 349 | } 350 | 351 | #pragma mark - 352 | #pragma mark Setup 353 | 354 | - (id) init { 355 | if (self = [super init]) { 356 | self.data = [NSMutableData data]; 357 | self.inflatedFiles = [NSMutableArray array]; 358 | } 359 | return self; 360 | } 361 | 362 | - (void) dealloc { 363 | self.data = nil; 364 | self.inflatedFiles = nil; 365 | [super dealloc]; 366 | } 367 | 368 | - (void) finalize { 369 | self.data = nil; 370 | [self.inflatedFiles removeAllObjects]; 371 | self.inflatedFiles = nil; 372 | [super finalize]; 373 | } 374 | 375 | @synthesize data = _data, inflatedFiles = _inflatedFiles; 376 | 377 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKDefs.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKDefs.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #define ZK_TARGET_OS_MAC (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) 9 | #define ZK_TARGET_OS_IPHONE (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_IPHONE_SIMULATOR) 10 | 11 | enum ZKReturnCodes { 12 | zkFailed = -1, 13 | zkCancelled = 0, 14 | zkSucceeded = 1, 15 | }; 16 | 17 | // File & path naming 18 | extern NSString* const ZKArchiveFileExtension; 19 | extern NSString* const ZKMacOSXDirectory; 20 | extern NSString* const ZKDotUnderscore; 21 | extern NSString* const ZKExpansionDirectoryName; 22 | 23 | // Keys for dictionary passed to size calculation thread 24 | extern NSString* const ZKPathsKey; 25 | extern NSString* const ZKusingResourceForkKey; 26 | 27 | // Keys for dictionary returned from ZKDataArchive inflation 28 | extern NSString* const ZKFileDataKey; 29 | extern NSString* const ZKFileAttributesKey; 30 | extern NSString* const ZKPathKey; 31 | 32 | // Zipping & Unzipping 33 | extern const NSUInteger ZKZipBlockSize; 34 | extern const NSUInteger ZKNotificationIterations; 35 | 36 | // Magic numbers and lengths for zip records 37 | extern const NSUInteger ZKCDHeaderMagicNumber; 38 | extern const NSUInteger ZKCDHeaderFixedDataLength; 39 | 40 | extern const NSUInteger ZKCDTrailerMagicNumber; 41 | extern const NSUInteger ZKCDTrailerFixedDataLength; 42 | 43 | extern const NSUInteger ZKLFHeaderMagicNumber; 44 | extern const NSUInteger ZKLFHeaderFixedDataLength; 45 | 46 | extern const NSUInteger ZKCDTrailer64MagicNumber; 47 | extern const NSUInteger ZKCDTrailer64FixedDataLength; 48 | 49 | extern const NSUInteger ZKCDTrailer64LocatorMagicNumber; 50 | extern const NSUInteger ZKCDTrailer64LocatorFixedDataLength; 51 | -------------------------------------------------------------------------------- /External/ZipKit/ZKDefs.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKDefs.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "ZKDefs.h" 9 | 10 | NSString* const ZKArchiveFileExtension = @"zip"; 11 | NSString* const ZKMacOSXDirectory = @"__MACOSX"; 12 | NSString* const ZKDotUnderscore = @"._"; 13 | NSString* const ZKExpansionDirectoryName = @".ZipKit"; 14 | 15 | NSString* const ZKPathsKey = @"paths"; 16 | NSString* const ZKusingResourceForkKey = @"usingResourceFork"; 17 | 18 | NSString* const ZKFileDataKey = @"fileData"; 19 | NSString* const ZKFileAttributesKey = @"fileAttributes"; 20 | NSString* const ZKPathKey = @"path"; 21 | 22 | const NSUInteger ZKZipBlockSize = 262144; 23 | const NSUInteger ZKNotificationIterations = 100; 24 | 25 | const NSUInteger ZKCDHeaderMagicNumber = 0x02014B50; 26 | const NSUInteger ZKCDHeaderFixedDataLength = 46; 27 | 28 | const NSUInteger ZKCDTrailerMagicNumber = 0x06054B50; 29 | const NSUInteger ZKCDTrailerFixedDataLength = 22; 30 | 31 | const NSUInteger ZKLFHeaderMagicNumber = 0x04034B50; 32 | const NSUInteger ZKLFHeaderFixedDataLength = 30; 33 | 34 | const NSUInteger ZKCDTrailer64MagicNumber = 0x06064b50; 35 | const NSUInteger ZKCDTrailer64FixedDataLength = 56; 36 | 37 | const NSUInteger ZKCDTrailer64LocatorMagicNumber = 0x07064b50; 38 | const NSUInteger ZKCDTrailer64LocatorFixedDataLength = 20; 39 | -------------------------------------------------------------------------------- /External/ZipKit/ZKFileArchive.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKFileArchive.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | #import "ZKArchive.h" 10 | 11 | @class ZKCDHeader; 12 | 13 | @interface ZKFileArchive : ZKArchive { 14 | @private 15 | BOOL _useZip64Extensions; 16 | } 17 | 18 | + (ZKFileArchive *) process:(id) item usingResourceFork:(BOOL) flag withInvoker:(id) invoker andDelegate:(id) delegate; 19 | + (ZKFileArchive *) archiveWithArchivePath:(NSString *) archivePath; 20 | 21 | - (NSInteger) inflateToDiskUsingResourceFork:(BOOL) flag; 22 | - (NSInteger) inflateToDirectory:(NSString *)expansionDirectory usingResourceFork:(BOOL)rfFlag; 23 | - (NSInteger) inflateFile:(ZKCDHeader *) cdHeader toDirectory:(NSString *) expansionDirectory; 24 | 25 | - (NSInteger) deflateFiles:(NSArray *) paths relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) flag; 26 | - (NSInteger) deflateDirectory:(NSString *) dirPath relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) flag; 27 | - (NSInteger) deflateFile:(NSString *) path relativeToPath:(NSString *) basePath usingResourceFork:(BOOL) flag; 28 | 29 | @property (assign) BOOL useZip64Extensions; 30 | 31 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKLFHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKLFHeader.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | @interface ZKLFHeader : NSObject { 11 | @private 12 | NSUInteger magicNumber; 13 | NSUInteger versionNeededToExtract; 14 | NSUInteger generalPurposeBitFlag; 15 | NSUInteger compressionMethod; 16 | NSDate *lastModDate; 17 | NSUInteger crc; 18 | unsigned long long compressedSize; 19 | unsigned long long uncompressedSize; 20 | NSUInteger filenameLength; 21 | NSUInteger extraFieldLength; 22 | NSString *filename; 23 | NSData *extraField; 24 | } 25 | 26 | + (ZKLFHeader *) recordWithData:(NSData *)data atOffset:(NSUInteger)offset; 27 | + (ZKLFHeader *) recordWithArchivePath:(NSString *)path atOffset:(unsigned long long)offset; 28 | - (void) parseZip64ExtraField; 29 | - (NSData *) zip64ExtraField; 30 | - (NSData *) data; 31 | - (NSUInteger) length; 32 | - (BOOL) useZip64Extensions; 33 | - (BOOL) isResourceFork; 34 | 35 | @property (assign) NSUInteger magicNumber; 36 | @property (assign) NSUInteger versionNeededToExtract; 37 | @property (assign) NSUInteger generalPurposeBitFlag; 38 | @property (assign) NSUInteger compressionMethod; 39 | @property (retain) NSDate *lastModDate; 40 | @property (assign) NSUInteger crc; 41 | @property (assign) unsigned long long compressedSize; 42 | @property (assign) unsigned long long uncompressedSize; 43 | @property (assign) NSUInteger filenameLength; 44 | @property (assign) NSUInteger extraFieldLength; 45 | @property (copy) NSString *filename; 46 | @property (retain) NSData *extraField; 47 | 48 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKLFHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKLFHeader.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "ZKLFHeader.h" 9 | #import "NSDate+ZKAdditions.h" 10 | #import "NSData+ZKAdditions.h" 11 | #import "NSString+ZKAdditions.h" 12 | #import "ZKDefs.h" 13 | #import "zlib.h" 14 | 15 | @implementation ZKLFHeader 16 | 17 | - (id) init { 18 | if (self = [super init]) { 19 | self.magicNumber = ZKLFHeaderMagicNumber; 20 | self.versionNeededToExtract = 20; 21 | self.generalPurposeBitFlag = 0; 22 | self.compressionMethod = Z_DEFLATED; 23 | self.lastModDate = [NSDate date]; 24 | self.crc = 0; 25 | self.compressedSize = 0; 26 | self.uncompressedSize = 0; 27 | self.filenameLength = 0; 28 | self.extraFieldLength = 0; 29 | self.filename = nil; 30 | self.extraField = nil; 31 | 32 | [self addObserver:self forKeyPath:@"compressedSize" options:NSKeyValueObservingOptionNew context:nil]; 33 | [self addObserver:self forKeyPath:@"uncompressedSize" options:NSKeyValueObservingOptionNew context:nil]; 34 | [self addObserver:self forKeyPath:@"extraField" options:NSKeyValueObservingOptionNew context:nil]; 35 | [self addObserver:self forKeyPath:@"filename" options:NSKeyValueObservingOptionNew context:nil]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void) removeObservers { 41 | [self removeObserver:self forKeyPath:@"compressedSize"]; 42 | [self removeObserver:self forKeyPath:@"uncompressedSize"]; 43 | [self removeObserver:self forKeyPath:@"extraField"]; 44 | [self removeObserver:self forKeyPath:@"filename"]; 45 | } 46 | 47 | - (void) finalize { 48 | [self removeObservers]; 49 | [super finalize]; 50 | } 51 | 52 | - (void) dealloc { 53 | [self removeObservers]; 54 | self.lastModDate = nil; 55 | self.filename = nil; 56 | self.extraField = nil; 57 | [super dealloc]; 58 | } 59 | 60 | - (void) observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context { 61 | if ([keyPath isEqualToString:@"compressedSize"] || [keyPath isEqualToString:@"uncompressedSize"]) { 62 | self.versionNeededToExtract = ([self useZip64Extensions] ? 45 : 20); 63 | } else if ([keyPath isEqualToString:@"extraField"] && self.extraFieldLength < 1) { 64 | self.extraFieldLength = [self.extraField length]; 65 | } else if ([keyPath isEqualToString:@"filename"] && self.filenameLength < 1) { 66 | self.filenameLength = [self.filename zk_precomposedUTF8Length]; 67 | } 68 | } 69 | 70 | + (ZKLFHeader *) recordWithData:(NSData *) data atOffset:(NSUInteger) offset { 71 | if (!data) return nil; 72 | NSUInteger mn = [data zk_hostInt32OffsetBy:&offset]; 73 | if (mn != ZKLFHeaderMagicNumber) return nil; 74 | ZKLFHeader *record = [[ZKLFHeader new] autorelease]; 75 | record.magicNumber = mn; 76 | record.versionNeededToExtract = [data zk_hostInt16OffsetBy:&offset]; 77 | record.generalPurposeBitFlag = [data zk_hostInt16OffsetBy:&offset]; 78 | record.compressionMethod = [data zk_hostInt16OffsetBy:&offset]; 79 | record.lastModDate = [NSDate zk_dateWithDosDate:[data zk_hostInt32OffsetBy:&offset]]; 80 | record.crc = [data zk_hostInt32OffsetBy:&offset]; 81 | record.compressedSize = [data zk_hostInt32OffsetBy:&offset]; 82 | record.uncompressedSize = [data zk_hostInt32OffsetBy:&offset]; 83 | record.filenameLength = [data zk_hostInt16OffsetBy:&offset]; 84 | record.extraFieldLength = [data zk_hostInt16OffsetBy:&offset]; 85 | if ([data length] > ZKLFHeaderFixedDataLength) { 86 | if (record.filenameLength > 0) 87 | record.filename = [data zk_stringOffsetBy:&offset length:record.filenameLength]; 88 | if (record.extraFieldLength > 0) { 89 | record.extraField = [data subdataWithRange:NSMakeRange(offset, record.extraFieldLength)]; 90 | [record parseZip64ExtraField]; 91 | } 92 | } 93 | return record; 94 | } 95 | 96 | + (ZKLFHeader *) recordWithArchivePath:(NSString *) path atOffset:(unsigned long long) offset { 97 | NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; 98 | [file seekToFileOffset:offset]; 99 | NSData *fixedData = [file readDataOfLength:ZKLFHeaderFixedDataLength]; 100 | ZKLFHeader *record = [self recordWithData:fixedData atOffset:0]; 101 | if (record.filenameLength > 0) { 102 | NSData *data = [file readDataOfLength:record.filenameLength]; 103 | record.filename = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; 104 | } 105 | if (record.extraFieldLength > 0) { 106 | record.extraField = [file readDataOfLength:record.extraFieldLength]; 107 | [record parseZip64ExtraField]; 108 | } 109 | [file closeFile]; 110 | return record; 111 | } 112 | 113 | - (NSData *) data { 114 | self.extraField = [self zip64ExtraField]; 115 | 116 | NSMutableData *data = [NSMutableData zk_dataWithLittleInt32:self.magicNumber]; 117 | [data zk_appendLittleInt16:self.versionNeededToExtract]; 118 | [data zk_appendLittleInt16:self.generalPurposeBitFlag]; 119 | [data zk_appendLittleInt16:self.compressionMethod]; 120 | [data zk_appendLittleInt32:[self.lastModDate zk_dosDate]]; 121 | [data zk_appendLittleInt32:self.crc]; 122 | if ([self useZip64Extensions]) { 123 | [data zk_appendLittleInt32:0xFFFFFFFF]; 124 | [data zk_appendLittleInt32:0xFFFFFFFF]; 125 | } else { 126 | [data zk_appendLittleInt32:self.compressedSize]; 127 | [data zk_appendLittleInt32:self.uncompressedSize]; 128 | } 129 | [data zk_appendLittleInt16:self.filenameLength]; 130 | [data zk_appendLittleInt16:[self.extraField length]]; 131 | [data zk_appendPrecomposedUTF8String:self.filename]; 132 | [data appendData:self.extraField]; 133 | return data; 134 | } 135 | 136 | - (void) parseZip64ExtraField { 137 | NSUInteger offset = 0, tag, length; 138 | while (offset < self.extraFieldLength) { 139 | tag = [self.extraField zk_hostInt16OffsetBy:&offset]; 140 | length = [self.extraField zk_hostInt16OffsetBy:&offset]; 141 | if (tag == 0x0001) { 142 | if (length >= 8) 143 | self.uncompressedSize = [self.extraField zk_hostInt64OffsetBy:&offset]; 144 | if (length >= 16) 145 | self.compressedSize = [self.extraField zk_hostInt64OffsetBy:&offset]; 146 | break; 147 | } else { 148 | offset += length; 149 | } 150 | } 151 | } 152 | 153 | - (NSData *) zip64ExtraField { 154 | NSMutableData *zip64ExtraField = nil; 155 | if ([self useZip64Extensions]) { 156 | zip64ExtraField = [NSMutableData zk_dataWithLittleInt16:0x0001]; 157 | [zip64ExtraField zk_appendLittleInt16:16]; 158 | [zip64ExtraField zk_appendLittleInt64:self.uncompressedSize]; 159 | [zip64ExtraField zk_appendLittleInt64:self.compressedSize]; 160 | } 161 | return zip64ExtraField; 162 | } 163 | 164 | - (NSUInteger) length { 165 | if (!self.extraField || [self.extraField length] == 0) 166 | self.extraField = [self zip64ExtraField]; 167 | return ZKLFHeaderFixedDataLength + self.filenameLength + [self.extraField length]; 168 | } 169 | 170 | - (BOOL) useZip64Extensions { 171 | return (self.uncompressedSize >= 0xFFFFFFFF) || (self.compressedSize >= 0xFFFFFFFF); 172 | } 173 | 174 | - (NSString *) description { 175 | return [NSString stringWithFormat:@"%@ modified %@, %qu bytes (%qu compressed)", 176 | self.filename, self.lastModDate, self.uncompressedSize, self.compressedSize]; 177 | } 178 | 179 | - (BOOL) isResourceFork { 180 | return [self.filename zk_isResourceForkPath]; 181 | } 182 | 183 | @synthesize magicNumber, versionNeededToExtract, generalPurposeBitFlag, compressionMethod, lastModDate, crc, compressedSize, uncompressedSize, filenameLength, extraFieldLength, filename, extraField; 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /External/ZipKit/ZKLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZKLog.h 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import 9 | 10 | enum ZKLogLevel { 11 | ZKLogLevelNotice = 3, 12 | ZKLogLevelError = 2, 13 | ZKLogLevelDebug = 1, 14 | ZKLogLevelAll = 0, 15 | }; 16 | 17 | #define ZKLog(s, l, ...) [[ZKLog sharedInstance] logFile:__FILE__ lineNumber:__LINE__ level:l format:(s), ## __VA_ARGS__] 18 | 19 | #define ZKLogError(s, ...) ZKLog((s), ZKLogLevelError, ## __VA_ARGS__) 20 | #define ZKLogNotice(s, ...) ZKLog((s), ZKLogLevelNotice, ## __VA_ARGS__) 21 | #define ZKLogDebug(s, ...) ZKLog((s), ZKLogLevelDebug, ## __VA_ARGS__) 22 | 23 | #define ZKLogWithException(e) ZKLogError(@"Exception in %@: \n\tname: %@\n\treason: %@\n\tuserInfo: %@", NSStringFromSelector(_cmd), [e name], [e reason], [e userInfo]); 24 | #define ZKLogWithError(e) ZKLogError(@"Error in %@: \n\tdomain: %@\n\tcode: %@\n\tdescription: %@", NSStringFromSelector(_cmd), [e domain], [e code], [e localizedDescription]); 25 | 26 | #define ZKStringFromBOOL(b) (b ? @"YES": @"NO") 27 | 28 | extern NSString* const ZKLogLevelKey; 29 | extern NSString* const ZKLogToFileKey; 30 | 31 | @interface ZKLog : NSObject { 32 | @private 33 | NSUInteger minimumLevel; 34 | NSDateFormatter *dateFormatter; 35 | int pid; 36 | NSString *logFilePath; 37 | FILE *logFilePointer; 38 | } 39 | 40 | - (void) logFile:(char*) sourceFile lineNumber:(NSUInteger) lineNumber level:(NSUInteger) level format:(NSString*) format, ...; 41 | 42 | - (NSString *) levelToLabel:(NSUInteger) level; 43 | 44 | + (ZKLog *) sharedInstance; 45 | 46 | @property (assign) NSUInteger minimumLevel; 47 | @property (retain) NSDateFormatter *dateFormatter; 48 | @property (assign) int pid; 49 | @property (copy) NSString *logFilePath; 50 | @property (assign) FILE *logFilePointer; 51 | 52 | @end -------------------------------------------------------------------------------- /External/ZipKit/ZKLog.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZKLog.m 3 | // ZipKit 4 | // 5 | // Created by Karl Moskowski on 01/04/09. 6 | // 7 | 8 | #import "ZKLog.h" 9 | 10 | NSString* const ZKLogLevelKey = @"ZKLogLevel"; 11 | NSString* const ZKLogToFileKey = @"ZKLogToFile"; 12 | 13 | @implementation ZKLog 14 | 15 | - (void) logFile:(char*) sourceFile lineNumber:(NSUInteger) lineNumber level:(NSUInteger) level format:(NSString*) format, ... { 16 | if (level >= self.minimumLevel) { 17 | va_list args; 18 | va_start(args, format); 19 | NSString *message = [[[NSString alloc] initWithFormat:format arguments:args] autorelease]; 20 | va_end(args); 21 | NSString *label = [self levelToLabel:level]; 22 | NSString *now = [self.dateFormatter stringFromDate:[NSDate date]]; 23 | if (label) { 24 | NSString *line = [NSString stringWithFormat:@"%@ [%i] %@ %@ (%@:%u)", now, self.pid, label, message, [[NSString stringWithUTF8String:sourceFile] lastPathComponent], lineNumber]; 25 | fprintf(stderr, "%s\n", [line UTF8String]); 26 | fflush(stderr); 27 | } 28 | } 29 | return; 30 | } 31 | 32 | - (NSUInteger) minimumLevel { 33 | return minimumLevel; 34 | } 35 | - (void) setMinimumLevel:(NSUInteger) value { 36 | switch (value) { 37 | case ZKLogLevelError: 38 | case ZKLogLevelNotice: 39 | case ZKLogLevelDebug: 40 | case ZKLogLevelAll: 41 | minimumLevel = value; 42 | break; 43 | default: 44 | ZKLogError(@"Invalid logging level: %u. Old value %@ unchanged.", value, [self levelToLabel:self.minimumLevel]); 45 | break; 46 | } 47 | return; 48 | } 49 | 50 | - (NSString *) levelToLabel:(NSUInteger) level { 51 | NSString *label = nil; 52 | switch (level) { 53 | case ZKLogLevelError: 54 | label = @""; 55 | break; 56 | case ZKLogLevelNotice: 57 | label = @""; 58 | break; 59 | case ZKLogLevelDebug: 60 | label = @""; 61 | break; 62 | default: 63 | label = nil; 64 | break; 65 | } 66 | return label; 67 | } 68 | 69 | static ZKLog *sharedInstance = nil; 70 | + (ZKLog *) sharedInstance { 71 | @synchronized(self) { 72 | if (sharedInstance == nil) { 73 | sharedInstance = [self new]; 74 | } 75 | } 76 | return sharedInstance; 77 | } 78 | 79 | - (id) init { 80 | @synchronized([self class]) { 81 | if (sharedInstance == nil) { 82 | if (self = [super init]) { 83 | sharedInstance = self; 84 | 85 | self.pid = [[NSProcessInfo processInfo] processIdentifier]; 86 | self.minimumLevel = ZKLogLevelError; 87 | self.dateFormatter = [[NSDateFormatter new] autorelease]; 88 | [self.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; 89 | 90 | if ([[NSUserDefaults standardUserDefaults] boolForKey:ZKLogToFileKey]) { 91 | NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); 92 | NSString *libraryFolder = [searchPaths objectAtIndex:0]; 93 | NSString *logFolder = [libraryFolder stringByAppendingPathComponent:@"Logs"]; 94 | [[[NSFileManager new] autorelease] createDirectoryAtPath:logFolder withIntermediateDirectories:YES attributes:nil error:nil]; 95 | self.logFilePath = [logFolder stringByAppendingPathComponent: 96 | [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"] 97 | stringByAppendingPathExtension:@"log"]]; 98 | freopen([self.logFilePath fileSystemRepresentation], "a+", stderr); 99 | } 100 | } 101 | } 102 | } 103 | return sharedInstance; 104 | } 105 | 106 | + (id) allocWithZone:(NSZone *) zone { 107 | @synchronized(self) { 108 | if (sharedInstance == nil) { 109 | return [super allocWithZone:zone]; 110 | } 111 | } 112 | return sharedInstance; 113 | } 114 | 115 | + (void) initialize { 116 | [[NSUserDefaults standardUserDefaults] registerDefaults: 117 | [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:ZKLogToFileKey]]; 118 | [super initialize]; 119 | } 120 | 121 | - (id) copyWithZone:(NSZone *) zone { 122 | return self; 123 | } 124 | 125 | - (void) finalize { 126 | if (self.logFilePointer) 127 | fclose(self.logFilePointer); 128 | [super finalize]; 129 | } 130 | 131 | - (void) dealloc { 132 | if (self.logFilePointer) 133 | fclose(self.logFilePointer); 134 | self.dateFormatter = nil; 135 | self.logFilePath = nil; 136 | [super dealloc]; 137 | } 138 | 139 | @synthesize dateFormatter, pid, logFilePath, logFilePointer; 140 | @dynamic minimumLevel; 141 | 142 | @end -------------------------------------------------------------------------------- /IPAViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 10K549 6 | 1938 7 | 1038.36 8 | 461.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 933 12 | 13 | 14 | IBUISearchDisplayController 15 | IBUITableView 16 | IBUISearchBar 17 | IBProxyObject 18 | 19 | 20 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 21 | 22 | 23 | PluginDependencyRecalculationVersion 24 | 25 | 26 | 27 | 28 | IBFilesOwner 29 | IBCocoaTouchFramework 30 | 31 | 32 | IBFirstResponder 33 | IBCocoaTouchFramework 34 | 35 | 36 | 37 | 274 38 | 39 | 40 | 41 | 290 42 | {320, 44} 43 | 44 | 45 | 3 46 | IBCocoaTouchFramework 47 | 48 | IBCocoaTouchFramework 49 | 50 | 51 | 52 | {320, 460} 53 | 54 | 55 | 56 | 57 | 3 58 | MC43NQA 59 | 60 | 2 61 | 62 | 63 | YES 64 | IBCocoaTouchFramework 65 | YES 66 | 1 67 | 0 68 | YES 69 | 44 70 | 22 71 | 22 72 | 73 | 74 | 75 | IBCocoaTouchFramework 76 | 77 | 78 | 79 | 80 | 81 | 82 | view 83 | 84 | 85 | 86 | 4 87 | 88 | 89 | 90 | searchDisplayController 91 | 92 | 93 | 94 | 15 95 | 96 | 97 | 98 | delegate 99 | 100 | 101 | 102 | 20 103 | 104 | 105 | 106 | searchContentsController 107 | 108 | 109 | 110 | 16 111 | 112 | 113 | 114 | searchResultsDataSource 115 | 116 | 117 | 118 | 17 119 | 120 | 121 | 122 | searchResultsDelegate 123 | 124 | 125 | 126 | 18 127 | 128 | 129 | 130 | delegate 131 | 132 | 133 | 134 | 19 135 | 136 | 137 | 138 | searchBar 139 | 140 | 141 | 142 | 14 143 | 144 | 145 | 146 | 147 | 148 | 0 149 | 150 | 151 | 152 | 153 | 154 | -1 155 | 156 | 157 | File's Owner 158 | 159 | 160 | -2 161 | 162 | 163 | 164 | 165 | 2 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 13 174 | 175 | 176 | 177 | 178 | 12 179 | 180 | 181 | 182 | 183 | 184 | 185 | IPAViewController 186 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 187 | UIResponder 188 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 189 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 190 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 191 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 192 | 193 | 194 | 195 | 196 | 197 | 20 198 | 199 | 200 | 201 | 202 | IPAViewController 203 | UITableViewController 204 | 205 | IBProjectSource 206 | ./Classes/IPAViewController.h 207 | 208 | 209 | 210 | 211 | 0 212 | IBCocoaTouchFramework 213 | YES 214 | 3 215 | 933 216 | 217 | 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## iOS Artwork 2 | 3 | *iOS Artwork Extractor* extracts all the artwork and emoji symbols contained in iOS into png files. 4 | 5 | In order to extract *Retina Display @2x* high resolution images, choose the **Hardware > Device > iPhone 4** menu in the iPhone Simulator. 6 | 7 | See instructions on the wiki to [extract more artwork](https://github.com/0xced/iOS-Artwork-Extractor/wiki/Extracting-more-artwork). 8 | 9 | * Set the `ARTWORK_DIRECTORY` environment variable to control where the png files are saved. If it is not set, the files will be saved into a folder on your desktop. 10 | 11 | ## Glossy Buttons 12 | 13 | *iOS Artwork Extractor* can also generate glossy buttons png files if you are using a simulator running **iOS 5.0 or older**. Thanks to [@schwa](http://twitter.com/schwa/status/9288691077) for the original code. Three states (normal/highlighted/disabled) glossy buttons png files are saved into the same directory as iOS artwork png files under the *UIGlassButton* subdirectory. 14 | 15 | ## IPAs 16 | 17 | *iOS Artwork Extractor* also knows how to extract artwork from apps you downloaded from the App Store. It goes without saying that this is for educational purpose only and that you should not steal others' artwork. 18 | 19 | * Use the `MOBILE_APPLICATIONS_DIRECTORY` environment variable if your iTunes library is not located in the standard location, i.e. `~/Music/iTunes`. 20 | 21 | ## Screenshots 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Resources/Artwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Artwork.png -------------------------------------------------------------------------------- /Resources/Artwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Artwork@2x.png -------------------------------------------------------------------------------- /Resources/Checkerboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Checkerboard.png -------------------------------------------------------------------------------- /Resources/Emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Emoji.png -------------------------------------------------------------------------------- /Resources/Emoji@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Emoji@2x.png -------------------------------------------------------------------------------- /Resources/GlossyButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/GlossyButton.png -------------------------------------------------------------------------------- /Resources/GlossyButton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/GlossyButton@2x.png -------------------------------------------------------------------------------- /Resources/IPA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/IPA.png -------------------------------------------------------------------------------- /Resources/IPA@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/IPA@2x.png -------------------------------------------------------------------------------- /Resources/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Icon.png -------------------------------------------------------------------------------- /Resources/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Icon@2x.png -------------------------------------------------------------------------------- /Resources/Shared/UITintedGlassButtonHighlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Shared/UITintedGlassButtonHighlight@2x.png -------------------------------------------------------------------------------- /Resources/Shared/UITintedGlassButtonMask@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Shared/UITintedGlassButtonMask@2x.png -------------------------------------------------------------------------------- /Resources/Shared/UITintedGlassButtonShadow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Shared/UITintedGlassButtonShadow@2x.png -------------------------------------------------------------------------------- /Resources/Unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Unknown.png -------------------------------------------------------------------------------- /Resources/Unknown@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Resources/Unknown@2x.png -------------------------------------------------------------------------------- /Screenshots/Artwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Screenshots/Artwork.png -------------------------------------------------------------------------------- /Screenshots/Emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Screenshots/Emoji.png -------------------------------------------------------------------------------- /Screenshots/GlossyButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Screenshots/GlossyButton.png -------------------------------------------------------------------------------- /Screenshots/IPA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Screenshots/IPA.png -------------------------------------------------------------------------------- /Screenshots/UISwitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ide/iOS-Artwork-Extractor/17e6f1a62ca846c9c6535a8104a0f7e7a1221a66/Screenshots/UISwitch.png -------------------------------------------------------------------------------- /iOS Artwork Extractor.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS_Artwork_Extractor-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | Extractor 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | Icon.png 14 | Icon@2x.png 15 | 16 | CFBundleIdentifier 17 | ch.pitaya.${PRODUCT_NAME:rfc1034identifier} 18 | CFBundleInfoDictionaryVersion 19 | 6.0 20 | CFBundleName 21 | ${PRODUCT_NAME} 22 | CFBundlePackageType 23 | APPL 24 | CFBundleVersion 25 | 1.0 26 | LSRequiresIPhoneOS 27 | 28 | NSMainNibFile 29 | MainWindow 30 | UIPrerenderedIcon 31 | 32 | UIFileSharingEnabled 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /iOS_Artwork_Extractor_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'iOS Artwork Extractor' target in the 'iOS Artwork Extractor' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #import 9 | 10 | #if __IPHONE_OS_VERSION_MAX_ALLOWED < 40000 11 | @interface UIScreen (iOS4) 12 | @property(nonatomic,readonly) CGFloat scale; 13 | @end 14 | 15 | @interface UIImage (iOS4) 16 | @property(nonatomic,readonly) CGFloat scale; 17 | @end 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iOS Artwork Extractor 4 | // 5 | // Created by Cédric Luthi on 19.02.10. 6 | // Copyright Cédric Luthi 2010. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | CGFloat iOS3_scale(id self, SEL _cmd) 13 | { 14 | return 1.0; 15 | } 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 20 | 21 | // -[UIView alpha] has the same method signature as -[UIScreen/UIImage scale] 22 | Method alpha = class_getInstanceMethod([UIView class], @selector(alpha)); 23 | if (![UIScreen instancesRespondToSelector:@selector(scale)]) 24 | class_addMethod([UIScreen class], @selector(scale), (IMP)iOS3_scale, method_getTypeEncoding(alpha)); 25 | if (![UIImage instancesRespondToSelector:@selector(scale)]) 26 | class_addMethod([UIImage class], @selector(scale), (IMP)iOS3_scale, method_getTypeEncoding(alpha)); 27 | 28 | int retVal = UIApplicationMain(argc, argv, nil, nil); 29 | [pool release]; 30 | return retVal; 31 | } 32 | --------------------------------------------------------------------------------