├── SnapchatHax
├── en.lproj
│ └── InfoPlist.strings
├── Snapchat
│ ├── Data
│ │ ├── Blobs
│ │ │ ├── SCImageBlob.h
│ │ │ ├── SCVideoBlob.h
│ │ │ ├── SCBlob.h
│ │ │ ├── SCVideoBlob.m
│ │ │ ├── SCImageBlob.m
│ │ │ └── SCBlob.m
│ │ ├── SCSnap.h
│ │ └── SCSnap.m
│ ├── Internal
│ │ ├── SCAPIRequest.h
│ │ ├── SCAPIConfiguration.h
│ │ ├── SCAPIRequest.m
│ │ └── SCAPIConfiguration.m
│ ├── SCFetcher.h
│ ├── SCAPILogin.h
│ ├── Managing
│ │ ├── SCSnapManager.h
│ │ └── SCSnapManager.m
│ ├── SCAPISession.h
│ ├── SCFetcher.m
│ ├── SCAPILogin.m
│ └── SCAPISession.m
├── main.m
├── SnapchatHax-Prefix.pch
├── ANAppDelegate.h
├── Images.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── LaunchImage.launchimage
│ │ └── Contents.json
├── ANLoginVC.h
├── ANSnapsVC.h
├── SnapchatHax-Info.plist
├── ANSnapVC.h
├── ANLoginVC.m
├── ANAppDelegate.m
├── ANLoginVC.xib
├── ANSnapVC.m
├── ANSnapsVC.m
└── ANSnapVC.xib
├── SnapchatHaxTests
├── en.lproj
│ └── InfoPlist.strings
├── SnapchatHaxTests-Info.plist
└── SnapchatHaxTests.m
├── SnapchatHax.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── alex.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── SnapchatHax.xcscheme
└── project.pbxproj
└── README.md
/SnapchatHax/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/SnapchatHaxTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/SnapchatHax.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/Blobs/SCImageBlob.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCImageBlob.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCBlob.h"
10 |
11 | @interface SCImageBlob : SCBlob
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/Blobs/SCVideoBlob.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCVideoBlob.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCBlob.h"
10 |
11 | @interface SCVideoBlob : SCBlob
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SnapchatHax/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "ANAppDelegate.h"
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ANAppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SnapchatHax/SnapchatHax-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_3_0
10 | #warning "This project uses features only available in iOS SDK 3.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #endif
17 |
--------------------------------------------------------------------------------
/SnapchatHax/ANAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // ANAppDelegate.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ANLoginVC.h"
11 |
12 | @interface ANAppDelegate : UIResponder {
13 | UINavigationController * navCont;
14 | }
15 |
16 | @property (strong, nonatomic) UIWindow * window;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/SnapchatHax/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/Blobs/SCBlob.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCBlob.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SCBlob : NSObject
12 |
13 | @property (nonatomic, retain) NSData * blobData;
14 |
15 | + (SCBlob *)blobWithData:(NSData *)data;
16 | - (id)initWithData:(NSData *)data;
17 |
18 | - (NSString *)blobFileExtension;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/SnapchatHax/ANLoginVC.h:
--------------------------------------------------------------------------------
1 | //
2 | // ANLoginVC.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ANSnapsVC.h"
11 | #import "SCAPILogin.h"
12 |
13 | @interface ANLoginVC : UIViewController {
14 | IBOutlet UITextField * username, * password;
15 | IBOutlet UIButton * button;
16 | }
17 |
18 | - (IBAction)loginPressed:(id)sender;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/SnapchatHax/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/Blobs/SCVideoBlob.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCVideoBlob.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCVideoBlob.h"
10 |
11 | @implementation SCVideoBlob
12 |
13 | - (id)initWithData:(NSData *)data {
14 | if (data.length < 2) return nil;
15 | if (((const char *)data.bytes)[0] != 0 || ((const char *)data.bytes)[1] != 0) return nil;
16 | if ((self = [super init])) {
17 | self.blobData = data;
18 | }
19 | return self;
20 | }
21 |
22 | - (NSString *)blobFileExtension {
23 | return @"mp4";
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/Blobs/SCImageBlob.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCImageBlob.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCImageBlob.h"
10 |
11 | @implementation SCImageBlob
12 |
13 | - (id)initWithData:(NSData *)data {
14 | if (data.length < 2) return nil;
15 | if (((const unsigned char *)data.bytes)[0] != 0xff ||
16 | ((const unsigned char *)data.bytes)[1] != 0xd8) return nil;
17 | if ((self = [super init])) {
18 | self.blobData = data;
19 | }
20 | return self;
21 | }
22 |
23 | - (NSString *)blobFileExtension {
24 | return @"jpg";
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/Blobs/SCBlob.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCBlob.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCBlob.h"
10 | #import "SCImageBlob.h"
11 | #import "SCVideoBlob.h"
12 |
13 | @implementation SCBlob
14 |
15 | + (SCBlob *)blobWithData:(NSData *)data {
16 | NSArray * blobs = @[SCImageBlob.class, SCVideoBlob.class];
17 | for (Class c in blobs) {
18 | id val = [[c alloc] initWithData:data];
19 | if (val) return val;
20 | }
21 | return nil;
22 | }
23 |
24 | - (id)initWithData:(NSData *)data {
25 | return nil;
26 | }
27 |
28 | - (NSString *)blobFileExtension {
29 | return @"txt";
30 | }
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/SnapchatHax.xcodeproj/xcuserdata/alex.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SnapchatHax.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | FAF75EA91860F9CC006C7D11
16 |
17 | primary
18 |
19 |
20 | FAF75EC41860F9CC006C7D11
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Internal/SCAPIRequest.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPIRequest.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SCAPIConfiguration.h"
11 |
12 | @interface SCAPIRequest : NSMutableURLRequest {
13 | SCAPIConfiguration * encryption;
14 | }
15 |
16 | + (NSString *)timestampString;
17 | + (NSString *)encodeQueryParam:(NSString *)param;
18 | + (NSString *)encodeQuery:(NSDictionary *)dict;
19 |
20 | - (id)initWithConfiguration:(SCAPIConfiguration *)enc
21 | path:(NSString *)path
22 | token:(NSString *)token
23 | dictionary:(NSDictionary *)dict;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/SnapchatHax/ANSnapsVC.h:
--------------------------------------------------------------------------------
1 | //
2 | // ANSnapsVC.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SCAPISession.h"
11 | #import "SCSnapManager.h"
12 | #import "ANSnapVC.h"
13 |
14 | @interface ANSnapsVC : UITableViewController {
15 | SCFetcher * reloadFetcher;
16 | SCSnapManager * snaps;
17 |
18 | UIActivityIndicatorView * loader;
19 | UIBarButtonItem * loadButton;
20 | }
21 |
22 | @property (nonatomic, retain) SCAPISession * session;
23 |
24 | - (id)initWithSession:(SCAPISession *)session;
25 |
26 | - (IBAction)reloadPressed:(id)sender;
27 | - (void)setReloading:(BOOL)reloading;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/SnapchatHaxTests/SnapchatHaxTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.aqnichol.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SnapchatHaxTests/SnapchatHaxTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // SnapchatHaxTests.m
3 | // SnapchatHaxTests
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SnapchatHaxTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation SnapchatHaxTests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | [super tearDown];
27 | }
28 |
29 | - (void)testExample
30 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/SCSnap.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCSnap.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef enum {
12 | SCSnapTypeImage = 0,
13 | SCSnapTypeVideo = 1,
14 | SCSnapTypeSilentVideo = 2,
15 | SCSnapTypeFriendFlag = 4
16 | } SCSnapType;
17 |
18 | @interface SCSnap : NSObject
19 |
20 | @property (readwrite) unsigned long long status;
21 | @property (readwrite) unsigned long long timestamp;
22 | @property (readwrite) unsigned long long media;
23 | @property (readwrite) unsigned long long tField;
24 | @property (nonatomic) NSString * identifier;
25 | @property (nonatomic) NSString * user;
26 |
27 | - (id)initWithDictionary:(NSDictionary *)dictionary;
28 | - (BOOL)isImageOrVideo;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/SCFetcher.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCFetcher.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef void (^SCFetcherBlock)(NSError * error, id result);
12 |
13 | @interface SCFetcher : NSObject {
14 | NSMutableData * data;
15 | NSURLConnection * connection;
16 | }
17 |
18 | @property (readwrite) BOOL parseJSON;
19 | @property (nonatomic, copy) SCFetcherBlock callback;
20 |
21 | + (SCFetcher *)fetcherStartedForRequest:(NSURLRequest *)req callback:(SCFetcherBlock)block;
22 | + (SCFetcher *)fetcherStartedForRequestNoJSON:(NSURLRequest *)req callback:(SCFetcherBlock)block;
23 |
24 | - (id)initWithRequest:(NSURLRequest *)request;
25 | - (void)start;
26 | - (void)cancel;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/SCAPILogin.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPILogin.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCAPISession.h"
10 |
11 | @protocol SCAPILoginDelegate
12 |
13 | - (void)scAPILogin:(id)sender failedWithError:(NSError *)error;
14 | - (void)scAPILogin:(id)sender succeededWithSession:(SCAPISession *)session;
15 |
16 | @end
17 |
18 | @interface SCAPILogin : NSObject {
19 | NSMutableData * responseData;
20 | NSURLConnection * connection;
21 | }
22 |
23 | @property (nonatomic, weak) id delegate;
24 | @property (nonatomic, weak) SCAPIConfiguration * configuration;
25 | @property (nonatomic, retain) NSString * username;
26 | @property (nonatomic, retain) NSString * password;
27 |
28 | - (id)initWithConfiguration:(SCAPIConfiguration *)configuration;
29 | - (void)startLogin;
30 | - (void)cancel;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Internal/SCAPIConfiguration.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPI.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface SCAPIConfiguration : NSObject {
13 | NSDictionary * options;
14 | }
15 |
16 | @property (readonly) NSData * encryptionKey;
17 | @property (readonly) NSData * secret;
18 | @property (readonly) NSString * baseURL;
19 | @property (readonly) NSString * staticToken;
20 | @property (readonly) NSString * userAgent;
21 |
22 | + (NSDictionary *)defaultOptions;
23 | + (SCAPIConfiguration *)defaultAPIConfiguration;
24 |
25 | - (id)initWithOptions:(NSDictionary *)opts;
26 |
27 | - (BOOL)isValidBlobHeader:(NSData *)header;
28 | - (NSData *)decrypt:(NSData *)data;
29 | - (NSData *)encrypt:(NSData *)data;
30 | - (NSString *)dualHash:(NSData *)value1 andHash:(NSData *)value2;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Managing/SCSnapManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCSnapManager.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SCAPISession.h"
11 |
12 | @protocol SCSnapManagerDelegate
13 |
14 | - (void)scSnapManager:(id)sender insertedAtIndex:(NSInteger)index;
15 | - (void)scSnapManager:(id)sender deletedAtIndex:(NSInteger)index;
16 | - (void)scSnapManagerFinishedLoading:(id)sender;
17 | - (void)scSnapManager:(id)sender failedWithError:(NSError *)e;
18 |
19 | @end
20 |
21 | @interface SCSnapManager : NSObject {
22 | NSMutableArray * fetchers;
23 | NSCache * blobs;
24 | NSMutableArray * snaps;
25 | }
26 |
27 | @property (readonly) NSMutableArray * snaps;
28 | @property (readonly) NSCache * blobs;
29 | @property (nonatomic, weak) id delegate;
30 |
31 | - (void)cancelAll;
32 | - (void)startFetchingBlobs:(SCAPISession *)session;
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/SnapchatHax/SnapchatHax-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | Hackchat
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.aqnichol.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/SnapchatHax/ANSnapVC.h:
--------------------------------------------------------------------------------
1 | //
2 | // ANSnapVC.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SCAPISession.h"
11 | #import "SCImageBlob.h"
12 | #import "SCVideoBlob.h"
13 |
14 | @interface ANSnapVC : UIViewController {
15 | IBOutlet UILabel * typeLabel;
16 | IBOutlet UILabel * dateLabel;
17 | IBOutlet UILabel * sizeLabel;
18 | IBOutlet UILabel * senderLabel;
19 | NSString * tempFile;
20 |
21 | IBOutlet UIActivityIndicatorView * loader;
22 | IBOutlet UIView * buttonsView;
23 | SCFetcher * fetcher;
24 |
25 | UIDocumentInteractionController * currentDocument;
26 | }
27 |
28 | @property (nonatomic, retain) SCSnap * snap;
29 | @property (nonatomic, retain) SCBlob * blob;
30 | @property (nonatomic, retain) SCAPISession * session;
31 |
32 | - (IBAction)viewPressed:(id)sender;
33 | - (IBAction)markScreenshotPressed:(id)sender;
34 | - (IBAction)markAsReadPressed:(id)sender;
35 |
36 | - (void)setLoading:(BOOL)flag;
37 |
38 | - (id)initWithSnap:(SCSnap *)snap;
39 | - (id)initWithSnap:(SCSnap *)snap session:(SCAPISession *)session;
40 | - (id)initWithSnap:(SCSnap *)snap blob:(SCBlob *)blob session:(SCAPISession *)session;
41 | - (void)handleBlobLoaded;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Data/SCSnap.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCSnap.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCSnap.h"
10 |
11 | @implementation SCSnap
12 |
13 | - (id)initWithDictionary:(NSDictionary *)dictionary {
14 | if ((self = [super init])) {
15 | self.user = dictionary[@"sn"];
16 | self.timestamp = [dictionary[@"ts"] longLongValue];
17 | self.status = [dictionary[@"st"] longLongValue];
18 | self.identifier = dictionary[@"id"];
19 | self.media = [dictionary[@"m"] longLongValue];
20 | self.tField = [dictionary[@"t"] longLongValue];
21 | }
22 | return self;
23 | }
24 |
25 | - (BOOL)isImageOrVideo {
26 | return (self.media < 7 && self.media != 3);
27 | }
28 |
29 | #pragma mark - Obj-C Overrides -
30 |
31 | - (NSString *)description {
32 | return [NSString stringWithFormat:@"<%@ user=%@, timestamp=%llu, status=%llu, identifier=%@, media=%llu, t=%llu>",
33 | NSStringFromClass(self.class), self.user, self.timestamp,
34 | self.status, self.identifier, self.media, self.tField];
35 | }
36 |
37 | - (BOOL)isEqual:(id)object {
38 | if (![object isKindOfClass:[SCSnap class]]) return NO;
39 | return [[((SCSnap *)object) identifier] isEqualToString:self.identifier];
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/SCAPISession.h:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPISession.h
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCAPIRequest.h"
10 | #import "SCFetcher.h"
11 |
12 | #import "SCSnap.h"
13 | #import "SCBlob.h"
14 |
15 | @interface SCAPISession : NSObject {
16 |
17 | }
18 |
19 | @property (nonatomic, retain) SCAPIConfiguration * configuration;
20 | @property (nonatomic, retain) NSString * authToken;
21 | @property (nonatomic, retain) NSString * username;
22 | @property (nonatomic, retain) NSArray * snaps;
23 |
24 | + (NSArray *)parseSnaps:(NSArray *)jsonSnaps;
25 |
26 | - (SCAPIRequest *)requestForBlob:(NSString *)blobIdentifier;
27 | - (SCFetcher *)fetchBlob:(NSString *)blobIdentifier
28 | callback:(void (^)(NSError * error, SCBlob * blob))cb;
29 |
30 | - (SCAPIRequest *)requestForSendingEvents:(NSArray *)list snapInfo:(NSDictionary *)info;
31 | - (SCFetcher *)markSnapViewed:(NSString *)blobId time:(NSTimeInterval)delay callback:(void (^)(NSError * error))cb;
32 | - (SCFetcher *)markSnapScreenshot:(NSString *)blobId time:(NSTimeInterval)delay callback:(void (^)(NSError * error))cb;
33 |
34 | /**
35 | * Asynchronously reload the snaps and authToken.
36 | */
37 | - (SCFetcher *)reloadAll:(void (^)(NSError * error))callback;
38 |
39 | - (NSArray *)mediaSnaps;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Note
2 |
3 | While I am no longer actively developing this project, others have stepped in to fix it along the way. I have heard that it works as of January 6, 2015.
4 |
5 | # Purpose
6 |
7 | Quick, we don't want them to know that we saved this pic, what shall we do? SnapchatHax to the rescue! The purpose of this project is twofold:
8 |
9 | * to provide an easy-to-use Objective-C platform to interface with the Snapchat backend.
10 | * to provide users with an easy-to-use iOS application for the purpose of bypassing Snapchat's inherent limitations.
11 |
12 | Currently, this bare-bones app does my minimal requirements. Now, however, I have my heart set on beating the guy who wrote [SnapHack](https://itunes.apple.com/us/app/snaphack-pro-for-snapchat/id716560946?mt=8&ign-mpt=uo%3D4). By the end of this, I should have a relatively full-featured Objective-C interface for Snapchat's backend!
13 |
14 |
15 | # To-do
16 |
17 | Here's a list of things I think are pretty much essential:
18 |
19 | * Make the backlog include old snaps that are no longer viewable
20 | * Option to clear feed
21 | * Change nickname and email address
22 |
23 | Here are some features which would ideally be added:
24 |
25 | * Send snaps to friends (pictures & video)
26 | * Add & remove friends
27 | * Block and unblock users
28 | * Do *something* with stories, although I don't even understand them.
29 | * Get "bests" of users
30 |
31 | # References
32 |
33 | See [tlack/snaphax](https://github.com/tlack/snaphax) for my main source of reverse-engineered information.
34 |
35 | Update: I have since started using [dstelljes/php-snapchat/](https://github.com/dstelljes/php-snapchat/) for reference. This is a more complete set of functions.
36 |
--------------------------------------------------------------------------------
/SnapchatHax/ANLoginVC.m:
--------------------------------------------------------------------------------
1 | //
2 | // ANLoginVC.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "ANLoginVC.h"
10 |
11 | @interface ANLoginVC ()
12 |
13 | @end
14 |
15 | @implementation ANLoginVC
16 |
17 | - (id)init {
18 | if ((self = [super initWithNibName:NSStringFromClass(self.class)
19 | bundle:[NSBundle mainBundle]])) {
20 | self.title = @"Login";
21 | }
22 | return self;
23 | }
24 |
25 | - (void)viewDidLoad {
26 | [super viewDidLoad];
27 | NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
28 | username.text = [defaults objectForKey:@"username"] ?: @"";
29 | password.text = [defaults objectForKey:@"password"] ?: @"";
30 | }
31 |
32 | - (IBAction)loginPressed:(id)sender {
33 | [button setEnabled:NO];
34 | SCAPILogin * login = [[SCAPILogin alloc] init];
35 | login.username = username.text;
36 | login.password = password.text;
37 | login.delegate = self;
38 | [login startLogin];
39 | }
40 |
41 | - (void)scAPILogin:(id)sender failedWithError:(NSError *)error {
42 | [button setEnabled:YES];
43 | UIAlertView * av = [[UIAlertView alloc] initWithTitle:@"Error"
44 | message:[error localizedDescription]
45 | delegate:nil
46 | cancelButtonTitle:nil
47 | otherButtonTitles:@"OK", nil];
48 | [av show];
49 | }
50 |
51 | - (void)scAPILogin:(id)sender succeededWithSession:(SCAPISession *)session {
52 | [button setEnabled:YES];
53 | ANSnapsVC * snaps = [[ANSnapsVC alloc] initWithSession:session];
54 | [self.navigationController pushViewController:snaps animated:YES];
55 |
56 | NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
57 | [defs setObject:username.text forKey:@"username"];
58 | [defs setObject:password.text forKey:@"password"];
59 | [defs synchronize];
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/SCFetcher.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCFetcher.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCFetcher.h"
10 |
11 | @implementation SCFetcher
12 |
13 | + (SCFetcher *)fetcherStartedForRequest:(NSURLRequest *)req callback:(SCFetcherBlock)block {
14 | SCFetcher * fetcher = [[SCFetcher alloc] initWithRequest:req];
15 | fetcher.callback = block;
16 | fetcher.parseJSON = YES;
17 | [fetcher start];
18 | return fetcher;
19 | }
20 |
21 | + (SCFetcher *)fetcherStartedForRequestNoJSON:(NSURLRequest *)req callback:(SCFetcherBlock)block {
22 | SCFetcher * fetcher = [[SCFetcher alloc] initWithRequest:req];
23 | fetcher.callback = block;
24 | [fetcher start];
25 | return fetcher;
26 | }
27 |
28 | - (id)initWithRequest:(NSURLRequest *)request {
29 | if ((self = [super init])) {
30 | connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
31 | }
32 | return self;
33 | }
34 |
35 | - (void)start {
36 | data = [NSMutableData data];
37 | [connection start];
38 | }
39 |
40 | - (void)cancel {
41 | data = nil;
42 | [connection cancel];
43 | connection = nil;
44 | self.callback = nil;
45 | }
46 |
47 | #pragma mark - NSURLConnection -
48 |
49 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
50 | self.callback(error, nil);
51 | self.callback = nil;
52 | }
53 |
54 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)_data {
55 | [data appendData:_data];
56 | }
57 |
58 | - (void)connectionDidFinishLoading:(NSURLConnection *)conn {
59 | connection = nil;
60 | if (self.parseJSON) {
61 | NSError * error = nil;
62 | NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
63 | data = nil;
64 | if (![dict isKindOfClass:[NSDictionary class]]) {
65 | self.callback(error, nil);
66 | self.callback = nil;
67 | return;
68 | }
69 | self.callback(nil, dict);
70 | } else {
71 | self.callback(nil, [data copy]);
72 | data = nil;
73 | }
74 | self.callback = nil;
75 | }
76 |
77 | @end
78 |
--------------------------------------------------------------------------------
/SnapchatHax/ANAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // ANAppDelegate.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "ANAppDelegate.h"
10 | #import "SCAPIConfiguration.h"
11 |
12 | @implementation ANAppDelegate
13 |
14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
15 | {
16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
17 |
18 | ANLoginVC * login = [[ANLoginVC alloc] init];
19 | navCont = [[UINavigationController alloc] init];
20 | [navCont pushViewController:login animated:NO];
21 | self.window.rootViewController = navCont;
22 | self.window.backgroundColor = [UIColor whiteColor];
23 | [self.window makeKeyAndVisible];
24 |
25 | return YES;
26 | }
27 |
28 | - (void)applicationWillResignActive:(UIApplication *)application
29 | {
30 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
31 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
32 | }
33 |
34 | - (void)applicationDidEnterBackground:(UIApplication *)application
35 | {
36 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
38 | }
39 |
40 | - (void)applicationWillEnterForeground:(UIApplication *)application
41 | {
42 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
43 | }
44 |
45 | - (void)applicationDidBecomeActive:(UIApplication *)application
46 | {
47 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
48 | }
49 |
50 | - (void)applicationWillTerminate:(UIApplication *)application
51 | {
52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Internal/SCAPIRequest.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPIRequest.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCAPIRequest.h"
10 |
11 | @implementation SCAPIRequest
12 |
13 | + (NSString *)timestampString {
14 | NSTimeInterval time = [NSDate date].timeIntervalSince1970;
15 | return [NSString stringWithFormat:@"%llu", (unsigned long long)round(time * 1000.0)];
16 | }
17 |
18 | + (NSString *)encodeQueryParam:(NSString *)param {
19 | NSMutableString * str = [NSMutableString string];
20 | for (NSInteger i = 0; i < param.length; i++) {
21 | unichar aChar = [param characterAtIndex:i];
22 | if (isalnum(aChar)) {
23 | [str appendFormat:@"%C", aChar];
24 | } else {
25 | [str appendFormat:@"%%%02X", (unsigned char)aChar];
26 | }
27 | }
28 | return str;
29 | }
30 |
31 | + (NSString *)encodeQuery:(NSDictionary *)dict {
32 | NSMutableString * str = [NSMutableString string];
33 |
34 | for (NSString * key in dict) {
35 | if (str.length) [str appendString:@"&"];
36 | [str appendFormat:@"%@=%@", [self encodeQueryParam:key],
37 | [self encodeQueryParam:[dict[key] description]]];
38 | }
39 |
40 | return str;
41 | }
42 |
43 | - (id)initWithConfiguration:(SCAPIConfiguration *)enc
44 | path:(NSString *)path
45 | token:(NSString *)token
46 | dictionary:(NSDictionary *)dict {
47 | if ((self = [super init])) {
48 | [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@", enc.baseURL, path]]];
49 | [self setHTTPMethod:@"POST"];
50 | NSMutableDictionary * jsonBody = [dict mutableCopy];
51 | NSString * timestamp = self.class.timestampString;
52 | jsonBody[@"req_token"] = [enc dualHash:[token dataUsingEncoding:NSUTF8StringEncoding]
53 | andHash:[timestamp dataUsingEncoding:NSUTF8StringEncoding]];
54 | jsonBody[@"timestamp"] = @([timestamp longLongValue]);
55 | NSData * encoded = [[self.class encodeQuery:jsonBody] dataUsingEncoding:NSASCIIStringEncoding];
56 | [self setHTTPBody:encoded];
57 | [self setValue:[NSString stringWithFormat:@"%d", (int)encoded.length]
58 | forHTTPHeaderField:@"Content-Length"];
59 | [self setValue:enc.userAgent forHTTPHeaderField:@"User-Agent"];
60 | [self setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
61 | }
62 | return self;
63 | }
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/SCAPILogin.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPILogin.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCAPILogin.h"
10 |
11 | @implementation SCAPILogin
12 |
13 | - (id)init {
14 | self = [self initWithConfiguration:[SCAPIConfiguration defaultAPIConfiguration]];
15 | return self;
16 | }
17 |
18 | - (id)initWithConfiguration:(SCAPIConfiguration *)configuration {
19 | if ((self = [super init])) {
20 | self.configuration = configuration;
21 | responseData = [NSMutableData data];
22 | }
23 | return self;
24 | }
25 |
26 | - (void)startLogin {
27 | NSDictionary * post = @{@"username": self.username,
28 | @"password": self.password};
29 | SCAPIRequest * req = [[SCAPIRequest alloc] initWithConfiguration:self.configuration
30 | path:@"/ph/login"
31 | token:self.configuration.staticToken
32 | dictionary:post];
33 | connection = [NSURLConnection connectionWithRequest:req delegate:self];
34 | }
35 |
36 | - (void)cancel {
37 | [connection cancel];
38 | connection = nil;
39 | }
40 |
41 | #pragma mark - Connection -
42 |
43 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
44 | [self.delegate scAPILogin:self failedWithError:error];
45 | }
46 |
47 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
48 | [responseData appendData:data];
49 | }
50 |
51 | - (void)connectionDidFinishLoading:(NSURLConnection *)conn {
52 | connection = nil;
53 | NSError * error = nil;
54 | NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
55 | if (![dict isKindOfClass:[NSDictionary class]]) {
56 | return [self.delegate scAPILogin:self failedWithError:error];
57 | }
58 | if (![dict[@"auth_token"] isKindOfClass:[NSString class]]) {
59 | return [self.delegate scAPILogin:self failedWithError:[NSError errorWithDomain:@"SCAPILogin"
60 | code:1
61 | userInfo:@{NSLocalizedDescriptionKey:@"Invalid username or password."}]];
62 | }
63 |
64 | SCAPISession * session = [[SCAPISession alloc] init];
65 | session.authToken = dict[@"auth_token"];
66 | session.configuration = self.configuration;
67 | session.snaps = [SCAPISession parseSnaps:dict[@"snaps"]];
68 | session.username = self.username;
69 | [self.delegate scAPILogin:self succeededWithSession:session];
70 | }
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Managing/SCSnapManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCSnapManager.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCSnapManager.h"
10 |
11 | @implementation SCSnapManager
12 |
13 | @synthesize blobs;
14 | @synthesize snaps;
15 |
16 | - (id)init {
17 | if ((self = [super init])) {
18 | snaps = [NSMutableArray array];
19 | fetchers = [NSMutableArray array];
20 | blobs = [[NSCache alloc] init];
21 | blobs.totalCostLimit = (1 << 27); // maximum of 2^27 blob bytes
22 | }
23 | return self;
24 | }
25 |
26 | - (void)cancelAll {
27 | while (fetchers.count > 0) {
28 | [fetchers[0] cancel];
29 | [fetchers removeObjectAtIndex:0];
30 | }
31 | }
32 |
33 | - (void)startFetchingBlobs:(SCAPISession *)session {
34 | // remove snaps
35 | NSArray * mediaSnaps = session.mediaSnaps;
36 | for (int i = 0; i < self.snaps.count; i++) {
37 | SCSnap * s = self.snaps[i];
38 | if (![mediaSnaps containsObject:s]) {
39 | [self.snaps removeObject:s];
40 | [self.delegate scSnapManager:self deletedAtIndex:i];
41 | i--;
42 | }
43 | }
44 | for (SCSnap * s in mediaSnaps) {
45 | __weak SCSnapManager * weakSelf = self;
46 | __block SCFetcher * f = [session fetchBlob:s.identifier callback:^(NSError * error, SCBlob * blob) {
47 | [fetchers removeObject:f];
48 | if (error && ![error.domain isEqualToString:@"SCBlob"]) {
49 | [weakSelf.delegate scSnapManager:weakSelf failedWithError:error];
50 | } else {
51 | if (blob) {
52 | [weakSelf.blobs setObject:blob forKey:s.identifier
53 | cost:blob.blobData.length];
54 | if (![weakSelf.snaps containsObject:s]) {
55 | [weakSelf.snaps addObject:s];
56 |
57 | // sort it by date
58 | [weakSelf.snaps sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
59 | SCSnap * s1 = obj1, * s2 = obj2;
60 | if (s1.timestamp < s2.timestamp) return NSOrderedAscending;
61 | if (s1.timestamp > s2.timestamp) return NSOrderedDescending;
62 | return NSOrderedSame;
63 | }];
64 |
65 | [weakSelf.delegate scSnapManager:weakSelf
66 | insertedAtIndex:[weakSelf.snaps indexOfObject:s]];
67 | }
68 | } else {
69 | if ([weakSelf.snaps containsObject:s]) {
70 | NSInteger index = [weakSelf.snaps indexOfObject:s];
71 | [weakSelf.snaps removeObject:s];
72 | [weakSelf.delegate scSnapManager:self deletedAtIndex:index];
73 | }
74 | }
75 | if (!fetchers.count) {
76 | [weakSelf.delegate scSnapManagerFinishedLoading:weakSelf];
77 | }
78 | }
79 | }];
80 | [fetchers addObject:f];
81 | }
82 | if (!fetchers.count) {
83 | [(id)self.delegate performSelector:@selector(scSnapManagerFinishedLoading:)
84 | withObject:self afterDelay:0];
85 | }
86 | }
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/SnapchatHax.xcodeproj/xcuserdata/alex.xcuserdatad/xcschemes/SnapchatHax.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/SnapchatHax/ANLoginVC.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
43 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/SnapchatHax/ANSnapVC.m:
--------------------------------------------------------------------------------
1 | //
2 | // ANSnapVC.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "ANSnapVC.h"
10 |
11 | @interface ANSnapVC ()
12 |
13 | @end
14 |
15 | @implementation ANSnapVC
16 |
17 | - (id)initWithSnap:(SCSnap *)snap {
18 | if ((self = [super initWithNibName:NSStringFromClass(self.class)
19 | bundle:[NSBundle mainBundle]])) {
20 | self.snap = snap;
21 | self.title = @"Snap";
22 | }
23 | return self;
24 | }
25 |
26 | - (id)initWithSnap:(SCSnap *)snap session:(SCAPISession *)session {
27 | if ((self = [self initWithSnap:snap])) {
28 | // load the data
29 | self.session = session;
30 | fetcher = [session fetchBlob:self.snap.identifier callback:^(NSError * error, SCBlob * blob) {
31 | if (!blob) {
32 | UIAlertView * av = [[UIAlertView alloc] initWithTitle:@"Error"
33 | message:[error localizedDescription]
34 | delegate:nil
35 | cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
36 | [av show];
37 | } else {
38 | fetcher = nil;
39 | self.blob = blob;
40 | [self handleBlobLoaded];
41 | }
42 | }];
43 | }
44 | return self;
45 | }
46 |
47 | - (id)initWithSnap:(SCSnap *)snap blob:(SCBlob *)blob session:(SCAPISession *)session {
48 | if ((self = [self initWithSnap:snap])) {
49 | self.blob = blob;
50 | self.session = session;
51 | }
52 | return self;
53 | }
54 |
55 | - (void)setLoading:(BOOL)flag {
56 | if (flag) {
57 | [loader startAnimating];
58 | [buttonsView setHidden:YES];
59 | } else {
60 | [loader stopAnimating];
61 | [buttonsView setHidden:NO];
62 | }
63 | }
64 |
65 | #pragma mark - Events -
66 |
67 | - (IBAction)viewPressed:(id)sender {
68 | NSURL * theURL = [NSURL fileURLWithPath:tempFile];
69 | currentDocument = [UIDocumentInteractionController interactionControllerWithURL:theURL];
70 | currentDocument.delegate = self;
71 |
72 | [currentDocument presentOptionsMenuFromRect:CGRectZero
73 | inView:self.view
74 | animated:YES];
75 | }
76 |
77 | - (IBAction)markScreenshotPressed:(id)sender {
78 | [self setLoading:YES];
79 | fetcher = [self.session markSnapScreenshot:self.snap.identifier time:1 callback:^(NSError * error) {
80 | if (error) {
81 | UIAlertView * av = [[UIAlertView alloc] initWithTitle:@"Error"
82 | message:[error localizedDescription]
83 | delegate:nil
84 | cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
85 | [av show];
86 | }
87 | [self setLoading:NO];
88 | }];
89 | }
90 |
91 | - (IBAction)markAsReadPressed:(id)sender {
92 | [self setLoading:YES];
93 | fetcher = [self.session markSnapViewed:self.snap.identifier time:1 callback:^(NSError * error) {
94 | if (error) {
95 | UIAlertView * av = [[UIAlertView alloc] initWithTitle:@"Error"
96 | message:[error localizedDescription]
97 | delegate:nil
98 | cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
99 | [av show];
100 | }
101 | [self setLoading:NO];
102 | }];
103 | }
104 |
105 | #pragma mark - Loading -
106 |
107 | - (void)viewDidLoad {
108 | [super viewDidLoad];
109 |
110 | if (self.blob) [self handleBlobLoaded];
111 | dateLabel.text = [[NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)self.snap.timestamp / 1000.0] description];
112 | senderLabel.text = self.snap.user;
113 | }
114 |
115 | - (void)handleBlobLoaded {
116 | if (!buttonsView || !typeLabel || !sizeLabel) return;
117 |
118 | NSString * fileName = [NSString stringWithFormat:@"%@.%@", self.snap.identifier, [self.blob blobFileExtension]];
119 | tempFile = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
120 | [self.blob.blobData writeToFile:tempFile atomically:YES];
121 |
122 | [self setLoading:NO];
123 | typeLabel.text = [self.blob isKindOfClass:[SCImageBlob class]] ? @"Image" : @"Video";
124 | sizeLabel.text = [NSString stringWithFormat:@"%d KB", (int)self.blob.blobData.length >> 10];
125 | }
126 |
127 | - (void)viewDidDisappear:(BOOL)animated {
128 | if (!self.navigationController) {
129 | [fetcher cancel];
130 | if (tempFile) [[NSFileManager defaultManager] removeItemAtPath:tempFile error:nil];
131 | }
132 | }
133 |
134 | #pragma mark - Document Interaction -
135 |
136 | - (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller {
137 | return self.navigationController;
138 | }
139 |
140 | @end
141 |
--------------------------------------------------------------------------------
/SnapchatHax/ANSnapsVC.m:
--------------------------------------------------------------------------------
1 | //
2 | // ANSnapsVC.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/18/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "ANSnapsVC.h"
10 |
11 | @interface ANSnapsVC ()
12 |
13 | @end
14 |
15 | @implementation ANSnapsVC
16 |
17 | - (id)initWithSession:(SCAPISession *)session {
18 | if ((self = [super init])) {
19 | self.session = session;
20 | self.title = session.username;
21 | snaps = [[SCSnapManager alloc] init];
22 | snaps.delegate = self;
23 | [snaps startFetchingBlobs:session];
24 |
25 | loader = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
26 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:loader];
27 |
28 | loadButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
29 | target:self
30 | action:@selector(reloadPressed:)];
31 | [self setReloading:YES];
32 | }
33 | return self;
34 | }
35 |
36 | - (IBAction)reloadPressed:(id)sender {
37 | reloadFetcher = [self.session reloadAll:^(NSError * error) {
38 | reloadFetcher = nil;
39 | if (error) {
40 | UIAlertView * av = [[UIAlertView alloc] initWithTitle:@"Error"
41 | message:[error localizedDescription]
42 | delegate:nil cancelButtonTitle:nil
43 | otherButtonTitles:@"OK", nil];
44 | [av show];
45 | [self setReloading:NO];
46 | } else {
47 | [snaps startFetchingBlobs:self.session];
48 | }
49 | }];
50 | [self setReloading:YES];
51 | }
52 |
53 | - (void)setReloading:(BOOL)reloading {
54 | if (reloading) {
55 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:loader];
56 | [loader startAnimating];
57 | } else {
58 | [loader stopAnimating];
59 | self.navigationItem.rightBarButtonItem = loadButton;
60 | }
61 | }
62 |
63 | #pragma mark - View Methods -
64 |
65 | - (void)didReceiveMemoryWarning {
66 | [super didReceiveMemoryWarning];
67 | [snaps.blobs removeAllObjects];
68 | }
69 |
70 | - (void)viewDidDisappear:(BOOL)animated {
71 | if (!self.navigationController) {
72 | [snaps cancelAll];
73 | [reloadFetcher cancel];
74 | }
75 | }
76 |
77 | #pragma mark - Table View -
78 |
79 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
80 | return 1;
81 | }
82 |
83 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
84 | return snaps.snaps.count;
85 | }
86 |
87 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
88 | UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
89 | if (!cell) {
90 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
91 | reuseIdentifier:@"Cell"];
92 | }
93 |
94 | SCSnap * snap = snaps.snaps[indexPath.row];
95 | cell.textLabel.text = snap.user;
96 |
97 | NSDate * date = [NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)snap.timestamp / 1000.0];
98 | cell.detailTextLabel.text = [NSString stringWithFormat:@"At %@", [date description]];
99 |
100 | return cell;
101 | }
102 |
103 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
104 | SCSnap * snap = snaps.snaps[indexPath.row];
105 | SCBlob * blob = [snaps.blobs objectForKey:snap.identifier];
106 | ANSnapVC * vc = nil;
107 | if (blob) vc = [[ANSnapVC alloc] initWithSnap:snap blob:blob session:self.session];
108 | else vc = [[ANSnapVC alloc] initWithSnap:snap session:self.session];
109 | [self.navigationController pushViewController:vc animated:YES];
110 | }
111 |
112 | #pragma mark - SCSnapManager -
113 |
114 | - (void)scSnapManager:(id)sender insertedAtIndex:(NSInteger)index {
115 | [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:(index) inSection:0]]
116 | withRowAnimation:UITableViewRowAnimationAutomatic];
117 | }
118 |
119 | - (void)scSnapManager:(id)sender deletedAtIndex:(NSInteger)index {
120 | [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:(index) inSection:0]]
121 | withRowAnimation:UITableViewRowAnimationAutomatic];
122 | }
123 |
124 | - (void)scSnapManagerFinishedLoading:(id)sender {
125 | [self setReloading:NO];
126 | }
127 |
128 | - (void)scSnapManager:(id)sender failedWithError:(NSError *)e {
129 | UIAlertView * av = [[UIAlertView alloc] initWithTitle:@"Error"
130 | message:[e localizedDescription]
131 | delegate:nil
132 | cancelButtonTitle:nil
133 | otherButtonTitles:@"OK", nil];
134 | [av show];
135 | [self setReloading:NO];
136 | }
137 |
138 | @end
139 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/SCAPISession.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPISession.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCAPISession.h"
10 |
11 | @implementation SCAPISession
12 |
13 | + (NSArray *)parseSnaps:(NSArray *)jsonSnaps {
14 | NSMutableArray * snaps = [[NSMutableArray alloc] init];
15 | for (NSDictionary * snap in jsonSnaps) {
16 | [snaps addObject:[[SCSnap alloc] initWithDictionary:snap]];
17 | }
18 | return snaps;
19 | }
20 |
21 | - (NSString *)description {
22 | return [NSString stringWithFormat:@"<%@ authToken=%@, snaps=%@>", NSStringFromClass(self.class), self.authToken, self.snaps];
23 | }
24 |
25 | #pragma mark - Blobs -
26 |
27 | - (SCAPIRequest *)requestForBlob:(NSString *)blobIdentifier {
28 | NSDictionary * params = @{@"username": self.username,
29 | @"id": blobIdentifier};
30 | return [[SCAPIRequest alloc] initWithConfiguration:self.configuration
31 | path:@"/bq/blob"
32 | token:self.authToken
33 | dictionary:params];
34 | }
35 |
36 | - (SCFetcher *)fetchBlob:(NSString *)blobIdentifier
37 | callback:(void (^)(NSError * error, SCBlob * blob))cb {
38 | NSURLRequest * req = [self requestForBlob:blobIdentifier];
39 | return [SCFetcher fetcherStartedForRequestNoJSON:req callback:^(NSError * error, id result) {
40 | if (error) return cb(error, nil);
41 | SCBlob * blob = [SCBlob blobWithData:result];
42 | if (!blob) {
43 | // decrypt the data
44 | NSData * testData = [self.configuration decrypt:result];
45 | blob = [SCBlob blobWithData:testData];
46 | }
47 | if (!blob) return cb([NSError errorWithDomain:@"SCBlob"
48 | code:1
49 | userInfo:@{NSLocalizedDescriptionKey: @"Unknown blob type."}], nil);
50 | cb(nil, blob);
51 | }];
52 | }
53 |
54 | #pragma mark - Events -
55 |
56 | - (SCAPIRequest *)requestForSendingEvents:(NSArray *)list snapInfo:(NSDictionary *)info {
57 | NSData * jsonData = [NSJSONSerialization dataWithJSONObject:info options:0 error:nil];
58 | NSData * eventsData = [NSJSONSerialization dataWithJSONObject:list options:0 error:nil];
59 | NSDictionary * req = @{@"username": self.username,
60 | @"json": [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding],
61 | @"events": [[NSString alloc] initWithData:eventsData encoding:NSUTF8StringEncoding]};
62 | return [[SCAPIRequest alloc] initWithConfiguration:self.configuration
63 | path:@"/bq/update_snaps"
64 | token:self.authToken
65 | dictionary:req];
66 | }
67 |
68 | - (SCFetcher *)markSnapViewed:(NSString *)blobId time:(NSTimeInterval)delay callback:(void (^)(NSError * error))cb {
69 | NSTimeInterval ts = [[NSDate date] timeIntervalSince1970];
70 | NSDictionary * timeInfo = @{@"t": @(ts),
71 | @"sv": @(delay)};
72 | NSDictionary * snapInfo = @{blobId: timeInfo};
73 | NSArray * events = @[@{@"eventName": @"SNAP_VIEW", @"params": @{@"id": blobId}, @"ts": @(ts - delay)},
74 | @{@"eventName": @"SNAP_EXPIRED", @"params": @{@"id": blobId}, @"ts": @(ts)}];
75 | return [SCFetcher fetcherStartedForRequestNoJSON:[self requestForSendingEvents:events snapInfo:snapInfo]
76 | callback:^(NSError * error, id result) {
77 | cb(error);
78 | }];
79 | }
80 |
81 | - (SCFetcher *)markSnapScreenshot:(NSString *)blobId time:(NSTimeInterval)delay callback:(void (^)(NSError * error))cb {
82 | NSTimeInterval ts = [[NSDate date] timeIntervalSince1970];
83 | NSDictionary * timeInfo = @{@"t": @(ts),
84 | @"sv": @(delay),
85 | @"c": @(3)};
86 | NSDictionary * snapInfo = @{blobId: timeInfo};
87 | NSArray * events = @[@{@"eventName": @"SNAP_SCREENSHOT", @"params": @{@"id": blobId}, @"ts": @(ts - delay)}];
88 | return [SCFetcher fetcherStartedForRequestNoJSON:[self requestForSendingEvents:events snapInfo:snapInfo]
89 | callback:^(NSError * error, id result) {
90 | cb(error);
91 | }];
92 | }
93 |
94 | #pragma mark - Extra -
95 |
96 | - (SCFetcher *)reloadAll:(void (^)(NSError * error))callback {
97 | NSDictionary * reqArgs = @{@"username": self.username};
98 | NSURLRequest * req = [[SCAPIRequest alloc] initWithConfiguration:self.configuration
99 | path:@"/bq/all_updates"
100 | token:self.authToken
101 | dictionary:reqArgs];
102 | return [SCFetcher fetcherStartedForRequest:req callback:^(NSError * error, id result) {
103 | if (error) return callback(error);
104 | NSDictionary * dict = result;
105 | if (dict[@"updates_response"]) {
106 | dict = dict[@"updates_response"];
107 | self.snaps = [self.class parseSnaps:dict[@"snaps"]];
108 | self.authToken = dict[@"auth_token"];
109 | } else if (dict[@"snaps"]) {
110 | self.snaps = [self.class parseSnaps:dict[@"snaps"]];
111 | }
112 | callback(nil);
113 | }];
114 | }
115 |
116 | - (NSArray *)mediaSnaps {
117 | NSMutableArray * snaps = [NSMutableArray array];
118 |
119 | for (SCSnap * snap in self.snaps) {
120 | if ([snap isImageOrVideo]) {
121 | [snaps addObject:snap];
122 | }
123 | }
124 |
125 | return snaps;
126 | }
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/SnapchatHax/Snapchat/Internal/SCAPIConfiguration.m:
--------------------------------------------------------------------------------
1 | //
2 | // SCAPI.m
3 | // SnapchatHax
4 | //
5 | // Created by Alex Nichol on 12/17/13.
6 | // Copyright (c) 2013 Alex Nichol. All rights reserved.
7 | //
8 |
9 | #import "SCAPIConfiguration.h"
10 |
11 | static NSString * hexHash(NSData * input);
12 |
13 | @implementation SCAPIConfiguration
14 |
15 | + (NSDictionary *)defaultOptions {
16 | /**
17 | * Graciously taken from https://github.com/tlack/snaphax/blob/master/snaphax.php
18 | */
19 | return @{@"blob_enc_key": @"M02cnQ51Ji97vwT4",
20 | @"pattern": @"0001110111101110001111010101111011010001001110011000110001000110",
21 | @"secret": @"iEk21fuwZApXlz93750dmW22pw389dPwOk",
22 | @"static_token": @"m198sOkJEn37DjqZ32lpRu76xmw288xSQ9",
23 | @"url": @"https://feelinsonice-hrd.appspot.com",
24 | @"user_agent": @"Snapchat/8.1.1 (iPad; iPhone OS 6.0; en_US; gzip)"};
25 | }
26 |
27 | + (SCAPIConfiguration *)defaultAPIConfiguration {
28 | static SCAPIConfiguration * api = nil;
29 | static dispatch_once_t onceToken;
30 | dispatch_once(&onceToken, ^{
31 | api = [[SCAPIConfiguration alloc] initWithOptions:[self defaultOptions]];
32 | });
33 | return api;
34 | }
35 |
36 | - (id)initWithOptions:(NSDictionary *)opts {
37 | if ((self = [super init])) {
38 | options = opts;
39 | }
40 | return self;
41 | }
42 |
43 | - (BOOL)isValidBlobHeader:(NSData *)header {
44 | if (header.length < 2) return NO;
45 | unsigned const char * bytes = (unsigned const char *)header.bytes;
46 | return (bytes[0] == 0 && bytes[1] == 0) ||
47 | (bytes[0] == 0xff && bytes[1] == 0xd8);
48 | }
49 |
50 | - (NSData *)decrypt:(NSData *)data {
51 | NSData * result = nil;
52 |
53 | // setup key
54 | unsigned char cKey[16];
55 | bzero(cKey, sizeof(cKey));
56 | [self.encryptionKey getBytes:cKey length:16];
57 |
58 | // setup output buffer
59 | size_t bufferSize = [data length];
60 | void * buffer = malloc(bufferSize);
61 |
62 | // do decrypt
63 | size_t decryptedSize = 0;
64 | CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
65 | kCCAlgorithmAES128,
66 | kCCOptionECBMode,
67 | cKey,
68 | 16,
69 | NULL,
70 | [data bytes],
71 | [data length],
72 | buffer,
73 | bufferSize,
74 | &decryptedSize);
75 |
76 | if (cryptStatus == kCCSuccess) {
77 | result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
78 | } else {
79 | free(buffer);
80 | NSLog(@"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus);
81 | }
82 |
83 | return result;
84 | }
85 |
86 | - (NSData *)encrypt:(NSData *)data {
87 | NSData * result = nil;
88 |
89 | // setup key
90 | unsigned char cKey[16];
91 | bzero(cKey, sizeof(cKey));
92 | [self.encryptionKey getBytes:cKey length:16];
93 |
94 | // setup output buffer
95 | size_t bufferSize = [data length] + (data.length % 16);
96 | void * buffer = malloc(bufferSize);
97 |
98 | void * strBuffer = malloc(bufferSize);
99 | bzero(strBuffer, bufferSize);
100 | [data getBytes:strBuffer];
101 |
102 | // do encrypt
103 | size_t encSize = 0;
104 | CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
105 | kCCAlgorithmAES128,
106 | kCCOptionECBMode,
107 | cKey,
108 | 16,
109 | NULL,
110 | strBuffer,
111 | bufferSize,
112 | buffer,
113 | bufferSize,
114 | &encSize);
115 | free(strBuffer);
116 | if (cryptStatus == kCCSuccess) {
117 | result = [NSData dataWithBytesNoCopy:buffer length:encSize];
118 | } else {
119 | free(buffer);
120 | NSLog(@"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus);
121 | }
122 |
123 | return result;
124 | }
125 |
126 | - (NSString *)dualHash:(NSData *)value1 andHash:(NSData *)value2 {
127 | NSMutableData * s1 = [self.secret mutableCopy];
128 | [s1 appendData:value1];
129 | NSMutableData * s2 = [value2 mutableCopy];
130 | [s2 appendData:self.secret];
131 | NSString * s3 = hexHash(s1);
132 | NSString * s4 = hexHash(s2);
133 |
134 | NSString * pattern = options[@"pattern"];
135 | NSMutableString * result = [NSMutableString string];
136 | for (int i = 0; i < pattern.length; i++) {
137 | if ([pattern characterAtIndex:i] == '0') {
138 | [result appendFormat:@"%C", [s3 characterAtIndex:i]];
139 | } else {
140 | [result appendFormat:@"%C", [s4 characterAtIndex:i]];
141 | }
142 | }
143 | return result;
144 | }
145 |
146 | #pragma mark - Properties -
147 |
148 | - (NSData *)encryptionKey {
149 | return [options[@"blob_enc_key"] dataUsingEncoding:NSASCIIStringEncoding];
150 | }
151 |
152 | - (NSData *)secret {
153 | return [options[@"secret"] dataUsingEncoding:NSASCIIStringEncoding];
154 | }
155 |
156 | - (NSString *)baseURL {
157 | return options[@"url"];
158 | }
159 |
160 | - (NSString *)staticToken {
161 | return options[@"static_token"];
162 | }
163 |
164 | - (NSString *)userAgent {
165 | return options[@"user_agent"];
166 | }
167 |
168 | @end
169 |
170 | static NSString * hexHash(NSData * input) {
171 | unsigned char output[CC_SHA256_DIGEST_LENGTH];
172 | CC_SHA256(input.bytes, (unsigned int)input.length, output);
173 | NSMutableString * str = [NSMutableString string];
174 | for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
175 | [str appendFormat:@"%02x", output[i]];
176 | }
177 | return str;
178 | }
179 |
--------------------------------------------------------------------------------
/SnapchatHax/ANSnapVC.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
35 |
41 |
47 |
53 |
59 |
65 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
90 |
100 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/SnapchatHax.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | FAAF8C00186289680049B692 /* SCBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAF8BFB186289680049B692 /* SCBlob.m */; };
11 | FAAF8C01186289680049B692 /* SCImageBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAF8BFD186289680049B692 /* SCImageBlob.m */; };
12 | FAAF8C02186289680049B692 /* SCVideoBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAF8BFF186289680049B692 /* SCVideoBlob.m */; };
13 | FAF75EAE1860F9CC006C7D11 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAF75EAD1860F9CC006C7D11 /* Foundation.framework */; };
14 | FAF75EB01860F9CC006C7D11 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAF75EAF1860F9CC006C7D11 /* CoreGraphics.framework */; };
15 | FAF75EB21860F9CC006C7D11 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAF75EB11860F9CC006C7D11 /* UIKit.framework */; };
16 | FAF75EB81860F9CC006C7D11 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAF75EB61860F9CC006C7D11 /* InfoPlist.strings */; };
17 | FAF75EBA1860F9CC006C7D11 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EB91860F9CC006C7D11 /* main.m */; };
18 | FAF75EBE1860F9CC006C7D11 /* ANAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EBD1860F9CC006C7D11 /* ANAppDelegate.m */; };
19 | FAF75EC01860F9CC006C7D11 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FAF75EBF1860F9CC006C7D11 /* Images.xcassets */; };
20 | FAF75EC71860F9CC006C7D11 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAF75EC61860F9CC006C7D11 /* XCTest.framework */; };
21 | FAF75EC81860F9CC006C7D11 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAF75EAD1860F9CC006C7D11 /* Foundation.framework */; };
22 | FAF75EC91860F9CC006C7D11 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAF75EB11860F9CC006C7D11 /* UIKit.framework */; };
23 | FAF75ED11860F9CC006C7D11 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAF75ECF1860F9CC006C7D11 /* InfoPlist.strings */; };
24 | FAF75ED31860F9CC006C7D11 /* SnapchatHaxTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75ED21860F9CC006C7D11 /* SnapchatHaxTests.m */; };
25 | FAF75EE118610DAE006C7D11 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAF75EE018610DAE006C7D11 /* Security.framework */; };
26 | FAF75EF61861205F006C7D11 /* SCAPIConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EEF1861205F006C7D11 /* SCAPIConfiguration.m */; };
27 | FAF75EF71861205F006C7D11 /* SCAPIRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EF11861205F006C7D11 /* SCAPIRequest.m */; };
28 | FAF75EF81861205F006C7D11 /* SCAPILogin.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EF31861205F006C7D11 /* SCAPILogin.m */; };
29 | FAF75EF91861205F006C7D11 /* SCAPISession.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EF51861205F006C7D11 /* SCAPISession.m */; };
30 | FAF75EFC18612069006C7D11 /* SCSnap.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EFB18612069006C7D11 /* SCSnap.m */; };
31 | FAF75EFF18612E91006C7D11 /* SCFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75EFE18612E91006C7D11 /* SCFetcher.m */; };
32 | FAF75F0D186241DA006C7D11 /* ANLoginVC.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75F0C186241DA006C7D11 /* ANLoginVC.m */; };
33 | FAF75F10186241F1006C7D11 /* ANSnapsVC.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75F0F186241F1006C7D11 /* ANSnapsVC.m */; };
34 | FAF75F1218624836006C7D11 /* ANLoginVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAF75F1118624836006C7D11 /* ANLoginVC.xib */; };
35 | FAF75F1818625274006C7D11 /* SCSnapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75F1718625274006C7D11 /* SCSnapManager.m */; };
36 | FAF75F1C1862591E006C7D11 /* ANSnapVC.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF75F1A1862591E006C7D11 /* ANSnapVC.m */; };
37 | FAF75F1D1862591E006C7D11 /* ANSnapVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAF75F1B1862591E006C7D11 /* ANSnapVC.xib */; };
38 | /* End PBXBuildFile section */
39 |
40 | /* Begin PBXContainerItemProxy section */
41 | FAF75ECA1860F9CC006C7D11 /* PBXContainerItemProxy */ = {
42 | isa = PBXContainerItemProxy;
43 | containerPortal = FAF75EA21860F9CC006C7D11 /* Project object */;
44 | proxyType = 1;
45 | remoteGlobalIDString = FAF75EA91860F9CC006C7D11;
46 | remoteInfo = SnapchatHax;
47 | };
48 | /* End PBXContainerItemProxy section */
49 |
50 | /* Begin PBXFileReference section */
51 | FAAF8BFA186289680049B692 /* SCBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCBlob.h; sourceTree = ""; };
52 | FAAF8BFB186289680049B692 /* SCBlob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCBlob.m; sourceTree = ""; };
53 | FAAF8BFC186289680049B692 /* SCImageBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCImageBlob.h; sourceTree = ""; };
54 | FAAF8BFD186289680049B692 /* SCImageBlob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCImageBlob.m; sourceTree = ""; };
55 | FAAF8BFE186289680049B692 /* SCVideoBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCVideoBlob.h; sourceTree = ""; };
56 | FAAF8BFF186289680049B692 /* SCVideoBlob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCVideoBlob.m; sourceTree = ""; };
57 | FAF75EAA1860F9CC006C7D11 /* SnapchatHax.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SnapchatHax.app; sourceTree = BUILT_PRODUCTS_DIR; };
58 | FAF75EAD1860F9CC006C7D11 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
59 | FAF75EAF1860F9CC006C7D11 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
60 | FAF75EB11860F9CC006C7D11 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
61 | FAF75EB51860F9CC006C7D11 /* SnapchatHax-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SnapchatHax-Info.plist"; sourceTree = ""; };
62 | FAF75EB71860F9CC006C7D11 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
63 | FAF75EB91860F9CC006C7D11 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
64 | FAF75EBB1860F9CC006C7D11 /* SnapchatHax-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SnapchatHax-Prefix.pch"; sourceTree = ""; };
65 | FAF75EBC1860F9CC006C7D11 /* ANAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ANAppDelegate.h; sourceTree = ""; };
66 | FAF75EBD1860F9CC006C7D11 /* ANAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ANAppDelegate.m; sourceTree = ""; };
67 | FAF75EBF1860F9CC006C7D11 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
68 | FAF75EC51860F9CC006C7D11 /* SnapchatHaxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SnapchatHaxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
69 | FAF75EC61860F9CC006C7D11 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
70 | FAF75ECE1860F9CC006C7D11 /* SnapchatHaxTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SnapchatHaxTests-Info.plist"; sourceTree = ""; };
71 | FAF75ED01860F9CC006C7D11 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
72 | FAF75ED21860F9CC006C7D11 /* SnapchatHaxTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SnapchatHaxTests.m; sourceTree = ""; };
73 | FAF75EE018610DAE006C7D11 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
74 | FAF75EEE1861205F006C7D11 /* SCAPIConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCAPIConfiguration.h; sourceTree = ""; };
75 | FAF75EEF1861205F006C7D11 /* SCAPIConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCAPIConfiguration.m; sourceTree = ""; };
76 | FAF75EF01861205F006C7D11 /* SCAPIRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCAPIRequest.h; sourceTree = ""; };
77 | FAF75EF11861205F006C7D11 /* SCAPIRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCAPIRequest.m; sourceTree = ""; };
78 | FAF75EF21861205F006C7D11 /* SCAPILogin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCAPILogin.h; sourceTree = ""; };
79 | FAF75EF31861205F006C7D11 /* SCAPILogin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCAPILogin.m; sourceTree = ""; };
80 | FAF75EF41861205F006C7D11 /* SCAPISession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCAPISession.h; sourceTree = ""; };
81 | FAF75EF51861205F006C7D11 /* SCAPISession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCAPISession.m; sourceTree = ""; };
82 | FAF75EFA18612069006C7D11 /* SCSnap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCSnap.h; sourceTree = ""; };
83 | FAF75EFB18612069006C7D11 /* SCSnap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCSnap.m; sourceTree = ""; };
84 | FAF75EFD18612E91006C7D11 /* SCFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCFetcher.h; sourceTree = ""; };
85 | FAF75EFE18612E91006C7D11 /* SCFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCFetcher.m; sourceTree = ""; };
86 | FAF75F0B186241DA006C7D11 /* ANLoginVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANLoginVC.h; sourceTree = ""; };
87 | FAF75F0C186241DA006C7D11 /* ANLoginVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANLoginVC.m; sourceTree = ""; };
88 | FAF75F0E186241F1006C7D11 /* ANSnapsVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANSnapsVC.h; sourceTree = ""; };
89 | FAF75F0F186241F1006C7D11 /* ANSnapsVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANSnapsVC.m; sourceTree = ""; };
90 | FAF75F1118624836006C7D11 /* ANLoginVC.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ANLoginVC.xib; sourceTree = ""; };
91 | FAF75F1618625274006C7D11 /* SCSnapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCSnapManager.h; sourceTree = ""; };
92 | FAF75F1718625274006C7D11 /* SCSnapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCSnapManager.m; sourceTree = ""; };
93 | FAF75F191862591E006C7D11 /* ANSnapVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANSnapVC.h; sourceTree = ""; };
94 | FAF75F1A1862591E006C7D11 /* ANSnapVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANSnapVC.m; sourceTree = ""; };
95 | FAF75F1B1862591E006C7D11 /* ANSnapVC.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ANSnapVC.xib; sourceTree = ""; };
96 | /* End PBXFileReference section */
97 |
98 | /* Begin PBXFrameworksBuildPhase section */
99 | FAF75EA71860F9CC006C7D11 /* Frameworks */ = {
100 | isa = PBXFrameworksBuildPhase;
101 | buildActionMask = 2147483647;
102 | files = (
103 | FAF75EE118610DAE006C7D11 /* Security.framework in Frameworks */,
104 | FAF75EB01860F9CC006C7D11 /* CoreGraphics.framework in Frameworks */,
105 | FAF75EB21860F9CC006C7D11 /* UIKit.framework in Frameworks */,
106 | FAF75EAE1860F9CC006C7D11 /* Foundation.framework in Frameworks */,
107 | );
108 | runOnlyForDeploymentPostprocessing = 0;
109 | };
110 | FAF75EC21860F9CC006C7D11 /* Frameworks */ = {
111 | isa = PBXFrameworksBuildPhase;
112 | buildActionMask = 2147483647;
113 | files = (
114 | FAF75EC71860F9CC006C7D11 /* XCTest.framework in Frameworks */,
115 | FAF75EC91860F9CC006C7D11 /* UIKit.framework in Frameworks */,
116 | FAF75EC81860F9CC006C7D11 /* Foundation.framework in Frameworks */,
117 | );
118 | runOnlyForDeploymentPostprocessing = 0;
119 | };
120 | /* End PBXFrameworksBuildPhase section */
121 |
122 | /* Begin PBXGroup section */
123 | FAAF8BF9186289680049B692 /* Blobs */ = {
124 | isa = PBXGroup;
125 | children = (
126 | FAAF8BFA186289680049B692 /* SCBlob.h */,
127 | FAAF8BFB186289680049B692 /* SCBlob.m */,
128 | FAAF8BFC186289680049B692 /* SCImageBlob.h */,
129 | FAAF8BFD186289680049B692 /* SCImageBlob.m */,
130 | FAAF8BFE186289680049B692 /* SCVideoBlob.h */,
131 | FAAF8BFF186289680049B692 /* SCVideoBlob.m */,
132 | );
133 | path = Blobs;
134 | sourceTree = "";
135 | };
136 | FAF75EA11860F9CC006C7D11 = {
137 | isa = PBXGroup;
138 | children = (
139 | FAF75EB31860F9CC006C7D11 /* SnapchatHax */,
140 | FAF75ECC1860F9CC006C7D11 /* SnapchatHaxTests */,
141 | FAF75EAC1860F9CC006C7D11 /* Frameworks */,
142 | FAF75EAB1860F9CC006C7D11 /* Products */,
143 | );
144 | sourceTree = "";
145 | };
146 | FAF75EAB1860F9CC006C7D11 /* Products */ = {
147 | isa = PBXGroup;
148 | children = (
149 | FAF75EAA1860F9CC006C7D11 /* SnapchatHax.app */,
150 | FAF75EC51860F9CC006C7D11 /* SnapchatHaxTests.xctest */,
151 | );
152 | name = Products;
153 | sourceTree = "";
154 | };
155 | FAF75EAC1860F9CC006C7D11 /* Frameworks */ = {
156 | isa = PBXGroup;
157 | children = (
158 | FAF75EE018610DAE006C7D11 /* Security.framework */,
159 | FAF75EAD1860F9CC006C7D11 /* Foundation.framework */,
160 | FAF75EAF1860F9CC006C7D11 /* CoreGraphics.framework */,
161 | FAF75EB11860F9CC006C7D11 /* UIKit.framework */,
162 | FAF75EC61860F9CC006C7D11 /* XCTest.framework */,
163 | );
164 | name = Frameworks;
165 | sourceTree = "";
166 | };
167 | FAF75EB31860F9CC006C7D11 /* SnapchatHax */ = {
168 | isa = PBXGroup;
169 | children = (
170 | FAF75EEB1861205F006C7D11 /* Snapchat */,
171 | FAF75EBC1860F9CC006C7D11 /* ANAppDelegate.h */,
172 | FAF75EBD1860F9CC006C7D11 /* ANAppDelegate.m */,
173 | FAF75F0B186241DA006C7D11 /* ANLoginVC.h */,
174 | FAF75F0C186241DA006C7D11 /* ANLoginVC.m */,
175 | FAF75F1118624836006C7D11 /* ANLoginVC.xib */,
176 | FAF75EBF1860F9CC006C7D11 /* Images.xcassets */,
177 | FAF75EB41860F9CC006C7D11 /* Supporting Files */,
178 | FAF75F0E186241F1006C7D11 /* ANSnapsVC.h */,
179 | FAF75F0F186241F1006C7D11 /* ANSnapsVC.m */,
180 | FAF75F191862591E006C7D11 /* ANSnapVC.h */,
181 | FAF75F1A1862591E006C7D11 /* ANSnapVC.m */,
182 | FAF75F1B1862591E006C7D11 /* ANSnapVC.xib */,
183 | );
184 | path = SnapchatHax;
185 | sourceTree = "";
186 | };
187 | FAF75EB41860F9CC006C7D11 /* Supporting Files */ = {
188 | isa = PBXGroup;
189 | children = (
190 | FAF75EB51860F9CC006C7D11 /* SnapchatHax-Info.plist */,
191 | FAF75EB61860F9CC006C7D11 /* InfoPlist.strings */,
192 | FAF75EB91860F9CC006C7D11 /* main.m */,
193 | FAF75EBB1860F9CC006C7D11 /* SnapchatHax-Prefix.pch */,
194 | );
195 | name = "Supporting Files";
196 | sourceTree = "";
197 | };
198 | FAF75ECC1860F9CC006C7D11 /* SnapchatHaxTests */ = {
199 | isa = PBXGroup;
200 | children = (
201 | FAF75ED21860F9CC006C7D11 /* SnapchatHaxTests.m */,
202 | FAF75ECD1860F9CC006C7D11 /* Supporting Files */,
203 | );
204 | path = SnapchatHaxTests;
205 | sourceTree = "";
206 | };
207 | FAF75ECD1860F9CC006C7D11 /* Supporting Files */ = {
208 | isa = PBXGroup;
209 | children = (
210 | FAF75ECE1860F9CC006C7D11 /* SnapchatHaxTests-Info.plist */,
211 | FAF75ECF1860F9CC006C7D11 /* InfoPlist.strings */,
212 | );
213 | name = "Supporting Files";
214 | sourceTree = "";
215 | };
216 | FAF75EEB1861205F006C7D11 /* Snapchat */ = {
217 | isa = PBXGroup;
218 | children = (
219 | FAF75F151862526C006C7D11 /* Managing */,
220 | FAF75EEC1861205F006C7D11 /* Data */,
221 | FAF75EED1861205F006C7D11 /* Internal */,
222 | FAF75EF21861205F006C7D11 /* SCAPILogin.h */,
223 | FAF75EF31861205F006C7D11 /* SCAPILogin.m */,
224 | FAF75EF41861205F006C7D11 /* SCAPISession.h */,
225 | FAF75EF51861205F006C7D11 /* SCAPISession.m */,
226 | FAF75EFD18612E91006C7D11 /* SCFetcher.h */,
227 | FAF75EFE18612E91006C7D11 /* SCFetcher.m */,
228 | );
229 | path = Snapchat;
230 | sourceTree = "";
231 | };
232 | FAF75EEC1861205F006C7D11 /* Data */ = {
233 | isa = PBXGroup;
234 | children = (
235 | FAAF8BF9186289680049B692 /* Blobs */,
236 | FAF75EFA18612069006C7D11 /* SCSnap.h */,
237 | FAF75EFB18612069006C7D11 /* SCSnap.m */,
238 | );
239 | path = Data;
240 | sourceTree = "";
241 | };
242 | FAF75EED1861205F006C7D11 /* Internal */ = {
243 | isa = PBXGroup;
244 | children = (
245 | FAF75EEE1861205F006C7D11 /* SCAPIConfiguration.h */,
246 | FAF75EEF1861205F006C7D11 /* SCAPIConfiguration.m */,
247 | FAF75EF01861205F006C7D11 /* SCAPIRequest.h */,
248 | FAF75EF11861205F006C7D11 /* SCAPIRequest.m */,
249 | );
250 | path = Internal;
251 | sourceTree = "";
252 | };
253 | FAF75F151862526C006C7D11 /* Managing */ = {
254 | isa = PBXGroup;
255 | children = (
256 | FAF75F1618625274006C7D11 /* SCSnapManager.h */,
257 | FAF75F1718625274006C7D11 /* SCSnapManager.m */,
258 | );
259 | path = Managing;
260 | sourceTree = "";
261 | };
262 | /* End PBXGroup section */
263 |
264 | /* Begin PBXNativeTarget section */
265 | FAF75EA91860F9CC006C7D11 /* SnapchatHax */ = {
266 | isa = PBXNativeTarget;
267 | buildConfigurationList = FAF75ED61860F9CC006C7D11 /* Build configuration list for PBXNativeTarget "SnapchatHax" */;
268 | buildPhases = (
269 | FAF75EA61860F9CC006C7D11 /* Sources */,
270 | FAF75EA71860F9CC006C7D11 /* Frameworks */,
271 | FAF75EA81860F9CC006C7D11 /* Resources */,
272 | );
273 | buildRules = (
274 | );
275 | dependencies = (
276 | );
277 | name = SnapchatHax;
278 | productName = SnapchatHax;
279 | productReference = FAF75EAA1860F9CC006C7D11 /* SnapchatHax.app */;
280 | productType = "com.apple.product-type.application";
281 | };
282 | FAF75EC41860F9CC006C7D11 /* SnapchatHaxTests */ = {
283 | isa = PBXNativeTarget;
284 | buildConfigurationList = FAF75ED91860F9CC006C7D11 /* Build configuration list for PBXNativeTarget "SnapchatHaxTests" */;
285 | buildPhases = (
286 | FAF75EC11860F9CC006C7D11 /* Sources */,
287 | FAF75EC21860F9CC006C7D11 /* Frameworks */,
288 | FAF75EC31860F9CC006C7D11 /* Resources */,
289 | );
290 | buildRules = (
291 | );
292 | dependencies = (
293 | FAF75ECB1860F9CC006C7D11 /* PBXTargetDependency */,
294 | );
295 | name = SnapchatHaxTests;
296 | productName = SnapchatHaxTests;
297 | productReference = FAF75EC51860F9CC006C7D11 /* SnapchatHaxTests.xctest */;
298 | productType = "com.apple.product-type.bundle.unit-test";
299 | };
300 | /* End PBXNativeTarget section */
301 |
302 | /* Begin PBXProject section */
303 | FAF75EA21860F9CC006C7D11 /* Project object */ = {
304 | isa = PBXProject;
305 | attributes = {
306 | CLASSPREFIX = AN;
307 | LastUpgradeCheck = 0500;
308 | ORGANIZATIONNAME = "Alex Nichol";
309 | TargetAttributes = {
310 | FAF75EC41860F9CC006C7D11 = {
311 | TestTargetID = FAF75EA91860F9CC006C7D11;
312 | };
313 | };
314 | };
315 | buildConfigurationList = FAF75EA51860F9CC006C7D11 /* Build configuration list for PBXProject "SnapchatHax" */;
316 | compatibilityVersion = "Xcode 3.2";
317 | developmentRegion = English;
318 | hasScannedForEncodings = 0;
319 | knownRegions = (
320 | en,
321 | );
322 | mainGroup = FAF75EA11860F9CC006C7D11;
323 | productRefGroup = FAF75EAB1860F9CC006C7D11 /* Products */;
324 | projectDirPath = "";
325 | projectRoot = "";
326 | targets = (
327 | FAF75EA91860F9CC006C7D11 /* SnapchatHax */,
328 | FAF75EC41860F9CC006C7D11 /* SnapchatHaxTests */,
329 | );
330 | };
331 | /* End PBXProject section */
332 |
333 | /* Begin PBXResourcesBuildPhase section */
334 | FAF75EA81860F9CC006C7D11 /* Resources */ = {
335 | isa = PBXResourcesBuildPhase;
336 | buildActionMask = 2147483647;
337 | files = (
338 | FAF75EB81860F9CC006C7D11 /* InfoPlist.strings in Resources */,
339 | FAF75EC01860F9CC006C7D11 /* Images.xcassets in Resources */,
340 | FAF75F1218624836006C7D11 /* ANLoginVC.xib in Resources */,
341 | FAF75F1D1862591E006C7D11 /* ANSnapVC.xib in Resources */,
342 | );
343 | runOnlyForDeploymentPostprocessing = 0;
344 | };
345 | FAF75EC31860F9CC006C7D11 /* Resources */ = {
346 | isa = PBXResourcesBuildPhase;
347 | buildActionMask = 2147483647;
348 | files = (
349 | FAF75ED11860F9CC006C7D11 /* InfoPlist.strings in Resources */,
350 | );
351 | runOnlyForDeploymentPostprocessing = 0;
352 | };
353 | /* End PBXResourcesBuildPhase section */
354 |
355 | /* Begin PBXSourcesBuildPhase section */
356 | FAF75EA61860F9CC006C7D11 /* Sources */ = {
357 | isa = PBXSourcesBuildPhase;
358 | buildActionMask = 2147483647;
359 | files = (
360 | FAAF8C02186289680049B692 /* SCVideoBlob.m in Sources */,
361 | FAF75EBA1860F9CC006C7D11 /* main.m in Sources */,
362 | FAF75EFC18612069006C7D11 /* SCSnap.m in Sources */,
363 | FAF75EBE1860F9CC006C7D11 /* ANAppDelegate.m in Sources */,
364 | FAF75F10186241F1006C7D11 /* ANSnapsVC.m in Sources */,
365 | FAF75EF81861205F006C7D11 /* SCAPILogin.m in Sources */,
366 | FAF75EF71861205F006C7D11 /* SCAPIRequest.m in Sources */,
367 | FAAF8C00186289680049B692 /* SCBlob.m in Sources */,
368 | FAF75EFF18612E91006C7D11 /* SCFetcher.m in Sources */,
369 | FAAF8C01186289680049B692 /* SCImageBlob.m in Sources */,
370 | FAF75F0D186241DA006C7D11 /* ANLoginVC.m in Sources */,
371 | FAF75EF61861205F006C7D11 /* SCAPIConfiguration.m in Sources */,
372 | FAF75F1C1862591E006C7D11 /* ANSnapVC.m in Sources */,
373 | FAF75F1818625274006C7D11 /* SCSnapManager.m in Sources */,
374 | FAF75EF91861205F006C7D11 /* SCAPISession.m in Sources */,
375 | );
376 | runOnlyForDeploymentPostprocessing = 0;
377 | };
378 | FAF75EC11860F9CC006C7D11 /* Sources */ = {
379 | isa = PBXSourcesBuildPhase;
380 | buildActionMask = 2147483647;
381 | files = (
382 | FAF75ED31860F9CC006C7D11 /* SnapchatHaxTests.m in Sources */,
383 | );
384 | runOnlyForDeploymentPostprocessing = 0;
385 | };
386 | /* End PBXSourcesBuildPhase section */
387 |
388 | /* Begin PBXTargetDependency section */
389 | FAF75ECB1860F9CC006C7D11 /* PBXTargetDependency */ = {
390 | isa = PBXTargetDependency;
391 | target = FAF75EA91860F9CC006C7D11 /* SnapchatHax */;
392 | targetProxy = FAF75ECA1860F9CC006C7D11 /* PBXContainerItemProxy */;
393 | };
394 | /* End PBXTargetDependency section */
395 |
396 | /* Begin PBXVariantGroup section */
397 | FAF75EB61860F9CC006C7D11 /* InfoPlist.strings */ = {
398 | isa = PBXVariantGroup;
399 | children = (
400 | FAF75EB71860F9CC006C7D11 /* en */,
401 | );
402 | name = InfoPlist.strings;
403 | sourceTree = "";
404 | };
405 | FAF75ECF1860F9CC006C7D11 /* InfoPlist.strings */ = {
406 | isa = PBXVariantGroup;
407 | children = (
408 | FAF75ED01860F9CC006C7D11 /* en */,
409 | );
410 | name = InfoPlist.strings;
411 | sourceTree = "";
412 | };
413 | /* End PBXVariantGroup section */
414 |
415 | /* Begin XCBuildConfiguration section */
416 | FAF75ED41860F9CC006C7D11 /* Debug */ = {
417 | isa = XCBuildConfiguration;
418 | buildSettings = {
419 | ALWAYS_SEARCH_USER_PATHS = NO;
420 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
422 | CLANG_CXX_LIBRARY = "libc++";
423 | CLANG_ENABLE_MODULES = YES;
424 | CLANG_ENABLE_OBJC_ARC = YES;
425 | CLANG_WARN_BOOL_CONVERSION = YES;
426 | CLANG_WARN_CONSTANT_CONVERSION = YES;
427 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
428 | CLANG_WARN_EMPTY_BODY = YES;
429 | CLANG_WARN_ENUM_CONVERSION = YES;
430 | CLANG_WARN_INT_CONVERSION = YES;
431 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
432 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
433 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
434 | COPY_PHASE_STRIP = NO;
435 | GCC_C_LANGUAGE_STANDARD = gnu99;
436 | GCC_DYNAMIC_NO_PIC = NO;
437 | GCC_OPTIMIZATION_LEVEL = 0;
438 | GCC_PREPROCESSOR_DEFINITIONS = (
439 | "DEBUG=1",
440 | "$(inherited)",
441 | );
442 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
443 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
444 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
445 | GCC_WARN_UNDECLARED_SELECTOR = YES;
446 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
447 | GCC_WARN_UNUSED_FUNCTION = YES;
448 | GCC_WARN_UNUSED_VARIABLE = YES;
449 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
450 | ONLY_ACTIVE_ARCH = YES;
451 | SDKROOT = iphoneos;
452 | };
453 | name = Debug;
454 | };
455 | FAF75ED51860F9CC006C7D11 /* Release */ = {
456 | isa = XCBuildConfiguration;
457 | buildSettings = {
458 | ALWAYS_SEARCH_USER_PATHS = NO;
459 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
460 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
461 | CLANG_CXX_LIBRARY = "libc++";
462 | CLANG_ENABLE_MODULES = YES;
463 | CLANG_ENABLE_OBJC_ARC = YES;
464 | CLANG_WARN_BOOL_CONVERSION = YES;
465 | CLANG_WARN_CONSTANT_CONVERSION = YES;
466 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
467 | CLANG_WARN_EMPTY_BODY = YES;
468 | CLANG_WARN_ENUM_CONVERSION = YES;
469 | CLANG_WARN_INT_CONVERSION = YES;
470 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
471 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
472 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
473 | COPY_PHASE_STRIP = YES;
474 | ENABLE_NS_ASSERTIONS = NO;
475 | GCC_C_LANGUAGE_STANDARD = gnu99;
476 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
477 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
478 | GCC_WARN_UNDECLARED_SELECTOR = YES;
479 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
480 | GCC_WARN_UNUSED_FUNCTION = YES;
481 | GCC_WARN_UNUSED_VARIABLE = YES;
482 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
483 | SDKROOT = iphoneos;
484 | VALIDATE_PRODUCT = YES;
485 | };
486 | name = Release;
487 | };
488 | FAF75ED71860F9CC006C7D11 /* Debug */ = {
489 | isa = XCBuildConfiguration;
490 | buildSettings = {
491 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
492 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
493 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
494 | GCC_PREFIX_HEADER = "SnapchatHax/SnapchatHax-Prefix.pch";
495 | INFOPLIST_FILE = "SnapchatHax/SnapchatHax-Info.plist";
496 | PRODUCT_NAME = "$(TARGET_NAME)";
497 | WRAPPER_EXTENSION = app;
498 | };
499 | name = Debug;
500 | };
501 | FAF75ED81860F9CC006C7D11 /* Release */ = {
502 | isa = XCBuildConfiguration;
503 | buildSettings = {
504 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
505 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
506 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
507 | GCC_PREFIX_HEADER = "SnapchatHax/SnapchatHax-Prefix.pch";
508 | INFOPLIST_FILE = "SnapchatHax/SnapchatHax-Info.plist";
509 | PRODUCT_NAME = "$(TARGET_NAME)";
510 | WRAPPER_EXTENSION = app;
511 | };
512 | name = Release;
513 | };
514 | FAF75EDA1860F9CC006C7D11 /* Debug */ = {
515 | isa = XCBuildConfiguration;
516 | buildSettings = {
517 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
518 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SnapchatHax.app/SnapchatHax";
519 | FRAMEWORK_SEARCH_PATHS = (
520 | "$(SDKROOT)/Developer/Library/Frameworks",
521 | "$(inherited)",
522 | "$(DEVELOPER_FRAMEWORKS_DIR)",
523 | );
524 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
525 | GCC_PREFIX_HEADER = "SnapchatHax/SnapchatHax-Prefix.pch";
526 | GCC_PREPROCESSOR_DEFINITIONS = (
527 | "DEBUG=1",
528 | "$(inherited)",
529 | );
530 | INFOPLIST_FILE = "SnapchatHaxTests/SnapchatHaxTests-Info.plist";
531 | PRODUCT_NAME = "$(TARGET_NAME)";
532 | TEST_HOST = "$(BUNDLE_LOADER)";
533 | WRAPPER_EXTENSION = xctest;
534 | };
535 | name = Debug;
536 | };
537 | FAF75EDB1860F9CC006C7D11 /* Release */ = {
538 | isa = XCBuildConfiguration;
539 | buildSettings = {
540 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
541 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SnapchatHax.app/SnapchatHax";
542 | FRAMEWORK_SEARCH_PATHS = (
543 | "$(SDKROOT)/Developer/Library/Frameworks",
544 | "$(inherited)",
545 | "$(DEVELOPER_FRAMEWORKS_DIR)",
546 | );
547 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
548 | GCC_PREFIX_HEADER = "SnapchatHax/SnapchatHax-Prefix.pch";
549 | INFOPLIST_FILE = "SnapchatHaxTests/SnapchatHaxTests-Info.plist";
550 | PRODUCT_NAME = "$(TARGET_NAME)";
551 | TEST_HOST = "$(BUNDLE_LOADER)";
552 | WRAPPER_EXTENSION = xctest;
553 | };
554 | name = Release;
555 | };
556 | /* End XCBuildConfiguration section */
557 |
558 | /* Begin XCConfigurationList section */
559 | FAF75EA51860F9CC006C7D11 /* Build configuration list for PBXProject "SnapchatHax" */ = {
560 | isa = XCConfigurationList;
561 | buildConfigurations = (
562 | FAF75ED41860F9CC006C7D11 /* Debug */,
563 | FAF75ED51860F9CC006C7D11 /* Release */,
564 | );
565 | defaultConfigurationIsVisible = 0;
566 | defaultConfigurationName = Release;
567 | };
568 | FAF75ED61860F9CC006C7D11 /* Build configuration list for PBXNativeTarget "SnapchatHax" */ = {
569 | isa = XCConfigurationList;
570 | buildConfigurations = (
571 | FAF75ED71860F9CC006C7D11 /* Debug */,
572 | FAF75ED81860F9CC006C7D11 /* Release */,
573 | );
574 | defaultConfigurationIsVisible = 0;
575 | defaultConfigurationName = Release;
576 | };
577 | FAF75ED91860F9CC006C7D11 /* Build configuration list for PBXNativeTarget "SnapchatHaxTests" */ = {
578 | isa = XCConfigurationList;
579 | buildConfigurations = (
580 | FAF75EDA1860F9CC006C7D11 /* Debug */,
581 | FAF75EDB1860F9CC006C7D11 /* Release */,
582 | );
583 | defaultConfigurationIsVisible = 0;
584 | defaultConfigurationName = Release;
585 | };
586 | /* End XCConfigurationList section */
587 | };
588 | rootObject = FAF75EA21860F9CC006C7D11 /* Project object */;
589 | }
590 |
--------------------------------------------------------------------------------