diff --git a/Students/Benny/1. OCMock+Faro/Lesson 1 - Objective-C Foundation via Mocks.md b/Students/Benny/1. OCMock+Faro/Lesson 1 - Objective-C Foundation via Mocks.md new file mode 100644 index 0000000..a43759f --- /dev/null +++ b/Students/Benny/1. OCMock+Faro/Lesson 1 - Objective-C Foundation via Mocks.md @@ -0,0 +1,140 @@ +# Lesson 1- Objective-C Foundation via Mocks +## Running into Objective-C from swift +As a funny intro to Objective-C checkout the following website +* http://fuckingblocksyntax.com +* http://fuckingclosuresyntax.com + +We will now have a look at: +* Functions (Methods) +* Pointers +* Unit testing +* Mocking +* Runtime +* Assigment + +## ​Method structure +![](Lesson%201%20-%20Objective-C%20Foundation%20via%20Mocks/screenshot.png) + +![](Lesson%201%20-%20Objective-C%20Foundation%20via%20Mocks/screenshot.png) + + +### Pointers VS Value type + +Dit is in Swift veel beter gedefinieerd. In Objective-C mag alles! + +#### Array’s +Best om dit te begrijpen is met een voorbeeld in array + +```swift +let array: [String] = ["string"] +``` + +```objective-c +NSArray* array; //je moet het geen waarde geven +array = @[@"string"]; +``` + +**In Objective-C kan je alles mixen in een array** +```objective-c +NSArray* array; //je moet het geen waarde geven +Foo* foo= [[Foo alloc] init]; +array = @[@"string", 12, foo] +``` + +Dit zou in swift in een Any array kunnen: + +```swift +let array: [Any] = ["string", 12] +``` + +##### Mutability +Arrays manipuleren maakt duidelijk dat er een verschil is tussen objective-C en swift + +In objective-C heb je van veel classes een mutable tegenhanger +* NSMutableArray & NSArray +* NSMutableURlRequest * NSURLRequest + +In swift is dit opgelost met `let` & `var` + +##### Objective-C meets swift +Je kan ook in Objective-C dezelfde type safety gaan opzoeken als in Swift. Daarvoor is er vorig jaar aan Objective-C een soort [Leight Weigth Generics](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-ID173) toegevoegd. + +```Objective-C +NSArray * array = @[@"string"] +``` + +Nu kan er in een array enkel een string *steken* + +### Instantiation and now finally about pointers and value types +![](Lesson%201%20-%20Objective-C%20Foundation%20via%20Mocks/screenshot.png) + +Zoals gezegd is objective-C een oude taal. Dus gaat zij er vanuit dat je alles begrijpt over memory. +* Plaats maken voor iets = *alloceren* +* Plaats opvullen met iets = *instantieren* + +Ook is code opgedeeld in 2 files +* Hetgeen de buitenwereld moet weten om aan de code te kunnen + +Om iets aan te maken als `Foo` heb je dus twee stappen nodig +```Objective-c +// in een file met extensie .h +@interface Foo: NSObject +// alles hierin is publiek +@end + +// Als je toch private dingen wil hebben zet je die in dezelfde file + +@interface Foo() // de haken zijn nodig maar magisch +@end +// Eventueel in tweede file +@implementation Foo + +@end +``` + +![](Lesson%201%20-%20Objective-C%20Foundation%20via%20Mocks/screenshot.png) + +![](Lesson%201%20-%20Objective-C%20Foundation%20via%20Mocks/screenshot.png) + +Objective-C is veel dynamischer als Swift. Het heeft namelijk een runtime die bepaald hoe de code gaat werken. Dit is belangrijk voor Unit testing!!! + +* Swift: -> Hoe de code gaat ‘draaien’ wordt bepaald wanneer je compileerd +* Objective-C: -> de basis wordt opgezet maar tijdens het doorlopen van het programma kunnen er *alternatieve* paden aangebracht worden. Of anders de beslissing over welk code path er gevolgd zal worden wordt ad runtime gedaan. + +# Uitdaging: Gebruiken bij unit testen +Om dit beter te begrijpen is het gemakkelijkste dat we unit testen beginnen schrijven. + +[OCMOCK](http://ocmock.org/introduction/) is een framework dat je toe laat met de RunTime te spelen. Dit kan je ook *Dependency Injection* noemen als je graag hebt dat mensen je niet snappen en slim vinden. + +## Opdracht +* Maak objective-C project +* Maak een unit test target +* `pod init` +* voeg OCMock toe via `pod 'OCMock', '~> 3.4’` +* voeg Quick en Nimble toe +* doe pod project open en verander voor Quick en Nimble de `Us legacy Swift` naar __NO__ + +Wat ga je maken: +1. TableView die labels vult vanaf een viewModel +2. ViewModel ga je testen op basis van OCMock en OCMSTub [Stubbing](http://ocmock.org/reference/#stubing-methods) [Mock Objects](http://ocmock.org/reference/#creating-mock-objects) +3. Toon het aantal cellen vanaf het viewModel + +Uitbreiding: +1. Voeg Faro toe +2. Maak een Mock van Faro +3. Doe een `gemockte` service call + +# Links +* We hebben een account bij code-school: https://www.codeschool.com/courses/try-objective-c +* We hebben een account op Ray Wenderlich: https://videos.raywenderlich.com + + + + + + + + + + + diff --git a/Students/Benny/2. Object Oriented C/Lesson 2: How Apple teaches Objective-C.md b/Students/Benny/2. Object Oriented C/Lesson 2: How Apple teaches Objective-C.md new file mode 100644 index 0000000..a654517 --- /dev/null +++ b/Students/Benny/2. Object Oriented C/Lesson 2: How Apple teaches Objective-C.md @@ -0,0 +1,319 @@ +# Lesson 2: How Apple teaches Objective-C +* [WWDC 2012 video 405](https://developer.apple.com/videos/play/wwdc2012/405/) +* [Apple Conceptual intro to objective-C](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html) + +--- + +## As a preparation for this lesson you can do: +1. Google drive SDK voor objective-C opzoeken +2. . Lottie van AirBnb opzoeken en beschikbaar voor Objective-C +3. Plannetje op papier hoe je de app zou bouwen +4. Lijstje maken met dingen die je in Swift doet en hoe je die zou doen in objective-c + +--- + +# WWDC video +session_405__modern_objectivec.pdf + +![](Lesson%202:%20How%20Apple%20teaches%20Objective-C/screenshot.png) + +* Object-Oriented C +* Retain and Release +* Properties +* Blocks +* ARC + +--- + +## Method ordering +Before you had to put the method implementation or declaration before you use it. This is no longer needed. + +```objectivec +@interface SongPlayer : NSObject - (void)playSong:(Song *)song; @end @implementation SongPlayer - (void)playSong:(Song *)song { NSError *error; + //In Old objective-C you would have to put this in the header or class extension [self startAudio:&error]; ... } - (void)startAudio:(NSError **)error { ... } @end +``` +--- + +Whats is a class extension? + +When you write __()__ it is a class extension. + +```objectivec +@interface SongPlayer () - (void)startAudio:(NSError **)error; @end + +``` +--- + +### Special error + +```objectivec +NSError* error; + +[self startAudio: &error]; + +if (error != nil) { + // handle error +} + +``` +--- + +## Enum with explicit types + +```objectivec +enum { NSNumberFormatterNoStyle, NSNumberFormatterDecimalStyle, NSNumberFormatterCurrencyStyle, NSNumberFormatterPercentStyle, NSNumberFormatterScientificStyle, NSNumberFormatterSpellOutStyle }; typedef NSUInteger NSNumberFormatterStyle; +``` +--- + +Ok but butter to + +```objectivec +typedef enum NSNumberFormatterStyle : NSUInteger { NSNumberFormatterNoStyle, NSNumberFormatterDecimalStyle, NSNumberFormatterCurrencyStyle, NSNumberFormatterPercentStyle, NSNumberFormatterScientificStyle, NSNumberFormatterSpellOutStyle } NSNumberFormatterStyle; +``` +--- + +## Because then you have Strong type checking + +You can use them easily in switches: + +```objectivec + switch (style) { case NSNumberFormatterNoStyle: break; case NSNumberFormatterSpellOutStyle: break; +} +``` + +--- + +# Synthesize +We talked already about properties and their need for setters and getters: +Always write as less as possible: + +```objectivec +@interface Person : NSObject @property(strong) NSString *name; @end @implementation Person @end +``` + +--- + +__But__!! for Core Data this is different! +### Core Data Synthesize + +```objectivec +@interface Person : NSManagedObject @property(strong) NSString *name; @end @implementation Person +@dynamic name; @end +``` + +--- + +# Literals +## Single Literals +### Old NSNumber + +```objectivec +NSNumber *value; value = [NSNumber numberWithChar:'X']; value = [NSNumber numberWithInt:12345]; value = [NSNumber numberWithUnsignedLong:12345ul]; value = [NSNumber numberWithLongLong:12345ll]; value = [NSNumber numberWithFloat:123.45f]; value = [NSNumber numberWithDouble:123.45]; value = [NSNumber numberWithBool:YES]; +``` + +--- + +### Much better +```objectivec +NSNumber *value; value = @'X'; value = @12345; value = @12345ul; value = @12345ll; value = @123.45f; value = @123.45; value = @YES; +``` + +--- + +Also a calculation result can be boxed into an NSNumber + +```objectivec + +NSNumber *piOverSixteen = @( M_PI / 16 ); + +``` + +--- + +## Collection Literals +### OLD Array creation + +```objectivec +NSArray *array; array = [NSArray array]; array = [NSArray arrayWithObject:a]; array = [NSArray arrayWithObjects:a, b, c, nil]; id objects[] = { a, b, c }; NSUInteger count = sizeof(objects) / sizeof(id); array = [NSArray arrayWithObjects:objects count:count]; +``` +--- + +### New Array creation + +```objectivec +NSArray *array; array = @[]; array = @[ a ]; array = @[ a, b, c ]; array = @[ a, b, c ]; +``` + +--- + +### Old Dictionary creation + +```objectivec + NSDictionary *dict; dict = [NSDictionary dictionary]; dict = [NSDictionary dictionaryWithObject:o1 forKey:k1]; dict = [NSDictionary dictionaryWithObjectsAndKeys: o1, k1, o2, k2, o3, k3, nil]; id objects[] = { o1, o2, o3 }; id keys[] = { k1, k2, k3 }; NSUInteger count = sizeof(objects) / sizeof(id); dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:count]; +``` +--- + +## New Dictionary creation + +```objectivec +NSDictionary *dict; dict = @{}; dict = @{ k1 : o1 }; dict = @{ k1 : o1, k2 : o2, k3 : o3 }; +``` +--- + +### Mutable Collections +Use `-mutableCopy` + +```objectivec + +NSMutableArray *array = [@[1,2] mutableCopy]; + +``` + +Then you can do: + +```objectivec + +[array append: 3]; + +``` + +--- + +## Constant Containers + +```objectivec +// Will give an error +static NSArray * thePlanets = @[ @"Mercury", @"Venus", @"Earth", @"Mars", @"Jupiter", @"Saturn", @"Uranus", @"Neptune" ]; +``` + +--- + +### Use `+initialize` + +```objectivec + @implementation MyClass static NSArray *thePlanets; + (void)initialize { if (self == [MyClass class]) { thePlanets = @[ @"Mercury", @"Venus", @"Earth", @"Mars", @"Jupiter", @"Saturn", @"Uranus", @"Neptune" ]; } +} +``` + +--- + +This does __NOT__ work for Dictionaries because of compiler optimalizations [See WWDC 2012 video 405](https://developer.apple.com/videos/play/wwdc2012/405/) + +--- + +## Subscripting and object literals, boxed expressions + +With dictionaries and arrays you can do: + +__Array__ + +```objectivec +NSArray* array = @[@1,@2]; +NSLog(@"%@", array[1]) // will print 2 +``` +__Dictionary__ + +```objectivec +NSDictionary* dict = @{"first": @1, "second": @2} +NSLog(@"%@", dict[@"second"]) // will print 2 +``` + +--- + +# !! You can make your class _Subscriptable_ +[See WWDC 2012 video 405](https://developer.apple.com/videos/play/wwdc2012/405/) + +--- + +# ARC: Automatic Reference Counting +In Objective-C __AND__ Swift you have the __SAME__ memory management!!!! +Swift is no better at handling memory then Objective-C, it just has some language features like @escaping and the use of self to help you. + +--- + +## How to make a memory leak? + +```objectivec + +@interface Foo () +@property (nonatomic, strong) Service* service; +@property (nonatomic, strong) Model* model; +@end + +@implementation + +- (void) load { + self.service = [[Service alloc] init]; + [self.service perform: ^ {(Model* model) in + self.model = model // this is a leak + }]; +} +@end +``` +--- + +possible solution 1: + +```objectivec + +@interface Foo () +@property (nonatomic, strong) Service* service; +@property (nonatomic, strong) ViewModel* viewModel; +@end + +@implementation + +- (void) load { + self.service = [[Service alloc] init]; + ViewModel* viewModel = self.viewModel; // viewModel retaincount +1 + [self.service perform: ^ {(Model* model) in // viewModel retaincount +1 = 2 + viewModel.model = model // this is NO leak + // viewModel retaincount -1 [viewModel release]; + }]; + // viewModel retaincount -1 +} +@end +``` + +--- + +### How to fix it? + +```objectivec + +@interface Foo () +@property (nonatomic, strong) Service* service; +@property (nonatomic, strong) Model* model; +@end + +@implementation + +- (void) load { + self.service = [[Service alloc] init]; + __weak Foo* weakSelf = self; + [self.service perform: ^ {(Model* model) in + weakSelf.model = model; // this is not a leak + }]; +} +@end + +``` +--- + +# When you use see memory management becomes more __difficult__ +> [See WWDC 2012 video 405](https://developer.apple.com/videos/play/wwdc2012/405/) + +--- +It bowls down to using stuff like: + +```objectivec +NSArray *people = CFBridgingRelease( ABAddressBookCopyPeopleWithName(addressBook,CFSTR("Appleseed"))); +``` +--- + +# Summary + +• `@synthesize` by default • Forward declarations optional +• Fixed underlying type enums • Literals and subscripting +• Boxed expressions +• GC is deprecated diff --git a/Students/Benny/3. Protocols and bridging/Images/Keychain.png b/Students/Benny/3. Protocols and bridging/Images/Keychain.png new file mode 100644 index 0000000..8fdfa43 Binary files /dev/null and b/Students/Benny/3. Protocols and bridging/Images/Keychain.png differ diff --git a/Students/Benny/3. Protocols and bridging/Lesson 3: Protocols and Bridging.md b/Students/Benny/3. Protocols and bridging/Lesson 3: Protocols and Bridging.md new file mode 100644 index 0000000..0f6b41b --- /dev/null +++ b/Students/Benny/3. Protocols and bridging/Lesson 3: Protocols and Bridging.md @@ -0,0 +1,536 @@ +# Lesson 3: Protocols and Bridging +1. Protocols: Why use Introspection +2. Casting +3. Common patterns that are discouraged in Swift but used in Objective-C +4. Bridging between objective-C And Swift +5. How imports work and how are they different for Swift. + 1. Difference from Swift + 2. Header import + 3. Framework Header import + 4. (New) Modular import + +#Programming/objective-c #Programmig/objective-c/Protocols #Programmig/objective-c/Introspection +#Programming/Objective-C/Modules + +This lesson was deducted while building open-source app [LottyDropper](https://github.com/icapps/ios_lotty_dropper) + +- - - - + +## Protocols: Why use Introspection +You can put them in separate header files: +```objective-c +@protocol DropboxLoginable + +@end +``` + +Be sure to import them when using + +```objective-c +#import +#import "DropboxLoginable.h" + +@interface ViewController : UIViewController + +@end +``` + +### Introspection +See if an object implements a protocol, or a method in a protocol. + +```objective-c +if ([self.window.rootViewController isKindOfClass:[UINavigationController class]]) { + UINavigationController * nav = (UINavigationController *) self.window.rootViewController; + if ([[nav.topViewController class] conformsToProtocol:@protocol(DropboxLoginable)]) { + [nav.topViewController performSelector:@selector(proceed)]; + } + } +``` + +`[nav.topViewController performSelector:@selector(proceed)];` the performSelector is something common in objective-c. This is done actually to *trick* the compiler. You can put in any selector and *@runtime* the special Objective-C runtime will try to look for **compiled code** to execute on the **target**. In the example above the target is `nav.topViewController` +#### Target: What is that? +A `target` is the object receiving messages. You know it from `@IBAction`. If you want to know more and understand the *magic* behind all of this [NSRunloop Apple docs](https://developer.apple.com/reference/foundation/nsrunloop?language=objc). But the main usefull points are: +1. [performSelector:target:argument:order:modes: - NSRunLoop | Apple Developer Documentation](https://developer.apple.com/reference/foundation/nsrunloop/1409310-performselector?language=objc) +```objective-c +if ([target canPerfromSelector:@selector(proceed)]) { + // Do something +} +``` +2. Use it to *bind* buttons to code +3. Use it on an array to perform a selector on any object in the array +```objective-c +NSArray *newArray = [[NSArray alloc] initWithArray:oldArray copyItems:YES]; +[newArray makeObjectsPerformSelector:@selector(doSomethingToObject)]; +``` +4. [performSelector:withObject:afterDelay:inModes: - NSObject | Apple Developer Documentation](https://developer.apple.com/reference/objectivec/nsobject/1415652-performselector) Use it for delayed actions +```objective-c +[self performSelector:@selector(doSomethingToObject) + withObject:foo + afterDelay:15.0]; +``` +- - - - + +## Casting +Casting is more implicit then it is in Swift. Why? +1. You have something like `id` that can be casted to anything, without the need to explicitly cast +```objective-c +id someObject = [NSMutableArray new]; // you don't need to cast id explicitly +``` +2. Casting from an `int` to a `float` will work but you loose precision +```objective-c +int i = (int)19.5f; // (precision is lost) +``` + +## Common patterns that are discouraged in Swift but used in Objective-C +### Perform selector +It is very common to use this. Evan if it is dangerous because if the `target` does not implement the selector your app will crash. You use it mainly to see if an optional method from a protocol is implemented +### Casting from Array elements +GIVEN: You have an array of stuff could have all kinds of types +THEN: You loop trough the array +EXPECTED: You inspect every element if it is a kind of type. If it is the type you expect you perform an action +```objective-c + +for (object in objectArray) { + if ([object isKindOfClass: [Foo class]) { + // Do specific action for Foo + } else if ([object isKindOfClass: [Bar class]]){ + // Do something with a Bar. + } +} +``` +## Side node understand MVC Better. +I noticed in projects we do that MVC is used but not understand. In Dutch some notes and tips are given [Side note: MVC](bear://x-callback-url/open-note?id=E8982FEC-1725-4478-A6D4-661813D8BD26-6928-0000133C018EA631) + +## Bridging between objective-C And Swift +### Why should we bridge? +Bridging add’s an extra layer of complexity over a project. But you can have good reason to do so. Here are a few of my favourites: + +1. Use a TOP Swift only library/Framework/Pod/… +2. Be more future prove. + +### Example: Using the keychain +Using the keychain has always been a hassle. @iCapps we build a handle Swift framework [Stella](https://github.com/icapps/ios-stella) that handles this nicely. Say for instance you want to store access tokens. + +Using Objective-C only you would have to +> [Apple reference on keychain](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html) + +--- +**Personal notes: Keychain** + +**Basic Keychain Services functions** +* Add an item to a keychain +* Find an item in a keychain +* Get the attributes and data in a keychain item +* Change attributes and data in a keychain item + +![](Images/Keychain.png) + +``` +In iOS, Keychain rights depend on the provisioning profile used to sign your application. Be sure to consistently use the same provisioning profile across different versions of your application. +``` +--- + +```objective-c +#import +#import + +//Define an Objective-C wrapper class to hold Keychain Services code. +@interface KeychainWrapper : NSObject { + NSMutableDictionary *keychainData; + NSMutableDictionary *genericPasswordQuery; +} + +@property (nonatomic, strong) NSMutableDictionary *keychainData; +@property (nonatomic, strong) NSMutableDictionary *genericPasswordQuery; + +- (void)mySetObject:(id)inObject forKey:(id)key; +- (id)myObjectForKey:(id)key; +- (void)resetKeychainItem; + +@end +/* ********************************************************************** */ +//Unique string used to identify the keychain item: +static const UInt8 kKeychainItemIdentifier[] = "com.apple.dts.KeychainUI\0"; + +@interface KeychainWrapper (PrivateMethods) + + +//The following two methods translate dictionaries between the format used by +// the view controller (NSString *) and the Keychain Services API: +- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert; +- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert; +// Method used to write data to the keychain: +- (void)writeToKeychain; + +@end + +@implementation KeychainWrapper + +//Synthesize the getter and setter: +@synthesize keychainData, genericPasswordQuery; + +- (id)init +{ + if ((self = [super init])) { + + OSStatus keychainErr = noErr; + // Set up the keychain search dictionary: + genericPasswordQuery = [[NSMutableDictionary alloc] init]; + // This keychain item is a generic password. + [genericPasswordQuery setObject:(__bridge id)kSecClassGenericPassword + forKey:(__bridge id)kSecClass]; + // The kSecAttrGeneric attribute is used to store a unique string that is used + // to easily identify and find this keychain item. The string is first + // converted to an NSData object: + NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier + length:strlen((const char *)kKeychainItemIdentifier)]; + [genericPasswordQuery setObject:keychainItemID forKey:(__bridge id)kSecAttrGeneric]; + // Return the attributes of the first match only: + [genericPasswordQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + // Return the attributes of the keychain item (the password is + // acquired in the secItemFormatToDictionary: method): + [genericPasswordQuery setObject:(__bridge id)kCFBooleanTrue + forKey:(__bridge id)kSecReturnAttributes]; + + //Initialize the dictionary used to hold return data from the keychain: + CFMutableDictionaryRef outDictionary = nil; + // If the keychain item exists, return the attributes of the item: + keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, + (CFTypeRef *)&outDictionary); + if (keychainErr == noErr) { + // Convert the data dictionary into the format used by the view controller: + self.keychainData = [self secItemFormatToDictionary:(__bridge_transfer NSMutableDictionary *)outDictionary]; + } else if (keychainErr == errSecItemNotFound) { + // Put default values into the keychain if no matching + // keychain item is found: + [self resetKeychainItem]; + if (outDictionary) CFRelease(outDictionary); + } else { + // Any other error is unexpected. + NSAssert(NO, @"Serious error.\n"); + if (outDictionary) CFRelease(outDictionary); + } + } + return self; +} + +// Implement the mySetObject:forKey method, which writes attributes to the keychain: +- (void)mySetObject:(id)inObject forKey:(id)key +{ + if (inObject == nil) return; + id currentObject = [keychainData objectForKey:key]; + if (![currentObject isEqual:inObject]) + { + [keychainData setObject:inObject forKey:key]; + [self writeToKeychain]; + } +} + +// Implement the myObjectForKey: method, which reads an attribute value from a dictionary: +- (id)myObjectForKey:(id)key +{ + return [keychainData objectForKey:key]; +} + +// Reset the values in the keychain item, or create a new item if it +// doesn't already exist: + +- (void)resetKeychainItem +{ + if (!keychainData) //Allocate the keychainData dictionary if it doesn't exist yet. + { + self.keychainData = [[NSMutableDictionary alloc] init]; + } + else if (keychainData) + { + // Format the data in the keychainData dictionary into the format needed for a query + // and put it into tmpDictionary: + NSMutableDictionary *tmpDictionary = + [self dictionaryToSecItemFormat:keychainData]; + // Delete the keychain item in preparation for resetting the values: + OSStatus errorcode = SecItemDelete((__bridge CFDictionaryRef)tmpDictionary); + NSAssert(errorcode == noErr, @"Problem deleting current keychain item." ); + } + + // Default generic data for Keychain Item: + [keychainData setObject:@"Item label" forKey:(__bridge id)kSecAttrLabel]; + [keychainData setObject:@"Item description" forKey:(__bridge id)kSecAttrDescription]; + [keychainData setObject:@"Account" forKey:(__bridge id)kSecAttrAccount]; + [keychainData setObject:@"Service" forKey:(__bridge id)kSecAttrService]; + [keychainData setObject:@"Your comment here." forKey:(__bridge id)kSecAttrComment]; + [keychainData setObject:@"password" forKey:(__bridge id)kSecValueData]; +} + +// Implement the dictionaryToSecItemFormat: method, which takes the attributes that +// you want to add to the keychain item and sets up a dictionary in the format +// needed by Keychain Services: +- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert +{ + // This method must be called with a properly populated dictionary + // containing all the right key/value pairs for a keychain item search. + + // Create the return dictionary: + NSMutableDictionary *returnDictionary = + [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert]; + + // Add the keychain item class and the generic attribute: + NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier + length:strlen((const char *)kKeychainItemIdentifier)]; + [returnDictionary setObject:keychainItemID forKey:(__bridge id)kSecAttrGeneric]; + [returnDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + + // Convert the password NSString to NSData to fit the API paradigm: + NSString *passwordString = [dictionaryToConvert objectForKey:(__bridge id)kSecValueData]; + [returnDictionary setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding] + forKey:(__bridge id)kSecValueData]; + return returnDictionary; +} + +// Implement the secItemFormatToDictionary: method, which takes the attribute dictionary +// obtained from the keychain item, acquires the password from the keychain, and +// adds it to the attribute dictionary: +- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert +{ + // This method must be called with a properly populated dictionary + // containing all the right key/value pairs for the keychain item. + + // Create a return dictionary populated with the attributes: + NSMutableDictionary *returnDictionary = [NSMutableDictionary + dictionaryWithDictionary:dictionaryToConvert]; + + // To acquire the password data from the keychain item, + // first add the search key and class attribute required to obtain the password: + [returnDictionary setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; + [returnDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + // Then call Keychain Services to get the password: + CFDataRef passwordData = NULL; + OSStatus keychainError = noErr; // + keychainError = SecItemCopyMatching((__bridge CFDictionaryRef)returnDictionary, + (CFTypeRef *)&passwordData); + if (keychainError == noErr) + { + // Remove the kSecReturnData key; we don't need it anymore: + [returnDictionary removeObjectForKey:(__bridge id)kSecReturnData]; + + // Convert the password to an NSString and add it to the return dictionary: + NSString *password = [[NSString alloc] initWithBytes:[(__bridge_transfer NSData *)passwordData bytes] + length:[(__bridge NSData *)passwordData length] encoding:NSUTF8StringEncoding]; + [returnDictionary setObject:password forKey:(__bridge id)kSecValueData]; + } + // Don't do anything if nothing is found. + else if (keychainError == errSecItemNotFound) { + NSAssert(NO, @"Nothing was found in the keychain.\n"); + if (passwordData) CFRelease(passwordData); + } + // Any other error is unexpected. + else + { + NSAssert(NO, @"Serious error.\n"); + if (passwordData) CFRelease(passwordData); + } + + return returnDictionary; +} + +// Implement the writeToKeychain method, which is called by the mySetObject routine, +// which in turn is called by the UI when there is new data for the keychain. This +// method modifies an existing keychain item, or--if the item does not already +// exist--creates a new keychain item with the new attribute value plus +// default values for the other attributes. +- (void)writeToKeychain +{ + CFDictionaryRef attributes = nil; + NSMutableDictionary *updateItem = nil; + + // If the keychain item already exists, modify it: + if (SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, + (CFTypeRef *)&attributes) == noErr) + { + // First, get the attributes returned from the keychain and add them to the + // dictionary that controls the update: + updateItem = [NSMutableDictionary dictionaryWithDictionary:(__bridge_transfer NSDictionary *)attributes]; + + // Second, get the class value from the generic password query dictionary and + // add it to the updateItem dictionary: + [updateItem setObject:[genericPasswordQuery objectForKey:(__bridge id)kSecClass] + forKey:(__bridge id)kSecClass]; + + // Finally, set up the dictionary that contains new values for the attributes: + NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainData]; + //Remove the class--it's not a keychain attribute: + [tempCheck removeObjectForKey:(__bridge id)kSecClass]; + + // You can update only a single keychain item at a time. + OSStatus errorcode = SecItemUpdate( + (__bridge CFDictionaryRef)updateItem, + (__bridge CFDictionaryRef)tempCheck); + NSAssert(errorcode == noErr, @"Couldn't update the Keychain Item." ); + } + else + { + // No previous item found; add the new item. + // The new value was added to the keychainData dictionary in the mySetObject routine, + // and the other values were added to the keychainData dictionary previously. + // No pointer to the newly-added items is needed, so pass NULL for the second parameter: + OSStatus errorcode = SecItemAdd( + (__bridge CFDictionaryRef)[self dictionaryToSecItemFormat:keychainData], + NULL); + NSAssert(errorcode == noErr, @"Couldn't add the Keychain Item." ); + if (attributes) CFRelease(attributes); + } +} + + +@end +``` + +### Using Stella + +Like in the above example we write a `Wrapper` to access keychain data +```swift +import Foundation +import Stella + +extension Keys { + static let dropBoxAccessToken = Key("dropBoxAccessToken") + static let dropBoxAccessTokenUID = Key("dropBoxAccessTokenUID") +} + +class LottieDropperKeyChainBridge: NSObject { + static let shared = LottieDropperKeyChainBridge() + + var dropBoxAccessToken: DBAccessToken? { + get { + guard let token = Keychain[.dropBoxAccessToken], let uid = Keychain[.dropBoxAccessTokenUID] else { + return nil + } + return DBAccessToken(accessToken: token , uid:uid) + } + + set { + Keychain[.dropBoxAccessToken] = newValue?.accessToken + Keychain[.dropBoxAccessTokenUID] = newValue?.uid + + } + } + +} +``` + +Now that this is done in `Objective-C` we can write: + +```objective-c + LottieDropperKeyChainBridge.shared.dropBoxAccessToken = authResult.accessToken; +``` + +### Conclusion +Writing secure code should be easy. Not having to write complex Keychain code is one of that reasons. This is why bridging to Swift is allowed in this case. +- - - - +## How imports work and how are they different for Swift. +1. [Modules and Precompiled Headers](https://useyourloaf.com/blog/modules-and-precompiled-headers/) Very good comparison between old and new +2. [Modules — Clang 5 documentation](https://clang.llvm.org/docs/Modules.html#objective-c-import-declaration) Full explanation about what a module is and what its advantages are. + +**Personal notes: Modules** +### Modules +* Loads a standalone precompiled version of the framework +* Automatically takes care of linking to the module (no need to manually add the framework) + +### Using Modules +* Settings (Enable Modules & Link Frameworks Automatically) are default YES + +```Objective-C +@import UIKit; +``` +--- + +### Difference from Swift +In swift you do not import Headers. Swift imports modules +> **Objective-C** has no namespace!. A namespace is a part of the compiled code where your `Symbols` are uniquely named. +*So what is a Symbol* +> A `Symbol` is a reference the compiler uses to find the binary reference of your code. +```objective-c +@interfase UIViewController +@end + +// Inside the UIKit framework a viewcontroller exists. This would not compile! +``` + +Compiler keeps track of names of classes: +* `UIViewController` +* `Foo` + +```swift + +// We are inside module Lesson +import UIKit +class UIViewController { +} + +// This will compile +``` + +* `Lesson.UIViewController` +* `Lesson.Foo` + +This is why in Objective-C importing is more important. And you should also be more careful with imports. More detailed info can be found in the link [4 Ways Precompiled Headers Cripple Your Code](http://qualitycoding.org/precompiled-header/). But in general: + +1. Only import the stuff you **need!** +2. **Clean up** imports if you do not use the files any more +Kind of imports in Objective-C: +> The `#import` directive used by Objective-C is almost identical to the classic `#include` mechanism it inherited from the C programming language. The only difference is that it makes sure the same file is never included more than once. + +```objective-c +#import "Foo.h" // A file you own and is in your project +#import // A file inside a framework/module +// If this framework is a module you can write +@import UIKit +``` + +The `@import UIKit` is preferred for 2 reasons: +1. More modern +2. Modules are precompiled and the compiler does some optimisations so compile time is better + +#### How to use modules +> Opting into using modules is as easy as setting the Apple LLVM 6.0 - Language - Modules Xcode build settings: + +[Modules and Precompiled Headers](https://useyourloaf.com/blog/modules-and-precompiled-headers/) + +### Prefix header +A prefix header is **something of the past** and you should avoid using it! But you can encounter it in projects. So what is it? + +It is a file ending with `.pch` and usually starts with the project name. You let the compiler know this file exists via the build settings. +In this file you write imports that the compiler will add to every file in your project. +## @class? why use that? +As you make files, header and implementation files the number of imports in the header can become long. Plus you also might import things you do not know. Sometimes this goes wrong! + +```objective-c +#import Bar.h +@interface Foo +@end + +/// Next file +#import "Foo.h" +@interface Bar +@porperty (nonatomic, strong) Foo* foo; +@end +``` +The above example will go wrong for `Foo`. As `Foo` Header also imports the `Foo.h` header when it imports `Bar.h`!! + +A way to solve this problem is write in the `@class Foo` in the `Bar` header. + +```objective-C +@class Foo; +@interface Bar +@porperty (nonatomic, strong) Foo* foo; +@end +```` + +The `@class Foo` tells the compiler that you promise by the time the implementation has been reached you will have imported the header of `Foo` + +So in the implementation of `Bar` you do + +```objective-c +#import "Foo.h" +@implementation Bar +@end +``` diff --git a/Students/Benny/3. Protocols and bridging/Questions.md b/Students/Benny/3. Protocols and bridging/Questions.md new file mode 100644 index 0000000..0486fca --- /dev/null +++ b/Students/Benny/3. Protocols and bridging/Questions.md @@ -0,0 +1,40 @@ +# Questions + +## Lesson 3: + +1. Is there a difference between protocols in swift and protocols in Objective-C? + +2. Why is using Introspection important when we already imported and conformed the ViewController to the "DropboxLoginable" protocol? + +3. Can't you just cast the nav.topViewController to the desired class instead? + +4. If performSelector has no target given, will it use the target it is being called from? e.g. +```Objective-C +[aClass performSelector: @selector(aSelector)]; +``` + +5. If modules are theoretically the better option over #import for things like UIKit, why do we still use #import ? + + + +## Lesson 4: + +1. What's the importance of 'arrayWithCapacity' when mapping an array. Is this required? + +2. Can you explain why we use an NSOperationQueue mainQueue and not simply dispatch the mainQueue in the following example? + +```Objective-C +[[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self.collectionView reloadData]; + }]; +``` + +3. Explain the difference between NSOperation and GDC please. + +4. NSDictionary 'bindings' argument in NSPredicate filtering? + +## SideNote + +1. When having to react to delegates, like for example UITextFieldDidEndEditing(), it seems unlikely that you're not going to retain your viewModel inside the collectionViewCell. Isn't "never" a bit harsh? + +2. So when only displaying a certain amount of data ,structs are the way to go, but as soon as we need to display more or edit data , viewModel? diff --git "a/Students/Benny/4. Mapping, sort, reduce/Lesson 4: Mapping, filtering, reduce, sort\342\200\246.md" "b/Students/Benny/4. Mapping, sort, reduce/Lesson 4: Mapping, filtering, reduce, sort\342\200\246.md" new file mode 100644 index 0000000..89e7e61 --- /dev/null +++ "b/Students/Benny/4. Mapping, sort, reduce/Lesson 4: Mapping, filtering, reduce, sort\342\200\246.md" @@ -0,0 +1,72 @@ +# Lesson 4: Mapping, filtering, reduce, sort… +#Programming/Objective-C/Mapping&Filtering + +1. Mapping +2. Filtering +3. Reduce +4. Sort +5. Lazy +6. QUEUE + +**For Mapping, filtering, reduce** +Objective-C has no language support. This only came when Swift came out. +Code examples come form: [Lottie Dropper](https://github.com/icapps/ios_lottie_dropper) + +## Mapping the Objective-C way +```objective-c +- (NSArray *)fileNames { + NSMutableArray *mapped = [NSMutableArray arrayWithCapacity:[self.entries count]]; + [self.entries enumerateObjectsUsingBlock:^(DBFILESMetadata * obj, NSUInteger idx, BOOL *stop) { + [mapped addObject:obj.name]; + }]; + return mapped; +} +``` + +## Filter +- [ ] Add an alternative + +## Reduce +- [ ] Add an alternative + +## Sort +Also this is rather *nasty*in Objective-C. There are many options of which non is as readable as in swift `array.sort {$0 < $1}` translates to: + +```objective-c +- (NSArray *)fileDetails { +// assume mapped is array of DropboxDetailViewModel's. + NSComparisonResult (^sortBlock)(id, id) = ^(DropboxDetailViewModel * obj1, DropboxDetailViewModel * obj2) + { + return [[obj1 fileName] compare: [obj2 fileName]]; + }; + return [mapped sortedArrayUsingComparator:sortBlock]; +} +``` + +## Lazy +**Does not exist in Objective-C** + +But you can do it in code. + +```objective-c +- (DBUserClient *)client { + if (_client == nil) { + NSString * accessToken = LottieDropperKeyChainBridge.shared.dropBoxAccessToken.accessToken; + if (accessToken != nil) { + _client = [[DBUserClient alloc] initWithAccessToken: accessToken]; + } else { + NSLog(@" No Dropbox user client"); + } + } + return _client; +} +``` + +## QUEUE +You have GCD. Grand central dispatch. This is a relatively complex API in `C` . You can also use `NSOperation` + +```objective-c +[[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self.collectionView reloadData]; + }]; +``` diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/.gitignore b/Students/Benny/GoogleDriveTest/GoogleDriveProject/.gitignore new file mode 100755 index 0000000..a3cd143 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/.gitignore @@ -0,0 +1,26 @@ +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control +# +# Pods/ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/CONTRIBUTING.md b/Students/Benny/GoogleDriveTest/GoogleDriveProject/CONTRIBUTING.md new file mode 100755 index 0000000..51c5b7f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/CONTRIBUTING.md @@ -0,0 +1,56 @@ +# How to become a contributor and submit your own code + +## Contributor License Agreements + +We'd love to accept your sample apps and patches! Before we can take them, we +have to jump a couple of legal hurdles. + +Please fill out either the individual or corporate Contributor License Agreement +(CLA). + + * If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an [individual CLA] + (http://code.google.com/legal/individual-cla-v1.0.html). + * If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a [corporate CLA] + (http://code.google.com/legal/corporate-cla-v1.0.html). + +Follow either of the two links above to access the appropriate CLA and +instructions for how to sign and return it. Once we receive it, we'll be able to +accept your pull requests. + +## Contributing a Patch + +1. Sign a Contributor License Agreement, if you have not yet done so (see + details above). +1. Create your change to the repo in question. + * Fork the desired repo, develop and test your code changes. + * Ensure that your code is clear and comprehensible. + * Ensure that your code has an appropriate set of unit tests which all pass. +1. Submit a pull request. +1. The repo owner will review your request. If it is approved, the change will + be merged. If it needs additional work, the repo owner will respond with + useful comments. + +## Contributing a New Sample App + +1. Sign a Contributor License Agreement, if you have not yet done so (see + details above). +1. Create your own repo for your app following this naming convention: + * mirror-{app-name}-{language or plaform} + * apps: quickstart, photohunt-server, photohunt-client + * example: mirror-quickstart-android + * For multi-language apps, concatenate the primary languages like this: + mirror-photohunt-server-java-python. + +1. Create your sample app in this repo. + * Be sure to clone the README.md, CONTRIBUTING.md and LICENSE files from the + googlesamples repo. + * Ensure that your code is clear and comprehensible. + * Ensure that your code has an appropriate set of unit tests which all pass. + * Instructional value is the top priority when evaluating new app proposals for + this collection of repos. +1. Submit a request to fork your repo in googlesamples organization. +1. The repo owner will review your request. If it is approved, the sample will + be merged. If it needs additional work, the repo owner will respond with + useful comments. diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/LICENSE b/Students/Benny/GoogleDriveTest/GoogleDriveProject/LICENSE new file mode 100755 index 0000000..e06d208 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/README.md b/Students/Benny/GoogleDriveTest/GoogleDriveProject/README.md new file mode 100755 index 0000000..9c90437 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/README.md @@ -0,0 +1,40 @@ +# ios-quickeditor + +A sample text editor for iOS illustrating how to open and save files with the [Google Drive API](https://developers.google.com/drive/ios) + +## Overview + +Quickeditor is a sample Google Drive app written in Objective-C for iOS. It is a text editor +capable of editing files with the MIME type text/* that are stored in a user's Google Drive + +## Prerequisites + +Building this sample requires: + +* [Xcode 6](https://developer.apple.com/xcode/downloads/) + +## Building the sample + +### Create a Google APIs project and activate the Drive API + +First, you need to activate the Drive API for your app. You can do it by configuring your API project in the +[Google Developers Console](https://console.developers.google.com/). + + +- Use [this wizard](https://console.developers.google.com/start/api?id=drive) to create or select a project in the Google Developers Console and automatically enable the API. +- In the sidebar on the left, select **Consent screen**. Select an **EMAIL ADDRESS** and enter a **PRODUCT NAME** if not already set and click the Save button. +- In the sidebar on the left, select **Credentials** and click **Create new Client ID**. +- Select the application type **Installed application**, **Other**, and click the **Create Client ID** button. +- Note the **CLIENT ID** and **CLIENT SECRET** values + +### Fetch and build the app + +1. Clone the git repo + + git clone git@github.com:googledrive/ios-quickeditor.git + cd ios-quickeditor +1. Open `ios-quickeditor/ios-quickeditor.xcworkspace` in Xcode +1. Edit `QEFilesListViewController.m` and replace `` and `` with the values from the +[Google Developers Console](https://console.developers.google.com/apis/console/) +1. Build the project and run it on the iOS simulator. + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Podfile b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Podfile new file mode 100755 index 0000000..7ba3c86 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Podfile @@ -0,0 +1,5 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '7.0' + +link_with 'ios-quickeditor', 'ios-quickeditorTests' +pod 'Google-API-Client/Drive', '~> 1.0' diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Podfile.lock b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Podfile.lock new file mode 100755 index 0000000..d8bdd94 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Podfile.lock @@ -0,0 +1,21 @@ +PODS: + - Google-API-Client/Common (1.0.422): + - gtm-http-fetcher (~> 1.0.141) + - gtm-oauth2 (~> 1.0.125) + - Google-API-Client/Drive (1.0.422): + - Google-API-Client/Common + - gtm-http-fetcher (~> 1.0.141) + - gtm-oauth2 (~> 1.0.125) + - gtm-http-fetcher (1.0.141) + - gtm-oauth2 (1.0.126): + - gtm-http-fetcher (~> 1.0.141) + +DEPENDENCIES: + - Google-API-Client/Drive (~> 1.0) + +SPEC CHECKSUMS: + Google-API-Client: 94e15390b2f5507e81a9a8c0edd58a02d2ab464b + gtm-http-fetcher: 6d4617e7d343b6e4c082b777541c334eb6f5d81e + gtm-oauth2: 60651b37376fa8fa5d1b92c9a631bd36ba093fd3 + +COCOAPODS: 0.35.0 diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/GTLDefines.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/GTLDefines.h new file mode 100755 index 0000000..b12eb9e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/GTLDefines.h @@ -0,0 +1,144 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDefines.h +// + +// Ensure Apple's conditionals we depend on are defined. +#import +#import + +// +// The developer may choose to define these in the project: +// +// #define GTL_TARGET_NAMESPACE Xxx // preface all GTL class names with Xxx (recommended for building plug-ins) +// #define GTL_FOUNDATION_ONLY 1 // builds without AppKit or Carbon (default for iPhone builds) +// #define STRIP_GTM_FETCH_LOGGING 1 // omit http logging code (default for iPhone release builds) +// +// Mac developers may find GTL_SIMPLE_DESCRIPTIONS and STRIP_GTM_FETCH_LOGGING useful for +// reducing code size. +// + +// Define later OS versions when building on earlier versions +#ifdef MAC_OS_X_VERSION_10_0 + #ifndef MAC_OS_X_VERSION_10_6 + #define MAC_OS_X_VERSION_10_6 1060 + #endif +#endif + + +#ifdef GTL_TARGET_NAMESPACE +// prefix all GTL class names with GTL_TARGET_NAMESPACE for this target + #import "GTLTargetNamespace.h" +#endif + +// Provide a common definition for externing constants/functions +#if defined(__cplusplus) + #define GTL_EXTERN extern "C" +#else + #define GTL_EXTERN extern +#endif + +#if TARGET_OS_IPHONE // iPhone SDK + + #define GTL_IPHONE 1 + +#endif + +#if GTL_IPHONE + + #define GTL_FOUNDATION_ONLY 1 + +#endif + +// +// GTL_ASSERT is like NSAssert, but takes a variable number of arguments: +// +// GTL_ASSERT(condition, @"Problem in argument %@", argStr); +// +// GTL_DEBUG_ASSERT is similar, but compiles in only for debug builds +// + +#ifndef GTL_ASSERT + // we directly invoke the NSAssert handler so we can pass on the varargs + #if !defined(NS_BLOCK_ASSERTIONS) + #define GTL_ASSERT(condition, ...) \ + do { \ + if (!(condition)) { \ + [[NSAssertionHandler currentHandler] \ + handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ + file:[NSString stringWithUTF8String:__FILE__] \ + lineNumber:__LINE__ \ + description:__VA_ARGS__]; \ + } \ + } while(0) + #else + #define GTL_ASSERT(condition, ...) do { } while (0) + #endif // !defined(NS_BLOCK_ASSERTIONS) +#endif // GTL_ASSERT + +#ifndef GTL_DEBUG_ASSERT + #if DEBUG + #define GTL_DEBUG_ASSERT(condition, ...) GTL_ASSERT(condition, __VA_ARGS__) + #else + #define GTL_DEBUG_ASSERT(condition, ...) do { } while (0) + #endif +#endif + +#ifndef GTL_DEBUG_LOG + #if DEBUG + #define GTL_DEBUG_LOG(...) NSLog(__VA_ARGS__) + #else + #define GTL_DEBUG_LOG(...) do { } while (0) + #endif +#endif + +#ifndef STRIP_GTM_FETCH_LOGGING + #if GTL_IPHONE && !DEBUG + #define STRIP_GTM_FETCH_LOGGING 1 + #else + #define STRIP_GTM_FETCH_LOGGING 0 + #endif +#endif + +// Some support for advanced clang static analysis functionality +// See http://clang-analyzer.llvm.org/annotations.html +#ifndef __has_feature // Optional. + #define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif +#ifndef NS_RETURNS_NOT_RETAINED + #if __has_feature(attribute_ns_returns_not_retained) + #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) + #else + #define NS_RETURNS_NOT_RETAINED + #endif +#endif + +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif + +#if 1 + // We will start using nonnull declarations once the static analyzer seems + // to support it without false positives. + #define GTL_NONNULL(x) +#else + #if __has_attribute(nonnull) + #define GTL_NONNULL(x) __attribute__((nonnull x)) + #else + #define GTL_NONNULL(x) + #endif +#endif diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchQuery.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchQuery.h new file mode 100755 index 0000000..d4fb1d3 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchQuery.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLBatchQuery.h +// + +// Batch query documentation: +// https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Batch_Operations + +#import "GTLQuery.h" + +@interface GTLBatchQuery : NSObject { + @private + NSMutableArray *queries_; + NSMutableDictionary *requestIDMap_; + BOOL skipAuthorization_; + NSDictionary *additionalHTTPHeaders_; + NSDictionary *urlQueryParameters_; +} + +// Queries included in this batch. Each query should have a unique requestID. +@property (retain) NSArray *queries; + +// Clients may set this to YES to disallow authorization. Defaults to NO. +@property (assign) BOOL shouldSkipAuthorization; + +// Any additional HTTP headers for this batch. +// +// These headers override the same keys from the service object's +// additionalHTTPHeaders. +@property (copy) NSDictionary *additionalHTTPHeaders; + +// Any URL query parameters to add to the query (useful for debugging with some +// services). +@property (copy) NSDictionary *urlQueryParameters; + ++ (id)batchQuery; ++ (id)batchQueryWithQueries:(NSArray *)array; + +- (void)addQuery:(GTLQuery *)query GTL_NONNULL((1)); + +- (GTLQuery *)queryForRequestID:(NSString *)requestID GTL_NONNULL((1)); + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchQuery.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchQuery.m new file mode 100755 index 0000000..c584368 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchQuery.m @@ -0,0 +1,135 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLBatchQuery.m +// + +#import "GTLBatchQuery.h" + +@implementation GTLBatchQuery + +@synthesize shouldSkipAuthorization = skipAuthorization_, + additionalHTTPHeaders = additionalHTTPHeaders_, + urlQueryParameters = urlQueryParameters_; + ++ (id)batchQuery { + GTLBatchQuery *obj = [[[self alloc] init] autorelease]; + return obj; +} + ++ (id)batchQueryWithQueries:(NSArray *)queries { + GTLBatchQuery *obj = [self batchQuery]; + obj.queries = queries; + return obj; +} + +- (id)copyWithZone:(NSZone *)zone { + // Deep copy the list of queries + NSArray *copiesOfQueries = [[[NSArray alloc] initWithArray:self.queries + copyItems:YES] autorelease]; + GTLBatchQuery *newBatch = [[[self class] allocWithZone:zone] init]; + newBatch.queries = copiesOfQueries; + newBatch.shouldSkipAuthorization = self.shouldSkipAuthorization; + newBatch.additionalHTTPHeaders = self.additionalHTTPHeaders; + return newBatch; +} + +- (void)dealloc { + [queries_ release]; + [additionalHTTPHeaders_ release]; + [urlQueryParameters_ release]; + [requestIDMap_ release]; + + [super dealloc]; +} + +- (NSString *)description { + NSArray *queries = self.queries; + NSArray *methodNames = [queries valueForKey:@"methodName"]; + NSArray *dedupedNames = [[NSSet setWithArray:methodNames] allObjects]; + NSString *namesStr = [dedupedNames componentsJoinedByString:@","]; + + return [NSString stringWithFormat:@"%@ %p (queries:%lu methods:%@)", + [self class], self, (unsigned long) [queries count], namesStr]; +} + +#pragma mark - + +- (BOOL)isBatchQuery { + return YES; +} + +- (GTLUploadParameters *)uploadParameters { + // File upload is not supported for batches + return nil; +} + +- (void)executionDidStop { + NSArray *queries = self.queries; + [queries makeObjectsPerformSelector:@selector(executionDidStop)]; +} + +- (GTLQuery *)queryForRequestID:(NSString *)requestID { + GTLQuery *result = [requestIDMap_ objectForKey:requestID]; + if (result) return result; + + // We've not before tried to look up a query, or the map is stale + [requestIDMap_ release]; + requestIDMap_ = [[NSMutableDictionary alloc] init]; + + for (GTLQuery *query in queries_) { + [requestIDMap_ setObject:query forKey:query.requestID]; + } + + result = [requestIDMap_ objectForKey:requestID]; + return result; +} + +#pragma mark - + +- (void)setQueries:(NSArray *)array { +#if DEBUG + for (id obj in array) { + GTLQuery *query = obj; + GTL_DEBUG_ASSERT([query isKindOfClass:[GTLQuery class]], + @"unexpected query class: %@", [obj class]); + GTL_DEBUG_ASSERT(query.uploadParameters == nil, + @"batch may not contain upload: %@", query); + } +#endif + + [queries_ autorelease]; + queries_ = [array mutableCopy]; +} + +- (NSArray *)queries { + return queries_; +} + +- (void)addQuery:(GTLQuery *)query { + GTL_DEBUG_ASSERT([query isKindOfClass:[GTLQuery class]], + @"unexpected query class: %@", [query class]); + GTL_DEBUG_ASSERT(query.uploadParameters == nil, + @"batch may not contain upload: %@", query); + + if (queries_ == nil) { + queries_ = [[NSMutableArray alloc] init]; + } + + [queries_ addObject:query]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchResult.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchResult.h new file mode 100755 index 0000000..9675aaf --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchResult.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2011 Google Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// +// GTLBatchResult.h +// + +#import "GTLObject.h" + +@interface GTLBatchResult : GTLObject { + @private + NSMutableDictionary *successes_; + NSMutableDictionary *failures_; +} + +// Dictionaries of results for all queries in the batch +// +// Dictionary keys are requestID strings; objects are results or +// GTLErrorObjects. +// +// For successes with no returned object (such as from delete operations), +// the object for the dictionary entry is NSNull. +// +// +// The original query for each result is available from the service ticket, +// for example +// +// NSDictionary *successes = batchResults.successes; +// for (NSString *requestID in successes) { +// GTLObject *obj = [successes objectForKey:requestID]; +// GTLQuery *query = [ticket queryForRequestID:requestID]; +// NSLog(@"Query %@ returned object %@", query, obj); +// } +// +// NSDictionary *failures = batchResults.failures; +// for (NSString *requestID in failures) { +// GTLErrorObject *errorObj = [failures objectForKey:requestID]; +// GTLQuery *query = [ticket queryForRequestID:requestID]; +// NSLog(@"Query %@ failed with error %@", query, errorObj); +// } +// + +@property (retain) NSMutableDictionary *successes; +@property (retain) NSMutableDictionary *failures; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchResult.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchResult.m new file mode 100755 index 0000000..f17748d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLBatchResult.m @@ -0,0 +1,92 @@ +/* Copyright (c) 2011 Google Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// +// GTLBatchResult.m +// + +#import "GTLBatchResult.h" + +#import "GTLErrorObject.h" + +@implementation GTLBatchResult + +@synthesize successes = successes_, + failures = failures_; + +- (id)copyWithZone:(NSZone *)zone { + GTLBatchResult* newObject = [super copyWithZone:zone]; + newObject.successes = [[self.successes mutableCopyWithZone:zone] autorelease]; + newObject.failures = [[self.failures mutableCopyWithZone:zone] autorelease]; + return newObject; +} + +- (void)dealloc { + [successes_ release]; + [failures_ release]; + + [super dealloc]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p (successes:%lu failures:%lu)", + [self class], self, + (unsigned long) [self.successes count], + (unsigned long) [self.failures count]]; +} + +#pragma mark - + +- (void)createItemsWithClassMap:(NSDictionary *)batchClassMap { + // This is called by GTLObject objectForJSON:defaultClass: + // JSON is defined to be a dictionary, but for batch results, it really + // is any array. + id json = self.JSON; + GTL_DEBUG_ASSERT([json isKindOfClass:[NSArray class]], + @"didn't get an array for the batch results"); + NSArray *jsonArray = json; + + NSMutableDictionary *successes = [NSMutableDictionary dictionary]; + NSMutableDictionary *failures = [NSMutableDictionary dictionary]; + + for (NSMutableDictionary *rpcResponse in jsonArray) { + NSString *responseID = [rpcResponse objectForKey:@"id"]; + + NSMutableDictionary *errorJSON = [rpcResponse objectForKey:@"error"]; + if (errorJSON) { + GTLErrorObject *errorObject = [GTLErrorObject objectWithJSON:errorJSON]; + [failures setValue:errorObject forKey:responseID]; + } else { + NSMutableDictionary *resultJSON = [rpcResponse objectForKey:@"result"]; + + NSDictionary *surrogates = self.surrogates; + Class defaultClass = [batchClassMap objectForKey:responseID]; + + id resultObject = [[self class] objectForJSON:resultJSON + defaultClass:defaultClass + surrogates:surrogates + batchClassMap:nil]; + if (resultObject == nil) { + // methods like delete return no object + resultObject = [NSNull null]; + } + [successes setValue:resultObject forKey:responseID]; + } + } + self.successes = successes; + self.failures = failures; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLDateTime.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLDateTime.h new file mode 100755 index 0000000..f6b1ffb --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLDateTime.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2011 Google Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// +// GTLDateTime.h +// +// This is an immutable class representing a date and optionally a +// time with time zone. +// + +#import +#import "GTLDefines.h" + +@interface GTLDateTime : NSObject { + NSDateComponents *dateComponents_; + NSInteger milliseconds_; // This is only for the fraction of a second 0-999 + NSInteger offsetSeconds_; // may be NSUndefinedDateComponent + BOOL isUniversalTime_; // preserves "Z" + NSTimeZone *timeZone_; // specific time zone by name, if known +} + ++ (GTLDateTime *)dateTimeWithRFC3339String:(NSString *)str; + +// timeZone may be nil if the time zone is not known. ++ (GTLDateTime *)dateTimeWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz; + +// Use this method to make a dateTime for an all-day event (date only, so +// hasTime is NO.) ++ (GTLDateTime *)dateTimeForAllDayWithDate:(NSDate *)date; + ++ (GTLDateTime *)dateTimeWithDateComponents:(NSDateComponents *)date; + +@property (nonatomic, readonly) NSDate *date; +@property (nonatomic, readonly) NSCalendar *calendar; + +@property (nonatomic, readonly) NSString *RFC3339String; +@property (nonatomic, readonly) NSString *stringValue; // same as RFC3339String + +@property (nonatomic, readonly, retain) NSTimeZone *timeZone; +@property (nonatomic, readonly, copy) NSDateComponents *dateComponents; +@property (nonatomic, readonly) NSInteger milliseconds; // This is only for the fraction of a second 0-999 + +@property (nonatomic, readonly) BOOL hasTime; +@property (nonatomic, readonly) NSInteger offsetSeconds; +@property (nonatomic, readonly, getter=isUniversalTime) BOOL universalTime; + + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLDateTime.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLDateTime.m new file mode 100755 index 0000000..e15684b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLDateTime.m @@ -0,0 +1,543 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDateTime.m +// + +#import "GTLDateTime.h" + +#if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0) +#define GTL_NEW_CALENDAR_ENUMS 1 +#else +#define GTL_NEW_CALENDAR_ENUMS 0 +#endif + +#if GTL_NEW_CALENDAR_ENUMS +static const NSInteger kGTLUndefinedDateComponent = NSDateComponentUndefined; +#else +static const NSInteger kGTLUndefinedDateComponent = NSUndefinedDateComponent; +#endif + + +@interface GTLDateTime () + +- (void)setFromDate:(NSDate *)date timeZone:(NSTimeZone *)tz; +- (void)setFromRFC3339String:(NSString *)str; + +@property (nonatomic, retain, readwrite) NSTimeZone *timeZone; +@property (nonatomic, copy, readwrite) NSDateComponents *dateComponents; +@property (nonatomic, assign, readwrite) NSInteger milliseconds; + +@property (nonatomic, assign, readwrite) BOOL hasTime; +@property (nonatomic, assign, readwrite) NSInteger offsetSeconds; +@property (nonatomic, assign, getter=isUniversalTime, readwrite) BOOL universalTime; + +@end + +static NSCharacterSet *gDashSet = nil; +static NSCharacterSet *gTSet = nil; +static NSCharacterSet *gColonSet = nil; +static NSCharacterSet *gPlusMinusZSet = nil; +static NSMutableDictionary *gCalendarsForTimeZones = nil; + +@implementation GTLDateTime + +// A note about milliseconds_: +// RFC 3339 has support for fractions of a second. NSDateComponents is all +// NSInteger based, so it can't handle a fraction of a second. NSDate is +// built on NSTimeInterval so it has sub-millisecond precision. GTL takes +// the compromise of supporting the RFC's optional fractional second support +// by maintaining a number of milliseconds past what fits in the +// NSDateComponents. The parsing and string conversions will include +// 3 decimal digits (hence milliseconds). When going to a string, the decimal +// digits are only included if the milliseconds are non zero. + +@dynamic date; +@dynamic calendar; +@dynamic RFC3339String; +@dynamic stringValue; +@dynamic timeZone; +@dynamic hasTime; + +@synthesize dateComponents = dateComponents_, + milliseconds = milliseconds_, + offsetSeconds = offsetSeconds_, + universalTime = isUniversalTime_; + ++ (void)initialize { + // Note that initialize is guaranteed by the runtime to be called in a + // thread-safe manner. + if (gDashSet == nil) { + gDashSet = [[NSCharacterSet characterSetWithCharactersInString:@"-"] retain]; + gTSet = [[NSCharacterSet characterSetWithCharactersInString:@"Tt "] retain]; + gColonSet = [[NSCharacterSet characterSetWithCharactersInString:@":"] retain]; + gPlusMinusZSet = [[NSCharacterSet characterSetWithCharactersInString:@"+-zZ"] retain]; + + gCalendarsForTimeZones = [[NSMutableDictionary alloc] init]; + } +} + ++ (GTLDateTime *)dateTimeWithRFC3339String:(NSString *)str { + if (str == nil) return nil; + + GTLDateTime *result = [[[self alloc] init] autorelease]; + [result setFromRFC3339String:str]; + return result; +} + ++ (GTLDateTime *)dateTimeWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz { + if (date == nil) return nil; + + GTLDateTime *result = [[[self alloc] init] autorelease]; + [result setFromDate:date timeZone:tz]; + return result; +} + ++ (GTLDateTime *)dateTimeForAllDayWithDate:(NSDate *)date { + if (date == nil) return nil; + + GTLDateTime *result = [[[self alloc] init] autorelease]; + [result setFromDate:date timeZone:nil]; + result.hasTime = NO; + return result; +} + ++ (GTLDateTime *)dateTimeWithDateComponents:(NSDateComponents *)components { +#if GTL_NEW_CALENDAR_ENUMS + NSString *calendarID = NSCalendarIdentifierGregorian; +#else + NSString *calendarID = NSGregorianCalendar; +#endif + NSCalendar *cal = [[[NSCalendar alloc] initWithCalendarIdentifier:calendarID] autorelease]; + NSDate *date = [cal dateFromComponents:components]; +#if GTL_IPHONE + NSTimeZone *tz = [components timeZone]; +#else + // NSDateComponents added timeZone: in Mac OS X 10.7. + NSTimeZone *tz = nil; + if ([components respondsToSelector:@selector(timeZone)]) { + tz = [components timeZone]; + } +#endif + return [self dateTimeWithDate:date timeZone:tz]; +} + +- (void)dealloc { + [dateComponents_ release]; + [timeZone_ release]; + [super dealloc]; +} + +- (id)copyWithZone:(NSZone *)zone { + // Object is immutable + return [self retain]; +} + +// On 10.9 and iOS 7 (and possibly earlier systems) NSDateComponents isEqual: works; check if +// we're guaranteed to be running on those systems or later. +#if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_7_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0) + #define GTL_CAN_TRUST_DATE_COMPONENTS_ISEQUAL 1 +#else + #define GTL_CAN_TRUST_DATE_COMPONENTS_ISEQUAL 0 +#endif + +// weekOfMonth and weekOfYear are available on 10.7 and iOS 5; check that we're building +// for at least those systems. +#if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_5_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0) + #define GTL_HAS_WEEK_OF_MONTH 1 +#else + #define GTL_HAS_WEEK_OF_MONTH 0 +#endif + +// week is not available starting with 10.10 and iOS 8 SDKs; check that we're not building +// with those SDKs. +#if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10) \ +|| (TARGET_OS_IPHONE && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0) + #define GTL_HAS_WEEK 0 +#else + #define GTL_HAS_WEEK 1 +#endif + +// until NSDateComponent implements isEqual, we'll use this +#if !GTL_CAN_TRUST_DATE_COMPONENTS_ISEQUAL +- (BOOL)doesDateComponents:(NSDateComponents *)dc1 + equalDateComponents:(NSDateComponents *)dc2 { + + return [dc1 era] == [dc2 era] + && [dc1 year] == [dc2 year] + && [dc1 month] == [dc2 month] + && [dc1 day] == [dc2 day] + && [dc1 hour] == [dc2 hour] + && [dc1 minute] == [dc2 minute] + && [dc1 second] == [dc2 second] +#if GTL_HAS_WEEK_OF_MONTH + && [dc1 weekOfMonth] == [dc2 weekOfMonth] + && [dc1 weekOfYear] == [dc2 weekOfYear] +#endif +#if GTL_HAS_WEEK + && [dc1 week] == [dc2 week] +#endif + && [dc1 weekday] == [dc2 weekday] + + && [dc1 weekdayOrdinal] == [dc2 weekdayOrdinal]; + +} +#endif // !GTL_CAN_TRUST_DATE_COMPONENTS_ISEQUAL + +- (BOOL)isEqual:(GTLDateTime *)other { + + if (self == other) return YES; + if (![other isKindOfClass:[GTLDateTime class]]) return NO; + +#if GTL_CAN_TRUST_DATE_COMPONENTS_ISEQUAL + BOOL areDateComponentsEqual = [self.dateComponents isEqual:other.dateComponents]; +#else + BOOL areDateComponentsEqual = [self doesDateComponents:self.dateComponents + equalDateComponents:other.dateComponents]; +#endif + + NSTimeZone *tz1 = self.timeZone; + NSTimeZone *tz2 = other.timeZone; + BOOL areTimeZonesEqual = (tz1 == tz2 || (tz2 && [tz1 isEqual:tz2])); + + return self.offsetSeconds == other.offsetSeconds + && self.isUniversalTime == other.isUniversalTime + && self.milliseconds == other.milliseconds + && areDateComponentsEqual + && areTimeZonesEqual; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p: {%@}", + [self class], self, self.RFC3339String]; +} + +- (NSTimeZone *)timeZone { + if (timeZone_) { + return timeZone_; + } + + if (self.isUniversalTime) { + NSTimeZone *ztz = [NSTimeZone timeZoneWithName:@"Universal"]; + return ztz; + } + + NSInteger offsetSeconds = self.offsetSeconds; + + if (offsetSeconds != kGTLUndefinedDateComponent) { + NSTimeZone *tz = [NSTimeZone timeZoneForSecondsFromGMT:offsetSeconds]; + return tz; + } + return nil; +} + +- (void)setTimeZone:(NSTimeZone *)timeZone { + [timeZone_ release]; + timeZone_ = [timeZone retain]; + + if (timeZone) { + NSInteger offsetSeconds = [timeZone secondsFromGMTForDate:self.date]; + self.offsetSeconds = offsetSeconds; + } else { + self.offsetSeconds = kGTLUndefinedDateComponent; + } +} + +- (NSCalendar *)calendarForTimeZone:(NSTimeZone *)tz { + NSCalendar *cal = nil; + @synchronized(gCalendarsForTimeZones) { + id tzKey = (tz ? tz : [NSNull null]); + cal = [gCalendarsForTimeZones objectForKey:tzKey]; + if (cal == nil) { +#if GTL_NEW_CALENDAR_ENUMS + NSString *calendarID = NSCalendarIdentifierGregorian; +#else + NSString *calendarID = NSGregorianCalendar; +#endif + cal = [[[NSCalendar alloc] initWithCalendarIdentifier:calendarID] autorelease]; + if (tz) { + [cal setTimeZone:tz]; + } + [gCalendarsForTimeZones setObject:cal forKey:tzKey]; + } + } + return cal; +} + +- (NSCalendar *)calendar { + NSTimeZone *tz = self.timeZone; + return [self calendarForTimeZone:tz]; +} + +- (NSDate *)date { + NSDateComponents *dateComponents = self.dateComponents; + NSTimeInterval extraMillisecondsAsSeconds = 0.0; + NSCalendar *cal; + + if (!self.hasTime) { + // We're not keeping track of a time, but NSDate always is based on + // an absolute time. We want to avoid returning an NSDate where the + // calendar date appears different from what was used to create our + // date-time object. + // + // We'll make a copy of the date components, setting the time on our + // copy to noon GMT, since that ensures the date renders correctly for + // any time zone. + NSDateComponents *noonDateComponents = [[dateComponents copy] autorelease]; + [noonDateComponents setHour:12]; + [noonDateComponents setMinute:0]; + [noonDateComponents setSecond:0]; + dateComponents = noonDateComponents; + + NSTimeZone *gmt = [NSTimeZone timeZoneWithName:@"Universal"]; + cal = [self calendarForTimeZone:gmt]; + } else { + cal = self.calendar; + + // Add in the fractional seconds that don't fit into NSDateComponents. + extraMillisecondsAsSeconds = ((NSTimeInterval)self.milliseconds) / 1000.0; + } + + NSDate *date = [cal dateFromComponents:dateComponents]; + + // Add in any milliseconds that didn't fit into the dateComponents. + if (extraMillisecondsAsSeconds > 0.0) { +#if GTL_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) + date = [date dateByAddingTimeInterval:extraMillisecondsAsSeconds]; +#else + date = [date addTimeInterval:extraMillisecondsAsSeconds]; +#endif + } + + return date; +} + +- (NSString *)stringValue { + return self.RFC3339String; +} + +- (NSString *)RFC3339String { + NSDateComponents *dateComponents = self.dateComponents; + NSInteger offset = self.offsetSeconds; + + NSString *timeString = @""; // timeString like "T15:10:46-08:00" + + if (self.hasTime) { + + NSString *timeOffsetString; // timeOffsetString like "-08:00" + + if (self.isUniversalTime) { + timeOffsetString = @"Z"; + } else if (offset == kGTLUndefinedDateComponent) { + // unknown offset is rendered as -00:00 per + // http://www.ietf.org/rfc/rfc3339.txt section 4.3 + timeOffsetString = @"-00:00"; + } else { + NSString *sign = @"+"; + if (offset < 0) { + sign = @"-"; + offset = -offset; + } + timeOffsetString = [NSString stringWithFormat:@"%@%02ld:%02ld", + sign, (long)(offset/(60*60)) % 24, (long)(offset / 60) % 60]; + } + + NSString *fractionalSecondsString = @""; + if (self.milliseconds > 0.0) { + fractionalSecondsString = [NSString stringWithFormat:@".%03ld", (long)self.milliseconds]; + } + + timeString = [NSString stringWithFormat:@"T%02ld:%02ld:%02ld%@%@", + (long)[dateComponents hour], (long)[dateComponents minute], + (long)[dateComponents second], fractionalSecondsString, timeOffsetString]; + } + + // full dateString like "2006-11-17T15:10:46-08:00" + NSString *dateString = [NSString stringWithFormat:@"%04ld-%02ld-%02ld%@", + (long)[dateComponents year], (long)[dateComponents month], + (long)[dateComponents day], timeString]; + + return dateString; +} + +- (void)setFromDate:(NSDate *)date timeZone:(NSTimeZone *)tz { + NSCalendar *cal = [self calendarForTimeZone:tz]; + +#if GTL_NEW_CALENDAR_ENUMS + NSUInteger const kComponentBits = (NSCalendarUnitYear | NSCalendarUnitMonth + | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute + | NSCalendarUnitSecond); +#else + NSUInteger const kComponentBits = (NSYearCalendarUnit | NSMonthCalendarUnit + | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit + | NSSecondCalendarUnit); +#endif + + NSDateComponents *components = [cal components:kComponentBits fromDate:date]; + self.dateComponents = components; + + // Extract the fractional seconds. + NSTimeInterval asTimeInterval = [date timeIntervalSince1970]; + NSTimeInterval worker = asTimeInterval - trunc(asTimeInterval); + self.milliseconds = (NSInteger)round(worker * 1000.0); + + self.universalTime = NO; + + NSInteger offset = kGTLUndefinedDateComponent; + + if (tz) { + offset = [tz secondsFromGMTForDate:date]; + + if (offset == 0 && [tz isEqualToTimeZone:[NSTimeZone timeZoneWithName:@"Universal"]]) { + self.universalTime = YES; + } + } + self.offsetSeconds = offset; + + // though offset seconds are authoritative, we'll retain the time zone + // since we can't regenerate it reliably from just the offset + timeZone_ = [tz retain]; +} + +- (void)setFromRFC3339String:(NSString *)str { + + NSInteger year = kGTLUndefinedDateComponent; + NSInteger month = kGTLUndefinedDateComponent; + NSInteger day = kGTLUndefinedDateComponent; + NSInteger hour = kGTLUndefinedDateComponent; + NSInteger minute = kGTLUndefinedDateComponent; + NSInteger sec = kGTLUndefinedDateComponent; + NSInteger milliseconds = 0; + double secDouble = -1.0; + NSString* sign = nil; + NSInteger offsetHour = 0; + NSInteger offsetMinute = 0; + + if ([str length] > 0) { + NSScanner* scanner = [NSScanner scannerWithString:str]; + // There should be no whitespace, so no skip characters. + [scanner setCharactersToBeSkipped:nil]; + + // for example, scan 2006-11-17T15:10:46-08:00 + // or 2006-11-17T15:10:46Z + if (// yyyy-mm-dd + [scanner scanInteger:&year] && + [scanner scanCharactersFromSet:gDashSet intoString:NULL] && + [scanner scanInteger:&month] && + [scanner scanCharactersFromSet:gDashSet intoString:NULL] && + [scanner scanInteger:&day] && + // Thh:mm:ss + [scanner scanCharactersFromSet:gTSet intoString:NULL] && + [scanner scanInteger:&hour] && + [scanner scanCharactersFromSet:gColonSet intoString:NULL] && + [scanner scanInteger:&minute] && + [scanner scanCharactersFromSet:gColonSet intoString:NULL] && + [scanner scanDouble:&secDouble]) { + + // At this point we got secDouble, pull it apart. + sec = (NSInteger)secDouble; + double worker = secDouble - ((double)sec); + milliseconds = (NSInteger)round(worker * 1000.0); + + // Finish parsing, now the offset info. + if (// Z or +hh:mm + [scanner scanCharactersFromSet:gPlusMinusZSet intoString:&sign] && + [scanner scanInteger:&offsetHour] && + [scanner scanCharactersFromSet:gColonSet intoString:NULL] && + [scanner scanInteger:&offsetMinute]) { + } + } + } + + NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease]; + [dateComponents setYear:year]; + [dateComponents setMonth:month]; + [dateComponents setDay:day]; + [dateComponents setHour:hour]; + [dateComponents setMinute:minute]; + [dateComponents setSecond:sec]; + + self.dateComponents = dateComponents; + self.milliseconds = milliseconds; + + // determine the offset, like from Z, or -08:00:00.0 + + self.timeZone = nil; + + NSInteger totalOffset = kGTLUndefinedDateComponent; + self.universalTime = NO; + + if ([sign caseInsensitiveCompare:@"Z"] == NSOrderedSame) { + + self.universalTime = YES; + totalOffset = 0; + + } else if (sign != nil) { + + totalOffset = (60 * offsetMinute) + (60 * 60 * offsetHour); + + if ([sign isEqual:@"-"]) { + + if (totalOffset == 0) { + // special case: offset of -0.00 means undefined offset + totalOffset = kGTLUndefinedDateComponent; + } else { + totalOffset *= -1; + } + } + } + + self.offsetSeconds = totalOffset; +} + +- (BOOL)hasTime { + NSDateComponents *dateComponents = self.dateComponents; + + BOOL hasTime = ([dateComponents hour] != kGTLUndefinedDateComponent + && [dateComponents minute] != kGTLUndefinedDateComponent); + + return hasTime; +} + +- (void)setHasTime:(BOOL)shouldHaveTime { + + // we'll set time values to zero or kUndefinedDateComponent as appropriate + BOOL hadTime = self.hasTime; + + if (shouldHaveTime && !hadTime) { + [dateComponents_ setHour:0]; + [dateComponents_ setMinute:0]; + [dateComponents_ setSecond:0]; + milliseconds_ = 0; + offsetSeconds_ = kGTLUndefinedDateComponent; + isUniversalTime_ = NO; + + } else if (hadTime && !shouldHaveTime) { + [dateComponents_ setHour:kGTLUndefinedDateComponent]; + [dateComponents_ setMinute:kGTLUndefinedDateComponent]; + [dateComponents_ setSecond:kGTLUndefinedDateComponent]; + milliseconds_ = 0; + offsetSeconds_ = kGTLUndefinedDateComponent; + isUniversalTime_ = NO; + self.timeZone = nil; + } +} + + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLErrorObject.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLErrorObject.h new file mode 100755 index 0000000..c2ec67d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLErrorObject.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLErrorObject.h +// + +#import "GTLObject.h" + +@class GTLErrorObjectData; + +@interface GTLErrorObject : GTLObject +@property (retain) NSNumber *code; +@property (retain) NSString *message; +@property (retain) NSArray *data; // of GTLErrorObjectData + +// Convenience accessor for creating an NSError from a GTLErrorObject. +@property (readonly) NSError *foundationError; + +// Convenience accessor for extracting the GTLErrorObject that was used to +// create an NSError. +// +// Returns nil if the error was not originally from a GTLErrorObject. ++ (GTLErrorObject *)underlyingObjectForError:(NSError *)foundationError; + +@end + +@interface GTLErrorObjectData : GTLObject +@property (retain) NSString *domain; +@property (retain) NSString *reason; +@property (retain) NSString *message; +@property (retain) NSString *location; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLErrorObject.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLErrorObject.m new file mode 100755 index 0000000..1fa1023 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLErrorObject.m @@ -0,0 +1,78 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLErrorObject.m +// + +#import "GTLErrorObject.h" +#import "GTLService.h" + +@implementation GTLErrorObject + +@dynamic code; +@dynamic message; +@dynamic data; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = [NSDictionary dictionaryWithObject:[GTLErrorObjectData class] + forKey:@"data"]; + return map; +} + +- (NSError *)foundationError { + NSMutableDictionary *userInfo; + + // This structured GTLErrorObject will be available in the error's userInfo + // dictionary + userInfo = [NSMutableDictionary dictionaryWithObject:self + forKey:kGTLStructuredErrorKey]; + + NSString *reasonStr = self.message; + if (reasonStr) { + // We always store an error in the userInfo key "error" + [userInfo setObject:reasonStr + forKey:kGTLServerErrorStringKey]; + + // Store a user-readable "reason" to show up when an error is logged, + // in parentheses like NSError does it + NSString *parenthesized = [NSString stringWithFormat:@"(%@)", reasonStr]; + [userInfo setObject:parenthesized + forKey:NSLocalizedFailureReasonErrorKey]; + } + + NSInteger code = [self.code integerValue]; + NSError *error = [NSError errorWithDomain:kGTLJSONRPCErrorDomain + code:code + userInfo:userInfo]; + return error; +} + ++ (GTLErrorObject *)underlyingObjectForError:(NSError *)foundationError { + NSDictionary *userInfo = [foundationError userInfo]; + GTLErrorObject *errorObj = [userInfo objectForKey:kGTLStructuredErrorKey]; + return errorObj; +} + +@end + +@implementation GTLErrorObjectData +@dynamic domain; +@dynamic reason; +@dynamic message; +@dynamic location; +@end + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLObject.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLObject.h new file mode 100755 index 0000000..787ae0e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLObject.h @@ -0,0 +1,198 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLObject.h +// + +// GTLObject documentation: +// https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Objects_and_Queries + +#import + +#import "GTLDefines.h" +#import "GTLUtilities.h" +#import "GTLDateTime.h" + +@protocol GTLCollectionProtocol +@optional +@property (retain) NSArray *items; +@end + +@protocol GTLBatchItemCreationProtocol +- (void)createItemsWithClassMap:(NSDictionary *)batchClassMap; +@end + +@interface GTLObject : NSObject { + + @private + + NSMutableDictionary *json_; + + // Used when creating the subobjects from this one. + NSDictionary *surrogates_; + + // Any complex object hung off this object goes into the cache so the + // next fetch will get the same object back instead of having to recreate + // it. + NSMutableDictionary *childCache_; + + // Anything defined by the client; retained but not used internally; not + // copied by copyWithZone: + NSMutableDictionary *userProperties_; +} + +@property (nonatomic, retain) NSMutableDictionary *JSON; +@property (nonatomic, retain) NSDictionary *surrogates; +@property (nonatomic, retain) NSMutableDictionary *userProperties; + +/////////////////////////////////////////////////////////////////////////////// +// +// Public methods +// +// These methods are intended for users of the library +// + ++ (id)object; ++ (id)objectWithJSON:(NSMutableDictionary *)dict; + +- (id)copyWithZone:(NSZone *)zone; + +- (NSString *)JSONString; + +// generic access to json; also creates it if necessary +- (void)setJSONValue:(id)obj forKey:(NSString *)key GTL_NONNULL((2)); +- (id)JSONValueForKey:(NSString *)key; + +// Returns the list of keys in this object's JSON that aren't listed as +// properties on the object. +- (NSArray *)additionalJSONKeys; + +// Any keys in the JSON that aren't listed as @properties on the object +// are counted as "additional properties". These allow you to get/set them. +- (id)additionalPropertyForName:(NSString *)name; +- (void)setAdditionalProperty:(id)obj forName:(NSString *)name GTL_NONNULL((2)); +- (NSDictionary *)additionalProperties; + +// User properties are supported for client convenience, but are not copied by +// copyWithZone. User Properties keys beginning with _ are reserved by the library. +// +// Set nil for obj to remove the property. +- (void)setProperty:(id)obj forKey:(NSString *)key GTL_NONNULL((2)); +- (id)propertyForKey:(NSString *)key GTL_NONNULL((1)); + +// userData is stored as a property with key "_userData" +- (void)setUserData:(id)obj; +- (id)userData; + +// Makes a partial query-compatible string describing the fields present +// in this object. (Note: only the first element of any array is examined.) +// +// http://code.google.com/apis/tasks/v1/performance.html#partial +// +- (NSString *)fieldsDescription; + +// Makes an object containing only the changes needed to do a partial update +// (patch), where the patch would be to change an object from the original +// to the receiver, such as +// +// GTLSomeObject *patchObject = [newVersion patchObjectFromOriginal:oldVersion]; +// +// http://code.google.com/apis/tasks/v1/performance.html#patch +// +// NOTE: this method returns nil if there are no changes between the original +// and the receiver. +- (id)patchObjectFromOriginal:(GTLObject *)original; + +// Method creating a null value to set object properties for patch queries that +// delete fields. Do not use this except when setting an object property for +// a patch query. ++ (id)nullValue; + +/////////////////////////////////////////////////////////////////////////////// +// +// Protected methods +// +// These methods are intended for subclasses of GTLObject +// + +// class registration ("kind" strings) for subclasses ++ (Class)registeredObjectClassForKind:(NSString *)kind; ++ (void)registerObjectClassForKind:(NSString *)kind; + +// creation of objects from a JSON dictionary ++ (GTLObject *)objectForJSON:(NSMutableDictionary *)json + defaultClass:(Class)defaultClass + surrogates:(NSDictionary *)surrogates + batchClassMap:(NSDictionary *)batchClassMap; + +// property-to-key mapping (for JSON keys which are not used as method names) ++ (NSDictionary *)propertyToJSONKeyMap; + +// property-to-Class mapping for array properties (to say what is in the array) ++ (NSDictionary *)arrayPropertyToClassMap; + +// The default class for additional JSON keys ++ (Class)classForAdditionalProperties; + +@end + +// Collection objects with an "items" property should derive from GTLCollection +// object. This provides support for fast object enumeration, the +// itemAtIndex: convenience method, and indexed subscripts. +// +// Subclasses must implement the items method dynamically. +@interface GTLCollectionObject : GTLObject { + @private + NSDictionary *identifierMap_; +} + +// itemAtIndex: and objectAtIndexedSubscript: return nil when the index exceeds +// the bounds of the items array. +- (id)itemAtIndex:(NSUInteger)idx; + +- (id)objectAtIndexedSubscript:(NSInteger)idx; + +// itemForIdentifier: looks up items from the collection object by identifier, +// and returns the first one. +// +// Typically, items will have a unique identifier (with key "id" in the +// object's JSON). This method returns the first item found in the collection +// with the specified identifier. +// +// The first time this method is used, the collection will cache a map of +// identifiers to items. If the items list for the instance somehow changes, +// use the reset method below to force a new cache to be created for this +// collection. +- (id)itemForIdentifier:(NSString *)key GTL_NONNULL((1)); + +// Identifiers for all items are cached when the first one is obtained. +// This method resets the cache. It is needed only if the item list has +// changed. +- (void)resetIdentifierMap; + +@end + +@interface GTLCollectionObject (DynamicMethods) +- (NSArray *)items; +@end + +// Base object use for when an service method directly returns an array instead +// of an object. Normally methods should return an object with an 'items' +// property, but this exists for the methods not up to spec. +@interface GTLResultArray : GTLCollectionObject +// This method should only be called by subclasses. +- (NSArray *)itemsWithItemClass:(Class)itemClass; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLObject.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLObject.m new file mode 100755 index 0000000..b8c3ca8 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLObject.m @@ -0,0 +1,725 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLObject.m +// + +#include + +#import "GTLObject.h" +#import "GTLRuntimeCommon.h" +#import "GTLJSONParser.h" + +static NSString *const kUserDataPropertyKey = @"_userData"; + +@interface GTLObject () ++ (NSMutableArray *)allDeclaredProperties; ++ (NSArray *)allKnownKeys; + ++ (NSArray *)fieldsElementsForJSON:(NSDictionary *)targetJSON; ++ (NSString *)fieldsDescriptionForJSON:(NSDictionary *)targetJSON; + ++ (NSMutableDictionary *)patchDictionaryForJSON:(NSDictionary *)newJSON + fromOriginalJSON:(NSDictionary *)originalJSON; +@end + +@implementation GTLObject + +@synthesize JSON = json_, + surrogates = surrogates_, + userProperties = userProperties_; + ++ (id)object { + return [[[self alloc] init] autorelease]; +} + ++ (id)objectWithJSON:(NSMutableDictionary *)dict { + GTLObject *obj = [self object]; + obj.JSON = dict; + return obj; +} + ++ (NSDictionary *)propertyToJSONKeyMap { + return nil; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + return nil; +} + ++ (Class)classForAdditionalProperties { + return Nil; +} + +- (BOOL)isEqual:(GTLObject *)other { + if (self == other) return YES; + if (other == nil) return NO; + + // The objects should be the same class, or one should be a subclass of the + // other's class + if (![other isKindOfClass:[self class]] + && ![self isKindOfClass:[other class]]) return NO; + + // What we're not comparing here: + // properties + return GTL_AreEqualOrBothNil(json_, [other JSON]); +} + +// By definition, for two objects to potentially be considered equal, +// they must have the same hash value. The hash is mostly ignored, +// but removeObjectsInArray: in Leopard does seem to check the hash, +// and NSObject's default hash method just returns the instance pointer. +// We'll define hash here for all of our GTLObjects. +- (NSUInteger)hash { + return (NSUInteger) (void *) [GTLObject class]; +} + +- (id)copyWithZone:(NSZone *)zone { + GTLObject* newObject = [[[self class] allocWithZone:zone] init]; + CFPropertyListRef ref = CFPropertyListCreateDeepCopy(kCFAllocatorDefault, + json_, kCFPropertyListMutableContainers); + GTL_DEBUG_ASSERT(ref != NULL, @"GTLObject: copy failed (probably a non-plist type in the JSON)"); + newObject.JSON = [NSMakeCollectable(ref) autorelease]; + newObject.surrogates = self.surrogates; + + // What we're not copying: + // userProperties + return newObject; +} + +- (NSString *)descriptionWithLocale:(id)locale { + return [self description]; +} + +- (void)dealloc { + [json_ release]; + [surrogates_ release]; + [childCache_ release]; + [userProperties_ release]; + + [super dealloc]; +} + +#pragma mark JSON values + +- (void)setJSONValue:(id)obj forKey:(NSString *)key { + NSMutableDictionary *dict = self.JSON; + if (dict == nil && obj != nil) { + dict = [NSMutableDictionary dictionaryWithCapacity:1]; + self.JSON = dict; + } + [dict setValue:obj forKey:key]; +} + +- (id)JSONValueForKey:(NSString *)key { + id obj = [self.JSON objectForKey:key]; + return obj; +} + +- (NSString *)JSONString { + NSError *error = nil; + NSString *str = [GTLJSONParser stringWithObject:[self JSON] + humanReadable:YES + error:&error]; + if (error) { + return [error description]; + } + return str; +} + +- (NSArray *)additionalJSONKeys { + NSArray *knownKeys = [[self class] allKnownKeys]; + NSMutableArray *result = [NSMutableArray arrayWithArray:[json_ allKeys]]; + [result removeObjectsInArray:knownKeys]; + // Return nil instead of an empty array. + if ([result count] == 0) { + result = nil; + } + return result; +} + +#pragma mark Partial - Fields + +- (NSString *)fieldsDescription { + NSString *str = [GTLObject fieldsDescriptionForJSON:self.JSON]; + return str; +} + ++ (NSString *)fieldsDescriptionForJSON:(NSDictionary *)targetJSON { + // Internal routine: recursively generate a string field description + // by joining elements + NSArray *array = [self fieldsElementsForJSON:targetJSON]; + NSString *str = [array componentsJoinedByString:@","]; + return str; +} + ++ (NSArray *)fieldsElementsForJSON:(NSDictionary *)targetJSON { + // Internal routine: recursively generate an array of field description + // element strings + NSMutableArray *resultFields = [NSMutableArray array]; + + // Sorting the dictionary keys gives us deterministic results when iterating + NSArray *sortedKeys = [[targetJSON allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + for (NSString *key in sortedKeys) { + // We'll build a comma-separated list of fields + id value = [targetJSON objectForKey:key]; + if ([value isKindOfClass:[NSString class]] + || [value isKindOfClass:[NSNumber class]]) { + // Basic type (string, number), so the key is what we want + [resultFields addObject:key]; + } else if ([value isKindOfClass:[NSDictionary class]]) { + // Object (dictionary): "parent/child1,parent/child2,parent/child3" + NSArray *subElements = [self fieldsElementsForJSON:value]; + for (NSString *subElem in subElements) { + NSString *prepended = [NSString stringWithFormat:@"%@/%@", + key, subElem]; + [resultFields addObject:prepended]; + } + } else if ([value isKindOfClass:[NSArray class]]) { + // Array; we'll generate from the first array entry: + // "parent(child1,child2,child3)" + // + // Open question: should this instead create the union of elements for + // all items in the array, rather than just get fields from the first + // array object? + if ([(NSArray *)value count] > 0) { + id firstObj = [value objectAtIndex:0]; + if ([firstObj isKindOfClass:[NSDictionary class]]) { + // An array of objects + NSString *contentsStr = [self fieldsDescriptionForJSON:firstObj]; + NSString *encapsulated = [NSString stringWithFormat:@"%@(%@)", + key, contentsStr]; + [resultFields addObject:encapsulated]; + } else { + // An array of some basic type, or of arrays + [resultFields addObject:key]; + } + } + } else { + GTL_ASSERT(0, @"GTLObject unknown field element for %@ (%@)", + key, NSStringFromClass([value class])); + } + } + return resultFields; +} + +#pragma mark Partial - Patch + +- (id)patchObjectFromOriginal:(GTLObject *)original { + id resultObj; + NSMutableDictionary *resultJSON = [GTLObject patchDictionaryForJSON:self.JSON + fromOriginalJSON:original.JSON]; + if ([resultJSON count] > 0) { + resultObj = [[self class] objectWithJSON:resultJSON]; + } else { + // Client apps should not attempt to patch with an object containing + // empty JSON + resultObj = nil; + } + return resultObj; +} + ++ (NSMutableDictionary *)patchDictionaryForJSON:(NSDictionary *)newJSON + fromOriginalJSON:(NSDictionary *)originalJSON { + // Internal recursive routine to create an object suitable for + // our patch semantics + NSMutableDictionary *resultJSON = [NSMutableDictionary dictionary]; + + // Iterate through keys present in the old object + NSArray *originalKeys = [originalJSON allKeys]; + for (NSString *key in originalKeys) { + id originalValue = [originalJSON objectForKey:key]; + id newValue = [newJSON valueForKey:key]; + if (newValue == nil) { + // There is no new value for this key, so set the value to NSNull + [resultJSON setValue:[NSNull null] forKey:key]; + } else if (!GTL_AreEqualOrBothNil(originalValue, newValue)) { + // The values for this key differ + if ([originalValue isKindOfClass:[NSDictionary class]] + && [newValue isKindOfClass:[NSDictionary class]]) { + // Both are objects; recurse + NSMutableDictionary *subDict = [self patchDictionaryForJSON:newValue + fromOriginalJSON:originalValue]; + [resultJSON setValue:subDict forKey:key]; + } else { + // They are non-object values; the new replaces the old. Per the + // documentation for patch, this replaces entire arrays. + [resultJSON setValue:newValue forKey:key]; + } + } else { + // The values are the same; omit this key-value pair + } + } + + // Iterate through keys present only in the new object, and add them to the + // result + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:[newJSON allKeys]]; + [newKeys removeObjectsInArray:originalKeys]; + + for (NSString *key in newKeys) { + id value = [newJSON objectForKey:key]; + [resultJSON setValue:value forKey:key]; + } + return resultJSON; +} + ++ (id)nullValue { + return [NSNull null]; +} + +#pragma mark Additional Properties + +- (id)additionalPropertyForName:(NSString *)name { + // Return the cached object, if any, before creating one. + id result = [self cacheChildForKey:name]; + if (result != nil) { + return result; + } + + Class defaultClass = [[self class] classForAdditionalProperties]; + id jsonObj = [self JSONValueForKey:name]; + BOOL shouldCache = NO; + if (jsonObj != nil) { + NSDictionary *surrogates = self.surrogates; + result = [GTLRuntimeCommon objectFromJSON:jsonObj + defaultClass:defaultClass + surrogates:surrogates + isCacheable:&shouldCache]; + } + + [self setCacheChild:(shouldCache ? result : nil) + forKey:name]; + return result; +} + +- (void)setAdditionalProperty:(id)obj forName:(NSString *)name { + BOOL shouldCache = NO; + Class defaultClass = [[self class] classForAdditionalProperties]; + id json = [GTLRuntimeCommon jsonFromAPIObject:obj + expectedClass:defaultClass + isCacheable:&shouldCache]; + [self setJSONValue:json forKey:name]; + [self setCacheChild:(shouldCache ? obj : nil) + forKey:name]; +} + +- (NSDictionary *)additionalProperties { + NSMutableDictionary *result = [NSMutableDictionary dictionary]; + + NSArray *propertyNames = [self additionalJSONKeys]; + for (NSString *name in propertyNames) { + id obj = [self additionalPropertyForName:name]; + [result setObject:obj forKey:name]; + } + + return result; +} + +#pragma mark Child Cache methods + +// There is no property for childCache_ as there shouldn't be KVC/KVO +// support for it, it's an implementation detail. + +- (void)setCacheChild:(id)obj forKey:(NSString *)key { + if (childCache_ == nil && obj != nil) { + childCache_ = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + obj, key, nil]; + } else { + [childCache_ setValue:obj forKey:key]; + } +} + +- (id)cacheChildForKey:(NSString *)key { + id obj = [childCache_ objectForKey:key]; + return obj; +} + +#pragma mark userData and user properties + +- (void)setUserData:(id)userData { + [self setProperty:userData forKey:kUserDataPropertyKey]; +} + +- (id)userData { + // be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[[self propertyForKey:kUserDataPropertyKey] retain] autorelease]; +} + +- (void)setProperty:(id)obj forKey:(NSString *)key { + if (obj == nil) { + // user passed in nil, so delete the property + [userProperties_ removeObjectForKey:key]; + } else { + // be sure the property dictionary exists + if (userProperties_ == nil) { + self.userProperties = [NSMutableDictionary dictionary]; + } + [userProperties_ setObject:obj forKey:key]; + } +} + +- (id)propertyForKey:(NSString *)key { + id obj = [userProperties_ objectForKey:key]; + + // be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[obj retain] autorelease]; +} + +#pragma mark Support methods + ++ (NSMutableArray *)allDeclaredProperties { + NSMutableArray *array = [NSMutableArray array]; + + // walk from this class up the hierarchy to GTLObject + Class topClass = class_getSuperclass([GTLObject class]); + for (Class currClass = self; + currClass != topClass; + currClass = class_getSuperclass(currClass)) { + // step through this class's properties, and add the property names to the + // array + objc_property_t *properties = class_copyPropertyList(currClass, NULL); + if (properties) { + for (objc_property_t *prop = properties; + *prop != NULL; + ++prop) { + const char *propName = property_getName(*prop); + // We only want dynamic properties; their attributes contain ",D". + const char *attr = property_getAttributes(*prop); + const char *dynamicMarker = strstr(attr, ",D"); + if (dynamicMarker && + (dynamicMarker[2] == 0 || dynamicMarker[2] == ',' )) { + [array addObject:[NSString stringWithUTF8String:propName]]; + } + } + free(properties); + } + } + return array; +} + ++ (NSArray *)allKnownKeys { + NSArray *allProps = [self allDeclaredProperties]; + NSMutableArray *knownKeys = [NSMutableArray arrayWithArray:allProps]; + + NSDictionary *propMap = [GTLObject propertyToJSONKeyMapForClass:[self class]]; + + NSUInteger idx = 0; + for (NSString *propName in allProps) { + NSString *jsonKey = [propMap objectForKey:propName]; + if (jsonKey) { + [knownKeys replaceObjectAtIndex:idx + withObject:jsonKey]; + } + ++idx; + } + return knownKeys; +} + +- (NSString *)description { + // find the list of declared and otherwise known JSON keys for this class + NSArray *knownKeys = [[self class] allKnownKeys]; + + NSMutableString *descStr = [NSMutableString string]; + + NSString *spacer = @""; + for (NSString *key in json_) { + NSString *value = nil; + // show question mark for JSON keys not supported by a declared property: + // foo?:"Hi mom." + NSString *qmark = [knownKeys containsObject:key] ? @"" : @"?"; + + // determine property value to dislay + id rawValue = [json_ valueForKey:key]; + if ([rawValue isKindOfClass:[NSDictionary class]]) { + // for dictionaries, show the list of keys: + // {key1,key2,key3} + NSString *subkeyList = [[rawValue allKeys] componentsJoinedByString:@","]; + value = [NSString stringWithFormat:@"{%@}", subkeyList]; + } else if ([rawValue isKindOfClass:[NSArray class]]) { + // for arrays, show the number of items in the array: + // [3] + value = [NSString stringWithFormat:@"[%lu]", (unsigned long)[(NSArray *)rawValue count]]; + } else if ([rawValue isKindOfClass:[NSString class]]) { + // for strings, show the string in quotes: + // "Hi mom." + value = [NSString stringWithFormat:@"\"%@\"", rawValue]; + } else { + // for numbers, show just the number + value = [rawValue description]; + } + [descStr appendFormat:@"%@%@%@:%@", spacer, key, qmark, value]; + spacer = @" "; + } + + NSString *str = [NSString stringWithFormat:@"%@ %p: {%@}", + [self class], self, descStr]; + return str; +} + +#pragma mark Class Registration + +static NSMutableDictionary *gKindMap = nil; + ++ (Class)registeredObjectClassForKind:(NSString *)kind { + Class resultClass = [gKindMap objectForKey:kind]; + return resultClass; +} + ++ (void)registerObjectClassForKind:(NSString *)kind { + // there's no autorelease pool in place at +load time, so we'll create our own + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + if (gKindMap == nil) { + gKindMap = [[NSMutableDictionary alloc] init]; + } + + Class selfClass = [self class]; + +#if DEBUG + // ensure this is a unique registration + if ([gKindMap objectForKey:kind] != nil ) { + GTL_DEBUG_LOG(@"%@ (%@) registration conflicts with %@", + selfClass, kind, [gKindMap objectForKey:kind]); + } + if ([[gKindMap allKeysForObject:selfClass] count] != 0) { + GTL_DEBUG_LOG(@"%@ (%@) registration conflicts with %@", + selfClass, kind, [gKindMap allKeysForObject:selfClass]); + } +#endif + + [gKindMap setValue:selfClass forKey:kind]; + + // we drain here to keep the clang static analyzer quiet + [pool drain]; +} + +#pragma mark Object Instantiation + ++ (GTLObject *)objectForJSON:(NSMutableDictionary *)json + defaultClass:(Class)defaultClass + surrogates:(NSDictionary *)surrogates + batchClassMap:(NSDictionary *)batchClassMap { + if ([json isEqual:[NSNull null]] || [json count] == 0) { + if (json != nil && defaultClass != Nil) { + // The JSON included an empty dictionary, and a return class + // was specified. + return [defaultClass object]; + } + // No actual result, such as the response from a delete. + return nil; + } + + // Determine the class to instantiate, based on the original fetch + // request or by looking up "kind" string from the registration at + // +load time of GTLObject subclasses + // + // We're letting the dynamic kind override the default class so + // feeds of heterogenous entries can use the defaultClass as a + // fallback + Class classToCreate = defaultClass; + NSString *kind = nil; + if ([json isKindOfClass:[NSDictionary class]]) { + kind = [json valueForKey:@"kind"]; + if ([kind isKindOfClass:[NSString class]] && [kind length] > 0) { + Class dynamicClass = [GTLObject registeredObjectClassForKind:kind]; + if (dynamicClass) { + classToCreate = dynamicClass; + } + } + } + + // Warn the developer that no specific class of GTLObject + // was requested with the fetch call, and no class is found + // compiled in to match the "kind" attribute of the JSON + // returned by the server + GTL_ASSERT(classToCreate != nil, + @"Could not find registered GTLObject subclass to " + "match JSON with kind \"%@\"", kind); + + if (classToCreate == nil) { + classToCreate = [self class]; + } + + // See if the top-level class for the JSON is listed in the surrogates; + // if so, instantiate the surrogate class instead + Class baseSurrogate = [surrogates objectForKey:classToCreate]; + if (baseSurrogate) { + classToCreate = baseSurrogate; + } + + // now instantiate the GTLObject + GTLObject *parsedObject = [classToCreate object]; + + parsedObject.surrogates = surrogates; + parsedObject.JSON = json; + + // it's time to instantiate inner items + if ([parsedObject conformsToProtocol:@protocol(GTLBatchItemCreationProtocol)]) { + id batch = + (id ) parsedObject; + [batch createItemsWithClassMap:batchClassMap]; + } + + return parsedObject; +} + +#pragma mark Runtime Utilities + +static NSMutableDictionary *gJSONKeyMapCache = nil; +static NSMutableDictionary *gArrayPropertyToClassMapCache = nil; + ++ (void)initialize { + // Note that initialize is guaranteed by the runtime to be called in a + // thread-safe manner + if (gJSONKeyMapCache == nil) { + gJSONKeyMapCache = [[NSMutableDictionary alloc] init]; + } + if (gArrayPropertyToClassMapCache == nil) { + gArrayPropertyToClassMapCache = [[NSMutableDictionary alloc] init]; + } +} + ++ (NSDictionary *)propertyToJSONKeyMapForClass:(Class)aClass { + NSDictionary *resultMap = + [GTLUtilities mergedClassDictionaryForSelector:@selector(propertyToJSONKeyMap) + startClass:aClass + ancestorClass:[GTLObject class] + cache:gJSONKeyMapCache]; + return resultMap; +} + ++ (NSDictionary *)arrayPropertyToClassMapForClass:(Class)aClass { + NSDictionary *resultMap = + [GTLUtilities mergedClassDictionaryForSelector:@selector(arrayPropertyToClassMap) + startClass:aClass + ancestorClass:[GTLObject class] + cache:gArrayPropertyToClassMapCache]; + return resultMap; +} + +#pragma mark Runtime Support + ++ (Class)ancestorClass { + return [GTLObject class]; +} + ++ (BOOL)resolveInstanceMethod:(SEL)sel { + BOOL resolved = [GTLRuntimeCommon resolveInstanceMethod:sel onClass:self]; + if (resolved) + return YES; + + return [super resolveInstanceMethod:sel]; +} + +@end + +@implementation GTLCollectionObject +// Subclasses must implement the items method dynamically. + +- (void)dealloc { + [identifierMap_ release]; + [super dealloc]; +} + +- (id)itemAtIndex:(NSUInteger)idx { + NSArray *items = [self performSelector:@selector(items)]; + if (idx < [items count]) { + return [items objectAtIndex:idx]; + } + return nil; +} + +- (id)objectAtIndexedSubscript:(NSInteger)idx { + if (idx >= 0) { + return [self itemAtIndex:(NSUInteger)idx]; + } + return nil; +} + +- (id)itemForIdentifier:(NSString *)key { + if (identifierMap_ == nil) { + NSArray *items = [self performSelector:@selector(items)]; + NSMutableDictionary *dict = + [NSMutableDictionary dictionaryWithCapacity:[items count]]; + for (id item in items) { + id identifier = [item valueForKey:@"identifier"]; + if (identifier != nil && identifier != [NSNull null]) { + if ([dict objectForKey:identifier] == nil) { + [dict setObject:item forKey:identifier]; + } + } + } + identifierMap_ = [dict copy]; + } + return [identifierMap_ objectForKey:key]; +} + +- (void)resetIdentifierMap { + [identifierMap_ release]; + identifierMap_ = nil; +} + +// NSFastEnumeration protocol +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state + objects:(id *)stackbuf + count:(NSUInteger)len { + NSArray *items = [self performSelector:@selector(items)]; + NSUInteger result = [items countByEnumeratingWithState:state + objects:stackbuf + count:len]; + return result; +} + +@end + +@implementation GTLResultArray + +- (NSArray *)itemsWithItemClass:(Class)itemClass { + // Return the cached array before creating on demand. + NSString *cacheKey = @"result_array_items"; + NSMutableArray *cachedArray = [self cacheChildForKey:cacheKey]; + if (cachedArray != nil) { + return cachedArray; + } + NSArray *result = nil; + NSArray *array = (NSArray *)[self JSON]; + if (array != nil) { + if ([array isKindOfClass:[NSArray class]]) { + NSDictionary *surrogates = self.surrogates; + result = [GTLRuntimeCommon objectFromJSON:array + defaultClass:itemClass + surrogates:surrogates + isCacheable:NULL]; + } else { +#if DEBUG + if (![array isKindOfClass:[NSNull class]]) { + GTL_DEBUG_LOG(@"GTLObject: unexpected JSON: %@ should be an array, actually is a %@:\n%@", + NSStringFromClass([self class]), + NSStringFromClass([array class]), + array); + } +#endif + result = array; + } + } + + [self setCacheChild:result forKey:cacheKey]; + return result; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLQuery.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLQuery.h new file mode 100755 index 0000000..5334dc9 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLQuery.h @@ -0,0 +1,133 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLQuery.h +// + +// Query documentation: +// https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Query_Operations + +#import "GTLObject.h" +#import "GTLUploadParameters.h" + +@protocol GTLQueryProtocol +- (BOOL)isBatchQuery; +- (BOOL)shouldSkipAuthorization; +- (void)executionDidStop; +- (NSDictionary *)additionalHTTPHeaders; +- (NSDictionary *)urlQueryParameters; +- (GTLUploadParameters *)uploadParameters; +@end + +@protocol GTLQueryCollectionProtocol +@optional +@property (retain) NSString *pageToken; +@property (retain) NSNumber *startIndex; +@end + +@class GTLServiceTicket; + +@interface GTLQuery : NSObject { + @private + NSString *methodName_; + NSMutableDictionary *json_; + GTLObject *bodyObject_; + NSMutableDictionary *childCache_; + NSString *requestID_; + GTLUploadParameters *uploadParameters_; + NSDictionary *urlQueryParameters_; + NSDictionary *additionalHTTPHeaders_; + Class expectedObjectClass_; + BOOL skipAuthorization_; + void (^completionBlock_)(GTLServiceTicket *ticket, id object, NSError *error); +} + +// The rpc method name. +@property (readonly) NSString *methodName; + +// The JSON dictionary of all the parameters set on this query. +@property (retain) NSMutableDictionary *JSON; + +// The object set to be uploaded with the query. +@property (retain) GTLObject *bodyObject; + +// Each query must have a request ID string. The user may replace the +// default assigned request ID with a custom string, provided that if +// used in a batch query, all request IDs in the batch must be unique. +@property (copy) NSString *requestID; + +// For queries which support file upload, the MIME type and file handle +// or data must be provided. +@property (copy) GTLUploadParameters *uploadParameters; + +// Any URL query parameters to add to the query (useful for debugging with some +// services). +@property (copy) NSDictionary *urlQueryParameters; + +// Any additional HTTP headers for this query. Not valid when this query +// is added to a batch. +// +// These headers override the same keys from the service object's +// additionalHTTPHeaders. +@property (copy) NSDictionary *additionalHTTPHeaders; + +// The GTLObject subclass expected for results (used if the result doesn't +// include a kind attribute). +@property (assign) Class expectedObjectClass; + +// Clients may set this to YES to disallow authorization. Defaults to NO. +@property (assign) BOOL shouldSkipAuthorization; + +// Clients may provide an optional callback block to be called immediately +// before the executeQuery: callback. +// +// The completionBlock property is particularly useful for queries executed +// in a batch. +// +// Errors passed to the completionBlock will have an "underlying" GTLErrorObject +// when the server returned an error for this specific query: +// +// GTLErrorObject *errorObj = [GTLErrorObject underlyingObjectForError:error]; +// if (errorObj) { +// // the server returned this error for this specific query +// } else { +// // the batch execution failed +// } +@property (copy) void (^completionBlock)(GTLServiceTicket *ticket, id object, NSError *error); + +// methodName is the RPC method name to use. ++ (id)queryWithMethodName:(NSString *)methodName GTL_NONNULL((1)); + +// methodName is the RPC method name to use. +- (id)initWithMethodName:(NSString *)method GTL_NONNULL((1)); + +// If you need to set a parameter that is not listed as a property for a +// query class, you can do so via this api. If you need to clear it after +// setting, pass nil for obj. +- (void)setCustomParameter:(id)obj forKey:(NSString *)key GTL_NONNULL((2)); + +// Auto-generated request IDs ++ (NSString *)nextRequestID; + +// Methods for subclasses to override. ++ (NSDictionary *)parameterNameMap; ++ (NSDictionary *)arrayPropertyToClassMap; +@end + +// The library doesn't use GTLQueryCollectionImpl, but it provides a concrete implementation +// of the protocol so the methods do not cause a private method error in Xcode. +@interface GTLQueryCollectionImpl : GTLQuery +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLQuery.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLQuery.m new file mode 100755 index 0000000..f912565 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLQuery.m @@ -0,0 +1,262 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLQuery.m +// + +#include + +#import "GTLQuery.h" +#import "GTLRuntimeCommon.h" +#import "GTLUtilities.h" + +@interface GTLQuery () +@end + +@implementation GTLQuery + +// Implementation Note: bodyObject could be done as a dynamic property and map +// it to the key "resource". But we expose the object on the ServiceTicket +// for developers, and so sending it through the plumbing already in the +// parameters and outside of that gets into a grey area. For requests sent +// via this class, we don't need to touch the JSON, but for developers that +// have to use the lower level apis for something we'd need to know to add +// it to the JSON. + +@synthesize methodName = methodName_, + JSON = json_, + bodyObject = bodyObject_, + requestID = requestID_, + uploadParameters = uploadParameters_, + urlQueryParameters = urlQueryParameters_, + additionalHTTPHeaders = additionalHTTPHeaders_, + expectedObjectClass = expectedObjectClass_, + shouldSkipAuthorization = skipAuthorization_, + completionBlock = completionBlock_; + ++ (id)queryWithMethodName:(NSString *)methodName { + return [[[self alloc] initWithMethodName:methodName] autorelease]; +} + +- (id)initWithMethodName:(NSString *)methodName { + self = [super init]; + if (self) { + requestID_ = [[[self class] nextRequestID] retain]; + + methodName_ = [methodName copy]; + if ([methodName_ length] == 0) { + [self release]; + self = nil; + } + } + return self; +} + +- (void)dealloc { + [methodName_ release]; + [json_ release]; + [bodyObject_ release]; + [childCache_ release]; + [requestID_ release]; + [uploadParameters_ release]; + [urlQueryParameters_ release]; + [additionalHTTPHeaders_ release]; + [completionBlock_ release]; + + [super dealloc]; +} + + +- (id)copyWithZone:(NSZone *)zone { + GTLQuery *query = + [[[self class] allocWithZone:zone] initWithMethodName:self.methodName]; + + if ([json_ count] > 0) { + // Deep copy the parameters + CFPropertyListRef ref = CFPropertyListCreateDeepCopy(kCFAllocatorDefault, + json_, kCFPropertyListMutableContainers); + query.JSON = [NSMakeCollectable(ref) autorelease]; + } + query.bodyObject = self.bodyObject; + query.requestID = self.requestID; + query.uploadParameters = self.uploadParameters; + query.urlQueryParameters = self.urlQueryParameters; + query.additionalHTTPHeaders = self.additionalHTTPHeaders; + query.expectedObjectClass = self.expectedObjectClass; + query.shouldSkipAuthorization = self.shouldSkipAuthorization; + query.completionBlock = self.completionBlock; + return query; +} + +- (NSString *)description { + NSArray *keys = [self.JSON allKeys]; + NSArray *params = [keys sortedArrayUsingSelector:@selector(compare:)]; + NSString *paramsSummary = @""; + if ([params count] > 0) { + paramsSummary = [NSString stringWithFormat:@" params:(%@)", + [params componentsJoinedByString:@","]]; + } + + keys = [self.urlQueryParameters allKeys]; + NSArray *urlQParams = [keys sortedArrayUsingSelector:@selector(compare:)]; + NSString *urlQParamsSummary = @""; + if ([urlQParams count] > 0) { + urlQParamsSummary = [NSString stringWithFormat:@" urlQParams:(%@)", + [urlQParams componentsJoinedByString:@","]]; + } + + GTLObject *bodyObj = self.bodyObject; + NSString *bodyObjSummary = @""; + if (bodyObj != nil) { + bodyObjSummary = [NSString stringWithFormat:@" bodyObject:%@", [bodyObj class]]; + } + + NSString *uploadStr = @""; + GTLUploadParameters *uploadParams = self.uploadParameters; + if (uploadParams) { + uploadStr = [NSString stringWithFormat:@" %@", uploadParams]; + } + + return [NSString stringWithFormat:@"%@ %p: {method:%@%@%@%@%@}", + [self class], self, self.methodName, + paramsSummary, urlQParamsSummary, bodyObjSummary, uploadStr]; +} + +- (void)setCustomParameter:(id)obj forKey:(NSString *)key { + [self setJSONValue:obj forKey:key]; +} + +- (BOOL)isBatchQuery { + return NO; +} + +- (void)executionDidStop { + self.completionBlock = nil; +} + ++ (NSString *)nextRequestID { + static unsigned long lastRequestID = 0; + NSString *result; + + @synchronized([GTLQuery class]) { + ++lastRequestID; + result = [NSString stringWithFormat:@"gtl_%lu", + (unsigned long) lastRequestID]; + } + return result; +} + +#pragma mark GTLRuntimeCommon Support + +- (void)setJSONValue:(id)obj forKey:(NSString *)key { + NSMutableDictionary *dict = self.JSON; + if (dict == nil && obj != nil) { + dict = [NSMutableDictionary dictionaryWithCapacity:1]; + self.JSON = dict; + } + [dict setValue:obj forKey:key]; +} + +- (id)JSONValueForKey:(NSString *)key { + id obj = [self.JSON objectForKey:key]; + return obj; +} + +// There is no property for childCache_ as there shouldn't be KVC/KVO +// support for it, it's an implementation detail. + +- (void)setCacheChild:(id)obj forKey:(NSString *)key { + if (childCache_ == nil && obj != nil) { + childCache_ = + [[NSMutableDictionary alloc] initWithObjectsAndKeys:obj, key, nil]; + } else { + [childCache_ setValue:obj forKey:key]; + } +} + +- (id)cacheChildForKey:(NSString *)key { + id obj = [childCache_ objectForKey:key]; + return obj; +} + +#pragma mark Methods for Subclasses to Override + ++ (NSDictionary *)parameterNameMap { + return nil; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + return nil; +} + +#pragma mark Runtime Utilities + +static NSMutableDictionary *gQueryParameterNameMapCache = nil; +static NSMutableDictionary *gQueryArrayPropertyToClassMapCache = nil; + ++ (void)initialize { + // note that initialize is guaranteed by the runtime to be called in a + // thread-safe manner + if (gQueryParameterNameMapCache == nil) { + gQueryParameterNameMapCache = [[NSMutableDictionary alloc] init]; + } + if (gQueryArrayPropertyToClassMapCache == nil) { + gQueryArrayPropertyToClassMapCache = [[NSMutableDictionary alloc] init]; + } +} + ++ (NSDictionary *)propertyToJSONKeyMapForClass:(Class)aClass { + NSDictionary *resultMap = + [GTLUtilities mergedClassDictionaryForSelector:@selector(parameterNameMap) + startClass:aClass + ancestorClass:[GTLQuery class] + cache:gQueryParameterNameMapCache]; + return resultMap; +} + ++ (NSDictionary *)arrayPropertyToClassMapForClass:(Class)aClass { + NSDictionary *resultMap = + [GTLUtilities mergedClassDictionaryForSelector:@selector(arrayPropertyToClassMap) + startClass:aClass + ancestorClass:[GTLQuery class] + cache:gQueryArrayPropertyToClassMapCache]; + return resultMap; +} + +#pragma mark Runtime Support + +- (NSDictionary *)surrogates { + // Stub method just needed for RumtimeCommon, query doesn't use surrogates. + return nil; +} + ++ (Class)ancestorClass { + return [GTLQuery class]; +} + ++ (BOOL)resolveInstanceMethod:(SEL)sel { + BOOL resolved = [GTLRuntimeCommon resolveInstanceMethod:sel onClass:self]; + if (resolved) + return YES; + + return [super resolveInstanceMethod:sel]; +} + +@end + +@implementation GTLQueryCollectionImpl +@dynamic pageToken, startIndex; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLRuntimeCommon.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLRuntimeCommon.h new file mode 100755 index 0000000..28822b5 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLRuntimeCommon.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLRuntimeCommon.h +// + + +#import + +#import "GTLDefines.h" + +// This protocol and support class are an internal implementation detail so +// GTLObject and GTLQuery can share some code. + +@protocol GTLRuntimeCommon +@required +// Get/Set properties +- (void)setJSONValue:(id)obj forKey:(NSString *)key; +- (id)JSONValueForKey:(NSString *)key; +// Child cache +- (void)setCacheChild:(id)obj forKey:(NSString *)key; +- (id)cacheChildForKey:(NSString *)key; +// Surrogate class mappings. +- (NSDictionary *)surrogates; +// Key map ++ (NSDictionary *)propertyToJSONKeyMapForClass:(Class)aClass; +// Array item types ++ (NSDictionary *)arrayPropertyToClassMapForClass:(Class)aClass; +// The parent class for dynamic support ++ (Class)ancestorClass; +@end + +@interface GTLRuntimeCommon : NSObject +// Wire things up. ++ (BOOL)resolveInstanceMethod:(SEL)sel onClass:(Class)onClass; +// Helpers ++ (id)objectFromJSON:(id)json + defaultClass:(Class)defaultClass + surrogates:(NSDictionary *)surrogates + isCacheable:(BOOL*)isCacheable; ++ (id)jsonFromAPIObject:(id)obj + expectedClass:(Class)expectedClass + isCacheable:(BOOL*)isCacheable; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLRuntimeCommon.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLRuntimeCommon.m new file mode 100755 index 0000000..5efaa74 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLRuntimeCommon.m @@ -0,0 +1,1187 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLRuntimeCommon.m +// + +#include +#include + +#import "GTLRuntimeCommon.h" + +#import "GTLDateTime.h" +#import "GTLObject.h" +#import "GTLUtilities.h" + +static NSString *const kReturnClassKey = @"returnClass"; +static NSString *const kContainedClassKey = @"containedClass"; +static NSString *const kJSONKey = @"jsonKey"; + +// Note: NSObject's class is used as a marker for the expected/default class +// when Discovery says it can be any type of object. + +@implementation GTLRuntimeCommon + +// Helper to generically convert JSON to an api object type. ++ (id)objectFromJSON:(id)json + defaultClass:(Class)defaultClass + surrogates:(NSDictionary *)surrogates + isCacheable:(BOOL*)isCacheable { + id result = nil; + BOOL canBeCached = YES; + + // TODO(TVL): use defaultClass to validate things like expectedClass is + // done in jsonFromAPIObject:expectedClass:isCacheable:? + + if ([json isKindOfClass:[NSDictionary class]]) { + // If no default, or the default was any object, then default to base + // object here (and hope there is a kind to get the right thing). + if ((defaultClass == Nil) || [defaultClass isEqual:[NSObject class]]) { + defaultClass = [GTLObject class]; + } + result = [GTLObject objectForJSON:json + defaultClass:defaultClass + surrogates:surrogates + batchClassMap:nil]; + } else if ([json isKindOfClass:[NSArray class]]) { + NSArray *jsonArray = json; + // make an object for each JSON dictionary in the array + NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:[jsonArray count]]; + for (id jsonItem in jsonArray) { + id item = [self objectFromJSON:jsonItem + defaultClass:defaultClass + surrogates:surrogates + isCacheable:NULL]; + [resultArray addObject:item]; + } + result = resultArray; + } else if ([json isKindOfClass:[NSString class]]) { + // DateTimes live in JSON as strings, so convert + if ([defaultClass isEqual:[GTLDateTime class]]) { + result = [GTLDateTime dateTimeWithRFC3339String:json]; + } else { + result = json; + canBeCached = NO; + } + } else if ([json isKindOfClass:[NSNumber class]] || + [json isKindOfClass:[NSNull class]]) { + result = json; + canBeCached = NO; + } else { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: unsupported class '%s' in objectFromJSON", + class_getName([json class])); + } + + if (isCacheable) { + *isCacheable = canBeCached; + } + return result; +} + +// Helper to generically convert an api object type to JSON. +// |expectedClass| is the type that was expected for |obj|. ++ (id)jsonFromAPIObject:(id)obj + expectedClass:(Class)expectedClass + isCacheable:(BOOL*)isCacheable { + id result = nil; + BOOL canBeCached = YES; + BOOL checkExpected = (expectedClass != Nil); + + if ([obj isKindOfClass:[NSString class]]) { + result = [[obj copy] autorelease]; + canBeCached = NO; + } else if ([obj isKindOfClass:[NSNumber class]] || + [obj isKindOfClass:[NSNull class]]) { + result = obj; + canBeCached = NO; + } else if ([obj isKindOfClass:[GTLObject class]]) { + result = [obj JSON]; + if (result == nil) { + // adding an empty object; it should have a JSON dictionary so it can + // hold future assignments + [obj setJSON:[NSMutableDictionary dictionary]]; + result = [obj JSON]; + } + } else if ([obj isKindOfClass:[NSArray class]]) { + checkExpected = NO; + NSArray *array = obj; + // get the JSON for each thing in the array + NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:[array count]]; + for (id item in array) { + id itemJSON = [self jsonFromAPIObject:item + expectedClass:expectedClass + isCacheable:NULL]; + [resultArray addObject:itemJSON]; + } + result = resultArray; + } else if ([obj isKindOfClass:[GTLDateTime class]]) { + // DateTimes live in JSON as strings, so convert. + GTLDateTime *dateTime = obj; + result = [dateTime stringValue]; + } else { + checkExpected = NO; + if (obj) { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: unsupported class '%s' in jsonFromAPIObject", + class_getName([obj class])); + } + } + + if (checkExpected) { + // If the default was any object, then clear it to skip validation checks. + if ([expectedClass isEqual:[NSObject class]] || + [obj isKindOfClass:[NSNull class]]) { + expectedClass = nil; + } + if (expectedClass && ![obj isKindOfClass:expectedClass]) { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: jsonFromAPIObject expected class '%s' instead got '%s'", + class_getName(expectedClass), class_getName([obj class])); + } + } + + if (isCacheable) { + *isCacheable = canBeCached; + } + return result; +} + +#pragma mark JSON/Object Utilities + +static NSMutableDictionary *gDispatchCache = nil; + +static CFStringRef SelectorKeyCopyDescriptionCallBack(const void *key) { + // Make a CFString from the key + NSString *name = NSStringFromSelector((SEL) key); + CFStringRef str = CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef) name); + return str; +} + +// Save the dispatch details for the specified class and selector ++ (void)setStoredDispatchForClass:(Class)dispatchClass + selector:(SEL)sel + returnClass:(Class)returnClass + containedClass:(Class)containedClass + jsonKey:(NSString *)jsonKey { + // cache structure: + // class -> + // selector -> + // returnClass + // containedClass + // jsonKey + @synchronized([GTLRuntimeCommon class]) { + if (gDispatchCache == nil) { + gDispatchCache = [[NSMutableDictionary alloc] init]; + } + + CFMutableDictionaryRef classDict = + (CFMutableDictionaryRef) [gDispatchCache objectForKey:dispatchClass]; + if (classDict == nil) { + // We create a CFDictionary since the keys are raw selectors rather than + // NSStrings + const CFDictionaryKeyCallBacks keyCallBacks = { + .version = 0, + .retain = NULL, + .release = NULL, + .copyDescription = SelectorKeyCopyDescriptionCallBack, + .equal = NULL, // defaults to pointer comparison + .hash = NULL // defaults to the pointer value + }; + const CFIndex capacity = 0; // no limit + classDict = CFDictionaryCreateMutable(kCFAllocatorDefault, capacity, + &keyCallBacks, + &kCFTypeDictionaryValueCallBacks); + [gDispatchCache setObject:(id)classDict + forKey:(id)dispatchClass]; + CFRelease(classDict); + } + + NSDictionary *selDict = (NSDictionary *)CFDictionaryGetValue(classDict, sel); + if (selDict == nil) { + selDict = [NSDictionary dictionaryWithObjectsAndKeys: + jsonKey, kJSONKey, + returnClass, kReturnClassKey, // can be nil (primitive types) + containedClass, kContainedClassKey, // may be nil + nil]; + CFDictionarySetValue(classDict, sel, selDict); + } else { + // we already have a dictionary for this selector on this class, which is + // surprising + GTL_DEBUG_LOG(@"Storing duplicate dispatch for %@ selector %@", + dispatchClass, NSStringFromSelector(sel)); + } + } +} + ++ (BOOL)getStoredDispatchForClass:(Class)dispatchClass + selector:(SEL)sel + returnClass:(Class *)outReturnClass + containedClass:(Class *)outContainedClass + jsonKey:(NSString **)outJsonKey { + @synchronized([GTLRuntimeCommon class]) { + // walk from this class up the hierarchy to the ancestor class + Class topClass = class_getSuperclass([dispatchClass ancestorClass]); + for (Class currClass = dispatchClass; + currClass != topClass; + currClass = class_getSuperclass(currClass)) { + + CFMutableDictionaryRef classDict = + (CFMutableDictionaryRef) [gDispatchCache objectForKey:currClass]; + if (classDict) { + NSMutableDictionary *selDict = + (NSMutableDictionary *) CFDictionaryGetValue(classDict, sel); + if (selDict) { + if (outReturnClass) { + *outReturnClass = [selDict objectForKey:kReturnClassKey]; + } + if (outContainedClass) { + *outContainedClass = [selDict objectForKey:kContainedClassKey]; + } + if (outJsonKey) { + *outJsonKey = [selDict objectForKey:kJSONKey]; + } + return YES; + } + } + } + } + GTL_DEBUG_LOG(@"Failed to find stored dispatch info for %@ %s", + dispatchClass, sel_getName(sel)); + return NO; +} + +#pragma mark IMPs - getters and setters for specific object types + +#if !defined(__LP64__) || !__LP64__ + +// NSInteger on 32bit +static NSInteger DynamicInteger32Getter(id self, SEL sel) { + // get an NSInteger (NSNumber) from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [self JSONValueForKey:jsonKey]; + num = GTL_EnsureNSNumber(num); + NSInteger result = [num integerValue]; + return result; + } + return 0; +} + +static void DynamicInteger32Setter(id self, SEL sel, NSInteger val) { + // save an NSInteger (NSNumber) into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [NSNumber numberWithInteger:val]; + [self setJSONValue:num forKey:jsonKey]; + } +} + +// NSUInteger on 32bit +static NSUInteger DynamicUInteger32Getter(id self, SEL sel) { + // get an NSUInteger (NSNumber) from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [self JSONValueForKey:jsonKey]; + num = GTL_EnsureNSNumber(num); + NSUInteger result = [num unsignedIntegerValue]; + return result; + } + return 0; +} + +static void DynamicUInteger32Setter(id self, SEL sel, NSUInteger val) { + // save an NSUInteger (NSNumber) into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [NSNumber numberWithUnsignedInteger:val]; + [self setJSONValue:num forKey:jsonKey]; + } +} + +#endif // !__LP64__ + +// NSInteger on 64bit, long long on 32bit and 64bit +static long long DynamicLongLongGetter(id self, SEL sel) { + // get a long long (NSNumber) from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [self JSONValueForKey:jsonKey]; + num = GTL_EnsureNSNumber(num); + long long result = [num longLongValue]; + return result; + } + return 0; +} + +static void DynamicLongLongSetter(id self, SEL sel, long long val) { + // save a long long (NSNumber) into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [NSNumber numberWithLongLong:val]; + [self setJSONValue:num forKey:jsonKey]; + } +} + +// NSUInteger on 64bit, unsiged long long on 32bit and 64bit +static unsigned long long DynamicULongLongGetter(id self, SEL sel) { + // get an unsigned long long (NSNumber) from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [self JSONValueForKey:jsonKey]; + num = GTL_EnsureNSNumber(num); + unsigned long long result = [num unsignedLongLongValue]; + return result; + } + return 0; +} + +static void DynamicULongLongSetter(id self, SEL sel, unsigned long long val) { + // save an unsigned long long (NSNumber) into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [NSNumber numberWithUnsignedLongLong:val]; + [self setJSONValue:num forKey:jsonKey]; + } +} + +// float +static float DynamicFloatGetter(id self, SEL sel) { + // get a float (NSNumber) from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [self JSONValueForKey:jsonKey]; + num = GTL_EnsureNSNumber(num); + float result = [num floatValue]; + return result; + } + return 0.0f; +} + +static void DynamicFloatSetter(id self, SEL sel, float val) { + // save a float (NSNumber) into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [NSNumber numberWithFloat:val]; + [self setJSONValue:num forKey:jsonKey]; + } +} + +// double +static double DynamicDoubleGetter(id self, SEL sel) { + // get a double (NSNumber) from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [self JSONValueForKey:jsonKey]; + num = GTL_EnsureNSNumber(num); + double result = [num doubleValue]; + return result; + } + return 0.0; +} + +static void DynamicDoubleSetter(id self, SEL sel, double val) { + // save a double (NSNumber) into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [NSNumber numberWithDouble:val]; + [self setJSONValue:num forKey:jsonKey]; + } +} + +// BOOL +static BOOL DynamicBooleanGetter(id self, SEL sel) { + // get a BOOL (NSNumber) from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [self JSONValueForKey:jsonKey]; + BOOL flag = [num boolValue]; + return flag; + } + return NO; +} + +static void DynamicBooleanSetter(id self, SEL sel, BOOL val) { + // save a BOOL (NSNumber) into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSNumber *num = [NSNumber numberWithBool:val]; + [self setJSONValue:num forKey:jsonKey]; + } +} + +// NSString +static NSString *DynamicStringGetter(id self, SEL sel) { + // get an NSString from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + + NSString *str = [self JSONValueForKey:jsonKey]; + return str; + } + return nil; +} + +static void DynamicStringSetter(id self, SEL sel, + NSString *str) { + // save an NSString into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + NSString *copiedStr = [str copy]; + [self setJSONValue:copiedStr forKey:jsonKey]; + [copiedStr release]; + } +} + +// GTLDateTime +static GTLDateTime *DynamicDateTimeGetter(id self, SEL sel) { + // get a GTLDateTime from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + + // Return the cached object before creating on demand. + GTLDateTime *cachedDateTime = [self cacheChildForKey:jsonKey]; + if (cachedDateTime != nil) { + return cachedDateTime; + } + NSString *str = [self JSONValueForKey:jsonKey]; + id cacheValue, resultValue; + if (![str isKindOfClass:[NSNull class]]) { + GTLDateTime *dateTime = [GTLDateTime dateTimeWithRFC3339String:str]; + + cacheValue = dateTime; + resultValue = dateTime; + } else { + cacheValue = nil; + resultValue = [NSNull null]; + } + [self setCacheChild:cacheValue forKey:jsonKey]; + return resultValue; + } + return nil; +} + +static void DynamicDateTimeSetter(id self, SEL sel, + GTLDateTime *dateTime) { + // save an GTLDateTime into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + id cacheValue, jsonValue; + if (![dateTime isKindOfClass:[NSNull class]]) { + jsonValue = [dateTime stringValue]; + cacheValue = dateTime; + } else { + jsonValue = [NSNull null]; + cacheValue = nil; + } + + [self setJSONValue:jsonValue forKey:jsonKey]; + [self setCacheChild:cacheValue forKey:jsonKey]; + } +} + +// NSNumber +static NSNumber *DynamicNumberGetter(id self, SEL sel) { + // get an NSNumber from the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + + NSNumber *num = [self JSONValueForKey:jsonKey]; + num = GTL_EnsureNSNumber(num); + return num; + } + return nil; +} + +static void DynamicNumberSetter(id self, SEL sel, + NSNumber *num) { + // save an NSNumber into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + [self setJSONValue:num forKey:jsonKey]; + } +} + +// GTLObject +static GTLObject *DynamicObjectGetter(id self, SEL sel) { + // get a GTLObject from the JSON dictionary + NSString *jsonKey = nil; + Class returnClass = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:&returnClass + containedClass:NULL + jsonKey:&jsonKey]) { + + // Return the cached object before creating on demand. + GTLObject *cachedObj = [self cacheChildForKey:jsonKey]; + if (cachedObj != nil) { + return cachedObj; + } + NSMutableDictionary *dict = [self JSONValueForKey:jsonKey]; + if ([dict isKindOfClass:[NSMutableDictionary class]]) { + // get the class of the object being returned, and instantiate it + if (returnClass == Nil) { + returnClass = [GTLObject class]; + } + + NSDictionary *surrogates = self.surrogates; + GTLObject *obj = [GTLObject objectForJSON:dict + defaultClass:returnClass + surrogates:surrogates + batchClassMap:nil]; + [self setCacheChild:obj forKey:jsonKey]; + return obj; + } else if ([dict isKindOfClass:[NSNull class]]) { + [self setCacheChild:nil forKey:jsonKey]; + return (id) [NSNull null]; + } else if (dict != nil) { + // unexpected; probably got a string -- let the caller figure it out + GTL_DEBUG_LOG(@"GTLObject: unexpected JSON: %@.%@ should be a dictionary, actually is a %@:\n%@", + NSStringFromClass(selfClass), NSStringFromSelector(sel), + NSStringFromClass([dict class]), dict); + return (GTLObject *)dict; + } + } + return nil; +} + +static void DynamicObjectSetter(id self, SEL sel, + GTLObject *obj) { + // save a GTLObject into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + id cacheValue, jsonValue; + if (![obj isKindOfClass:[NSNull class]]) { + NSMutableDictionary *dict = [obj JSON]; + if (dict == nil && obj != nil) { + // adding an empty object; it should have a JSON dictionary so it can + // hold future assignments + obj.JSON = [NSMutableDictionary dictionary]; + jsonValue = obj.JSON; + } else { + jsonValue = dict; + } + cacheValue = obj; + } else { + jsonValue = [NSNull null]; + cacheValue = nil; + } + [self setJSONValue:jsonValue forKey:jsonKey]; + [self setCacheChild:cacheValue forKey:jsonKey]; + } +} + +// get an NSArray of GTLObjects, NSStrings, or NSNumbers from the +// JSON dictionary for this object +static NSMutableArray *DynamicArrayGetter(id self, SEL sel) { + NSString *jsonKey = nil; + Class containedClass = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:&containedClass + jsonKey:&jsonKey]) { + + // Return the cached array before creating on demand. + NSMutableArray *cachedArray = [self cacheChildForKey:jsonKey]; + if (cachedArray != nil) { + return cachedArray; + } + NSMutableArray *result = nil; + NSArray *array = [self JSONValueForKey:jsonKey]; + if (array != nil) { + if ([array isKindOfClass:[NSArray class]]) { + NSDictionary *surrogates = self.surrogates; + result = [GTLRuntimeCommon objectFromJSON:array + defaultClass:containedClass + surrogates:surrogates + isCacheable:NULL]; + } else { +#if DEBUG + if (![array isKindOfClass:[NSNull class]]) { + GTL_DEBUG_LOG(@"GTLObject: unexpected JSON: %@.%@ should be an array, actually is a %@:\n%@", + NSStringFromClass(selfClass), NSStringFromSelector(sel), + NSStringFromClass([array class]), array); + } +#endif + result = (NSMutableArray *)array; + } + } + + [self setCacheChild:result forKey:jsonKey]; + return result; + } + return nil; +} + +static void DynamicArraySetter(id self, SEL sel, + NSMutableArray *array) { + // save an array of GTLObjects objects into the JSON dictionary + NSString *jsonKey = nil; + Class selfClass = [self class]; + Class containedClass = nil; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:&containedClass + jsonKey:&jsonKey]) { + id json = [GTLRuntimeCommon jsonFromAPIObject:array + expectedClass:containedClass + isCacheable:NULL]; + [self setJSONValue:json forKey:jsonKey]; + [self setCacheChild:array forKey:jsonKey]; + } +} + +// type 'id' +static id DynamicNSObjectGetter(id self, SEL sel) { + NSString *jsonKey = nil; + Class returnClass = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:&returnClass + containedClass:NULL + jsonKey:&jsonKey]) { + + // Return the cached object before creating on demand. + id cachedObj = [self cacheChildForKey:jsonKey]; + if (cachedObj != nil) { + return cachedObj; + } + + id jsonObj = [self JSONValueForKey:jsonKey]; + if (jsonObj != nil) { + BOOL shouldCache = NO; + NSDictionary *surrogates = self.surrogates; + id result = [GTLRuntimeCommon objectFromJSON:jsonObj + defaultClass:nil + surrogates:surrogates + isCacheable:&shouldCache]; + + [self setCacheChild:(shouldCache ? result : nil) + forKey:jsonKey]; + return result; + } + } + return nil; +} + +static void DynamicNSObjectSetter(id self, SEL sel, id obj) { + NSString *jsonKey = nil; + Class selfClass = [self class]; + if ([GTLRuntimeCommon getStoredDispatchForClass:selfClass + selector:sel + returnClass:NULL + containedClass:NULL + jsonKey:&jsonKey]) { + BOOL shouldCache = NO; + id json = [GTLRuntimeCommon jsonFromAPIObject:obj + expectedClass:Nil + isCacheable:&shouldCache]; + [self setJSONValue:json forKey:jsonKey]; + [self setCacheChild:(shouldCache ? obj : nil) + forKey:jsonKey]; + } +} + +#pragma mark Runtime lookup support + +static objc_property_t PropertyForSel(Class startClass, + SEL sel, BOOL isSetter, + Class *outFoundClass) { + const char *selName = sel_getName(sel); + const char *baseName = selName; + size_t baseNameLen = strlen(baseName); + if (isSetter) { + baseName += 3; // skip "set" + baseNameLen -= 4; // subtract "set" and the final colon + } + + // walk from this class up the hierarchy to the ancestor class + Class topClass = class_getSuperclass([startClass ancestorClass]); + for (Class currClass = startClass; + currClass != topClass; + currClass = class_getSuperclass(currClass)) { + // step through this class's properties + objc_property_t foundProp = NULL; + objc_property_t *properties = class_copyPropertyList(currClass, NULL); + if (properties) { + for (objc_property_t *prop = properties; *prop != NULL; ++prop) { + const char *propAttrs = property_getAttributes(*prop); + const char *dynamicMarker = strstr(propAttrs, ",D"); + if (!dynamicMarker || + (dynamicMarker[2] != 0 && dynamicMarker[2] != ',' )) { + // It isn't dynamic, skip it. + continue; + } + + if (!isSetter) { + // See if this property has an explicit getter=. (the attributes always start with a T, + // so we can check for the leading ','. + const char *getterMarker = strstr(propAttrs, ",G"); + if (getterMarker) { + const char *getterStart = getterMarker + 2; + const char *getterEnd = getterStart; + while ((*getterEnd != 0) && (*getterEnd != ',')) { + ++getterEnd; + } + size_t getterLen = (size_t)(getterEnd - getterStart); + if ((strncmp(selName, getterStart, getterLen) == 0) + && (selName[getterLen] == 0)) { + // return the actual property + foundProp = *prop; + // if requested, return the class containing the property + if (outFoundClass) *outFoundClass = currClass; + break; + } + } // if (getterMarker) + } // if (!isSetter) + + // Search for an exact-name match (a getter), but case-insensitive on the + // first character (in case baseName comes from a setter) + const char *propName = property_getName(*prop); + size_t propNameLen = strlen(propName); + if (baseNameLen == propNameLen + && strncasecmp(baseName, propName, 1) == 0 + && (baseNameLen <= 1 + || strncmp(baseName + 1, propName + 1, baseNameLen - 1) == 0)) { + // return the actual property + foundProp = *prop; + + // if requested, return the class containing the property + if (outFoundClass) *outFoundClass = currClass; + break; + } + } // for (prop in properties) + free(properties); + } + if (foundProp) return foundProp; + } + + // not found; this occasionally happens when the system looks for a method + // like "getFoo" or "descriptionWithLocale:indent:" + return NULL; +} + +typedef struct { + const char *attributePrefix; + + const char *setterEncoding; + IMP setterFunction; + const char *getterEncoding; + IMP getterFunction; + + // These are the "fixed" return classes, but some properties will require + // looking up the return class instead (because it is a subclass of + // GTLObject). + const char *returnClassName; + Class returnClass; + BOOL extractReturnClass; + +} GTLDynamicImpInfo; + +static const GTLDynamicImpInfo *DynamicImpInfoForProperty(objc_property_t prop, + Class *outReturnClass) { + + if (outReturnClass) *outReturnClass = nil; + + // dynamic method resolution: + // http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html + // + // property runtimes: + // http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html + + // Get and parse the property attributes, which look something like + // T@"NSString",&,D,P + // Ti,D -- NSInteger on 32bit + // Tq,D -- NSInteger on 64bit, long long on 32bit & 64bit + // TB,D -- BOOL comes as bool on 64bit iOS + // Tc,D -- BOOL comes as char otherwise + // T@"NSString",D + // T@"GTLLink",D + // T@"NSArray",D + + + static GTLDynamicImpInfo kImplInfo[] = { +#if !defined(__LP64__) || !__LP64__ + { // NSInteger on 32bit + "Ti", + "v@:i", (IMP)DynamicInteger32Setter, + "i@:", (IMP)DynamicInteger32Getter, + nil, nil, + NO + }, + { // NSUInteger on 32bit + "TI", + "v@:I", (IMP)DynamicUInteger32Setter, + "I@:", (IMP)DynamicUInteger32Getter, + nil, nil, + NO + }, +#endif + { // NSInteger on 64bit, long long on 32bit and 64bit. + "Tq", + "v@:q", (IMP)DynamicLongLongSetter, + "q@:", (IMP)DynamicLongLongGetter, + nil, nil, + NO + }, + { // NSUInteger on 64bit, long long on 32bit and 64bit. + "TQ", + "v@:Q", (IMP)DynamicULongLongSetter, + "Q@:", (IMP)DynamicULongLongGetter, + nil, nil, + NO + }, + { // float + "Tf", + "v@:f", (IMP)DynamicFloatSetter, + "f@:", (IMP)DynamicFloatGetter, + nil, nil, + NO + }, + { // double + "Td", + "v@:d", (IMP)DynamicDoubleSetter, + "d@:", (IMP)DynamicDoubleGetter, + nil, nil, + NO + }, +// This conditional matches the one in iPhoneOS.platform version of +// that controls the definition of BOOL. +#if !defined(OBJC_HIDE_64) && TARGET_OS_IPHONE && (defined(__LP64__) && __LP64__) + { // BOOL as bool + "TB", + "v@:B", (IMP)DynamicBooleanSetter, + "B@:", (IMP)DynamicBooleanGetter, + nil, nil, + NO + }, +#else + { // BOOL as char + "Tc", + "v@:c", (IMP)DynamicBooleanSetter, + "c@:", (IMP)DynamicBooleanGetter, + nil, nil, + NO + }, +#endif + { // NSString + "T@\"NSString\"", + "v@:@", (IMP)DynamicStringSetter, + "@@:", (IMP)DynamicStringGetter, + "NSString", nil, + NO + }, + { // NSNumber + "T@\"NSNumber\"", + "v@:@", (IMP)DynamicNumberSetter, + "@@:", (IMP)DynamicNumberGetter, + "NSNumber", nil, + NO + }, + { // GTLDateTime +#if !defined(GTL_TARGET_NAMESPACE) + "T@\"GTLDateTime\"", + "v@:@", (IMP)DynamicDateTimeSetter, + "@@:", (IMP)DynamicDateTimeGetter, + "GTLDateTime", nil, + NO +#else + "T@\"" GTL_TARGET_NAMESPACE_STRING "_" "GTLDateTime\"", + "v@:@", (IMP)DynamicDateTimeSetter, + "@@:", (IMP)DynamicDateTimeGetter, + GTL_TARGET_NAMESPACE_STRING "_" "GTLDateTime", nil, + NO +#endif + }, + { // NSArray with type + "T@\"NSArray\"", + "v@:@", (IMP)DynamicArraySetter, + "@@:", (IMP)DynamicArrayGetter, + "NSArray", nil, + NO + }, + { // id (any of the objects above) + "T@,", + "v@:@", (IMP)DynamicNSObjectSetter, + "@@:", (IMP)DynamicNSObjectGetter, + "NSObject", nil, + NO + }, + { // GTLObject - Last, cause it's a special case and prefix is general + "T@\"", + "v@:@", (IMP)DynamicObjectSetter, + "@@:", (IMP)DynamicObjectGetter, + nil, nil, + YES + }, + }; + + static BOOL hasLookedUpClasses = NO; + if (!hasLookedUpClasses) { + // Unfortunately, you can't put [NSString class] into the static structure, + // so this lookup has to be done at runtime. + hasLookedUpClasses = YES; + for (uint32_t idx = 0; idx < sizeof(kImplInfo)/sizeof(kImplInfo[0]); ++idx) { + if (kImplInfo[idx].returnClassName) { + kImplInfo[idx].returnClass = objc_getClass(kImplInfo[idx].returnClassName); + NSCAssert1(kImplInfo[idx].returnClass != nil, + @"GTLRuntimeCommon: class lookup failed: %s", kImplInfo[idx].returnClassName); + } + } + } + + const char *attr = property_getAttributes(prop); + + const char *dynamicMarker = strstr(attr, ",D"); + if (!dynamicMarker || + (dynamicMarker[2] != 0 && dynamicMarker[2] != ',' )) { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: property %s isn't dynamic, attributes %s", + property_getName(prop), attr ? attr : "(nil)"); + return NULL; + } + + const GTLDynamicImpInfo *result = NULL; + + // Cycle over the list + + for (uint32_t idx = 0; idx < sizeof(kImplInfo)/sizeof(kImplInfo[0]); ++idx) { + const char *attributePrefix = kImplInfo[idx].attributePrefix; + if (strncmp(attr, attributePrefix, strlen(attributePrefix)) == 0) { + result = &kImplInfo[idx]; + if (outReturnClass) *outReturnClass = result->returnClass; + break; + } + } + + if (result == NULL) { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: unexpected attributes %s for property %s", + attr ? attr : "(nil)", property_getName(prop)); + return NULL; + } + + if (result->extractReturnClass && outReturnClass) { + + // add a null at the next quotation mark + char *attrCopy = strdup(attr); + char *classNameStart = attrCopy + 3; + char *classNameEnd = strstr(classNameStart, "\""); + if (classNameEnd) { + *classNameEnd = '\0'; + + // Lookup the return class + *outReturnClass = objc_getClass(classNameStart); + if (*outReturnClass == nil) { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: did not find class with name \"%s\" " + "for property \"%s\" with attributes \"%s\"", + classNameStart, property_getName(prop), attr); + } + } else { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: Failed to find end of class name for " + "property \"%s\" with attributes \"%s\"", + property_getName(prop), attr); + } + free(attrCopy); + } + + return result; +} + +#pragma mark Runtime - wiring point + ++ (BOOL)resolveInstanceMethod:(SEL)sel onClass:(Class)onClass { + // dynamic method resolution: + // http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html + // + // property runtimes: + // http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html + + const char *selName = sel_getName(sel); + size_t selNameLen = strlen(selName); + char lastChar = selName[selNameLen - 1]; + BOOL isSetter = (lastChar == ':'); + + // look for a declared property matching this selector name exactly + Class foundClass = nil; + + objc_property_t prop = PropertyForSel(onClass, sel, isSetter, &foundClass); + if (prop != NULL && foundClass != nil) { + + Class returnClass = nil; + const GTLDynamicImpInfo *implInfo = DynamicImpInfoForProperty(prop, + &returnClass); + if (implInfo == NULL) { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: unexpected return type class %s for " + "property \"%s\" of class \"%s\"", + returnClass ? class_getName(returnClass) : "", + property_getName(prop), + class_getName(onClass)); + } + + if (implInfo != NULL) { + IMP imp = ( isSetter ? implInfo->setterFunction : implInfo->getterFunction ); + const char *encoding = ( isSetter ? implInfo->setterEncoding : implInfo->getterEncoding ); + + class_addMethod(foundClass, sel, imp, encoding); + + const char *propName = property_getName(prop); + NSString *propStr = [NSString stringWithUTF8String:propName]; + + // replace the property name with the proper JSON key if it's + // special-cased with a map in the found class; otherwise, the property + // name is the JSON key + NSDictionary *keyMap = + [[foundClass ancestorClass] propertyToJSONKeyMapForClass:foundClass]; + NSString *jsonKey = [keyMap objectForKey:propStr]; + if (jsonKey == nil) { + jsonKey = propStr; + } + + Class containedClass = nil; + + // For arrays we need to look up what the contained class is. + if (imp == (IMP)DynamicArraySetter || imp == (IMP)DynamicArrayGetter) { + NSDictionary *classMap = + [[foundClass ancestorClass] arrayPropertyToClassMapForClass:foundClass]; + containedClass = [classMap objectForKey:jsonKey]; + if (containedClass == Nil) { + GTL_DEBUG_LOG(@"GTLRuntimeCommon: expected array item class for " + "property \"%s\" of class \"%s\"", + property_getName(prop), class_getName(foundClass)); + } + } + + // save the dispatch info to the cache + [GTLRuntimeCommon setStoredDispatchForClass:foundClass + selector:sel + returnClass:returnClass + containedClass:containedClass + jsonKey:jsonKey]; + return YES; + } + } + + return NO; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLService.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLService.h new file mode 100755 index 0000000..7415274 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLService.h @@ -0,0 +1,597 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLService.h +// + +// Service object documentation: +// https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Services_and_Tickets + +#import + +#import "GTLDefines.h" + +// Fetcher bridging macros -- Internal library use only. +// +// GTL_USE_SESSION_FETCHER should be set to force the GTL library to use +// GTMSessionFetcher rather than the older GTMHTTPFetcher. The session +// fetcher requires iOS 7/OS X 10.9 and supports out-of-process uploads. + +#ifndef GTL_USE_SESSION_FETCHER + #if GTM_USE_SESSION_FETCHER + #define GTL_USE_SESSION_FETCHER 1 + #else + #define GTL_USE_SESSION_FETCHER 0 + #endif // GTM_USE_SESSION_FETCHER +#endif // GTL_USE_SESSION_FETCHER + +#if GTL_USE_SESSION_FETCHER + #define GTLUploadFetcherClass GTMSessionUploadFetcher + #define GTLUploadFetcherClassStr @"GTMSessionUploadFetcher" + + #import "GTMSessionFetcher.h" + #import "GTMSessionFetcherService.h" +#else + // !GTL_USE_SESSION_FETCHER + #define GTLUploadFetcherClass GTMHTTPUploadFetcher + #define GTLUploadFetcherClassStr @"GTMHTTPUploadFetcher" + + #import "GTMHTTPFetcher.h" + #import "GTMHTTPFetcherService.h" +#endif // GTL_USE_SESSION_FETCHER + +#import "GTLBatchQuery.h" +#import "GTLBatchResult.h" +#import "GTLDateTime.h" +#import "GTLErrorObject.h" +#import "GTLFramework.h" +#import "GTLJSONParser.h" +#import "GTLObject.h" +#import "GTLQuery.h" +#import "GTLUtilities.h" + +// Error domains +extern NSString *const kGTLServiceErrorDomain; +enum { + kGTLErrorQueryResultMissing = -3000, + kGTLErrorWaitTimedOut = -3001 +}; + +extern NSString *const kGTLJSONRPCErrorDomain; + +// We'll consistently store the server error string in the userInfo under +// this key +extern NSString *const kGTLServerErrorStringKey; + +extern Class const kGTLUseRegisteredClass; + +extern NSUInteger const kGTLStandardUploadChunkSize; + +// When servers return us structured JSON errors, the NSError will +// contain a GTLErrorObject in the userInfo dictionary under the key +// kGTLStructuredErrorsKey +extern NSString *const kGTLStructuredErrorKey; + +// When specifying an ETag for updating or deleting a single entry, use +// kGTLETagWildcard to tell the server to replace the current value +// unconditionally. Do not use this in entries in a batch feed. +extern NSString *const kGTLETagWildcard; + +// Notifications when parsing of a fetcher feed or entry begins or ends +extern NSString *const kGTLServiceTicketParsingStartedNotification; +extern NSString *const kGTLServiceTicketParsingStoppedNotification ; + +@class GTLServiceTicket; + +// Block types used for fetch callbacks + +typedef void (^GTLServiceCompletionHandler)(GTLServiceTicket *ticket, id object, NSError *error); + +typedef void (^GTLServiceUploadProgressBlock)(GTLServiceTicket *ticket, unsigned long long numberOfBytesRead, unsigned long long dataLength); + +typedef BOOL (^GTLServiceRetryBlock)(GTLServiceTicket *ticket, BOOL suggestedWillRetry, NSError *error); + +#pragma mark - + +// +// Service base class +// + +@interface GTLService : NSObject { + @private + NSOperationQueue *parseQueue_; + NSString *userAgent_; + GTMBridgeFetcherService *fetcherService_; + NSString *userAgentAddition_; + + NSMutableDictionary *serviceProperties_; // initial values for properties in future tickets + + NSDictionary *surrogates_; // initial value for surrogates in future tickets + + SEL uploadProgressSelector_; // optional + + GTLServiceRetryBlock retryBlock_; + GTLServiceUploadProgressBlock uploadProgressBlock_; + + NSUInteger uploadChunkSize_; // zero when uploading via multi-part MIME http body + + BOOL isRetryEnabled_; // user allows auto-retries + SEL retrySelector_; // optional; set with setServiceRetrySelector + NSTimeInterval maxRetryInterval_; // default to 600. seconds + + BOOL shouldFetchNextPages_; + + BOOL allowInsecureQueries_; + + NSString *apiKey_; + BOOL isRESTDataWrapperRequired_; + NSString *apiVersion_; + NSURL *rpcURL_; + NSURL *rpcUploadURL_; + NSDictionary *urlQueryParameters_; + NSDictionary *additionalHTTPHeaders_; +} + +#pragma mark Query Execution + +// The finishedSelector has a signature matching: +// +// - (void)serviceTicket:(GTLServiceTicket *)ticket +// finishedWithObject:(GTLObject *)object +// error:(NSError *)error +// +// If an error occurs, the error parameter will be non-nil. Otherwise, +// the object parameter will point to a GTLObject, if any was returned by +// the fetch. (Delete fetches return no object, so the second parameter will +// be nil.) +// +// If the query object is a GTLBatchQuery, the object passed to the callback +// will be a GTLBatchResult; see the batch query documentation: +// https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Batch_Operations + +- (GTLServiceTicket *)executeQuery:(id)query + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)executeQuery:(id)query + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +// Automatic page fetches +// +// Tickets can optionally do a sequence of fetches for queries where +// repeated requests with nextPageToken or nextStartIndex values is required to +// retrieve items of all pages of the response collection. The client's +// callback is invoked only when all items have been retrieved, or an error has +// occurred. During the fetch, the items accumulated so far are available from +// the ticket. +// +// Note that the final object may be a combination of multiple page responses +// so it may not be the same as if all results had been returned in a single +// page. Some fields of the response such as total item counts may reflect only +// the final page's values. +// +// Automatic page fetches will return an error if more than 25 page fetches are +// required. For debug builds, this will log a warning to the console when more +// than 2 page fetches occur, as a reminder that the query's maxResults +// parameter should probably be increased to specify more items returned per +// page. +// +// Default value is NO. +@property (nonatomic, assign) BOOL shouldFetchNextPages; + +// Retrying; see comments on retry support at the top of GTMHTTPFetcher. +// +// Default value is NO. +@property (nonatomic, assign, getter=isRetryEnabled) BOOL retryEnabled; + +// Some services require a developer key for quotas and limits. Setting this +// will include it on all request sent to this service via a GTLQuery class. +@property (nonatomic, copy) NSString *APIKey; + +// An authorizer adds user authentication headers to the request as needed. +@property (nonatomic, retain) id authorizer; + +// Retry selector is optional for retries. +// +// If present, it should have the signature: +// -(BOOL)ticket:(GTLServiceTicket *)ticket willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error +// and return YES to cause a retry. Note that unlike the fetcher retry +// selector, this selector's first argument is a ticket, not a fetcher. + +@property (nonatomic, assign) SEL retrySelector; +@property (copy) GTLServiceRetryBlock retryBlock; + +@property (nonatomic, assign) NSTimeInterval maxRetryInterval; + +// +// Fetches may be done using RPC or REST APIs, without creating +// a GTLQuery object +// + +#pragma mark RPC Fetch Methods + +// +// These methods may be used for RPC fetches without creating a GTLQuery object +// + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + objectClass:(Class)objectClass + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +#pragma mark REST Fetch Methods + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)objectURL + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)objectURL + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchPublicObjectWithURL:(NSURL *)objectURL + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectByInsertingObject:(GTLObject *)bodyToPut + forURL:(NSURL *)destinationURL + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1,2)); + +- (GTLServiceTicket *)fetchObjectByUpdatingObject:(GTLObject *)bodyToPut + forURL:(NSURL *)destinationURL + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1,2)); + +- (GTLServiceTicket *)deleteResourceURL:(NSURL *)destinationURL + ETag:(NSString *)etagOrNil + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)objectURL + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectByInsertingObject:(GTLObject *)bodyToPut + forURL:(NSURL *)destinationURL + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +- (GTLServiceTicket *)fetchObjectByUpdatingObject:(GTLObject *)bodyToPut + forURL:(NSURL *)destinationURL + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +- (GTLServiceTicket *)deleteResourceURL:(NSURL *)destinationURL + ETag:(NSString *)etagOrNil + completionHandler:(GTLServiceCompletionHandler)handler GTL_NONNULL((1)); + +#pragma mark User Properties + +// Properties and userData are supported for client convenience. +// +// Property keys beginning with _ are reserved by the library. +// +// The service properties dictionary is copied to become the initial property +// dictionary for each ticket. +- (void)setServiceProperty:(id)obj forKey:(NSString *)key GTL_NONNULL((2)); // pass nil obj to remove property +- (id)servicePropertyForKey:(NSString *)key GTL_NONNULL((1)); + +@property (nonatomic, copy) NSDictionary *serviceProperties; + +// The service userData becomes the initial value for each future ticket's +// userData. +@property (nonatomic, retain) id serviceUserData; + +#pragma mark Request Settings + +// Set the surrogates to be used for future tickets. Surrogates are subclasses +// to be used instead of standard classes when creating objects from the JSON. +// For example, this code will make the framework generate objects +// using MyCalendarItemSubclass instead of GTLItemCalendar and +// MyCalendarEventSubclass instead of GTLItemCalendarEvent. +// +// NSDictionary *surrogates = [NSDictionary dictionaryWithObjectsAndKeys: +// [MyCalendarEntrySubclass class], [GTLItemCalendar class], +// [MyCalendarEventSubclass class], [GTLItemCalendarEvent class], +// nil]; +// [calendarService setServiceSurrogates:surrogates]; +// +@property (nonatomic, retain) NSDictionary *surrogates; + +// On iOS 4 and later, the fetch may optionally continue in the background +// until finished or stopped by OS expiration. +// +// The default value is NO. +// +// For Mac OS X, background fetches are always supported, and this property +// is ignored. +@property (nonatomic, assign) BOOL shouldFetchInBackground; + +// Callbacks can be invoked on an operation queue rather than via the run loop +// starting on 10.7 and iOS 6. Do not specify both run loop modes and an +// operation queue. Specifying a delegate queue typically looks like this: +// +// service.delegateQueue = [[[NSOperationQueue alloc] init] autorelease]; +// +// Since the callbacks will be on a thread of the operation queue, the client +// may re-dispatch from the callbacks to a known dispatch queue or to the +// main queue. +@property (nonatomic, retain) NSOperationQueue *delegateQueue; + +// Run loop modes are used for scheduling NSURLConnections. +// +// The default value, nil, schedules connections using the current run +// loop mode. To use the service during a modal dialog, be sure to specify +// NSModalPanelRunLoopMode as one of the modes. +@property (nonatomic, retain) NSArray *runLoopModes; + +// Normally, API requests must be made only via SSL to protect the user's +// data and the authentication token. This property allows the application +// to make non-SSL requests and localhost requests for testing. +// +// Defaults to NO. +@property (nonatomic, assign) BOOL allowInsecureQueries; + +// Applications needing an additional identifier in the server logs may specify +// one. +@property (nonatomic, copy) NSString *userAgentAddition; + +// Applications have a default user-agent based on the application signature +// in the Info.plist settings. Most applications should not explicitly set +// this property. +@property (nonatomic, copy) NSString *userAgent; + +// The request user agent includes the library and OS version appended to the +// base userAgent, along with the optional addition string. +@property (nonatomic, readonly) NSString *requestUserAgent; + +// Applications may call requestForURL:httpMethod to get a request with the +// proper user-agent and ETag headers +// +// For http method, pass nil (for default GET method), POST, PUT, or DELETE +- (NSMutableURLRequest *)requestForURL:(NSURL *)url + ETag:(NSString *)etagOrNil + httpMethod:(NSString *)httpMethodOrNil GTL_NONNULL((1)); + +// objectRequestForURL returns an NSMutableURLRequest for a JSON GTL object +// +// The object is the object being sent to the server, or nil; +// the http method may be nil for GET, or POST, PUT, DELETE +- (NSMutableURLRequest *)objectRequestForURL:(NSURL *)url + object:(GTLObject *)object + ETag:(NSString *)etag + httpMethod:(NSString *)httpMethod + isREST:(BOOL)isREST + additionalHeaders:(NSDictionary *)additionalHeaders + ticket:(GTLServiceTicket *)ticket GTL_NONNULL((1)); + +// The queue used for parsing JSON responses (previously this property +// was called operationQueue) +@property (nonatomic, retain) NSOperationQueue *parseQueue; + +// The fetcher service object issues the fetcher instances +// for this API service +@property (nonatomic, retain) GTMBridgeFetcherService *fetcherService; + +// Default storage for cookies is in the service object's fetchHistory. +// +// Apps that want to share cookies between all standalone fetchers and the +// service object may specify static application-wide cookie storage, +// kGTMHTTPFetcherCookieStorageMethodStatic. +#if !GTL_USE_SESSION_FETCHER +@property (nonatomic, assign) NSInteger cookieStorageMethod; +#endif + +// When sending REST style queries, should the payload be wrapped in a "data" +// element, and will the reply be wrapped in an "data" element. +@property (nonatomic, assign) BOOL isRESTDataWrapperRequired; + +// Any url query parameters to add to urls (useful for debugging with some +// services). +@property (copy) NSDictionary *urlQueryParameters; + +// Any extra http headers to set on requests for GTLObjects. +@property (copy) NSDictionary *additionalHTTPHeaders; + +// The service API version. +@property (nonatomic, copy) NSString *apiVersion; + +// The URL for sending RPC requests for this service. +@property (nonatomic, retain) NSURL *rpcURL; + +// The URL for sending RPC requests which initiate file upload. +@property (nonatomic, retain) NSURL *rpcUploadURL; + +// Set a non-zero value to enable uploading via chunked fetches +// (resumable uploads); typically this defaults to kGTLStandardUploadChunkSize +// for service subclasses that support chunked uploads +@property (nonatomic, assign) NSUInteger serviceUploadChunkSize; + +// Service subclasses may specify their own default chunk size ++ (NSUInteger)defaultServiceUploadChunkSize; + +// The service uploadProgressSelector becomes the initial value for each future +// ticket's uploadProgressSelector. +// +// The optional uploadProgressSelector will be called in the delegate as bytes +// are uploaded to the server. It should have a signature matching +// +// - (void)ticket:(GTLServiceTicket *)ticket +// hasDeliveredByteCount:(unsigned long long)numberOfBytesRead +// ofTotalByteCount:(unsigned long long)dataLength; +@property (nonatomic, assign) SEL uploadProgressSelector; + +@property (copy) GTLServiceUploadProgressBlock uploadProgressBlock; + +// Wait synchronously for fetch to complete (strongly discouraged) +// +// This just runs the current event loop until the fetch completes +// or the timout limit is reached. This may discard unexpected events +// that occur while spinning, so it's really not appropriate for use +// in serious applications. +// +// Returns true if an object was successfully fetched. If the wait +// timed out, returns false and the returned error is nil. +// +// The returned object or error, if any, will be already autoreleased +// +// This routine will likely be removed in some future releases of the library. +- (BOOL)waitForTicket:(GTLServiceTicket *)ticket + timeout:(NSTimeInterval)timeoutInSeconds + fetchedObject:(GTLObject **)outObjectOrNil + error:(NSError **)outErrorOrNil GTL_NONNULL((1)); +@end + +#pragma mark - + +// +// Ticket base class +// +@interface GTLServiceTicket : NSObject { + GTLService *service_; + + NSMutableDictionary *ticketProperties_; + NSDictionary *surrogates_; + + GTMBridgeFetcher *objectFetcher_; + SEL uploadProgressSelector_; + BOOL shouldFetchNextPages_; + BOOL isRetryEnabled_; + SEL retrySelector_; + NSTimeInterval maxRetryInterval_; + + GTLServiceRetryBlock retryBlock_; + GTLServiceUploadProgressBlock uploadProgressBlock_; + + GTLObject *postedObject_; + GTLObject *fetchedObject_; + id executingQuery_; + id originalQuery_; + NSError *fetchError_; + BOOL hasCalledCallback_; + NSUInteger pagesFetchedCounter_; + + NSString *apiKey_; + BOOL isREST_; + + NSOperation *parseOperation_; +} + ++ (id)ticketForService:(GTLService *)service; + +- (id)initWithService:(GTLService *)service; + +- (id)service; + +#pragma mark Execution Control +// if cancelTicket is called, the fetch is stopped if it is in progress, +// the callbacks will not be called, and the ticket will no longer be useful +// (though the client must still release the ticket if it retained the ticket) +- (void)cancelTicket; + +// chunked upload tickets may be paused +- (void)pauseUpload; +- (void)resumeUpload; +- (BOOL)isUploadPaused; + +@property (nonatomic, retain) GTMBridgeFetcher *objectFetcher; +@property (nonatomic, assign) SEL uploadProgressSelector; + +// Services which do not require an user authorization may require a developer +// API key for quota management +@property (nonatomic, copy) NSString *APIKey; + +#pragma mark User Properties + +// Properties and userData are supported for client convenience. +// +// Property keys beginning with _ are reserved by the library. +- (void)setProperty:(id)obj forKey:(NSString *)key GTL_NONNULL((1)); // pass nil obj to remove property +- (id)propertyForKey:(NSString *)key; + +@property (nonatomic, copy) NSDictionary *properties; +@property (nonatomic, retain) id userData; + +#pragma mark Payload + +@property (nonatomic, retain) GTLObject *postedObject; +@property (nonatomic, retain) GTLObject *fetchedObject; +@property (nonatomic, retain) id executingQuery; // Query currently being fetched by this ticket +@property (nonatomic, retain) id originalQuery; // Query used to create this ticket +- (GTLQuery *)queryForRequestID:(NSString *)requestID GTL_NONNULL((1)); // Returns the query from within the batch with the given id. + +@property (nonatomic, retain) NSDictionary *surrogates; + +#pragma mark Retry + +@property (nonatomic, assign, getter=isRetryEnabled) BOOL retryEnabled; +@property (nonatomic, assign) SEL retrySelector; +@property (copy) GTLServiceRetryBlock retryBlock; +@property (nonatomic, assign) NSTimeInterval maxRetryInterval; + +#pragma mark Status + +@property (nonatomic, readonly) NSInteger statusCode; // server status from object fetch +@property (nonatomic, retain) NSError *fetchError; +@property (nonatomic, assign) BOOL hasCalledCallback; + +#pragma mark Pagination + +@property (nonatomic, assign) BOOL shouldFetchNextPages; +@property (nonatomic, assign) NSUInteger pagesFetchedCounter; + +#pragma mark Upload + +@property (copy) GTLServiceUploadProgressBlock uploadProgressBlock; + +@end + + +// Category to provide opaque access to tickets stored in fetcher properties +@interface GTMBridgeFetcher (GTLServiceTicketAdditions) +- (id)ticket; +@end + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLService.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLService.m new file mode 100755 index 0000000..c1ea501 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLService.m @@ -0,0 +1,2524 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLService.m +// + +#import +#if TARGET_OS_MAC +#include +#endif + +#if TARGET_OS_IPHONE +#import +#endif + +#import "GTLService.h" + +NSString* const kGTLServiceErrorDomain = @"com.google.GTLServiceDomain"; +NSString* const kGTLJSONRPCErrorDomain = @"com.google.GTLJSONRPCErrorDomain"; +NSString* const kGTLServerErrorStringKey = @"error"; +Class const kGTLUseRegisteredClass = nil; +NSUInteger const kGTLStandardUploadChunkSize = NSUIntegerMax; +NSString* const kGTLStructuredErrorKey = @"GTLStructuredError"; +NSString* const kGTLETagWildcard = @"*"; + +NSString* const kGTLServiceTicketParsingStartedNotification = @"kGTLServiceTicketParsingStartedNotification"; +NSString* const kGTLServiceTicketParsingStoppedNotification = @"kGTLServiceTicketParsingStoppedNotification"; + + +static NSString *const kServiceUserDataPropertyKey = @"_userData"; + +static NSString* const kFetcherDelegateKey = @"_delegate"; +static NSString* const kFetcherObjectClassKey = @"_objectClass"; +static NSString* const kFetcherFinishedSelectorKey = @"_finishedSelector"; +static NSString* const kFetcherCompletionHandlerKey = @"_completionHandler"; +static NSString* const kFetcherTicketKey = @"_ticket"; +static NSString* const kFetcherFetchErrorKey = @"_fetchError"; +static NSString* const kFetcherParsingNotificationKey = @"_parseNotification"; +static NSString* const kFetcherParsedObjectKey = @"_parsedObject"; +static NSString* const kFetcherBatchClassMapKey = @"_batchClassMap"; +static NSString* const kFetcherCallbackThreadKey = @"_callbackThread"; +static NSString* const kFetcherCallbackRunLoopModesKey = @"_runLoopModes"; + +static const NSUInteger kMaxNumberOfNextPagesFetched = 25; + +// we'll enforce 50K chunks minimum just to avoid the server getting hit +// with too many small upload chunks +static const NSUInteger kMinimumUploadChunkSize = 50000; +static const NSUInteger kStandardUploadChunkSize = NSUIntegerMax; + +// Helper to get the ETag if it is defined on an object. +static NSString *ETagIfPresent(GTLObject *obj) { + NSString *result = [obj.JSON objectForKey:@"etag"]; + return result; +} + +@interface GTLServiceTicket () +@property (retain) NSOperation *parseOperation; +@property (assign) BOOL isREST; +@end + +// category to provide opaque access to tickets stored in fetcher properties +@implementation GTMBridgeFetcher (GTLServiceTicketAdditions) +- (id)ticket { + return [self propertyForKey:kFetcherTicketKey]; +} +@end + +// If the upload fetcher class is available, it can be used for chunked uploads +// +// We locally declare some methods of the upload fetcher so we +// do not need to import the header, as some projects may not have it available +@interface GTLUploadFetcherClass : GTMBridgeFetcher + +#if GTL_USE_SESSION_FETCHER ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTMSessionFetcherService *)fetcherServiceOrNil; + ++ (instancetype)uploadFetcherWithLocation:(NSURL *)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTMSessionFetcherService *)fetcherServiceOrNil; + +@property(strong) NSURL *uploadLocationURL; +@property(strong) NSData *uploadData; +@property(strong) NSURL *uploadFileURL; +@property(strong) NSFileHandle *uploadFileHandle; +#else ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + uploadData:(NSData *)data + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMBridgeFetcherService *)fetcherService; ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + uploadFileHandle:(NSFileHandle *)uploadFileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMBridgeFetcherService *)fetcherService; +// Use the old fetcher. ++ (instancetype)uploadFetcherWithLocation:(NSURL *)location + uploadFileHandle:(NSFileHandle *)fileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMBridgeFetcherService *)fetcherService; +#endif // GTL_USE_SESSION_FETCHER + +- (void)pauseFetching; +- (void)resumeFetching; +- (BOOL)isPaused; +@end + + +@interface GTLService () +- (void)prepareToParseObjectForFetcher:(GTMBridgeFetcher *)fetcher; +- (void)handleParsedObjectForFetcher:(GTMBridgeFetcher *)fetcher; +- (BOOL)fetchNextPageWithQuery:(GTLQuery *)query + delegate:(id)delegate + didFinishedSelector:(SEL)finishedSelector + completionHandler:(GTLServiceCompletionHandler)completionHandler + ticket:(GTLServiceTicket *)ticket; +- (id )nextPageQueryForQuery:(GTLQuery *)query + result:(GTLObject *)object + ticket:(GTLServiceTicket *)ticket; +- (GTLObject *)mergedNewResultObject:(GTLObject *)newResult + oldResultObject:(GTLObject *)oldResult + forQuery:(GTLQuery *)query; +- (GTLUploadFetcherClass *)uploadFetcherWithRequest:(NSURLRequest *)request + fetcherService:(GTMBridgeFetcherService *)fetcherService + params:(GTLUploadParameters *)uploadParams; ++ (void)invokeCallback:(SEL)callbackSel + target:(id)target + ticket:(id)ticket + object:(id)object + error:(id)error; +- (BOOL)invokeRetrySelector:(SEL)retrySelector + delegate:(id)delegate + ticket:(GTLServiceTicket *)ticket + willRetry:(BOOL)willRetry + error:(NSError *)error; +- (BOOL)objectFetcher:(GTMBridgeFetcher *)fetcher + willRetry:(BOOL)willRetry + forError:(NSError *)error; +- (void)objectFetcher:(GTMBridgeFetcher *)fetcher + finishedWithData:(NSData *)data + error:(NSError *)error; +- (void)parseObjectFromDataOfFetcher:(GTMBridgeFetcher *)fetcher; +@end + +@interface GTLObject (StandardProperties) +@property (retain) NSString *ETag; +@property (retain) NSString *nextPageToken; +@property (retain) NSNumber *nextStartIndex; +@end + +@implementation GTLService + +@synthesize userAgentAddition = userAgentAddition_, + fetcherService = fetcherService_, + parseQueue = parseQueue_, + shouldFetchNextPages = shouldFetchNextPages_, + surrogates = surrogates_, + uploadProgressSelector = uploadProgressSelector_, + retryEnabled = isRetryEnabled_, + retrySelector = retrySelector_, + maxRetryInterval = maxRetryInterval_, + APIKey = apiKey_, + isRESTDataWrapperRequired = isRESTDataWrapperRequired_, + urlQueryParameters = urlQueryParameters_, + additionalHTTPHeaders = additionalHTTPHeaders_, + apiVersion = apiVersion_, + rpcURL = rpcURL_, + rpcUploadURL = rpcUploadURL_, + allowInsecureQueries = allowInsecureQueries_, + retryBlock = retryBlock_, + uploadProgressBlock = uploadProgressBlock_; + ++ (Class)ticketClass { + return [GTLServiceTicket class]; +} + +- (id)init { + self = [super init]; + if (self) { + +#if GTL_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) + // For 10.6 and up, always use an operation queue + parseQueue_ = [[NSOperationQueue alloc] init]; +#elif !GTL_SKIP_PARSE_THREADING + // Avoid NSOperationQueue prior to 10.5.6, per + // http://www.mikeash.com/?page=pyblog/use-nsoperationqueue.html + SInt32 bcdSystemVersion = 0; + (void) Gestalt(gestaltSystemVersion, &bcdSystemVersion); + + if (bcdSystemVersion >= 0x1057) { + parseQueue_ = [[NSOperationQueue alloc] init]; + } +#else + // parseQueue_ defaults to nil, so parsing will be done immediately + // on the current thread +#endif + + fetcherService_ = [[GTMBridgeFetcherService alloc] init]; + + NSUInteger chunkSize = [[self class] defaultServiceUploadChunkSize]; + self.serviceUploadChunkSize = chunkSize; + } + return self; +} + +- (void)dealloc { + [parseQueue_ release]; + [userAgent_ release]; + [fetcherService_ release]; + [userAgentAddition_ release]; + [serviceProperties_ release]; + [surrogates_ release]; + [uploadProgressBlock_ release]; + [retryBlock_ release]; + [apiKey_ release]; + [apiVersion_ release]; + [rpcURL_ release]; + [rpcUploadURL_ release]; + [urlQueryParameters_ release]; + [additionalHTTPHeaders_ release]; + + [super dealloc]; +} + +- (NSString *)requestUserAgent { + NSString *userAgent = self.userAgent; + if ([userAgent length] == 0) { + // the service instance is missing an explicit user-agent; use the bundle ID + // or process name + NSBundle *owningBundle = [NSBundle bundleForClass:[self class]]; + if (owningBundle == nil + || [[owningBundle bundleIdentifier] isEqual:@"com.google.GTLFramework"]) { + + owningBundle = [NSBundle mainBundle]; + } + + userAgent = GTMBridgeApplicationIdentifier(owningBundle); + } + + NSString *requestUserAgent = userAgent; + + // if the user agent already specifies the library version, we'll + // use it verbatim in the request + NSString *libraryString = @"google-api-objc-client"; + NSRange libRange = [userAgent rangeOfString:libraryString + options:NSCaseInsensitiveSearch]; + if (libRange.location == NSNotFound) { + // the user agent doesn't specify the client library, so append that + // information, and the system version + NSString *libVersionString = GTLFrameworkVersionString(); + + NSString *systemString = GTMBridgeSystemVersionString(); + + // We don't clean this with GTMCleanedUserAgentString so spaces are + // preserved + NSString *userAgentAddition = self.userAgentAddition; + NSString *customString = userAgentAddition ? + [@" " stringByAppendingString:userAgentAddition] : @""; + + // Google servers look for gzip in the user agent before sending gzip- + // encoded responses. See Service.java + requestUserAgent = [NSString stringWithFormat:@"%@ %@/%@ %@%@ (gzip)", + userAgent, libraryString, libVersionString, systemString, customString]; + } + return requestUserAgent; +} + +- (NSMutableURLRequest *)requestForURL:(NSURL *)url + ETag:(NSString *)etag + httpMethod:(NSString *)httpMethod + ticket:(GTLServiceTicket *)ticket { + + // subclasses may add headers to this + NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringCacheData + timeoutInterval:60] autorelease]; + NSString *requestUserAgent = self.requestUserAgent; + [request setValue:requestUserAgent forHTTPHeaderField:@"User-Agent"]; + + if ([httpMethod length] > 0) { + [request setHTTPMethod:httpMethod]; + } + + if ([etag length] > 0) { + + // it's rather unexpected for an etagged object to be provided for a GET, + // but we'll check for an etag anyway, similar to HttpGDataRequest.java, + // and if present use it to request only an unchanged resource + + BOOL isDoingHTTPGet = (httpMethod == nil + || [httpMethod caseInsensitiveCompare:@"GET"] == NSOrderedSame); + + if (isDoingHTTPGet) { + + // set the etag header, even if weak, indicating we don't want + // another copy of the resource if it's the same as the object + [request setValue:etag forHTTPHeaderField:@"If-None-Match"]; + + } else { + + // if we're doing PUT or DELETE, set the etag header indicating + // we only want to update the resource if our copy matches the current + // one (unless the etag is weak and so shouldn't be a constraint at all) + BOOL isWeakETag = [etag hasPrefix:@"W/"]; + + BOOL isModifying = + [httpMethod caseInsensitiveCompare:@"PUT"] == NSOrderedSame + || [httpMethod caseInsensitiveCompare:@"DELETE"] == NSOrderedSame + || [httpMethod caseInsensitiveCompare:@"PATCH"] == NSOrderedSame; + + if (isModifying && !isWeakETag) { + [request setValue:etag forHTTPHeaderField:@"If-Match"]; + } + } + } + + return request; +} + +- (NSMutableURLRequest *)requestForURL:(NSURL *)url + ETag:(NSString *)etag + httpMethod:(NSString *)httpMethod { + // this public entry point authenticates from the service object but + // not from the auth token in the ticket + return [self requestForURL:url ETag:etag httpMethod:httpMethod ticket:nil]; +} + +// objectRequestForURL returns an NSMutableURLRequest for a GTLObject +// +// the object is the object being sent to the server, or nil; +// the http method may be nil for get, or POST, PUT, DELETE + +- (NSMutableURLRequest *)objectRequestForURL:(NSURL *)url + object:(GTLObject *)object + ETag:(NSString *)etag + httpMethod:(NSString *)httpMethod + isREST:(BOOL)isREST + additionalHeaders:(NSDictionary *)additionalHeaders + ticket:(GTLServiceTicket *)ticket { + if (object) { + // if the object being sent has an etag, add it to the request header to + // avoid retrieving a duplicate or to avoid writing over an updated + // version of the resource on the server + // + // Typically, delete requests will provide an explicit ETag parameter, and + // other requests will have the ETag carried inside the object being updated + if (etag == nil) { + SEL selEtag = @selector(ETag); + if ([object respondsToSelector:selEtag]) { + etag = [object performSelector:selEtag]; + } + } + } + + NSMutableURLRequest *request = [self requestForURL:url + ETag:etag + httpMethod:httpMethod + ticket:ticket]; + NSString *acceptValue; + NSString *contentTypeValue; + if (isREST) { + acceptValue = @"application/json"; + contentTypeValue = @"application/json; charset=utf-8"; + } else { + acceptValue = @"application/json-rpc"; + contentTypeValue = @"application/json-rpc; charset=utf-8"; + } + [request setValue:acceptValue forHTTPHeaderField:@"Accept"]; + [request setValue:contentTypeValue forHTTPHeaderField:@"Content-Type"]; + + [request setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"]; + + // Add the additional http headers from the service, and then from the query + NSDictionary *headers = self.additionalHTTPHeaders; + for (NSString *key in headers) { + NSString *value = [headers valueForKey:key]; + [request setValue:value forHTTPHeaderField:key]; + } + + headers = additionalHeaders; + for (NSString *key in headers) { + NSString *value = [headers valueForKey:key]; + [request setValue:value forHTTPHeaderField:key]; + } + + return request; +} + +#pragma mark - + +// common fetch starting method + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)targetURL + objectClass:(Class)objectClass + bodyObject:(GTLObject *)bodyObject + dataToPost:(NSData *)dataToPost + ETag:(NSString *)etag + httpMethod:(NSString *)httpMethod + mayAuthorize:(BOOL)mayAuthorize + isREST:(BOOL)isREST + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector + completionHandler:(id)completionHandler // GTLServiceCompletionHandler + executingQuery:(id)query + ticket:(GTLServiceTicket *)ticket { + + GTMBridgeAssertValidSelector(delegate, finishedSelector, @encode(GTLServiceTicket *), @encode(GTLObject *), @encode(NSError *), 0); + + // The completionHandler argument is declared as an id, not as a block + // pointer, so this can be built with the 10.6 SDK and still run on 10.5. + // If the argument were declared as a block pointer, the invocation for + // fetchObjectWithURL: created in GTLService would cause an exception + // since 10.5's NSInvocation cannot deal with encoding of block pointers. + + GTL_DEBUG_ASSERT(targetURL != nil, @"no url?"); + if (targetURL == nil) return nil; + + // we need to create a ticket unless one was created earlier (like during + // authentication) + if (!ticket) { + ticket = [[[self class] ticketClass] ticketForService:self]; + } + + ticket.isREST = isREST; + + // Add any service specific query parameters. + NSDictionary *urlQueryParameters = self.urlQueryParameters; + if ([urlQueryParameters count] > 0) { + targetURL = [GTLUtilities URLWithString:[targetURL absoluteString] + queryParameters:urlQueryParameters]; + } + + // If this is REST and there is a developer key, add it onto the url. RPC + // adds the key into the payload, not on the url. + NSString *apiKey = self.APIKey; + if (isREST && [apiKey length] > 0) { + NSString *const kDeveloperAPIQueryParamKey = @"key"; + NSDictionary *queryParameters; + queryParameters = [NSDictionary dictionaryWithObject:apiKey + forKey:kDeveloperAPIQueryParamKey]; + targetURL = [GTLUtilities URLWithString:[targetURL absoluteString] + queryParameters:queryParameters]; + } + + NSDictionary *additionalHeaders = query.additionalHTTPHeaders; + + NSMutableURLRequest *request = [self objectRequestForURL:targetURL + object:bodyObject + ETag:etag + httpMethod:httpMethod + isREST:isREST + additionalHeaders:additionalHeaders + ticket:ticket]; + + GTMBridgeAssertValidSelector(delegate, ticket.uploadProgressSelector, + @encode(GTLServiceTicket *), @encode(unsigned long long), + @encode(unsigned long long), 0); + GTMBridgeAssertValidSelector(delegate, ticket.retrySelector, + @encode(GTLServiceTicket *), @encode(BOOL), @encode(NSError *), 0); + + ticket.postedObject = bodyObject; + + ticket.executingQuery = query; + if (ticket.originalQuery == nil) { + ticket.originalQuery = query; + } + + GTMBridgeFetcherService *fetcherService = self.fetcherService; + GTMBridgeFetcher *fetcher; + + GTLUploadParameters *uploadParams = query.uploadParameters; + if (uploadParams == nil) { + // Not uploading a file with this request + fetcher = [fetcherService fetcherWithRequest:request]; + } else { + fetcher = [self uploadFetcherWithRequest:request + fetcherService:fetcherService + params:uploadParams]; + } + + if (self.allowInsecureQueries) { + fetcher.allowLocalhostRequest = YES; + fetcher.allowedInsecureSchemes = @[ @"http" ]; + } + + if (finishedSelector) { + // if we don't have a method name, default to the finished selector as + // a useful fetcher log comment + fetcher.comment = NSStringFromSelector(finishedSelector); + } + + // allow the user to specify static app-wide cookies for fetching +#if !GTL_USE_SESSION_FETCHER + NSInteger cookieStorageMethod = [self cookieStorageMethod]; + if (cookieStorageMethod >= 0) { + fetcher.cookieStorageMethod = cookieStorageMethod; + } +#endif + + if (!mayAuthorize) { + fetcher.authorizer = nil; + } + + // copy the ticket's retry settings into the fetcher + fetcher.retryEnabled = ticket.retryEnabled; + fetcher.maxRetryInterval = ticket.maxRetryInterval; + + BOOL shouldExamineRetries; + shouldExamineRetries = (ticket.retrySelector != nil + || ticket.retryBlock != nil); + if (shouldExamineRetries) { +#if GTL_USE_SESSION_FETCHER + __block GTMBridgeFetcher *fetcherRef = fetcher; + fetcher.retryBlock = ^(BOOL suggestedWillRetry, NSError *error, + GTMSessionFetcherRetryResponse response) { + BOOL shouldRetry = [self objectFetcher:fetcherRef + willRetry:suggestedWillRetry + forError:error]; + response(shouldRetry); + }; +#else + [fetcher setRetrySelector:@selector(objectFetcher:willRetry:forError:)]; +#endif + } + + // remember the object fetcher in the ticket + ticket.objectFetcher = fetcher; + + // add parameters used by the callbacks + + [fetcher setProperty:objectClass forKey:kFetcherObjectClassKey]; + + [fetcher setProperty:delegate forKey:kFetcherDelegateKey]; + + [fetcher setProperty:NSStringFromSelector(finishedSelector) + forKey:kFetcherFinishedSelectorKey]; + + [fetcher setProperty:ticket + forKey:kFetcherTicketKey]; + + // copy the completion handler block to the heap; this does nothing if the + // block is already on the heap + completionHandler = [[completionHandler copy] autorelease]; + [fetcher setProperty:completionHandler + forKey:kFetcherCompletionHandlerKey]; + + // set the upload data + fetcher.bodyData = dataToPost; +#if GTL_USE_SESSION_FETCHER + BOOL didFetch = YES; + [fetcher beginFetchWithDelegate:self + didFinishSelector:@selector(objectFetcher:finishedWithData:error:)]; +#else + // failed fetches call the failure selector, which will delete the ticket + BOOL didFetch = [fetcher beginFetchWithDelegate:self + didFinishSelector:@selector(objectFetcher:finishedWithData:error:)]; +#endif + + // If something weird happens and the networking callbacks have been called + // already synchronously, we don't want to return the ticket since the caller + // will never know when to stop retaining it, so we'll make sure the + // success/failure callbacks have not yet been called by checking the + // ticket + if (!didFetch || ticket.hasCalledCallback) { + fetcher.properties = nil; + return nil; + } + + return ticket; +} + +- (GTLUploadFetcherClass *)uploadFetcherWithRequest:(NSURLRequest *)request + fetcherService:(GTMBridgeFetcherService *)fetcherService + params:(GTLUploadParameters *)uploadParams { + // Hang on to the user's requested chunk size, and ensure it's not tiny + NSUInteger uploadChunkSize = [self serviceUploadChunkSize]; + if (uploadChunkSize < kMinimumUploadChunkSize) { + uploadChunkSize = kMinimumUploadChunkSize; + } + +#ifdef GTL_TARGET_NAMESPACE + // Prepend the class name prefix + Class uploadClass = NSClassFromString(@GTL_TARGET_NAMESPACE_STRING + @"_" GTLUploadFetcherClassStr); +#else + Class uploadClass = NSClassFromString(GTLUploadFetcherClassStr); +#endif + GTL_ASSERT(uploadClass != nil, GTLUploadFetcherClassStr @" needed"); + + NSString *uploadMIMEType = uploadParams.MIMEType; + NSData *uploadData = uploadParams.data; +#if GTL_USE_SESSION_FETCHER + NSURL *uploadFileURL = uploadParams.fileURL; +#endif + NSFileHandle *uploadFileHandle = uploadParams.fileHandle; + NSURL *uploadLocationURL = uploadParams.uploadLocationURL; + + // Create the upload fetcher. + GTLUploadFetcherClass *fetcher; +#if GTL_USE_SESSION_FETCHER + if (uploadLocationURL) { + // Resuming with the session fetcher and a file URL. + GTL_DEBUG_ASSERT(uploadFileURL != nil, @"Resume requires a file URL"); + fetcher = [uploadClass uploadFetcherWithLocation:uploadLocationURL + uploadMIMEType:uploadMIMEType + chunkSize:(int64_t)uploadChunkSize + fetcherService:fetcherService]; + fetcher.uploadFileURL = uploadFileURL; + } else { + fetcher = [uploadClass uploadFetcherWithRequest:request + uploadMIMEType:uploadMIMEType + chunkSize:(int64_t)uploadChunkSize + fetcherService:fetcherService]; + if (uploadFileURL) { + fetcher.uploadFileURL = uploadFileURL; + } else if (uploadData) { + fetcher.uploadData = uploadData; + } else if (uploadFileHandle) { + fetcher.uploadFileHandle = uploadFileHandle; + } + } +#else // !GTL_USE_SESSION_FETCHER + if (uploadLocationURL) { + // Resuming with the session fetcher and a file handle. + GTL_DEBUG_ASSERT(uploadFileHandle != nil, + @"Resume requires a file handle"); + fetcher = [uploadClass uploadFetcherWithLocation:uploadLocationURL + uploadFileHandle:uploadFileHandle + uploadMIMEType:uploadMIMEType + chunkSize:uploadChunkSize + fetcherService:fetcherService]; + } else if (uploadData) { + fetcher = [uploadClass uploadFetcherWithRequest:request + uploadData:uploadData + uploadMIMEType:uploadMIMEType + chunkSize:uploadChunkSize + fetcherService:fetcherService]; + } else { + fetcher = [uploadClass uploadFetcherWithRequest:request + uploadFileHandle:uploadFileHandle + uploadMIMEType:uploadMIMEType + chunkSize:uploadChunkSize + fetcherService:fetcherService]; + } +#endif // GTL_USE_SESSION_FETCHER + + NSString *slug = [uploadParams slug]; + if ([slug length] > 0) { + [[fetcher mutableRequest] setValue:slug forHTTPHeaderField:@"Slug"]; + } + return fetcher; +} + +#pragma mark - + +// RPC fetch methods + +- (NSDictionary *)rpcPayloadForMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + bodyObject:(GTLObject *)bodyObject + requestID:(NSString *)requestID { + GTL_DEBUG_ASSERT([requestID length] > 0, @"Got an empty request id"); + + // First, merge the developer key and bodyObject into the parameters. + + NSString *apiKey = self.APIKey; + NSUInteger apiKeyLen = [apiKey length]; + + NSString *const kDeveloperAPIParamKey = @"key"; + NSString *const kBodyObjectParamKey = @"resource"; + + NSDictionary *finalParams; + if ((apiKeyLen == 0) && (bodyObject == nil)) { + // Nothing needs to be added, just send the dict along. + finalParams = parameters; + } else { + NSMutableDictionary *worker = [NSMutableDictionary dictionary]; + if ([parameters count] > 0) { + [worker addEntriesFromDictionary:parameters]; + } + if ((apiKeyLen > 0) + && ([worker objectForKey:kDeveloperAPIParamKey] == nil)) { + [worker setObject:apiKey forKey:kDeveloperAPIParamKey]; + } + if (bodyObject != nil) { + GTL_DEBUG_ASSERT([parameters objectForKey:kBodyObjectParamKey] == nil, + @"There was already something under the 'data' key?!"); + NSMutableDictionary *json = [bodyObject JSON]; + if (json != nil) { + [worker setObject:json forKey:kBodyObjectParamKey]; + } + } + finalParams = worker; + } + + // Now, build up the full dictionary for the JSON-RPC (this is the body of + // the HTTP PUT). + + // Spec calls for the jsonrpc entry. Google doesn't require it, but include + // it so the code can work with other servers. + NSMutableDictionary *rpcPayload = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"2.0", @"jsonrpc", + methodName, @"method", + requestID, @"id", + nil]; + + // Google extension, provide the version of the api. + NSString *apiVersion = self.apiVersion; + if ([apiVersion length] > 0) { + [rpcPayload setObject:apiVersion forKey:@"apiVersion"]; + } + + if ([finalParams count] > 0) { + [rpcPayload setObject:finalParams forKey:@"params"]; + } + + return rpcPayload; +} + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + objectClass:(Class)objectClass + parameters:(NSDictionary *)parameters + bodyObject:(GTLObject *)bodyObject + requestID:(NSString *)requestID + urlQueryParameters:(NSDictionary *)urlQueryParameters + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector + completionHandler:(id)completionHandler // GTLServiceCompletionHandler + executingQuery:(id)executingQuery + ticket:(GTLServiceTicket *)ticket { + GTL_DEBUG_ASSERT([methodName length] > 0, @"Got an empty method name"); + if ([methodName length] == 0) return nil; + + // If we didn't get a requestID, assign one (call came from one of the public + // calls that doesn't take a GTLQuery object). + if (requestID == nil) { + requestID = [GTLQuery nextRequestID]; + } + + NSData *dataToPost = nil; + GTLUploadParameters *uploadParameters = executingQuery.uploadParameters; + BOOL shouldSendBody = !uploadParameters.shouldSendUploadOnly; + if (shouldSendBody) { + NSDictionary *rpcPayload = [self rpcPayloadForMethodNamed:methodName + parameters:parameters + bodyObject:bodyObject + requestID:requestID]; + + NSError *error = nil; + dataToPost = [GTLJSONParser dataWithObject:rpcPayload + humanReadable:NO + error:&error]; + if (dataToPost == nil) { + // There is the chance something went into parameters that wasn't valid. + GTL_DEBUG_LOG(@"JSON generation error: %@", error); + return nil; + } + } + + BOOL isUploading = (uploadParameters != nil); + NSURL *rpcURL = (isUploading ? self.rpcUploadURL : self.rpcURL); + + if ([urlQueryParameters count] > 0) { + rpcURL = [GTLUtilities URLWithString:[rpcURL absoluteString] + queryParameters:urlQueryParameters]; + } + + BOOL mayAuthorize = (executingQuery ? + !executingQuery.shouldSkipAuthorization : YES); + + GTLServiceTicket *resultTicket = [self fetchObjectWithURL:rpcURL + objectClass:objectClass + bodyObject:bodyObject + dataToPost:dataToPost + ETag:nil + httpMethod:@"POST" + mayAuthorize:mayAuthorize + isREST:NO + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:completionHandler + executingQuery:executingQuery + ticket:ticket]; + + // Set the fetcher log comment to default to the method name + NSUInteger pageNumber = resultTicket.pagesFetchedCounter; + if (pageNumber == 0) { + resultTicket.objectFetcher.comment = methodName; + } else { + // Also put the page number in the log comment + [resultTicket.objectFetcher setCommentWithFormat:@"%@ (page %lu)", + methodName, (unsigned long) (pageNumber + 1)]; + } + + return resultTicket; +} + +- (GTLServiceTicket *)executeBatchQuery:(GTLBatchQuery *)batch + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector + completionHandler:(id)completionHandler // GTLServiceCompletionHandler + ticket:(GTLServiceTicket *)ticket { + GTLBatchQuery *batchCopy = [[batch copy] autorelease]; + NSArray *queries = batchCopy.queries; + NSUInteger numberOfQueries = [queries count]; + if (numberOfQueries == 0) return nil; + + // Build up the array of RPC calls. + NSMutableArray *rpcPayloads = [NSMutableArray arrayWithCapacity:numberOfQueries]; + NSMutableSet *requestIDs = [NSMutableSet setWithCapacity:numberOfQueries]; + for (GTLQuery *query in queries) { + NSString *methodName = query.methodName; + NSDictionary *parameters = query.JSON; + GTLObject *bodyObject = query.bodyObject; + NSString *requestID = query.requestID; + + if ([methodName length] == 0 || [requestID length] == 0) { + GTL_DEBUG_ASSERT(0, @"Invalid query - id:%@ method:%@", + requestID, methodName); + return nil; + } + + GTL_DEBUG_ASSERT(query.additionalHTTPHeaders == nil, + @"additionalHTTPHeaders disallowed on queries added to a batch - query %@ (%@)", + requestID, methodName); + + GTL_DEBUG_ASSERT(query.urlQueryParameters == nil, + @"urlQueryParameters disallowed on queries added to a batch - query %@ (%@)", + requestID, methodName); + + GTL_DEBUG_ASSERT(query.uploadParameters == nil, + @"uploadParameters disallowed on queries added to a batch - query %@ (%@)", + requestID, methodName); + + NSDictionary *rpcPayload = [self rpcPayloadForMethodNamed:methodName + parameters:parameters + bodyObject:bodyObject + requestID:requestID]; + [rpcPayloads addObject:rpcPayload]; + + if ([requestIDs containsObject:requestID]) { + GTL_DEBUG_LOG(@"Duplicate request id in batch: %@", requestID); + return nil; + } + [requestIDs addObject:requestID]; + } + + NSError *error = nil; + NSData *dataToPost = nil; + dataToPost = [GTLJSONParser dataWithObject:rpcPayloads + humanReadable:NO + error:&error]; + if (dataToPost == nil) { + // There is the chance something went into parameters that wasn't valid. + GTL_DEBUG_LOG(@"JSON generation error: %@", error); + return nil; + } + + BOOL mayAuthorize = (batchCopy ? !batchCopy.shouldSkipAuthorization : YES); + + NSURL *rpcURL = self.rpcURL; + + // We'll use the batch query's URL parameters, and ignore the URL parameters + // specified on the individual queries. + NSDictionary *urlQueryParameters = batch.urlQueryParameters; + if ([urlQueryParameters count] > 0) { + rpcURL = [GTLUtilities URLWithString:[rpcURL absoluteString] + queryParameters:urlQueryParameters]; + } + + GTLServiceTicket *resultTicket = [self fetchObjectWithURL:rpcURL + objectClass:[GTLBatchResult class] + bodyObject:nil + dataToPost:dataToPost + ETag:nil + httpMethod:@"POST" + mayAuthorize:mayAuthorize + isREST:NO + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:completionHandler + executingQuery:batch + ticket:ticket]; + +#if !STRIP_GTM_FETCH_LOGGING + // Set the fetcher log comment + // + // Because this has expensive set operations, it's conditionally + // compiled in + NSArray *methodNames = [queries valueForKey:@"methodName"]; + methodNames = [[NSSet setWithArray:methodNames] allObjects]; // de-dupe + NSString *methodsStr = [methodNames componentsJoinedByString:@", "]; + + NSUInteger pageNumber = ticket.pagesFetchedCounter; + NSString *pageStr = @""; + if (pageNumber > 0) { + pageStr = [NSString stringWithFormat:@"page %lu, ", + (unsigned long) pageNumber + 1]; + } + [resultTicket.objectFetcher setCommentWithFormat:@"batch: %@ (%@%lu queries)", + methodsStr, pageStr, (unsigned long) numberOfQueries]; +#endif + + return resultTicket; +} + + +#pragma mark - + +// REST fetch methods + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)targetURL + objectClass:(Class)objectClass + bodyObject:(GTLObject *)bodyObject + ETag:(NSString *)etag + httpMethod:(NSString *)httpMethod + mayAuthorize:(BOOL)mayAuthorize + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector + completionHandler:(id)completionHandler // GTLServiceCompletionHandler + ticket:(GTLServiceTicket *)ticket { + // if no URL was supplied, treat this as if the fetch failed (below) + // and immediately return a nil ticket, skipping the callbacks + // + // this might be considered normal (say, updating a read-only entry + // that lacks an edit link) though higher-level calls may assert or + // return errors depending on the specific usage + if (targetURL == nil) return nil; + + NSData *dataToPost = nil; + if (bodyObject != nil) { + NSError *error = nil; + + NSDictionary *whatToSend; + NSDictionary *json = bodyObject.JSON; + if (isRESTDataWrapperRequired_) { + // create the top-level "data" object + NSDictionary *dataDict = [NSDictionary dictionaryWithObject:json + forKey:@"data"]; + whatToSend = dataDict; + } else { + whatToSend = json; + } + dataToPost = [GTLJSONParser dataWithObject:whatToSend + humanReadable:NO + error:&error]; + if (dataToPost == nil) { + GTL_DEBUG_LOG(@"JSON generation error: %@", error); + } + } + + return [self fetchObjectWithURL:targetURL + objectClass:objectClass + bodyObject:bodyObject + dataToPost:dataToPost + ETag:etag + httpMethod:httpMethod + mayAuthorize:mayAuthorize + isREST:YES + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:completionHandler + executingQuery:nil + ticket:ticket]; +} + +- (void)invokeProgressCallbackForTicket:(GTLServiceTicket *)ticket + deliveredBytes:(unsigned long long)numReadSoFar + totalBytes:(unsigned long long)total { + + SEL progressSelector = [ticket uploadProgressSelector]; + if (progressSelector) { + + GTMBridgeFetcher *fetcher = ticket.objectFetcher; + id delegate = [fetcher propertyForKey:kFetcherDelegateKey]; + + NSMethodSignature *signature = [delegate methodSignatureForSelector:progressSelector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + + [invocation setSelector:progressSelector]; + [invocation setTarget:delegate]; + [invocation setArgument:&ticket atIndex:2]; + [invocation setArgument:&numReadSoFar atIndex:3]; + [invocation setArgument:&total atIndex:4]; + [invocation invoke]; + } + + GTLServiceUploadProgressBlock block = ticket.uploadProgressBlock; + if (block) { + block(ticket, numReadSoFar, total); + } +} + +// sentData callback from fetcher +- (void)objectFetcher:(GTMBridgeFetcher *)fetcher + didSendBytes:(NSInteger)bytesSent + totalBytesSent:(NSInteger)totalBytesSent +totalBytesExpectedToSend:(NSInteger)totalBytesExpected { + + GTLServiceTicket *ticket = [fetcher propertyForKey:kFetcherTicketKey]; + + [self invokeProgressCallbackForTicket:ticket + deliveredBytes:(unsigned long long)totalBytesSent + totalBytes:(unsigned long long)totalBytesExpected]; +} + +- (void)objectFetcher:(GTMBridgeFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error { + // we now have the JSON data for an object, or an error + if (error == nil) { + if ([data length] > 0) { + [self prepareToParseObjectForFetcher:fetcher]; + } else { + // no data (such as when deleting) + [self handleParsedObjectForFetcher:fetcher]; + } + } else { + // There was an error from the fetch + NSInteger status = [error code]; + if (status >= 300) { + // Return the HTTP error status code along with a more descriptive error + // from within the HTTP response payload. + NSData *responseData = fetcher.downloadedData; + if ([responseData length] > 0) { + NSDictionary *responseHeaders = fetcher.responseHeaders; + NSString *contentType = [responseHeaders objectForKey:@"Content-Type"]; + + if ([data length] > 0) { + if ([contentType hasPrefix:@"application/json"]) { + NSError *parseError = nil; + NSMutableDictionary *jsonWrapper = [GTLJSONParser objectWithData:data + error:&parseError]; + if (parseError) { + // We could not parse the JSON payload + error = parseError; + } else { + // Convert the JSON error payload into a structured error + NSMutableDictionary *errorJSON = [jsonWrapper valueForKey:@"error"]; + GTLErrorObject *errorObject = [GTLErrorObject objectWithJSON:errorJSON]; + error = [errorObject foundationError]; + } + } else { + // No structured JSON error was available; make a plaintext server + // error response visible in the error object. + NSString *reasonStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:reasonStr + forKey:NSLocalizedFailureReasonErrorKey]; + error = [NSError errorWithDomain:kGTMBridgeFetcherStatusDomain + code:status + userInfo:userInfo]; + } + } else { + // Response data length is zero; we'll settle for returning the + // fetcher's error. + } + } + } + + // store the error, call the callbacks, and bail + [fetcher setProperty:error + forKey:kFetcherFetchErrorKey]; + + [self handleParsedObjectForFetcher:fetcher]; + } +} + +// Three methods handle parsing of the fetched JSON data: +// - prepareToParse posts a start notification and then spawns off parsing +// on the operation queue (if there's an operation queue) +// - parseObject does the parsing of the JSON string +// - handleParsedObject posts the stop notification and calls the callback +// with the parsed object or an error +// +// The middle method may run on a separate thread. + +- (void)prepareToParseObjectForFetcher:(GTMBridgeFetcher *)fetcher { + // save the current thread into the fetcher, since we'll handle additional + // fetches and callbacks on this thread + [fetcher setProperty:[NSThread currentThread] + forKey:kFetcherCallbackThreadKey]; + + // copy the run loop modes, if any, so we don't need to access them + // from the parsing thread + [fetcher setProperty:[[[self runLoopModes] copy] autorelease] + forKey:kFetcherCallbackRunLoopModesKey]; + + // we post parsing notifications now to ensure they're on caller's + // original thread + GTLServiceTicket *ticket = [fetcher propertyForKey:kFetcherTicketKey]; + NSNotificationCenter *defaultNC = [NSNotificationCenter defaultCenter]; + [defaultNC postNotificationName:kGTLServiceTicketParsingStartedNotification + object:ticket]; + [fetcher setProperty:@"1" + forKey:kFetcherParsingNotificationKey]; + + id executingQuery = ticket.executingQuery; + if ([executingQuery isBatchQuery]) { + // build a dictionary of expected classes for the batch responses + GTLBatchQuery *batchQuery = executingQuery; + NSArray *queries = batchQuery.queries; + NSDictionary *batchClassMap = [NSMutableDictionary dictionaryWithCapacity:[queries count]]; + for (GTLQuery *query in queries) { + [batchClassMap setValue:query.expectedObjectClass + forKey:query.requestID]; + } + [fetcher setProperty:batchClassMap + forKey:kFetcherBatchClassMapKey]; + } + + // if there's an operation queue, then use that to schedule parsing on another + // thread + SEL parseSel = @selector(parseObjectFromDataOfFetcher:); + NSOperationQueue *queue = self.parseQueue; + if (queue) { + NSInvocationOperation *op; + op = [[[NSInvocationOperation alloc] initWithTarget:self + selector:parseSel + object:fetcher] autorelease]; + ticket.parseOperation = op; + [queue addOperation:op]; + // the fetcher now belongs to the parsing thread + } else { + // parse on the current thread, on Mac OS X 10.4 through 10.5.7 + // or when the project defines GTL_SKIP_PARSE_THREADING + [self performSelector:parseSel + withObject:fetcher]; + } +} + +- (void)parseObjectFromDataOfFetcher:(GTMBridgeFetcher *)fetcher { + // This method runs in a separate thread + + // Generally protect the fetcher properties, since canceling a ticket would + // release the fetcher properties dictionary +#if GTL_USE_SESSION_FETCHER + NSDictionary *properties = [[fetcher.properties copy] autorelease]; +#else + NSMutableDictionary *properties = [[fetcher.properties retain] autorelease]; +#endif + + // The callback thread is retaining the fetcher, so the fetcher shouldn't keep + // retaining the callback thread + NSThread *callbackThread = [properties valueForKey:kFetcherCallbackThreadKey]; + [[callbackThread retain] autorelease]; + [fetcher setProperty:nil forKey:kFetcherCallbackThreadKey]; + + GTLServiceTicket *ticket = [properties valueForKey:kFetcherTicketKey]; + [[ticket retain] autorelease]; + + NSDictionary *responseHeaders = fetcher.responseHeaders; + NSString *contentType = [responseHeaders objectForKey:@"Content-Type"]; + NSData *data = fetcher.downloadedData; + + NSOperation *parseOperation = ticket.parseOperation; + + BOOL hasData = [data length] > 0; + BOOL isJSON = [contentType hasPrefix:@"application/json"]; + GTL_DEBUG_ASSERT(isJSON || !hasData, @"Got unexpected content type '%@'", contentType); + + if (hasData && isJSON) { +#if GTL_LOG_PERFORMANCE + NSTimeInterval secs1, secs2; + secs1 = [NSDate timeIntervalSinceReferenceDate]; +#endif + + NSError *parseError = nil; + NSMutableDictionary *jsonWrapper = [GTLJSONParser objectWithData:data + error:&parseError]; + if ([parseOperation isCancelled]) return; + + if (parseError != nil) { + [fetcher setProperty:parseError forKey:kFetcherFetchErrorKey]; + } else { + NSMutableDictionary *json; + NSDictionary *batchClassMap = nil; + + // In theory, just checking for "application/json-rpc" vs + // "application/json" would work. But the JSON-RPC spec allows for + // "application/json" also so we have to carry a flag all the way in + // saying which type of result to expect and process as. + BOOL isREST = ticket.isREST; + if (isREST) { + if (isRESTDataWrapperRequired_) { + json = [jsonWrapper valueForKey:@"data"]; + } else { + json = jsonWrapper; + } + } else { + batchClassMap = [properties valueForKey:kFetcherBatchClassMapKey]; + if (batchClassMap) { + // A batch gets the whole array as it's json. + json = jsonWrapper; + } else { + json = [jsonWrapper valueForKey:@"result"]; + } + } + + if (json != nil) { + Class defaultClass = [properties valueForKey:kFetcherObjectClassKey]; + NSDictionary *surrogates = ticket.surrogates; + + GTLObject *parsedObject = [GTLObject objectForJSON:json + defaultClass:defaultClass + surrogates:surrogates + batchClassMap:batchClassMap]; + + [fetcher setProperty:parsedObject forKey:kFetcherParsedObjectKey]; + } else if (!isREST) { + NSMutableDictionary *errorJSON = [jsonWrapper valueForKey:@"error"]; + GTL_DEBUG_ASSERT(errorJSON != nil, @"no result or error in response:\n%@", + jsonWrapper); + GTLErrorObject *errorObject = [GTLErrorObject objectWithJSON:errorJSON]; + NSError *error = [errorObject foundationError]; + + // Store the error and let it go to the callback + [fetcher setProperty:error + forKey:kFetcherFetchErrorKey]; + } + } + +#if GTL_LOG_PERFORMANCE + secs2 = [NSDate timeIntervalSinceReferenceDate]; + NSLog(@"allocation of %@ took %f seconds", objectClass, secs2 - secs1); +#endif + } + + if ([parseOperation isCancelled]) return; + + SEL parseDoneSel = @selector(handleParsedObjectForFetcher:); + NSArray *runLoopModes = [properties valueForKey:kFetcherCallbackRunLoopModesKey]; + // If this callback was enqueued, then the fetcher has already released + // its delegateQueue. We'll use our own delegateQueue to determine how to + // invoke the callbacks. + NSOperationQueue *delegateQueue = self.delegateQueue; + if (delegateQueue) { + NSInvocationOperation *op; + op = [[[NSInvocationOperation alloc] initWithTarget:self + selector:parseDoneSel + object:fetcher] autorelease]; + [delegateQueue addOperation:op]; + } else if (runLoopModes) { + [self performSelector:parseDoneSel + onThread:callbackThread + withObject:fetcher + waitUntilDone:NO + modes:runLoopModes]; + } else { + // Defaults to common modes + [self performSelector:parseDoneSel + onThread:callbackThread + withObject:fetcher + waitUntilDone:NO]; + } + // the fetcher now belongs to the callback thread +} + +- (void)handleParsedObjectForFetcher:(GTMBridgeFetcher *)fetcher { + // After parsing is complete, this is invoked on the thread that the + // fetch was performed on + // + // There may not be an object due to a fetch or parsing error + + GTLServiceTicket *ticket = [fetcher propertyForKey:kFetcherTicketKey]; + ticket.parseOperation = nil; + + // unpack the callback parameters + id delegate = [fetcher propertyForKey:kFetcherDelegateKey]; + NSString *selString = [fetcher propertyForKey:kFetcherFinishedSelectorKey]; + SEL finishedSelector = NSSelectorFromString(selString); + + GTLServiceCompletionHandler completionHandler; + completionHandler = [fetcher propertyForKey:kFetcherCompletionHandlerKey]; + + GTLObject *object = [fetcher propertyForKey:kFetcherParsedObjectKey]; + NSError *error = [fetcher propertyForKey:kFetcherFetchErrorKey]; + + GTLQuery *executingQuery = (GTLQuery *)ticket.executingQuery; + + BOOL shouldFetchNextPages = ticket.shouldFetchNextPages; + GTLObject *previousObject = ticket.fetchedObject; + + if (shouldFetchNextPages + && (previousObject != nil) + && (object != nil)) { + // Accumulate new results + object = [self mergedNewResultObject:object + oldResultObject:previousObject + forQuery:executingQuery]; + } + + ticket.fetchedObject = object; + ticket.fetchError = error; + + if ([fetcher propertyForKey:kFetcherParsingNotificationKey] != nil) { + // we want to always balance the start and stop notifications + NSNotificationCenter *defaultNC = [NSNotificationCenter defaultCenter]; + [defaultNC postNotificationName:kGTLServiceTicketParsingStoppedNotification + object:ticket]; + } + + BOOL shouldCallCallbacks = YES; + + // Use the nextPageToken to fetch any later pages for non-batch queries + // + // This assumes a pagination model where objects have entries in an "items" + // field and a "nextPageToken" field, and queries support a "pageToken" + // parameter. + if (ticket.shouldFetchNextPages) { + // Determine if we should fetch more pages of results + + GTLQuery *nextPageQuery = + (GTLQuery *)[self nextPageQueryForQuery:executingQuery + result:object + ticket:ticket]; + if (nextPageQuery) { + BOOL isFetchingMore = [self fetchNextPageWithQuery:nextPageQuery + delegate:delegate + didFinishedSelector:finishedSelector + completionHandler:completionHandler + ticket:ticket]; + if (isFetchingMore) { + shouldCallCallbacks = NO; + } + } else { + // No more page tokens are present +#if DEBUG && !GTL_SKIP_PAGES_WARNING + // Each next page followed to accumulate all pages of a feed takes up to + // a few seconds. When multiple pages are being fetched, that + // usually indicates that a larger page size (that is, more items per + // feed fetched) should be requested. + // + // To avoid fetching many pages, set query.maxResults so the feed + // requested is large enough to rarely need to follow next links. + NSUInteger pageCount = ticket.pagesFetchedCounter; + if (pageCount > 2) { + NSString *queryLabel = [executingQuery isBatchQuery] ? + @"batch query" : executingQuery.methodName; + NSLog(@"Executing %@ required fetching %u pages; use a query with a" + @" larger maxResults for faster results", + queryLabel, (unsigned int) pageCount); + } +#endif + } + } + + // We no longer care about the queries for page 2 or later, so for the client + // inspecting the ticket in the callback, the executing query should be + // the original one + ticket.executingQuery = ticket.originalQuery; + + if (shouldCallCallbacks) { + // First, call query-specific callback blocks. We do this before the + // fetch callback to let applications do any final clean-up (or update + // their UI) in the fetch callback. + GTLQuery *originalQuery = (GTLQuery *)ticket.originalQuery; + if (![originalQuery isBatchQuery]) { + // Single query + GTLServiceCompletionHandler completionBlock = originalQuery.completionBlock; + if (completionBlock) { + completionBlock(ticket, object, error); + } + } else { + // Batch query + // + // We'll step through the queries of the original batch, not of the + // batch result + GTLBatchQuery *batchQuery = (GTLBatchQuery *)originalQuery; + GTLBatchResult *batchResult = (GTLBatchResult *)object; + NSDictionary *successes = batchResult.successes; + NSDictionary *failures = batchResult.failures; + + for (GTLQuery *oneQuery in batchQuery.queries) { + GTLServiceCompletionHandler completionBlock = oneQuery.completionBlock; + if (completionBlock) { + // If there was no networking error, look for a query-specific + // error or result + GTLObject *oneResult = nil; + NSError *oneError = error; + if (oneError == nil) { + NSString *requestID = [oneQuery requestID]; + GTLErrorObject *gtlError = [failures objectForKey:requestID]; + if (gtlError) { + oneError = [gtlError foundationError]; + } else { + oneResult = [successes objectForKey:requestID]; + if (oneResult == nil) { + // We found neither a success nor a failure for this + // query, unexpectedly + GTL_DEBUG_LOG(@"GTLService: Batch result missing for request %@", + requestID); + oneError = [NSError errorWithDomain:kGTLServiceErrorDomain + code:kGTLErrorQueryResultMissing + userInfo:nil]; + } + } + } + completionBlock(ticket, oneResult, oneError); + } + } + } + + // Release query callback blocks + [originalQuery executionDidStop]; + + if (finishedSelector) { + [[self class] invokeCallback:finishedSelector + target:delegate + ticket:ticket + object:object + error:error]; + } + + if (completionHandler) { + completionHandler(ticket, object, error); + } + ticket.hasCalledCallback = YES; + } + fetcher.properties = nil; + + // Tickets don't know when the fetch has completed, so the service will + // release their blocks here to avoid unintended retain loops + ticket.retryBlock = nil; + ticket.uploadProgressBlock = nil; +} + +#pragma mark - + ++ (void)invokeCallback:(SEL)callbackSel + target:(id)target + ticket:(id)ticket + object:(id)object + error:(id)error { + + // GTL fetch callbacks have no return value + NSMethodSignature *signature = [target methodSignatureForSelector:callbackSel]; + NSInvocation *retryInvocation = [NSInvocation invocationWithMethodSignature:signature]; + [retryInvocation setSelector:callbackSel]; + [retryInvocation setTarget:target]; + [retryInvocation setArgument:&ticket atIndex:2]; + [retryInvocation setArgument:&object atIndex:3]; + [retryInvocation setArgument:&error atIndex:4]; + [retryInvocation invoke]; +} + +// The object fetcher may call into this retry method; this one invokes the +// selector provided by the user. +- (BOOL)objectFetcher:(GTMBridgeFetcher *)fetcher willRetry:(BOOL)willRetry forError:(NSError *)error { + + GTLServiceTicket *ticket = [fetcher propertyForKey:kFetcherTicketKey]; + SEL retrySelector = ticket.retrySelector; + if (retrySelector) { + id delegate = [fetcher propertyForKey:kFetcherDelegateKey]; + + willRetry = [self invokeRetrySelector:retrySelector + delegate:delegate + ticket:ticket + willRetry:willRetry + error:error]; + } + + GTLServiceRetryBlock retryBlock = ticket.retryBlock; + if (retryBlock) { + willRetry = retryBlock(ticket, willRetry, error); + } + + return willRetry; +} + +- (BOOL)invokeRetrySelector:(SEL)retrySelector + delegate:(id)delegate + ticket:(GTLServiceTicket *)ticket + willRetry:(BOOL)willRetry + error:(NSError *)error { + + if ([delegate respondsToSelector:retrySelector]) { + // Unlike the retry selector invocation in GTMBridgeFetcher, this invocation + // passes the ticket rather than the fetcher as argument 2 + NSMethodSignature *signature = [delegate methodSignatureForSelector:retrySelector]; + NSInvocation *retryInvocation = [NSInvocation invocationWithMethodSignature:signature]; + [retryInvocation setSelector:retrySelector]; + [retryInvocation setTarget:delegate]; + [retryInvocation setArgument:&ticket atIndex:2]; // ticket passed + [retryInvocation setArgument:&willRetry atIndex:3]; + [retryInvocation setArgument:&error atIndex:4]; + [retryInvocation invoke]; + + [retryInvocation getReturnValue:&willRetry]; + } + return willRetry; +} + +- (BOOL)waitForTicket:(GTLServiceTicket *)ticket + timeout:(NSTimeInterval)timeoutInSeconds + fetchedObject:(GTLObject **)outObjectOrNil + error:(NSError **)outErrorOrNil { + + NSDate* giveUpDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + + // loop until the fetch completes with an object or an error, + // or until the timeout has expired + while (![ticket hasCalledCallback] + && [giveUpDate timeIntervalSinceNow] > 0) { + + // run the current run loop 1/1000 of a second to give the networking + // code a chance to work + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:0.001]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } + + NSError *fetchError = ticket.fetchError; + + if (![ticket hasCalledCallback] && fetchError == nil) { + fetchError = [NSError errorWithDomain:kGTLServiceErrorDomain + code:kGTLErrorWaitTimedOut + userInfo:nil]; + } + + if (outObjectOrNil) *outObjectOrNil = ticket.fetchedObject; + if (outErrorOrNil) *outErrorOrNil = fetchError; + + return (fetchError == nil); +} + +#pragma mark - + +// Given a single or batch query and its result, make a new query +// for the next pages, if any. Returns nil if there's no additional +// query to make. +// +// This method calls itself recursively to make the individual next page +// queries for a batch query. +- (id )nextPageQueryForQuery:(GTLQuery *)query + result:(GTLObject *)object + ticket:(GTLServiceTicket *)ticket { + if (!query.isBatchQuery) { + // This is a single query + + // Determine if we should fetch more pages of results + GTLQuery *nextPageQuery = nil; + NSString *nextPageToken = nil; + NSNumber *nextStartIndex = nil; + + if ([object respondsToSelector:@selector(nextPageToken)] + && [query respondsToSelector:@selector(pageToken)]) { + nextPageToken = [object performSelector:@selector(nextPageToken)]; + } + + if ([object respondsToSelector:@selector(nextStartIndex)] + && [query respondsToSelector:@selector(startIndex)]) { + nextStartIndex = [object performSelector:@selector(nextStartIndex)]; + } + + if (nextPageToken || nextStartIndex) { + if ([object respondsToSelector:@selector(items)]) { + // Make a query for the next page, preserving the request ID + nextPageQuery = [[query copy] autorelease]; + nextPageQuery.requestID = query.requestID; + + if (nextPageToken) { + [nextPageQuery performSelector:@selector(setPageToken:) + withObject:nextPageToken]; + } else { + // Use KVC to unwrap the scalar type instead of converting the + // NSNumber to an integer and using NSInvocation + [nextPageQuery setValue:nextStartIndex + forKey:@"startIndex"]; + } + } else { + // Object does not provide an "items" method. +#if DEBUG + NSLog(@"%@ does not support shouldFetchNextPages because it lacks an \"items\" property", + [object class]); +#endif + } + } + return nextPageQuery; + } else { + // This is a batch query + // + // Check if there's a next page to fetch for any of the success + // results by invoking this method recursively on each of those results + GTLBatchResult *batchResult = (GTLBatchResult *)object; + GTLBatchQuery *nextPageBatchQuery = nil; + NSDictionary *successes = batchResult.successes; + + for (NSString *requestID in successes) { + GTLObject *singleObject = [successes objectForKey:requestID]; + GTLQuery *singleQuery = [ticket queryForRequestID:requestID]; + + GTLQuery *newQuery = + (GTLQuery *)[self nextPageQueryForQuery:singleQuery + result:singleObject + ticket:ticket]; + if (newQuery) { + // There is another query to fetch + if (nextPageBatchQuery == nil) { + nextPageBatchQuery = [GTLBatchQuery batchQuery]; + } + [nextPageBatchQuery addQuery:newQuery]; + } + } + return nextPageBatchQuery; + } +} + +// When a ticket is set to fetch more pages for feeds, this routine +// initiates the fetch for each additional feed page +- (BOOL)fetchNextPageWithQuery:(GTLQuery *)query + delegate:(id)delegate + didFinishedSelector:(SEL)finishedSelector + completionHandler:(GTLServiceCompletionHandler)completionHandler + ticket:(GTLServiceTicket *)ticket { + // Sanity check the number of pages fetched already + NSUInteger oldPagesFetchedCounter = ticket.pagesFetchedCounter; + + if (oldPagesFetchedCounter > kMaxNumberOfNextPagesFetched) { + // Sanity check failed: way too many pages were fetched + // + // The client should be querying with a higher max results per page + // to avoid this + GTL_DEBUG_ASSERT(0, @"Fetched too many next pages for %@", + query.methodName); + return NO; + } + + ticket.pagesFetchedCounter = 1 + oldPagesFetchedCounter; + + GTLServiceTicket *newTicket; + if (query.isBatchQuery) { + newTicket = [self executeBatchQuery:(GTLBatchQuery *)query + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:completionHandler + ticket:ticket]; + } else { + newTicket = [self fetchObjectWithMethodNamed:query.methodName + objectClass:query.expectedObjectClass + parameters:query.JSON + bodyObject:query.bodyObject + requestID:query.requestID + urlQueryParameters:query.urlQueryParameters + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:completionHandler + executingQuery:query + ticket:ticket]; + } + + // In the bizarre case that the fetch didn't begin, newTicket will be + // nil. So long as the new ticket is the same as the ticket we're + // continuing, then we're happy. + return (newTicket == ticket); +} + +// Given a new single or batch result (meaning additional pages for a previous +// query result), merge it into the old result. +- (GTLObject *)mergedNewResultObject:(GTLObject *)newResult + oldResultObject:(GTLObject *)oldResult + forQuery:(GTLQuery *)query { + if (query.isBatchQuery) { + // Batch query result + // + // The new batch results are a subset of the old result's queries, since + // not all queries in the batch necessarily have additional pages. + // + // New success objects replace old success objects, with the old items + // prepended; new failure objects replace old success objects. + // We will update the old batch results with accumulated items, using the + // new objects, and return the old batch. + // + // We reuse the old batch results object because it may include some earlier + // results which did not have additional pages. + GTLBatchResult *newBatchResult = (GTLBatchResult *)newResult; + GTLBatchResult *oldBatchResult = (GTLBatchResult *)oldResult; + + NSMutableDictionary *newSuccesses = newBatchResult.successes; + NSMutableDictionary *newFailures = newBatchResult.failures; + NSMutableDictionary *oldSuccesses = oldBatchResult.successes; + NSMutableDictionary *oldFailures = oldBatchResult.failures; + + for (NSString *requestID in newSuccesses) { + // Prepend the old items to the new response's items + // + // We can assume the objects are collections since they're present in + // additional pages. + GTLCollectionObject *newObj = [newSuccesses objectForKey:requestID]; + GTLCollectionObject *oldObj = [oldSuccesses objectForKey:requestID]; + + NSMutableArray *items = [NSMutableArray arrayWithArray:oldObj.items]; + [items addObjectsFromArray:newObj.items]; + [newObj performSelector:@selector(setItems:) withObject:items]; + + // Replace the old object with the new one + [oldSuccesses setObject:newObj forKey:requestID]; + } + + for (NSString *requestID in newFailures) { + // Replace old successes or failures with the new failure + GTLErrorObject *newError = [newFailures objectForKey:requestID]; + [oldFailures setObject:newError forKey:requestID]; + [oldSuccesses removeObjectForKey:requestID]; + } + return oldBatchResult; + } else { + // Single query result + // + // Merge the items into the new object, and return that. + // + // We can assume the objects are collections since they're present in + // additional pages. + GTLCollectionObject *newObj = (GTLCollectionObject *)newResult; + GTLCollectionObject *oldObj = (GTLCollectionObject *)oldResult; + + NSMutableArray *items = [NSMutableArray arrayWithArray:oldObj.items]; + [items addObjectsFromArray:newObj.items]; + [newObj performSelector:@selector(setItems:) withObject:items]; + + return newObj; + } +} + +#pragma mark - + +// GTLQuery methods. + +- (GTLServiceTicket *)executeQuery:(id)queryObj + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + if ([queryObj isBatchQuery]) { + return [self executeBatchQuery:queryObj + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:NULL + ticket:nil]; + } + + GTLQuery *query = [[(GTLQuery *)queryObj copy] autorelease]; + NSString *methodName = query.methodName; + NSDictionary *params = query.JSON; + GTLObject *bodyObject = query.bodyObject; + + return [self fetchObjectWithMethodNamed:methodName + objectClass:query.expectedObjectClass + parameters:params + bodyObject:bodyObject + requestID:query.requestID + urlQueryParameters:query.urlQueryParameters + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + executingQuery:query + ticket:nil]; +} + +- (GTLServiceTicket *)executeQuery:(id)queryObj + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + if ([queryObj isBatchQuery]) { + return [self executeBatchQuery:queryObj + delegate:nil + didFinishSelector:NULL + completionHandler:handler + ticket:nil]; + } + + GTLQuery *query = [[(GTLQuery *)queryObj copy] autorelease]; + NSString *methodName = query.methodName; + NSDictionary *params = query.JSON; + GTLObject *bodyObject = query.bodyObject; + + return [self fetchObjectWithMethodNamed:methodName + objectClass:query.expectedObjectClass + parameters:params + bodyObject:bodyObject + requestID:query.requestID + urlQueryParameters:query.urlQueryParameters + delegate:nil + didFinishSelector:NULL + completionHandler:handler + executingQuery:query + ticket:nil]; +} + +#pragma mark - + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + return [self fetchObjectWithMethodNamed:methodName + objectClass:objectClass + parameters:parameters + bodyObject:nil + requestID:nil + urlQueryParameters:nil + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + executingQuery:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + return [self fetchObjectWithMethodNamed:methodName + objectClass:objectClass + parameters:nil + bodyObject:bodyObject + requestID:nil + urlQueryParameters:nil + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + executingQuery:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + return [self fetchObjectWithMethodNamed:methodName + objectClass:objectClass + parameters:parameters + bodyObject:bodyObject + requestID:nil + urlQueryParameters:nil + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + executingQuery:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + objectClass:(Class)objectClass + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + return [self fetchObjectWithMethodNamed:methodName + objectClass:objectClass + parameters:parameters + bodyObject:nil + requestID:nil + urlQueryParameters:nil + delegate:nil + didFinishSelector:NULL + completionHandler:handler + executingQuery:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + return [self fetchObjectWithMethodNamed:methodName + objectClass:objectClass + parameters:nil + bodyObject:bodyObject + requestID:nil + urlQueryParameters:nil + delegate:nil + didFinishSelector:NULL + completionHandler:handler + executingQuery:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName + parameters:(NSDictionary *)parameters + insertingObject:(GTLObject *)bodyObject + objectClass:(Class)objectClass + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + return [self fetchObjectWithMethodNamed:methodName + objectClass:objectClass + parameters:parameters + bodyObject:bodyObject + requestID:nil + urlQueryParameters:nil + delegate:nil + didFinishSelector:NULL + completionHandler:handler + executingQuery:nil + ticket:nil]; +} + +#pragma mark - + +// These external entry points doing a REST style fetch. + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)feedURL + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + // no object class specified; use registered class + return [self fetchObjectWithURL:feedURL + objectClass:nil + bodyObject:nil + ETag:nil + httpMethod:nil + mayAuthorize:YES + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchPublicObjectWithURL:(NSURL *)feedURL + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + return [self fetchObjectWithURL:feedURL + objectClass:objectClass + bodyObject:nil + ETag:nil + httpMethod:nil + mayAuthorize:NO + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)feedURL + objectClass:(Class)objectClass + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + return [self fetchObjectWithURL:feedURL + objectClass:objectClass + bodyObject:nil + ETag:nil + httpMethod:nil + mayAuthorize:YES + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + ticket:nil]; +} + + +- (GTLServiceTicket *)fetchObjectByInsertingObject:(GTLObject *)bodyToPost + forURL:(NSURL *)destinationURL + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + Class objClass = [bodyToPost class]; + NSString *etag = ETagIfPresent(bodyToPost); + + return [self fetchObjectWithURL:destinationURL + objectClass:objClass + bodyObject:bodyToPost + ETag:etag + httpMethod:@"POST" + mayAuthorize:YES + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectByUpdatingObject:(GTLObject *)bodyToPut + forURL:(NSURL *)destinationURL + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + Class objClass = [bodyToPut class]; + NSString *etag = ETagIfPresent(bodyToPut); + + return [self fetchObjectWithURL:destinationURL + objectClass:objClass + bodyObject:bodyToPut + ETag:etag + httpMethod:@"PUT" + mayAuthorize:YES + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + ticket:nil]; +} + + +- (GTLServiceTicket *)deleteResourceURL:(NSURL *)destinationURL + ETag:(NSString *)etagOrNil + delegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + return [self fetchObjectWithURL:destinationURL + objectClass:nil + bodyObject:nil + ETag:etagOrNil + httpMethod:@"DELETE" + mayAuthorize:YES + delegate:delegate + didFinishSelector:finishedSelector + completionHandler:nil + ticket:nil]; +} + + +- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)objectURL + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + return [self fetchObjectWithURL:objectURL + objectClass:nil + bodyObject:nil + ETag:nil + httpMethod:nil + mayAuthorize:YES + delegate:nil + didFinishSelector:NULL + completionHandler:handler + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectByInsertingObject:(GTLObject *)bodyToPost + forURL:(NSURL *)destinationURL + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + Class objClass = [bodyToPost class]; + NSString *etag = ETagIfPresent(bodyToPost); + + return [self fetchObjectWithURL:destinationURL + objectClass:objClass + bodyObject:bodyToPost + ETag:etag + httpMethod:@"POST" + mayAuthorize:YES + delegate:nil + didFinishSelector:NULL + completionHandler:handler + ticket:nil]; +} + +- (GTLServiceTicket *)fetchObjectByUpdatingObject:(GTLObject *)bodyToPut + forURL:(NSURL *)destinationURL + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + Class objClass = [bodyToPut class]; + NSString *etag = ETagIfPresent(bodyToPut); + + return [self fetchObjectWithURL:destinationURL + objectClass:objClass + bodyObject:bodyToPut + ETag:etag + httpMethod:@"PUT" + mayAuthorize:YES + delegate:nil + didFinishSelector:NULL + completionHandler:handler + ticket:nil]; +} + +- (GTLServiceTicket *)deleteResourceURL:(NSURL *)destinationURL + ETag:(NSString *)etagOrNil + completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler { + return [self fetchObjectWithURL:destinationURL + objectClass:nil + bodyObject:nil + ETag:etagOrNil + httpMethod:@"DELETE" + mayAuthorize:YES + delegate:nil + didFinishSelector:NULL + completionHandler:handler + ticket:nil]; +} + +#pragma mark - + +- (NSString *)userAgent { + return userAgent_; +} + +- (void)setExactUserAgent:(NSString *)userAgent { + // internal use only + [userAgent_ release]; + userAgent_ = [userAgent copy]; +} + +- (void)setUserAgent:(NSString *)userAgent { + // remove whitespace and unfriendly characters + NSString *str = GTMBridgeCleanedUserAgentString(userAgent); + [self setExactUserAgent:str]; +} + +// +// The following methods pass through to the fetcher service object +// + +- (void)setCookieStorageMethod:(NSInteger)method { +#if !GTL_USE_SESSION_FETCHER + self.fetcherService.cookieStorageMethod = method; +#endif +} + +- (NSInteger)cookieStorageMethod { +#if !GTL_USE_SESSION_FETCHER + return self.fetcherService.cookieStorageMethod; +#else + return 1; +#endif +} + +- (void)setShouldFetchInBackground:(BOOL)flag { +#if !GTL_USE_SESSION_FETCHER + self.fetcherService.shouldFetchInBackground = flag; +#endif +} + +- (BOOL)shouldFetchInBackground { +#if !GTL_USE_SESSION_FETCHER + return self.fetcherService.shouldFetchInBackground; +#else + return YES; +#endif +} + +- (void)setDelegateQueue:(NSOperationQueue *)delegateQueue { +#if !GTL_USE_SESSION_FETCHER + self.fetcherService.delegateQueue = delegateQueue; +#endif +} + +- (NSOperationQueue *)delegateQueue { +#if !GTL_USE_SESSION_FETCHER + return self.fetcherService.delegateQueue; +#else + return nil; +#endif +} + +- (void)setRunLoopModes:(NSArray *)array { +#if !GTL_USE_SESSION_FETCHER + self.fetcherService.runLoopModes = array; +#endif +} + +- (NSArray *)runLoopModes { +#if !GTL_USE_SESSION_FETCHER + return self.fetcherService.runLoopModes; +#else + return nil; +#endif +} + +#pragma mark - + +// The service properties becomes the initial value for each future ticket's +// properties +- (void)setServiceProperties:(NSDictionary *)dict { + [serviceProperties_ autorelease]; + serviceProperties_ = [dict mutableCopy]; +} + +- (NSDictionary *)serviceProperties { + // be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[serviceProperties_ retain] autorelease]; +} + +- (void)setServiceProperty:(id)obj forKey:(NSString *)key { + + if (obj == nil) { + // user passed in nil, so delete the property + [serviceProperties_ removeObjectForKey:key]; + } else { + // be sure the property dictionary exists + if (serviceProperties_ == nil) { + [self setServiceProperties:[NSDictionary dictionary]]; + } + [serviceProperties_ setObject:obj forKey:key]; + } +} + +- (id)servicePropertyForKey:(NSString *)key { + id obj = [serviceProperties_ objectForKey:key]; + + // be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[obj retain] autorelease]; +} + +- (void)setServiceUserData:(id)userData { + [self setServiceProperty:userData forKey:kServiceUserDataPropertyKey]; +} + +- (id)serviceUserData { + return [[[self servicePropertyForKey:kServiceUserDataPropertyKey] retain] autorelease]; +} + +- (void)setAuthorizer:(id )authorizer { + self.fetcherService.authorizer = authorizer; +} + +- (id )authorizer { + return self.fetcherService.authorizer; +} + ++ (NSUInteger)defaultServiceUploadChunkSize { + // subclasses may override + return kStandardUploadChunkSize; +} + +- (NSUInteger)serviceUploadChunkSize { + return uploadChunkSize_; +} + +- (void)setServiceUploadChunkSize:(NSUInteger)val { + + if (val == kGTLStandardUploadChunkSize) { + // determine an appropriate upload chunk size for the system + +#if GTL_USE_SESSION_FETCHER + BOOL doesSupportSentDataCallback = YES; +#else + BOOL doesSupportSentDataCallback = [GTMHTTPFetcher doesSupportSentDataCallback]; +#endif + if (!doesSupportSentDataCallback) { + // for 10.4 and iPhone 2, we need a small upload chunk size so there + // are frequent intrachunk callbacks for progress monitoring + val = 75000; + } else { +#if GTL_IPHONE + val = 1000000; +#else + if (NSFoundationVersionNumber >= 751.00) { + // Mac OS X 10.6 + // + // we'll pick a huge upload chunk size, which minimizes http overhead + // and server effort, and we'll hope that NSURLConnection can finally + // handle big uploads reliably + val = 25000000; + } else { + // Mac OS X 10.5 + // + // NSURLConnection is more reliable on POSTs in 10.5 than it was in + // 10.4, but it still fails mysteriously on big uploads on some + // systems, so we'll limit the chunks to a megabyte + val = 1000000; + } +#endif + } + } + uploadChunkSize_ = val; +} + +@end + +@implementation GTLServiceTicket + +@synthesize shouldFetchNextPages = shouldFetchNextPages_, + surrogates = surrogates_, + uploadProgressSelector = uploadProgressSelector_, + retryEnabled = isRetryEnabled_, + hasCalledCallback = hasCalledCallback_, + retrySelector = retrySelector_, + maxRetryInterval = maxRetryInterval_, + objectFetcher = objectFetcher_, + postedObject = postedObject_, + fetchedObject = fetchedObject_, + executingQuery = executingQuery_, + originalQuery = originalQuery_, + fetchError = fetchError_, + pagesFetchedCounter = pagesFetchedCounter_, + APIKey = apiKey_, + parseOperation = parseOperation_, + isREST = isREST_, + retryBlock = retryBlock_; + ++ (id)ticketForService:(GTLService *)service { + return [[[self alloc] initWithService:service] autorelease]; +} + +- (id)initWithService:(GTLService *)service { + self = [super init]; + if (self) { + service_ = [service retain]; + + ticketProperties_ = [service.serviceProperties mutableCopy]; + surrogates_ = [service.surrogates retain]; + uploadProgressSelector_ = service.uploadProgressSelector; + isRetryEnabled_ = service.retryEnabled; + retrySelector_ = service.retrySelector; + maxRetryInterval_ = service.maxRetryInterval; + shouldFetchNextPages_ = service.shouldFetchNextPages; + apiKey_ = [service.APIKey copy]; + uploadProgressBlock_ = [service.uploadProgressBlock copy]; + retryBlock_ = [service.retryBlock copy]; + } + return self; +} + +- (void)dealloc { + [service_ release]; + [ticketProperties_ release]; + [surrogates_ release]; + [objectFetcher_ release]; + [uploadProgressBlock_ release]; + [retryBlock_ release]; + [postedObject_ release]; + [fetchedObject_ release]; + [executingQuery_ release]; + [originalQuery_ release]; + [fetchError_ release]; + [apiKey_ release]; + [parseOperation_ release]; + + [super dealloc]; +} + +- (NSString *)description { + NSString *devKeyInfo = @""; + if (apiKey_ != nil) { + devKeyInfo = [NSString stringWithFormat:@" devKey:%@", apiKey_]; + } + + NSString *authorizerInfo = @""; + id authorizer = self.objectFetcher.authorizer; + if (authorizer != nil) { + authorizerInfo = [NSString stringWithFormat:@" authorizer:%@", authorizer]; + } + + return [NSString stringWithFormat:@"%@ %p: {service:%@%@%@ fetcher:%@ }", + [self class], self, service_, devKeyInfo, authorizerInfo, objectFetcher_]; +} + +- (void)pauseUpload { + BOOL canPause = [objectFetcher_ respondsToSelector:@selector(pauseFetching)]; + GTL_DEBUG_ASSERT(canPause, @"unpauseable ticket"); + + if (canPause) { + [(GTLUploadFetcherClass *)objectFetcher_ pauseFetching]; + } +} + +- (void)resumeUpload { + BOOL canResume = [objectFetcher_ respondsToSelector:@selector(resumeFetching)]; + GTL_DEBUG_ASSERT(canResume, @"unresumable ticket"); + + if (canResume) { + [(GTLUploadFetcherClass *)objectFetcher_ resumeFetching]; + } +} + +- (BOOL)isUploadPaused { + BOOL isPausable = [objectFetcher_ respondsToSelector:@selector(isPaused)]; + GTL_DEBUG_ASSERT(isPausable, @"unpauseable ticket"); + + if (isPausable) { + return [(GTLUploadFetcherClass *)objectFetcher_ isPaused]; + } + return NO; +} + +- (void)cancelTicket { + NSOperation *parseOperation = self.parseOperation; + [parseOperation cancel]; + self.parseOperation = nil; + + [objectFetcher_ stopFetching]; + objectFetcher_.properties = nil; + + self.objectFetcher = nil; + self.properties = nil; + self.uploadProgressSelector = nil; + + self.uploadProgressBlock = nil; + self.retryBlock = nil; + + [self.executingQuery executionDidStop]; + self.executingQuery = self.originalQuery; + + [service_ autorelease]; + service_ = nil; +} + +- (id)service { + return service_; +} + +- (void)setUserData:(id)userData { + [self setProperty:userData forKey:kServiceUserDataPropertyKey]; +} + +- (id)userData { + // be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[[self propertyForKey:kServiceUserDataPropertyKey] retain] autorelease]; +} + +- (void)setProperties:(NSDictionary *)dict { + [ticketProperties_ autorelease]; + ticketProperties_ = [dict mutableCopy]; +} + +- (NSDictionary *)properties { + // be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[ticketProperties_ retain] autorelease]; +} + +- (void)setProperty:(id)obj forKey:(NSString *)key { + if (obj == nil) { + // user passed in nil, so delete the property + [ticketProperties_ removeObjectForKey:key]; + } else { + // be sure the property dictionary exists + if (ticketProperties_ == nil) { + // call setProperties so observers are notified + [self setProperties:[NSDictionary dictionary]]; + } + [ticketProperties_ setObject:obj forKey:key]; + } +} + +- (id)propertyForKey:(NSString *)key { + id obj = [ticketProperties_ objectForKey:key]; + + // be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[obj retain] autorelease]; +} + +- (NSDictionary *)surrogates { + return surrogates_; +} + +- (void)setSurrogates:(NSDictionary *)dict { + [surrogates_ autorelease]; + surrogates_ = [dict retain]; +} + +- (SEL)uploadProgressSelector { + return uploadProgressSelector_; +} + +- (void)setUploadProgressSelector:(SEL)progressSelector { + uploadProgressSelector_ = progressSelector; + + // if the user is turning on the progress selector in the ticket after the + // ticket's fetcher has been created, we need to give the fetcher our sentData + // callback. + // + // The progress monitor must be set in the service prior to creation of the + // ticket on 10.4 and iPhone 2.0, since on those systems the upload data must + // be wrapped with a ProgressMonitorInputStream prior to the creation of the + // fetcher. + if (progressSelector != NULL) { +#if GTL_USE_SESSION_FETCHER + __block GTMSessionFetcher *fetcher = [self objectFetcher]; + fetcher.sendProgressBlock = ^(int64_t bytesSent, int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + [service_ objectFetcher:fetcher + didSendBytes:(NSInteger)bytesSent + totalBytesSent:(NSInteger)totalBytesSent + totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend]; + }; +#else + SEL sentDataSel = @selector(objectFetcher:didSendBytes:totalBytesSent:totalBytesExpectedToSend:); + [[self objectFetcher] setSentDataSelector:sentDataSel]; +#endif + } +} + +- (void)setUploadProgressBlock:(GTLServiceUploadProgressBlock)block { + [uploadProgressBlock_ autorelease]; + uploadProgressBlock_ = [block copy]; + + if (uploadProgressBlock_) { + // As above, we need the fetcher to call us back when bytes are sent. +#if GTL_USE_SESSION_FETCHER + __block GTMSessionFetcher *fetcher = [self objectFetcher]; + fetcher.sendProgressBlock = ^(int64_t bytesSent, int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + [service_ objectFetcher:fetcher + didSendBytes:(NSInteger)bytesSent + totalBytesSent:(NSInteger)totalBytesSent + totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend]; + }; +#else + SEL sentDataSel = @selector(objectFetcher:didSendBytes:totalBytesSent:totalBytesExpectedToSend:); + [[self objectFetcher] setSentDataSelector:sentDataSel]; +#endif + } +} + +- (GTLServiceUploadProgressBlock)uploadProgressBlock { + return uploadProgressBlock_; +} + +- (NSInteger)statusCode { + return [objectFetcher_ statusCode]; +} + +- (GTLQuery *)queryForRequestID:(NSString *)requestID { + id queryObj = self.executingQuery; + if ([queryObj isBatchQuery]) { + GTLBatchQuery *batch = (GTLBatchQuery *)queryObj; + GTLQuery *result = [batch queryForRequestID:requestID]; + return result; + } else { + GTL_DEBUG_ASSERT(0, @"just use ticket.executingQuery"); + return nil; + } +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLUploadParameters.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLUploadParameters.h new file mode 100755 index 0000000..b436d9b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLUploadParameters.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLUploadParameters.h +// + +// Uploading documentation: +// https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Uploading_Files + +#import + +#import "GTLDefines.h" + +@interface GTLUploadParameters : NSObject { + @private + NSString *MIMEType_; + NSData *data_; + NSFileHandle *fileHandle_; + NSURL *fileURL_; + NSURL *uploadLocationURL_; + NSString *slug_; + BOOL shouldSendUploadOnly_; +} + +// Uploading requires MIME type and one of +// - data to be uploaded +// - URL of file to be uploaded (preferred for large files) +// - file handle for uploading +@property (copy) NSString *MIMEType; +@property (retain) NSData *data; +@property (retain) NSFileHandle *fileHandle; +@property (retain) NSURL *fileURL; + +// Resuming an in-progress upload is done with the upload location URL, +// and requires a file handle for uploading +@property (retain) NSURL *uploadLocationURL; + +// Some services need a slug (filename) header +@property (copy) NSString *slug; + +// Uploads may be done without a JSON body in the initial request +@property (assign) BOOL shouldSendUploadOnly; + ++ (instancetype)uploadParametersWithData:(NSData *)data + MIMEType:(NSString *)mimeType GTL_NONNULL((1,2)); + ++ (instancetype)uploadParametersWithFileHandle:(NSFileHandle *)fileHandle + MIMEType:(NSString *)mimeType GTL_NONNULL((1,2)); + ++ (instancetype)uploadParametersWithFileURL:(NSURL *)fileHandle + MIMEType:(NSString *)mimeType GTL_NONNULL((1,2)); + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLUploadParameters.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLUploadParameters.m new file mode 100755 index 0000000..03db6a1 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Objects/GTLUploadParameters.m @@ -0,0 +1,123 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLObject.m +// + +#include + +#import "GTLUploadParameters.h" + +@implementation GTLUploadParameters + +@synthesize MIMEType = MIMEType_, + data = data_, + fileHandle = fileHandle_, + uploadLocationURL = uploadLocationURL_, + fileURL = fileURL_, + slug = slug_, + shouldSendUploadOnly = shouldSendUploadOnly_; + ++ (instancetype)uploadParametersWithData:(NSData *)data + MIMEType:(NSString *)mimeType { + GTLUploadParameters *params = [[[self alloc] init] autorelease]; + params.data = data; + params.MIMEType = mimeType; + return params; +} + ++ (instancetype)uploadParametersWithFileHandle:(NSFileHandle *)fileHandle + MIMEType:(NSString *)mimeType { + GTLUploadParameters *params = [[[self alloc] init] autorelease]; + params.fileHandle = fileHandle; + params.MIMEType = mimeType; + return params; +} + ++ (instancetype)uploadParametersWithFileURL:(NSURL *)fileURL + MIMEType:(NSString *)mimeType { + GTLUploadParameters *params = [[[self alloc] init] autorelease]; + params.fileURL = fileURL; + params.MIMEType = mimeType; + return params; +} + +- (id)copyWithZone:(NSZone *)zone { + GTLUploadParameters *newParams = [[[self class] allocWithZone:zone] init]; + newParams.MIMEType = self.MIMEType; + newParams.data = self.data; + newParams.fileHandle = self.fileHandle; + newParams.fileURL = self.fileURL; + newParams.uploadLocationURL = self.uploadLocationURL; + newParams.slug = self.slug; + newParams.shouldSendUploadOnly = self.shouldSendUploadOnly; + return newParams; +} + +- (void)dealloc { + [MIMEType_ release]; + [data_ release]; + [fileHandle_ release]; + [fileURL_ release]; + [uploadLocationURL_ release]; + [slug_ release]; + + [super dealloc]; +} + +- (NSString *)description { + NSMutableArray *array = [NSMutableArray array]; + NSString *str = [NSString stringWithFormat:@"MIMEType:%@", MIMEType_]; + [array addObject:str]; + + if (data_) { + str = [NSString stringWithFormat:@"data:%llu bytes", + (unsigned long long)[data_ length]]; + [array addObject:str]; + } + + if (fileHandle_) { + str = [NSString stringWithFormat:@"fileHandle:%@", fileHandle_]; + [array addObject:str]; + } + + if (fileURL_) { + str = [NSString stringWithFormat:@"file:%@", [fileURL_ path]]; + [array addObject:str]; + } + + if (uploadLocationURL_) { + str = [NSString stringWithFormat:@"uploadLocation:%@", + [uploadLocationURL_ absoluteString]]; + [array addObject:str]; + } + + if (slug_) { + str = [NSString stringWithFormat:@"slug:%@", slug_]; + [array addObject:str]; + } + + if (shouldSendUploadOnly_) { + [array addObject:@"shouldSendUploadOnly"]; + } + + NSString *descStr = [array componentsJoinedByString:@", "]; + str = [NSString stringWithFormat:@"%@ %p: {%@}", + [self class], self, descStr]; + return str; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrive.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrive.h new file mode 100755 index 0000000..61fa0c9 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrive.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrive.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ + +#import "GTLDriveConstants.h" + +#import "GTLDriveAbout.h" +#import "GTLDriveApp.h" +#import "GTLDriveAppList.h" +#import "GTLDriveChange.h" +#import "GTLDriveChangeList.h" +#import "GTLDriveChannel.h" +#import "GTLDriveChildList.h" +#import "GTLDriveChildReference.h" +#import "GTLDriveComment.h" +#import "GTLDriveCommentList.h" +#import "GTLDriveCommentReply.h" +#import "GTLDriveCommentReplyList.h" +#import "GTLDriveFile.h" +#import "GTLDriveFileList.h" +#import "GTLDriveParentList.h" +#import "GTLDriveParentReference.h" +#import "GTLDrivePermission.h" +#import "GTLDrivePermissionId.h" +#import "GTLDrivePermissionList.h" +#import "GTLDriveProperty.h" +#import "GTLDrivePropertyList.h" +#import "GTLDriveRevision.h" +#import "GTLDriveRevisionList.h" +#import "GTLDriveUser.h" + +#import "GTLQueryDrive.h" +#import "GTLServiceDrive.h" diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAbout.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAbout.h new file mode 100755 index 0000000..48c38f0 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAbout.h @@ -0,0 +1,249 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveAbout.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveAbout (0 custom class methods, 23 custom properties) +// GTLDriveAboutAdditionalRoleInfoItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutExportFormatsItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutFeaturesItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutImportFormatsItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutMaxUploadSizesItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutQuotaBytesByServiceItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem (0 custom class methods, 2 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveAboutAdditionalRoleInfoItem; +@class GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem; +@class GTLDriveAboutExportFormatsItem; +@class GTLDriveAboutFeaturesItem; +@class GTLDriveAboutImportFormatsItem; +@class GTLDriveAboutMaxUploadSizesItem; +@class GTLDriveAboutQuotaBytesByServiceItem; +@class GTLDriveUser; + +// ---------------------------------------------------------------------------- +// +// GTLDriveAbout +// + +// An item with user information and settings. + +@interface GTLDriveAbout : GTLObject + +// Information about supported additional roles per file type. The most specific +// type takes precedence. +@property (retain) NSArray *additionalRoleInfo; // of GTLDriveAboutAdditionalRoleInfoItem + +// The domain sharing policy for the current user. +@property (copy) NSString *domainSharingPolicy; + +// The ETag of the item. +@property (copy) NSString *ETag; + +// The allowable export formats. +@property (retain) NSArray *exportFormats; // of GTLDriveAboutExportFormatsItem + +// List of additional features enabled on this account. +@property (retain) NSArray *features; // of GTLDriveAboutFeaturesItem + +// The allowable import formats. +@property (retain) NSArray *importFormats; // of GTLDriveAboutImportFormatsItem + +// A boolean indicating whether the authenticated app is installed by the +// authenticated user. +@property (retain) NSNumber *isCurrentAppInstalled; // boolValue + +// This is always drive#about. +@property (copy) NSString *kind; + +// The user's language or locale code, as defined by BCP 47, with some +// extensions from Unicode's LDML format (http://www.unicode.org/reports/tr35/). +@property (copy) NSString *languageCode; + +// The largest change id. +@property (retain) NSNumber *largestChangeId; // longLongValue + +// List of max upload sizes for each file type. The most specific type takes +// precedence. +@property (retain) NSArray *maxUploadSizes; // of GTLDriveAboutMaxUploadSizesItem + +// The name of the current user. +@property (copy) NSString *name; + +// The current user's ID as visible in the permissions collection. +@property (copy) NSString *permissionId; + +// The amount of storage quota used by different Google services. +@property (retain) NSArray *quotaBytesByService; // of GTLDriveAboutQuotaBytesByServiceItem + +// The total number of quota bytes. +@property (retain) NSNumber *quotaBytesTotal; // longLongValue + +// The number of quota bytes used by Google Drive. +@property (retain) NSNumber *quotaBytesUsed; // longLongValue + +// The number of quota bytes used by all Google apps (Drive, Picasa, etc.). +@property (retain) NSNumber *quotaBytesUsedAggregate; // longLongValue + +// The number of quota bytes used by trashed items. +@property (retain) NSNumber *quotaBytesUsedInTrash; // longLongValue + +// The type of the user's storage quota. Possible values are: +// - LIMITED +// - UNLIMITED +@property (copy) NSString *quotaType; + +// The number of remaining change ids. +@property (retain) NSNumber *remainingChangeIds; // longLongValue + +// The id of the root folder. +@property (copy) NSString *rootFolderId; + +// A link back to this item. +@property (copy) NSString *selfLink; + +// The authenticated user. +@property (retain) GTLDriveUser *user; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutAdditionalRoleInfoItem +// + +@interface GTLDriveAboutAdditionalRoleInfoItem : GTLObject + +// The supported additional roles per primary role. +@property (retain) NSArray *roleSets; // of GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem + +// The content type that this additional role info applies to. +@property (copy) NSString *type; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutExportFormatsItem +// + +@interface GTLDriveAboutExportFormatsItem : GTLObject + +// The content type to convert from. +@property (copy) NSString *source; + +// The possible content types to convert to. +@property (retain) NSArray *targets; // of NSString + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutFeaturesItem +// + +@interface GTLDriveAboutFeaturesItem : GTLObject + +// The name of the feature. +@property (copy) NSString *featureName; + +// The request limit rate for this feature, in queries per second. +@property (retain) NSNumber *featureRate; // doubleValue + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutImportFormatsItem +// + +@interface GTLDriveAboutImportFormatsItem : GTLObject + +// The imported file's content type to convert from. +@property (copy) NSString *source; + +// The possible content types to convert to. +@property (retain) NSArray *targets; // of NSString + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutMaxUploadSizesItem +// + +@interface GTLDriveAboutMaxUploadSizesItem : GTLObject + +// The max upload size for this type. +@property (retain) NSNumber *size; // longLongValue + +// The file type. +@property (copy) NSString *type; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutQuotaBytesByServiceItem +// + +@interface GTLDriveAboutQuotaBytesByServiceItem : GTLObject + +// The storage quota bytes used by the service. +@property (retain) NSNumber *bytesUsed; // longLongValue + +// The service's name, e.g. DRIVE, GMAIL, or PHOTOS. +@property (copy) NSString *serviceName; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem +// + +@interface GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem : GTLObject + +// The supported additional roles with the primary role. +@property (retain) NSArray *additionalRoles; // of NSString + +// A primary permission role. +@property (copy) NSString *primaryRole; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAbout.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAbout.m new file mode 100755 index 0000000..5fcc1e5 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAbout.m @@ -0,0 +1,181 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveAbout.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveAbout (0 custom class methods, 23 custom properties) +// GTLDriveAboutAdditionalRoleInfoItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutExportFormatsItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutFeaturesItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutImportFormatsItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutMaxUploadSizesItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutQuotaBytesByServiceItem (0 custom class methods, 2 custom properties) +// GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem (0 custom class methods, 2 custom properties) + +#import "GTLDriveAbout.h" + +#import "GTLDriveUser.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveAbout +// + +@implementation GTLDriveAbout +@dynamic additionalRoleInfo, domainSharingPolicy, ETag, exportFormats, features, + importFormats, isCurrentAppInstalled, kind, languageCode, + largestChangeId, maxUploadSizes, name, permissionId, + quotaBytesByService, quotaBytesTotal, quotaBytesUsed, + quotaBytesUsedAggregate, quotaBytesUsedInTrash, quotaType, + remainingChangeIds, rootFolderId, selfLink, user; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObjectsAndKeys: + [GTLDriveAboutAdditionalRoleInfoItem class], @"additionalRoleInfo", + [GTLDriveAboutExportFormatsItem class], @"exportFormats", + [GTLDriveAboutFeaturesItem class], @"features", + [GTLDriveAboutImportFormatsItem class], @"importFormats", + [GTLDriveAboutMaxUploadSizesItem class], @"maxUploadSizes", + [GTLDriveAboutQuotaBytesByServiceItem class], @"quotaBytesByService", + nil]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#about"]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutAdditionalRoleInfoItem +// + +@implementation GTLDriveAboutAdditionalRoleInfoItem +@dynamic roleSets, type; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem class] + forKey:@"roleSets"]; + return map; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutExportFormatsItem +// + +@implementation GTLDriveAboutExportFormatsItem +@dynamic source, targets; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[NSString class] + forKey:@"targets"]; + return map; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutFeaturesItem +// + +@implementation GTLDriveAboutFeaturesItem +@dynamic featureName, featureRate; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutImportFormatsItem +// + +@implementation GTLDriveAboutImportFormatsItem +@dynamic source, targets; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[NSString class] + forKey:@"targets"]; + return map; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutMaxUploadSizesItem +// + +@implementation GTLDriveAboutMaxUploadSizesItem +@dynamic size, type; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutQuotaBytesByServiceItem +// + +@implementation GTLDriveAboutQuotaBytesByServiceItem +@dynamic bytesUsed, serviceName; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem +// + +@implementation GTLDriveAboutAdditionalRoleInfoItemRoleSetsItem +@dynamic additionalRoles, primaryRole; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[NSString class] + forKey:@"additionalRoles"]; + return map; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveApp.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveApp.h new file mode 100755 index 0000000..9d08de8 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveApp.h @@ -0,0 +1,151 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveApp.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveApp (0 custom class methods, 24 custom properties) +// GTLDriveAppIconsItem (0 custom class methods, 3 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveAppIconsItem; + +// ---------------------------------------------------------------------------- +// +// GTLDriveApp +// + +// The apps resource provides a list of the apps that a user has installed, with +// information about each app's supported MIME types, file extensions, and other +// details. + +@interface GTLDriveApp : GTLObject + +// Whether the app is authorized to access data on the user's Drive. +@property (retain) NSNumber *authorized; // boolValue + +// The template url to create a new file with this app in a given folder. The +// template will contain {folderId} to be replaced by the folder to create the +// new file in. +@property (copy) NSString *createInFolderTemplate; + +// The url to create a new file with this app. +@property (copy) NSString *createUrl; + +// Whether the app has drive-wide scope. An app with drive-wide scope can access +// all files in the user's drive. +@property (retain) NSNumber *hasDriveWideScope; // boolValue + +// The various icons for the app. +@property (retain) NSArray *icons; // of GTLDriveAppIconsItem + +// The ID of the app. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// Whether the app is installed. +@property (retain) NSNumber *installed; // boolValue + +// This is always drive#app. +@property (copy) NSString *kind; + +// A long description of the app. +@property (copy) NSString *longDescription; + +// The name of the app. +@property (copy) NSString *name; + +// The type of object this app creates (e.g. Chart). If empty, the app name +// should be used instead. +@property (copy) NSString *objectType; + +// The template url for opening files with this app. The template will contain +// {ids} and/or {exportIds} to be replaced by the actual file ids. +@property (copy) NSString *openUrlTemplate; + +// The list of primary file extensions. +@property (retain) NSArray *primaryFileExtensions; // of NSString + +// The list of primary mime types. +@property (retain) NSArray *primaryMimeTypes; // of NSString + +// The ID of the product listing for this app. +@property (copy) NSString *productId; + +// A link to the product listing for this app. +@property (copy) NSString *productUrl; + +// The list of secondary file extensions. +@property (retain) NSArray *secondaryFileExtensions; // of NSString + +// The list of secondary mime types. +@property (retain) NSArray *secondaryMimeTypes; // of NSString + +// A short description of the app. +@property (copy) NSString *shortDescription; + +// Whether this app supports creating new objects. +@property (retain) NSNumber *supportsCreate; // boolValue + +// Whether this app supports importing Google Docs. +@property (retain) NSNumber *supportsImport; // boolValue + +// Whether this app supports opening more than one file. +@property (retain) NSNumber *supportsMultiOpen; // boolValue + +// Whether this app supports creating new files when offline. +@property (retain) NSNumber *supportsOfflineCreate; // boolValue + +// Whether the app is selected as the default handler for the types it supports. +@property (retain) NSNumber *useByDefault; // boolValue + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAppIconsItem +// + +@interface GTLDriveAppIconsItem : GTLObject + +// Category of the icon. Allowed values are: +// - application - icon for the application +// - document - icon for a file associated with the app +// - documentShared - icon for a shared file associated with the app +@property (copy) NSString *category; + +// URL for the icon. +@property (copy) NSString *iconUrl; + +// Size of the icon. Represented as the maximum of the width and height. +@property (retain) NSNumber *size; // intValue + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveApp.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveApp.m new file mode 100755 index 0000000..1e7eca7 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveApp.m @@ -0,0 +1,80 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveApp.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveApp (0 custom class methods, 24 custom properties) +// GTLDriveAppIconsItem (0 custom class methods, 3 custom properties) + +#import "GTLDriveApp.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveApp +// + +@implementation GTLDriveApp +@dynamic authorized, createInFolderTemplate, createUrl, hasDriveWideScope, + icons, identifier, installed, kind, longDescription, name, objectType, + openUrlTemplate, primaryFileExtensions, primaryMimeTypes, productId, + productUrl, secondaryFileExtensions, secondaryMimeTypes, + shortDescription, supportsCreate, supportsImport, supportsMultiOpen, + supportsOfflineCreate, useByDefault; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"id" + forKey:@"identifier"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObjectsAndKeys: + [GTLDriveAppIconsItem class], @"icons", + [NSString class], @"primaryFileExtensions", + [NSString class], @"primaryMimeTypes", + [NSString class], @"secondaryFileExtensions", + [NSString class], @"secondaryMimeTypes", + nil]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#app"]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveAppIconsItem +// + +@implementation GTLDriveAppIconsItem +@dynamic category, iconUrl, size; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAppList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAppList.h new file mode 100755 index 0000000..3df5674 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAppList.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveAppList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveAppList (0 custom class methods, 5 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveApp; + +// ---------------------------------------------------------------------------- +// +// GTLDriveAppList +// + +// A list of third-party applications which the user has installed or given +// access to Google Drive. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveAppList : GTLCollectionObject + +// List of app IDs that the user has specified to use by default. The list is in +// reverse-priority order (lowest to highest). +@property (retain) NSArray *defaultAppIds; // of NSString + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The actual list of apps. +@property (retain) NSArray *items; // of GTLDriveApp + +// This is always drive#appList. +@property (copy) NSString *kind; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAppList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAppList.m new file mode 100755 index 0000000..b88b83b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveAppList.m @@ -0,0 +1,63 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveAppList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveAppList (0 custom class methods, 5 custom properties) + +#import "GTLDriveAppList.h" + +#import "GTLDriveApp.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveAppList +// + +@implementation GTLDriveAppList +@dynamic defaultAppIds, ETag, items, kind, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObjectsAndKeys: + [NSString class], @"defaultAppIds", + [GTLDriveApp class], @"items", + nil]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#appList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChange.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChange.h new file mode 100755 index 0000000..7448360 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChange.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChange.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChange (0 custom class methods, 7 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveFile; + +// ---------------------------------------------------------------------------- +// +// GTLDriveChange +// + +// Representation of a change to a file. + +@interface GTLDriveChange : GTLObject + +// Whether the file has been deleted. +@property (retain) NSNumber *deleted; // boolValue + +// The updated state of the file. Present if the file has not been deleted. +@property (retain) GTLDriveFile *file; + +// The ID of the file associated with this change. +@property (copy) NSString *fileId; + +// The ID of the change. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (retain) NSNumber *identifier; // longLongValue + +// This is always drive#change. +@property (copy) NSString *kind; + +// The time of this modification. +@property (retain) GTLDateTime *modificationDate; + +// A link back to this change. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChange.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChange.m new file mode 100755 index 0000000..ea708a9 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChange.m @@ -0,0 +1,54 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChange.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChange (0 custom class methods, 7 custom properties) + +#import "GTLDriveChange.h" + +#import "GTLDriveFile.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveChange +// + +@implementation GTLDriveChange +@dynamic deleted, file, fileId, identifier, kind, modificationDate, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"id" + forKey:@"identifier"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#change"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChangeList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChangeList.h new file mode 100755 index 0000000..81c08e1 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChangeList.h @@ -0,0 +1,72 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChangeList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChangeList (0 custom class methods, 7 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveChange; + +// ---------------------------------------------------------------------------- +// +// GTLDriveChangeList +// + +// A list of changes for a user. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveChangeList : GTLCollectionObject + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The actual list of changes. +@property (retain) NSArray *items; // of GTLDriveChange + +// This is always drive#changeList. +@property (copy) NSString *kind; + +// The current largest change ID. +@property (retain) NSNumber *largestChangeId; // longLongValue + +// A link to the next page of changes. +@property (copy) NSString *nextLink; + +// The page token for the next page of changes. +@property (copy) NSString *nextPageToken; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChangeList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChangeList.m new file mode 100755 index 0000000..e6ef167 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChangeList.m @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChangeList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChangeList (0 custom class methods, 7 custom properties) + +#import "GTLDriveChangeList.h" + +#import "GTLDriveChange.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveChangeList +// + +@implementation GTLDriveChangeList +@dynamic ETag, items, kind, largestChangeId, nextLink, nextPageToken, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveChange class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#changeList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChannel.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChannel.h new file mode 100755 index 0000000..323a4a4 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChannel.h @@ -0,0 +1,97 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChannel.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChannel (0 custom class methods, 10 custom properties) +// GTLDriveChannelParams (0 custom class methods, 0 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveChannelParams; + +// ---------------------------------------------------------------------------- +// +// GTLDriveChannel +// + +// An notification channel used to watch for resource changes. + +@interface GTLDriveChannel : GTLObject + +// The address where notifications are delivered for this channel. +@property (copy) NSString *address; + +// Date and time of notification channel expiration, expressed as a Unix +// timestamp, in milliseconds. Optional. +@property (retain) NSNumber *expiration; // longLongValue + +// A UUID or similar unique string that identifies this channel. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// Identifies this as a notification channel used to watch for changes to a +// resource. Value: the fixed string "api#channel". +@property (copy) NSString *kind; + +// Additional parameters controlling delivery channel behavior. Optional. +@property (retain) GTLDriveChannelParams *params; + +// A Boolean value to indicate whether payload is wanted. Optional. +@property (retain) NSNumber *payload; // boolValue + +// An opaque ID that identifies the resource being watched on this channel. +// Stable across different API versions. +@property (copy) NSString *resourceId; + +// A version-specific identifier for the watched resource. +@property (copy) NSString *resourceUri; + +// An arbitrary string delivered to the target address with each notification +// delivered over this channel. Optional. +@property (copy) NSString *token; + +// The type of delivery mechanism used for this channel. +@property (copy) NSString *type; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveChannelParams +// + +@interface GTLDriveChannelParams : GTLObject +// This object is documented as having more properties that are NSString. Use +// -additionalJSONKeys and -additionalPropertyForName: to get the list of +// properties and then fetch them; or -additionalProperties to fetch them all at +// once. +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChannel.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChannel.m new file mode 100755 index 0000000..9af86c6 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChannel.m @@ -0,0 +1,68 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChannel.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChannel (0 custom class methods, 10 custom properties) +// GTLDriveChannelParams (0 custom class methods, 0 custom properties) + +#import "GTLDriveChannel.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveChannel +// + +@implementation GTLDriveChannel +@dynamic address, expiration, identifier, kind, params, payload, resourceId, + resourceUri, token, type; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"id" + forKey:@"identifier"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"api#channel"]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveChannelParams +// + +@implementation GTLDriveChannelParams + ++ (Class)classForAdditionalProperties { + return [NSString class]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildList.h new file mode 100755 index 0000000..20185f7 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildList.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChildList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChildList (0 custom class methods, 6 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveChildReference; + +// ---------------------------------------------------------------------------- +// +// GTLDriveChildList +// + +// A list of children of a file. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveChildList : GTLCollectionObject + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The actual list of children. +@property (retain) NSArray *items; // of GTLDriveChildReference + +// This is always drive#childList. +@property (copy) NSString *kind; + +// A link to the next page of children. +@property (copy) NSString *nextLink; + +// The page token for the next page of children. +@property (copy) NSString *nextPageToken; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildList.m new file mode 100755 index 0000000..61d5c84 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildList.m @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChildList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChildList (0 custom class methods, 6 custom properties) + +#import "GTLDriveChildList.h" + +#import "GTLDriveChildReference.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveChildList +// + +@implementation GTLDriveChildList +@dynamic ETag, items, kind, nextLink, nextPageToken, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveChildReference class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#childList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildReference.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildReference.h new file mode 100755 index 0000000..7aa3902 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildReference.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChildReference.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChildReference (0 custom class methods, 4 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +// ---------------------------------------------------------------------------- +// +// GTLDriveChildReference +// + +// A reference to a folder's child. + +@interface GTLDriveChildReference : GTLObject + +// A link to the child. +@property (copy) NSString *childLink; + +// The ID of the child. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// This is always drive#childReference. +@property (copy) NSString *kind; + +// A link back to this reference. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildReference.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildReference.m new file mode 100755 index 0000000..6c912da --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildReference.m @@ -0,0 +1,52 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveChildReference.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveChildReference (0 custom class methods, 4 custom properties) + +#import "GTLDriveChildReference.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveChildReference +// + +@implementation GTLDriveChildReference +@dynamic childLink, identifier, kind, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"id" + forKey:@"identifier"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#childReference"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveComment.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveComment.h new file mode 100755 index 0000000..df54dd0 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveComment.h @@ -0,0 +1,121 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveComment.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveComment (0 custom class methods, 15 custom properties) +// GTLDriveCommentContext (0 custom class methods, 2 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveCommentContext; +@class GTLDriveCommentReply; +@class GTLDriveUser; + +// ---------------------------------------------------------------------------- +// +// GTLDriveComment +// + +// A JSON representation of a comment on a file in Google Drive. + +@interface GTLDriveComment : GTLObject + +// A region of the document represented as a JSON string. See anchor +// documentation for details on how to define and interpret anchor properties. +@property (copy) NSString *anchor; + +// The user who wrote this comment. +@property (retain) GTLDriveUser *author; + +// The ID of the comment. +@property (copy) NSString *commentId; + +// The plain text content used to create this comment. This is not HTML safe and +// should only be used as a starting point to make edits to a comment's content. +@property (copy) NSString *content; + +// The context of the file which is being commented on. +@property (retain) GTLDriveCommentContext *context; + +// The date when this comment was first created. +@property (retain) GTLDateTime *createdDate; + +// Whether this comment has been deleted. If a comment has been deleted the +// content will be cleared and this will only represent a comment that once +// existed. +@property (retain) NSNumber *deleted; // boolValue + +// The file which this comment is addressing. +@property (copy) NSString *fileId; + +// The title of the file which this comment is addressing. +@property (copy) NSString *fileTitle; + +// HTML formatted content for this comment. +@property (copy) NSString *htmlContent; + +// This is always drive#comment. +@property (copy) NSString *kind; + +// The date when this comment or any of its replies were last modified. +@property (retain) GTLDateTime *modifiedDate; + +// Replies to this post. +@property (retain) NSArray *replies; // of GTLDriveCommentReply + +// A link back to this comment. +@property (copy) NSString *selfLink; + +// The status of this comment. Status can be changed by posting a reply to a +// comment with the desired status. +// - "open" - The comment is still open. +// - "resolved" - The comment has been resolved by one of its replies. +@property (copy) NSString *status; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentContext +// + +@interface GTLDriveCommentContext : GTLObject + +// The MIME type of the context snippet. +@property (copy) NSString *type; + +// Data representation of the segment of the file being commented on. In the +// case of a text file for example, this would be the actual text that the +// comment is about. +@property (copy) NSString *value; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveComment.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveComment.m new file mode 100755 index 0000000..f042e30 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveComment.m @@ -0,0 +1,68 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveComment.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveComment (0 custom class methods, 15 custom properties) +// GTLDriveCommentContext (0 custom class methods, 2 custom properties) + +#import "GTLDriveComment.h" + +#import "GTLDriveCommentReply.h" +#import "GTLDriveUser.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveComment +// + +@implementation GTLDriveComment +@dynamic anchor, author, commentId, content, context, createdDate, deleted, + fileId, fileTitle, htmlContent, kind, modifiedDate, replies, selfLink, + status; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveCommentReply class] + forKey:@"replies"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#comment"]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentContext +// + +@implementation GTLDriveCommentContext +@dynamic type, value; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentList.h new file mode 100755 index 0000000..62b6420 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentList.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveCommentList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveCommentList (0 custom class methods, 5 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveComment; + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentList +// + +// A JSON representation of a list of comments on a file in Google Drive. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveCommentList : GTLCollectionObject + +// List of comments. +@property (retain) NSArray *items; // of GTLDriveComment + +// This is always drive#commentList. +@property (copy) NSString *kind; + +// A link to the next page of comments. +@property (copy) NSString *nextLink; + +// The token to use to request the next page of results. +@property (copy) NSString *nextPageToken; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentList.m new file mode 100755 index 0000000..701ae90 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentList.m @@ -0,0 +1,54 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveCommentList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveCommentList (0 custom class methods, 5 custom properties) + +#import "GTLDriveCommentList.h" + +#import "GTLDriveComment.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentList +// + +@implementation GTLDriveCommentList +@dynamic items, kind, nextLink, nextPageToken, selfLink; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveComment class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#commentList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReply.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReply.h new file mode 100755 index 0000000..5d0c0cb --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReply.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveCommentReply.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveCommentReply (0 custom class methods, 9 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveUser; + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentReply +// + +// A JSON representation of a reply to a comment on a file in Google Drive. + +@interface GTLDriveCommentReply : GTLObject + +// The user who wrote this reply. +@property (retain) GTLDriveUser *author; + +// The plain text content used to create this reply. This is not HTML safe and +// should only be used as a starting point to make edits to a reply's content. +// This field is required on inserts if no verb is specified (resolve/reopen). +@property (copy) NSString *content; + +// The date when this reply was first created. +@property (retain) GTLDateTime *createdDate; + +// Whether this reply has been deleted. If a reply has been deleted the content +// will be cleared and this will only represent a reply that once existed. +@property (retain) NSNumber *deleted; // boolValue + +// HTML formatted content for this reply. +@property (copy) NSString *htmlContent; + +// This is always drive#commentReply. +@property (copy) NSString *kind; + +// The date when this reply was last modified. +@property (retain) GTLDateTime *modifiedDate; + +// The ID of the reply. +@property (copy) NSString *replyId; + +// The action this reply performed to the parent comment. When creating a new +// reply this is the action to be perform to the parent comment. Possible values +// are: +// - "resolve" - To resolve a comment. +// - "reopen" - To reopen (un-resolve) a comment. +@property (copy) NSString *verb; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReply.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReply.m new file mode 100755 index 0000000..237d1b9 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReply.m @@ -0,0 +1,48 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveCommentReply.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveCommentReply (0 custom class methods, 9 custom properties) + +#import "GTLDriveCommentReply.h" + +#import "GTLDriveUser.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentReply +// + +@implementation GTLDriveCommentReply +@dynamic author, content, createdDate, deleted, htmlContent, kind, modifiedDate, + replyId, verb; + ++ (void)load { + [self registerObjectClassForKind:@"drive#commentReply"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReplyList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReplyList.h new file mode 100755 index 0000000..ca826fd --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReplyList.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveCommentReplyList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveCommentReplyList (0 custom class methods, 5 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveCommentReply; + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentReplyList +// + +// A JSON representation of a list of replies to a comment on a file in Google +// Drive. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveCommentReplyList : GTLCollectionObject + +// List of reply. +@property (retain) NSArray *items; // of GTLDriveCommentReply + +// This is always drive#commentReplyList. +@property (copy) NSString *kind; + +// A link to the next page of replies. +@property (copy) NSString *nextLink; + +// The token to use to request the next page of results. +@property (copy) NSString *nextPageToken; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReplyList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReplyList.m new file mode 100755 index 0000000..8affe75 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReplyList.m @@ -0,0 +1,54 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveCommentReplyList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveCommentReplyList (0 custom class methods, 5 custom properties) + +#import "GTLDriveCommentReplyList.h" + +#import "GTLDriveCommentReply.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveCommentReplyList +// + +@implementation GTLDriveCommentReplyList +@dynamic items, kind, nextLink, nextPageToken, selfLink; + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveCommentReply class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#commentReplyList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveConstants.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveConstants.h new file mode 100755 index 0000000..a3de45b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveConstants.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveConstants.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ + +#import + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLDefines.h" +#else + #import "GTLDefines.h" +#endif + +// Authorization scope +// View and manage the files and documents in your Google Drive +GTL_EXTERN NSString * const kGTLAuthScopeDrive; // "https://www.googleapis.com/auth/drive" +// View and manage its own configuration data in your Google Drive +GTL_EXTERN NSString * const kGTLAuthScopeDriveAppdata; // "https://www.googleapis.com/auth/drive.appdata" +// View your Google Drive apps +GTL_EXTERN NSString * const kGTLAuthScopeDriveAppsReadonly; // "https://www.googleapis.com/auth/drive.apps.readonly" +// View and manage Google Drive files that you have opened or created with this +// app +GTL_EXTERN NSString * const kGTLAuthScopeDriveFile; // "https://www.googleapis.com/auth/drive.file" +// View metadata for files and documents in your Google Drive +GTL_EXTERN NSString * const kGTLAuthScopeDriveMetadataReadonly; // "https://www.googleapis.com/auth/drive.metadata.readonly" +// View the files and documents in your Google Drive +GTL_EXTERN NSString * const kGTLAuthScopeDriveReadonly; // "https://www.googleapis.com/auth/drive.readonly" +// Modify your Google Apps Script scripts' behavior +GTL_EXTERN NSString * const kGTLAuthScopeDriveScripts; // "https://www.googleapis.com/auth/drive.scripts" + +// GTLQueryDrive - Corpus +GTL_EXTERN NSString * const kGTLDriveCorpusDefault; // "DEFAULT" +GTL_EXTERN NSString * const kGTLDriveCorpusDomain; // "DOMAIN" + +// GTLQueryDrive - Projection +GTL_EXTERN NSString * const kGTLDriveProjectionBasic; // "BASIC" +GTL_EXTERN NSString * const kGTLDriveProjectionFull; // "FULL" + +// GTLQueryDrive - Visibility +GTL_EXTERN NSString * const kGTLDriveVisibilityDefault; // "DEFAULT" +GTL_EXTERN NSString * const kGTLDriveVisibilityPrivate; // "PRIVATE" diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveConstants.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveConstants.m new file mode 100755 index 0000000..6a4fb82 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveConstants.m @@ -0,0 +1,50 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveConstants.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ + +#import "GTLDriveConstants.h" + +// Authorization scope +NSString * const kGTLAuthScopeDrive = @"https://www.googleapis.com/auth/drive"; +NSString * const kGTLAuthScopeDriveAppdata = @"https://www.googleapis.com/auth/drive.appdata"; +NSString * const kGTLAuthScopeDriveAppsReadonly = @"https://www.googleapis.com/auth/drive.apps.readonly"; +NSString * const kGTLAuthScopeDriveFile = @"https://www.googleapis.com/auth/drive.file"; +NSString * const kGTLAuthScopeDriveMetadataReadonly = @"https://www.googleapis.com/auth/drive.metadata.readonly"; +NSString * const kGTLAuthScopeDriveReadonly = @"https://www.googleapis.com/auth/drive.readonly"; +NSString * const kGTLAuthScopeDriveScripts = @"https://www.googleapis.com/auth/drive.scripts"; + +// GTLQueryDrive - Corpus +NSString * const kGTLDriveCorpusDefault = @"DEFAULT"; +NSString * const kGTLDriveCorpusDomain = @"DOMAIN"; + +// GTLQueryDrive - Projection +NSString * const kGTLDriveProjectionBasic = @"BASIC"; +NSString * const kGTLDriveProjectionFull = @"FULL"; + +// GTLQueryDrive - Visibility +NSString * const kGTLDriveVisibilityDefault = @"DEFAULT"; +NSString * const kGTLDriveVisibilityPrivate = @"PRIVATE"; diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFile.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFile.h new file mode 100755 index 0000000..bd0e929 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFile.h @@ -0,0 +1,440 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveFile.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveFile (0 custom class methods, 50 custom properties) +// GTLDriveFileExportLinks (0 custom class methods, 0 custom properties) +// GTLDriveFileImageMediaMetadata (0 custom class methods, 21 custom properties) +// GTLDriveFileIndexableText (0 custom class methods, 1 custom properties) +// GTLDriveFileLabels (0 custom class methods, 5 custom properties) +// GTLDriveFileOpenWithLinks (0 custom class methods, 0 custom properties) +// GTLDriveFileThumbnail (0 custom class methods, 2 custom properties) +// GTLDriveFileVideoMediaMetadata (0 custom class methods, 3 custom properties) +// GTLDriveFileImageMediaMetadataLocation (0 custom class methods, 3 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveFileExportLinks; +@class GTLDriveFileImageMediaMetadata; +@class GTLDriveFileImageMediaMetadataLocation; +@class GTLDriveFileIndexableText; +@class GTLDriveFileLabels; +@class GTLDriveFileOpenWithLinks; +@class GTLDriveFileThumbnail; +@class GTLDriveFileVideoMediaMetadata; +@class GTLDriveParentReference; +@class GTLDrivePermission; +@class GTLDriveProperty; +@class GTLDriveUser; + +// ---------------------------------------------------------------------------- +// +// GTLDriveFile +// + +// The metadata for a file. + +@interface GTLDriveFile : GTLObject + +// A link for opening the file in a relevant Google editor or viewer. +@property (copy) NSString *alternateLink; + +// Whether this file is in the Application Data folder. +@property (retain) NSNumber *appDataContents; // boolValue + +// Whether the file can be copied by the current user. +@property (retain) NSNumber *copyable; // boolValue + +// Create time for this file (formatted RFC 3339 timestamp). +@property (retain) GTLDateTime *createdDate; + +// A link to open this file with the user's default app for this file. Only +// populated when the drive.apps.readonly scope is used. +@property (copy) NSString *defaultOpenWithLink; + +// A short description of the file. +// Remapped to 'descriptionProperty' to avoid NSObject's 'description'. +@property (copy) NSString *descriptionProperty; + +// Short lived download URL for the file. This is only populated for files with +// content stored in Drive. +@property (copy) NSString *downloadUrl; + +// Whether the file can be edited by the current user. +@property (retain) NSNumber *editable; // boolValue + +// A link for embedding the file. +@property (copy) NSString *embedLink; + +// ETag of the file. +@property (copy) NSString *ETag; + +// Whether this file has been explicitly trashed, as opposed to recursively +// trashed. This will only be populated if the file is trashed. +@property (retain) NSNumber *explicitlyTrashed; // boolValue + +// Links for exporting Google Docs to specific formats. +@property (retain) GTLDriveFileExportLinks *exportLinks; + +// The file extension used when downloading this file. This field is read only. +// To set the extension, include it in the title when creating the file. This is +// only populated for files with content stored in Drive. +@property (copy) NSString *fileExtension; + +// The size of the file in bytes. This is only populated for files with content +// stored in Drive. +@property (retain) NSNumber *fileSize; // longLongValue + +// The ID of the file's head revision. This will only be populated for files +// with content stored in Drive. +@property (copy) NSString *headRevisionId; + +// A link to the file's icon. +@property (copy) NSString *iconLink; + +// The ID of the file. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// Metadata about image media. This will only be present for image types, and +// its contents will depend on what can be parsed from the image content. +@property (retain) GTLDriveFileImageMediaMetadata *imageMediaMetadata; + +// Indexable text attributes for the file (can only be written) +@property (retain) GTLDriveFileIndexableText *indexableText; + +// The type of file. This is always drive#file. +@property (copy) NSString *kind; + +// A group of labels for the file. +@property (retain) GTLDriveFileLabels *labels; + +// The last user to modify this file. +@property (retain) GTLDriveUser *lastModifyingUser; + +// Name of the last user to modify this file. +@property (copy) NSString *lastModifyingUserName; + +// Last time this file was viewed by the user (formatted RFC 3339 timestamp). +@property (retain) GTLDateTime *lastViewedByMeDate; + +// Time this file was explicitly marked viewed by the user (formatted RFC 3339 +// timestamp). +@property (retain) GTLDateTime *markedViewedByMeDate; + +// An MD5 checksum for the content of this file. This is populated only for +// files with content stored in Drive. +@property (copy) NSString *md5Checksum; + +// The MIME type of the file. This is only mutable on update when uploading new +// content. This field can be left blank, and the mimetype will be determined +// from the uploaded content's MIME type. +@property (copy) NSString *mimeType; + +// Last time this file was modified by the user (formatted RFC 3339 timestamp). +// Note that setting modifiedDate will also update the modifiedByMe date for the +// user which set the date. +@property (retain) GTLDateTime *modifiedByMeDate; + +// Last time this file was modified by anyone (formatted RFC 3339 timestamp). +// This is only mutable on update when the setModifiedDate parameter is set. +@property (retain) GTLDateTime *modifiedDate; + +// A map of the id of each of the user's apps to a link to open this file with +// that app. Only populated when the drive.apps.readonly scope is used. +@property (retain) GTLDriveFileOpenWithLinks *openWithLinks; + +// The original filename if the file was uploaded manually, or the original +// title if the file was inserted through the API. Note that renames of the +// title will not change the original filename. This will only be populated on +// files with content stored in Drive. +@property (copy) NSString *originalFilename; + +// Name(s) of the owner(s) of this file. +@property (retain) NSArray *ownerNames; // of NSString + +// The owner(s) of this file. +@property (retain) NSArray *owners; // of GTLDriveUser + +// Collection of parent folders which contain this file. +// Setting this field will put the file in all of the provided folders. On +// insert, if no folders are provided, the file will be placed in the default +// root folder. +@property (retain) NSArray *parents; // of GTLDriveParentReference + +// The list of permissions for users with access to this file. +@property (retain) NSArray *permissions; // of GTLDrivePermission + +// The list of properties. +@property (retain) NSArray *properties; // of GTLDriveProperty + +// The number of quota bytes used by this file. +@property (retain) NSNumber *quotaBytesUsed; // longLongValue + +// A link back to this file. +@property (copy) NSString *selfLink; + +// Whether the file has been shared. +@property (retain) NSNumber *shared; // boolValue + +// Time at which this file was shared with the user (formatted RFC 3339 +// timestamp). +@property (retain) GTLDateTime *sharedWithMeDate; + +// User that shared the item with the current user, if available. +@property (retain) GTLDriveUser *sharingUser; + +// Thumbnail for the file. Only accepted on upload and for files that are not +// already thumbnailed by Google. +@property (retain) GTLDriveFileThumbnail *thumbnail; + +// A link to the file's thumbnail. +@property (copy) NSString *thumbnailLink; + +// The title of this file. +@property (copy) NSString *title; + +// The permissions for the authenticated user on this file. +@property (retain) GTLDrivePermission *userPermission; + +// A monotonically increasing version number for the file. This reflects every +// change made to the file on the server, even those not visible to the +// requesting user. +@property (retain) NSNumber *version; // longLongValue + +// Metadata about video media. This will only be present for video types. +@property (retain) GTLDriveFileVideoMediaMetadata *videoMediaMetadata; + +// A link for downloading the content of the file in a browser using cookie +// based authentication. In cases where the content is shared publicly, the +// content can be downloaded without any credentials. +@property (copy) NSString *webContentLink; + +// A link only available on public folders for viewing their static web assets +// (HTML, CSS, JS, etc) via Google Drive's Website Hosting. +@property (copy) NSString *webViewLink; + +// Whether writers can share the document with other users. +@property (retain) NSNumber *writersCanShare; // boolValue + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileExportLinks +// + +@interface GTLDriveFileExportLinks : GTLObject +// This object is documented as having more properties that are NSString. Use +// -additionalJSONKeys and -additionalPropertyForName: to get the list of +// properties and then fetch them; or -additionalProperties to fetch them all at +// once. +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileImageMediaMetadata +// + +@interface GTLDriveFileImageMediaMetadata : GTLObject + +// The aperture used to create the photo (f-number). +@property (retain) NSNumber *aperture; // floatValue + +// The make of the camera used to create the photo. +@property (copy) NSString *cameraMake; + +// The model of the camera used to create the photo. +@property (copy) NSString *cameraModel; + +// The color space of the photo. +@property (copy) NSString *colorSpace; + +// The date and time the photo was taken (EXIF format timestamp). +@property (copy) NSString *date; + +// The exposure bias of the photo (APEX value). +@property (retain) NSNumber *exposureBias; // floatValue + +// The exposure mode used to create the photo. +@property (copy) NSString *exposureMode; + +// The length of the exposure, in seconds. +@property (retain) NSNumber *exposureTime; // floatValue + +// Whether a flash was used to create the photo. +@property (retain) NSNumber *flashUsed; // boolValue + +// The focal length used to create the photo, in millimeters. +@property (retain) NSNumber *focalLength; // floatValue + +// The height of the image in pixels. +@property (retain) NSNumber *height; // intValue + +// The ISO speed used to create the photo. +@property (retain) NSNumber *isoSpeed; // intValue + +// The lens used to create the photo. +@property (copy) NSString *lens; + +// Geographic location information stored in the image. +@property (retain) GTLDriveFileImageMediaMetadataLocation *location; + +// The smallest f-number of the lens at the focal length used to create the +// photo (APEX value). +@property (retain) NSNumber *maxApertureValue; // floatValue + +// The metering mode used to create the photo. +@property (copy) NSString *meteringMode; + +// The rotation in clockwise degrees from the image's original orientation. +@property (retain) NSNumber *rotation; // intValue + +// The type of sensor used to create the photo. +@property (copy) NSString *sensor; + +// The distance to the subject of the photo, in meters. +@property (retain) NSNumber *subjectDistance; // intValue + +// The white balance mode used to create the photo. +@property (copy) NSString *whiteBalance; + +// The width of the image in pixels. +@property (retain) NSNumber *width; // intValue + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileIndexableText +// + +@interface GTLDriveFileIndexableText : GTLObject + +// The text to be indexed for this file. +@property (copy) NSString *text; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileLabels +// + +@interface GTLDriveFileLabels : GTLObject + +// Deprecated. +@property (retain) NSNumber *hidden; // boolValue + +// Whether viewers are prevented from downloading this file. +@property (retain) NSNumber *restricted; // boolValue + +// Whether this file is starred by the user. +@property (retain) NSNumber *starred; // boolValue + +// Whether this file has been trashed. +@property (retain) NSNumber *trashed; // boolValue + +// Whether this file has been viewed by this user. +@property (retain) NSNumber *viewed; // boolValue + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileOpenWithLinks +// + +@interface GTLDriveFileOpenWithLinks : GTLObject +// This object is documented as having more properties that are NSString. Use +// -additionalJSONKeys and -additionalPropertyForName: to get the list of +// properties and then fetch them; or -additionalProperties to fetch them all at +// once. +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileThumbnail +// + +@interface GTLDriveFileThumbnail : GTLObject + +// The URL-safe Base64 encoded bytes of the thumbnail image. +@property (copy) NSString *image; // GTLBase64 can encode/decode (probably web-safe format) + +// The MIME type of the thumbnail. +@property (copy) NSString *mimeType; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileVideoMediaMetadata +// + +@interface GTLDriveFileVideoMediaMetadata : GTLObject + +// The duration of the video in milliseconds. +@property (retain) NSNumber *durationMillis; // longLongValue + +// The height of the video in pixels. +@property (retain) NSNumber *height; // intValue + +// The width of the video in pixels. +@property (retain) NSNumber *width; // intValue + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileImageMediaMetadataLocation +// + +@interface GTLDriveFileImageMediaMetadataLocation : GTLObject + +// The altitude stored in the image. +@property (retain) NSNumber *altitude; // doubleValue + +// The latitude stored in the image. +@property (retain) NSNumber *latitude; // doubleValue + +// The longitude stored in the image. +@property (retain) NSNumber *longitude; // doubleValue + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFile.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFile.m new file mode 100755 index 0000000..21489d2 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFile.m @@ -0,0 +1,181 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveFile.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveFile (0 custom class methods, 50 custom properties) +// GTLDriveFileExportLinks (0 custom class methods, 0 custom properties) +// GTLDriveFileImageMediaMetadata (0 custom class methods, 21 custom properties) +// GTLDriveFileIndexableText (0 custom class methods, 1 custom properties) +// GTLDriveFileLabels (0 custom class methods, 5 custom properties) +// GTLDriveFileOpenWithLinks (0 custom class methods, 0 custom properties) +// GTLDriveFileThumbnail (0 custom class methods, 2 custom properties) +// GTLDriveFileVideoMediaMetadata (0 custom class methods, 3 custom properties) +// GTLDriveFileImageMediaMetadataLocation (0 custom class methods, 3 custom properties) + +#import "GTLDriveFile.h" + +#import "GTLDriveParentReference.h" +#import "GTLDrivePermission.h" +#import "GTLDriveProperty.h" +#import "GTLDriveUser.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveFile +// + +@implementation GTLDriveFile +@dynamic alternateLink, appDataContents, copyable, createdDate, + defaultOpenWithLink, descriptionProperty, downloadUrl, editable, + embedLink, ETag, explicitlyTrashed, exportLinks, fileExtension, + fileSize, headRevisionId, iconLink, identifier, imageMediaMetadata, + indexableText, kind, labels, lastModifyingUser, lastModifyingUserName, + lastViewedByMeDate, markedViewedByMeDate, md5Checksum, mimeType, + modifiedByMeDate, modifiedDate, openWithLinks, originalFilename, + ownerNames, owners, parents, permissions, properties, quotaBytesUsed, + selfLink, shared, sharedWithMeDate, sharingUser, thumbnail, + thumbnailLink, title, userPermission, version, videoMediaMetadata, + webContentLink, webViewLink, writersCanShare; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObjectsAndKeys: + @"description", @"descriptionProperty", + @"etag", @"ETag", + @"id", @"identifier", + nil]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObjectsAndKeys: + [NSString class], @"ownerNames", + [GTLDriveUser class], @"owners", + [GTLDriveParentReference class], @"parents", + [GTLDrivePermission class], @"permissions", + [GTLDriveProperty class], @"properties", + nil]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#file"]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileExportLinks +// + +@implementation GTLDriveFileExportLinks + ++ (Class)classForAdditionalProperties { + return [NSString class]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileImageMediaMetadata +// + +@implementation GTLDriveFileImageMediaMetadata +@dynamic aperture, cameraMake, cameraModel, colorSpace, date, exposureBias, + exposureMode, exposureTime, flashUsed, focalLength, height, isoSpeed, + lens, location, maxApertureValue, meteringMode, rotation, sensor, + subjectDistance, whiteBalance, width; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileIndexableText +// + +@implementation GTLDriveFileIndexableText +@dynamic text; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileLabels +// + +@implementation GTLDriveFileLabels +@dynamic hidden, restricted, starred, trashed, viewed; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileOpenWithLinks +// + +@implementation GTLDriveFileOpenWithLinks + ++ (Class)classForAdditionalProperties { + return [NSString class]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileThumbnail +// + +@implementation GTLDriveFileThumbnail +@dynamic image, mimeType; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileVideoMediaMetadata +// + +@implementation GTLDriveFileVideoMediaMetadata +@dynamic durationMillis, height, width; +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileImageMediaMetadataLocation +// + +@implementation GTLDriveFileImageMediaMetadataLocation +@dynamic altitude, latitude, longitude; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFileList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFileList.h new file mode 100755 index 0000000..5ffdfa3 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFileList.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveFileList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveFileList (0 custom class methods, 6 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveFile; + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileList +// + +// A list of files. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveFileList : GTLCollectionObject + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The actual list of files. +@property (retain) NSArray *items; // of GTLDriveFile + +// This is always drive#fileList. +@property (copy) NSString *kind; + +// A link to the next page of files. +@property (copy) NSString *nextLink; + +// The page token for the next page of files. +@property (copy) NSString *nextPageToken; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFileList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFileList.m new file mode 100755 index 0000000..f90b93c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveFileList.m @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveFileList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveFileList (0 custom class methods, 6 custom properties) + +#import "GTLDriveFileList.h" + +#import "GTLDriveFile.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveFileList +// + +@implementation GTLDriveFileList +@dynamic ETag, items, kind, nextLink, nextPageToken, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveFile class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#fileList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentList.h new file mode 100755 index 0000000..1c6ae12 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentList.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveParentList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveParentList (0 custom class methods, 4 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveParentReference; + +// ---------------------------------------------------------------------------- +// +// GTLDriveParentList +// + +// A list of a file's parents. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveParentList : GTLCollectionObject + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The actual list of parents. +@property (retain) NSArray *items; // of GTLDriveParentReference + +// This is always drive#parentList. +@property (copy) NSString *kind; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentList.m new file mode 100755 index 0000000..e4c9736 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentList.m @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveParentList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveParentList (0 custom class methods, 4 custom properties) + +#import "GTLDriveParentList.h" + +#import "GTLDriveParentReference.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveParentList +// + +@implementation GTLDriveParentList +@dynamic ETag, items, kind, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveParentReference class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#parentList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentReference.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentReference.h new file mode 100755 index 0000000..bdc8716 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentReference.h @@ -0,0 +1,62 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveParentReference.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveParentReference (0 custom class methods, 5 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +// ---------------------------------------------------------------------------- +// +// GTLDriveParentReference +// + +// A reference to a file's parent. + +@interface GTLDriveParentReference : GTLObject + +// The ID of the parent. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// Whether or not the parent is the root folder. +@property (retain) NSNumber *isRoot; // boolValue + +// This is always drive#parentReference. +@property (copy) NSString *kind; + +// A link to the parent. +@property (copy) NSString *parentLink; + +// A link back to this reference. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentReference.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentReference.m new file mode 100755 index 0000000..dc12c3f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentReference.m @@ -0,0 +1,52 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveParentReference.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveParentReference (0 custom class methods, 5 custom properties) + +#import "GTLDriveParentReference.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveParentReference +// + +@implementation GTLDriveParentReference +@dynamic identifier, isRoot, kind, parentLink, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"id" + forKey:@"identifier"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#parentReference"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermission.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermission.h new file mode 100755 index 0000000..43bc4dc --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermission.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePermission.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePermission (0 custom class methods, 14 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +// ---------------------------------------------------------------------------- +// +// GTLDrivePermission +// + +// A permission for a file. + +@interface GTLDrivePermission : GTLObject + +// Additional roles for this user. Only commenter is currently allowed. +@property (retain) NSArray *additionalRoles; // of NSString + +// The authkey parameter required for this permission. +@property (copy) NSString *authKey; + +// The domain name of the entity this permission refers to. This is an +// output-only field which is present when the permission type is user, group or +// domain. +@property (copy) NSString *domain; + +// The email address of the user or group this permission refers to. This is an +// output-only field which is present when the permission type is user or group. +@property (copy) NSString *emailAddress; + +// The ETag of the permission. +@property (copy) NSString *ETag; + +// The ID of the user this permission refers to, and identical to the +// permissionId in the About and Files resources. When making a +// drive.permissions.insert request, exactly one of the id or value fields must +// be specified. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// This is always drive#permission. +@property (copy) NSString *kind; + +// The name for this permission. +@property (copy) NSString *name; + +// A link to the profile photo, if available. +@property (copy) NSString *photoLink; + +// The primary role for this user. Allowed values are: +// - owner +// - reader +// - writer +@property (copy) NSString *role; + +// A link back to this permission. +@property (copy) NSString *selfLink; + +// The account type. Allowed values are: +// - user +// - group +// - domain +// - anyone +@property (copy) NSString *type; + +// The email address or domain name for the entity. This is used during inserts +// and is not populated in responses. When making a drive.permissions.insert +// request, exactly one of the id or value fields must be specified. +@property (copy) NSString *value; + +// Whether the link is required for this permission. +@property (retain) NSNumber *withLink; // boolValue + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermission.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermission.m new file mode 100755 index 0000000..5d8e63a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermission.m @@ -0,0 +1,62 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePermission.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePermission (0 custom class methods, 14 custom properties) + +#import "GTLDrivePermission.h" + +// ---------------------------------------------------------------------------- +// +// GTLDrivePermission +// + +@implementation GTLDrivePermission +@dynamic additionalRoles, authKey, domain, emailAddress, ETag, identifier, kind, + name, photoLink, role, selfLink, type, value, withLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObjectsAndKeys: + @"etag", @"ETag", + @"id", @"identifier", + nil]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[NSString class] + forKey:@"additionalRoles"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#permission"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionId.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionId.h new file mode 100755 index 0000000..ae28880 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionId.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePermissionId.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePermissionId (0 custom class methods, 2 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +// ---------------------------------------------------------------------------- +// +// GTLDrivePermissionId +// + +// An ID for a user or group as seen in Permission items. + +@interface GTLDrivePermissionId : GTLObject + +// The permission ID. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// This is always drive#permissionId. +@property (copy) NSString *kind; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionId.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionId.m new file mode 100755 index 0000000..997aca0 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionId.m @@ -0,0 +1,52 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePermissionId.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePermissionId (0 custom class methods, 2 custom properties) + +#import "GTLDrivePermissionId.h" + +// ---------------------------------------------------------------------------- +// +// GTLDrivePermissionId +// + +@implementation GTLDrivePermissionId +@dynamic identifier, kind; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"id" + forKey:@"identifier"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#permissionId"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionList.h new file mode 100755 index 0000000..5bd9c25 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionList.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePermissionList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePermissionList (0 custom class methods, 4 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDrivePermission; + +// ---------------------------------------------------------------------------- +// +// GTLDrivePermissionList +// + +// A list of permissions associated with a file. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDrivePermissionList : GTLCollectionObject + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The actual list of permissions. +@property (retain) NSArray *items; // of GTLDrivePermission + +// This is always drive#permissionList. +@property (copy) NSString *kind; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionList.m new file mode 100755 index 0000000..1d92b94 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionList.m @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePermissionList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePermissionList (0 custom class methods, 4 custom properties) + +#import "GTLDrivePermissionList.h" + +#import "GTLDrivePermission.h" + +// ---------------------------------------------------------------------------- +// +// GTLDrivePermissionList +// + +@implementation GTLDrivePermissionList +@dynamic ETag, items, kind, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDrivePermission class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#permissionList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveProperty.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveProperty.h new file mode 100755 index 0000000..d49178f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveProperty.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveProperty.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveProperty (0 custom class methods, 6 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +// ---------------------------------------------------------------------------- +// +// GTLDriveProperty +// + +// A key-value pair that is either public or private to an application. + +@interface GTLDriveProperty : GTLObject + +// ETag of the property. +@property (copy) NSString *ETag; + +// The key of this property. +@property (copy) NSString *key; + +// This is always drive#property. +@property (copy) NSString *kind; + +// The link back to this property. +@property (copy) NSString *selfLink; + +// The value of this property. +@property (copy) NSString *value; + +// The visibility of this property. +@property (copy) NSString *visibility; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveProperty.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveProperty.m new file mode 100755 index 0000000..bff81ed --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveProperty.m @@ -0,0 +1,52 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveProperty.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveProperty (0 custom class methods, 6 custom properties) + +#import "GTLDriveProperty.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveProperty +// + +@implementation GTLDriveProperty +@dynamic ETag, key, kind, selfLink, value, visibility; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#property"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePropertyList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePropertyList.h new file mode 100755 index 0000000..f051309 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePropertyList.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePropertyList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePropertyList (0 custom class methods, 4 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveProperty; + +// ---------------------------------------------------------------------------- +// +// GTLDrivePropertyList +// + +// A collection of properties, key-value pairs that are either public or private +// to an application. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDrivePropertyList : GTLCollectionObject + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The list of properties. +@property (retain) NSArray *items; // of GTLDriveProperty + +// This is always drive#propertyList. +@property (copy) NSString *kind; + +// The link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePropertyList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePropertyList.m new file mode 100755 index 0000000..42dea90 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDrivePropertyList.m @@ -0,0 +1,61 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDrivePropertyList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDrivePropertyList (0 custom class methods, 4 custom properties) + +#import "GTLDrivePropertyList.h" + +#import "GTLDriveProperty.h" + +// ---------------------------------------------------------------------------- +// +// GTLDrivePropertyList +// + +@implementation GTLDrivePropertyList +@dynamic ETag, items, kind, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveProperty class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#propertyList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevision.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevision.h new file mode 100755 index 0000000..f317a84 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevision.h @@ -0,0 +1,129 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveRevision.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveRevision (0 custom class methods, 18 custom properties) +// GTLDriveRevisionExportLinks (0 custom class methods, 0 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveRevisionExportLinks; +@class GTLDriveUser; + +// ---------------------------------------------------------------------------- +// +// GTLDriveRevision +// + +// A revision of a file. + +@interface GTLDriveRevision : GTLObject + +// Short term download URL for the file. This will only be populated on files +// with content stored in Drive. +@property (copy) NSString *downloadUrl; + +// The ETag of the revision. +@property (copy) NSString *ETag; + +// Links for exporting Google Docs to specific formats. +@property (retain) GTLDriveRevisionExportLinks *exportLinks; + +// The size of the revision in bytes. This will only be populated on files with +// content stored in Drive. +@property (retain) NSNumber *fileSize; // longLongValue + +// The ID of the revision. +// identifier property maps to 'id' in JSON (to avoid Objective C's 'id'). +@property (copy) NSString *identifier; + +// This is always drive#revision. +@property (copy) NSString *kind; + +// The last user to modify this revision. +@property (retain) GTLDriveUser *lastModifyingUser; + +// Name of the last user to modify this revision. +@property (copy) NSString *lastModifyingUserName; + +// An MD5 checksum for the content of this revision. This will only be populated +// on files with content stored in Drive. +@property (copy) NSString *md5Checksum; + +// The MIME type of the revision. +@property (copy) NSString *mimeType; + +// Last time this revision was modified (formatted RFC 3339 timestamp). +@property (retain) GTLDateTime *modifiedDate; + +// The original filename when this revision was created. This will only be +// populated on files with content stored in Drive. +@property (copy) NSString *originalFilename; + +// Whether this revision is pinned to prevent automatic purging. This will only +// be populated and can only be modified on files with content stored in Drive +// which are not Google Docs. Revisions can also be pinned when they are created +// through the drive.files.insert/update/copy by using the pinned query +// parameter. +@property (retain) NSNumber *pinned; // boolValue + +// Whether subsequent revisions will be automatically republished. This is only +// populated and can only be modified for Google Docs. +@property (retain) NSNumber *publishAuto; // boolValue + +// Whether this revision is published. This is only populated and can only be +// modified for Google Docs. +@property (retain) NSNumber *published; // boolValue + +// A link to the published revision. +@property (copy) NSString *publishedLink; + +// Whether this revision is published outside the domain. This is only populated +// and can only be modified for Google Docs. +@property (retain) NSNumber *publishedOutsideDomain; // boolValue + +// A link back to this revision. +@property (copy) NSString *selfLink; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveRevisionExportLinks +// + +@interface GTLDriveRevisionExportLinks : GTLObject +// This object is documented as having more properties that are NSString. Use +// -additionalJSONKeys and -additionalPropertyForName: to get the list of +// properties and then fetch them; or -additionalProperties to fetch them all at +// once. +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevision.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevision.m new file mode 100755 index 0000000..58c9dee --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevision.m @@ -0,0 +1,74 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveRevision.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveRevision (0 custom class methods, 18 custom properties) +// GTLDriveRevisionExportLinks (0 custom class methods, 0 custom properties) + +#import "GTLDriveRevision.h" + +#import "GTLDriveUser.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveRevision +// + +@implementation GTLDriveRevision +@dynamic downloadUrl, ETag, exportLinks, fileSize, identifier, kind, + lastModifyingUser, lastModifyingUserName, md5Checksum, mimeType, + modifiedDate, originalFilename, pinned, publishAuto, published, + publishedLink, publishedOutsideDomain, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObjectsAndKeys: + @"etag", @"ETag", + @"id", @"identifier", + nil]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#revision"]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveRevisionExportLinks +// + +@implementation GTLDriveRevisionExportLinks + ++ (Class)classForAdditionalProperties { + return [NSString class]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevisionList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevisionList.h new file mode 100755 index 0000000..72c1faf --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevisionList.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveRevisionList.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveRevisionList (0 custom class methods, 4 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveRevision; + +// ---------------------------------------------------------------------------- +// +// GTLDriveRevisionList +// + +// A list of revisions of a file. + +// This class supports NSFastEnumeration over its "items" property. It also +// supports -itemAtIndex: to retrieve individual objects from "items". + +@interface GTLDriveRevisionList : GTLCollectionObject + +// The ETag of the list. +@property (copy) NSString *ETag; + +// The actual list of revisions. +@property (retain) NSArray *items; // of GTLDriveRevision + +// This is always drive#revisionList. +@property (copy) NSString *kind; + +// A link back to this list. +@property (copy) NSString *selfLink; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevisionList.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevisionList.m new file mode 100755 index 0000000..3bdf6c7 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevisionList.m @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveRevisionList.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveRevisionList (0 custom class methods, 4 custom properties) + +#import "GTLDriveRevisionList.h" + +#import "GTLDriveRevision.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveRevisionList +// + +@implementation GTLDriveRevisionList +@dynamic ETag, items, kind, selfLink; + ++ (NSDictionary *)propertyToJSONKeyMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:@"etag" + forKey:@"ETag"]; + return map; +} + ++ (NSDictionary *)arrayPropertyToClassMap { + NSDictionary *map = + [NSDictionary dictionaryWithObject:[GTLDriveRevision class] + forKey:@"items"]; + return map; +} + ++ (void)load { + [self registerObjectClassForKind:@"drive#revisionList"]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveUser.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveUser.h new file mode 100755 index 0000000..4dcec83 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveUser.h @@ -0,0 +1,81 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveUser.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveUser (0 custom class methods, 6 custom properties) +// GTLDriveUserPicture (0 custom class methods, 1 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLObject.h" +#else + #import "GTLObject.h" +#endif + +@class GTLDriveUserPicture; + +// ---------------------------------------------------------------------------- +// +// GTLDriveUser +// + +// The JSON template for a user. + +@interface GTLDriveUser : GTLObject + +// A plain text displayable name for this user. +@property (copy) NSString *displayName; + +// The email address of the user. +@property (copy) NSString *emailAddress; + +// Whether this user is the same as the authenticated user for whom the request +// was made. +@property (retain) NSNumber *isAuthenticatedUser; // boolValue + +// This is always drive#user. +@property (copy) NSString *kind; + +// The user's ID as visible in the permissions collection. +@property (copy) NSString *permissionId; + +// The user's profile picture. +@property (retain) GTLDriveUserPicture *picture; + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveUserPicture +// + +@interface GTLDriveUserPicture : GTLObject + +// A URL that points to a profile picture of this user. +@property (copy) NSString *url; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveUser.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveUser.m new file mode 100755 index 0000000..23d7d1e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLDriveUser.m @@ -0,0 +1,57 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLDriveUser.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLDriveUser (0 custom class methods, 6 custom properties) +// GTLDriveUserPicture (0 custom class methods, 1 custom properties) + +#import "GTLDriveUser.h" + +// ---------------------------------------------------------------------------- +// +// GTLDriveUser +// + +@implementation GTLDriveUser +@dynamic displayName, emailAddress, isAuthenticatedUser, kind, permissionId, + picture; + ++ (void)load { + [self registerObjectClassForKind:@"drive#user"]; +} + +@end + + +// ---------------------------------------------------------------------------- +// +// GTLDriveUserPicture +// + +@implementation GTLDriveUserPicture +@dynamic url; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLQueryDrive.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLQueryDrive.h new file mode 100755 index 0000000..a711ea0 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLQueryDrive.h @@ -0,0 +1,1123 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLQueryDrive.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLQueryDrive (59 custom class methods, 45 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLQuery.h" +#else + #import "GTLQuery.h" +#endif + +@class GTLDriveChannel; +@class GTLDriveChildReference; +@class GTLDriveComment; +@class GTLDriveCommentReply; +@class GTLDriveFile; +@class GTLDriveParentReference; +@class GTLDrivePermission; +@class GTLDriveProperty; +@class GTLDriveRevision; + +@interface GTLQueryDrive : GTLQuery + +// +// Parameters valid on all methods. +// + +// Selector specifying which fields to include in a partial response. +@property (copy) NSString *fields; + +// +// Method-specific parameters; see the comments below for more information. +// +@property (assign) BOOL acknowledgeAbuse; +@property (copy) NSString *addParents; +@property (copy) NSString *appFilterExtensions; +@property (copy) NSString *appFilterMimeTypes; +@property (copy) NSString *appId; +@property (copy) NSString *baseRevision; +@property (copy) NSString *changeId; +@property (copy) NSString *childId; +@property (copy) NSString *commentId; +@property (assign) BOOL convert; +@property (copy) NSString *corpus; +@property (copy) NSString *email; +@property (copy) NSString *emailMessage; +@property (copy) NSString *fileId; +@property (copy) NSString *folderId; +@property (assign) BOOL includeDeleted; +@property (assign) BOOL includeSubscribed; +@property (copy) NSString *languageCode; +@property (assign) long long maxChangeIdCount; +@property (assign) NSInteger maxResults; +@property (assign) BOOL newRevision; +@property (assign) BOOL ocr; +@property (copy) NSString *ocrLanguage; +@property (copy) NSString *pageToken; +@property (copy) NSString *parentId; +@property (copy) NSString *permissionId; +@property (assign) BOOL pinned; +@property (copy) NSString *projection; +@property (copy) NSString *propertyKey; +@property (copy) NSString *q; +@property (copy) NSString *removeParents; +@property (copy) NSString *replyId; +@property (assign) NSInteger revision; +@property (copy) NSString *revisionId; +@property (assign) BOOL sendNotificationEmails; +@property (assign) BOOL setModifiedDate; +@property (assign) long long startChangeId; +@property (copy) NSString *timedTextLanguage; +@property (copy) NSString *timedTextTrackName; +@property (assign) BOOL transferOwnership; +@property (copy) NSString *updatedMin; +@property (assign) BOOL updateViewedDate; +@property (assign) BOOL useContentAsIndexableText; +@property (copy) NSString *visibility; + +#pragma mark - +#pragma mark "about" methods +// These create a GTLQueryDrive object. + +// Method: drive.about.get +// Gets the information about the current user along with Drive API settings +// Optional: +// includeSubscribed: When calculating the number of remaining change IDs, +// whether to include public files the user has opened and shared files. +// When set to false, this counts only change IDs for owned files and any +// shared or public files that the user has explicitly added to a folder +// they own. (Default true) +// maxChangeIdCount: Maximum number of remaining change IDs to count (Default +// 1) +// startChangeId: Change ID to start counting from when calculating number of +// remaining change IDs +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveAbout. ++ (id)queryForAboutGet; + +#pragma mark - +#pragma mark "apps" methods +// These create a GTLQueryDrive object. + +// Method: drive.apps.get +// Gets a specific app. +// Required: +// appId: The ID of the app. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveApp. ++ (id)queryForAppsGetWithAppId:(NSString *)appId; + +// Method: drive.apps.list +// Lists a user's installed apps. +// Optional: +// appFilterExtensions: A comma-separated list of file extensions for open +// with filtering. All apps within the given app query scope which can open +// any of the given file extensions will be included in the response. If +// appFilterMimeTypes are provided as well, the result is a union of the two +// resulting app lists. +// appFilterMimeTypes: A comma-separated list of MIME types for open with +// filtering. All apps within the given app query scope which can open any +// of the given MIME types will be included in the response. If +// appFilterExtensions are provided as well, the result is a union of the +// two resulting app lists. +// languageCode: A language or locale code, as defined by BCP 47, with some +// extensions from Unicode's LDML format +// (http://www.unicode.org/reports/tr35/). +// Authorization scope(s): +// kGTLAuthScopeDriveAppsReadonly +// Fetches a GTLDriveAppList. ++ (id)queryForAppsList; + +#pragma mark - +#pragma mark "changes" methods +// These create a GTLQueryDrive object. + +// Method: drive.changes.get +// Gets a specific change. +// Required: +// changeId: The ID of the change. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveChange. ++ (id)queryForChangesGetWithChangeId:(NSString *)changeId; + +// Method: drive.changes.list +// Lists the changes for a user. +// Optional: +// includeDeleted: Whether to include deleted items. (Default true) +// includeSubscribed: Whether to include public files the user has opened and +// shared files. When set to false, the list only includes owned files plus +// any shared or public files the user has explicitly added to a folder they +// own. (Default true) +// maxResults: Maximum number of changes to return. (Default 100) +// pageToken: Page token for changes. +// startChangeId: Change ID to start listing changes from. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveChangeList. ++ (id)queryForChangesList; + +// Method: drive.changes.watch +// Subscribe to changes for a user. +// Optional: +// includeDeleted: Whether to include deleted items. (Default true) +// includeSubscribed: Whether to include public files the user has opened and +// shared files. When set to false, the list only includes owned files plus +// any shared or public files the user has explicitly added to a folder they +// own. (Default true) +// maxResults: Maximum number of changes to return. (Default 100) +// pageToken: Page token for changes. +// startChangeId: Change ID to start listing changes from. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveChannel. ++ (id)queryForChangesWatchWithObject:(GTLDriveChannel *)object; + +#pragma mark - +#pragma mark "channels" methods +// These create a GTLQueryDrive object. + +// Method: drive.channels.stop +// Stop watching resources through this channel +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly ++ (id)queryForChannelsStopWithObject:(GTLDriveChannel *)object; + +#pragma mark - +#pragma mark "children" methods +// These create a GTLQueryDrive object. + +// Method: drive.children.delete +// Removes a child from a folder. +// Required: +// folderId: The ID of the folder. +// childId: The ID of the child. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile ++ (id)queryForChildrenDeleteWithFolderId:(NSString *)folderId + childId:(NSString *)childId; + +// Method: drive.children.get +// Gets a specific child reference. +// Required: +// folderId: The ID of the folder. +// childId: The ID of the child. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveChildReference. ++ (id)queryForChildrenGetWithFolderId:(NSString *)folderId + childId:(NSString *)childId; + +// Method: drive.children.insert +// Inserts a file into a folder. +// Required: +// folderId: The ID of the folder. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveChildReference. ++ (id)queryForChildrenInsertWithObject:(GTLDriveChildReference *)object + folderId:(NSString *)folderId; + +// Method: drive.children.list +// Lists a folder's children. +// Required: +// folderId: The ID of the folder. +// Optional: +// maxResults: Maximum number of children to return. (Default 100) +// pageToken: Page token for children. +// q: Query string for searching children. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveChildList. ++ (id)queryForChildrenListWithFolderId:(NSString *)folderId; + +#pragma mark - +#pragma mark "comments" methods +// These create a GTLQueryDrive object. + +// Method: drive.comments.delete +// Deletes a comment. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveReadonly ++ (id)queryForCommentsDeleteWithFileId:(NSString *)fileId + commentId:(NSString *)commentId; + +// Method: drive.comments.get +// Gets a comment by ID. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// Optional: +// includeDeleted: If set, this will succeed when retrieving a deleted +// comment, and will include any deleted replies. (Default false) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveComment. ++ (id)queryForCommentsGetWithFileId:(NSString *)fileId + commentId:(NSString *)commentId; + +// Method: drive.comments.insert +// Creates a new comment on the given file. +// Required: +// fileId: The ID of the file. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveComment. ++ (id)queryForCommentsInsertWithObject:(GTLDriveComment *)object + fileId:(NSString *)fileId; + +// Method: drive.comments.list +// Lists a file's comments. +// Required: +// fileId: The ID of the file. +// Optional: +// includeDeleted: If set, all comments and replies, including deleted +// comments and replies (with content stripped) will be returned. (Default +// false) +// maxResults: The maximum number of discussions to include in the response, +// used for paging. (0..100, default 20) +// pageToken: The continuation token, used to page through large result sets. +// To get the next page of results, set this parameter to the value of +// "nextPageToken" from the previous response. +// updatedMin: Only discussions that were updated after this timestamp will be +// returned. Formatted as an RFC 3339 timestamp. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveCommentList. ++ (id)queryForCommentsListWithFileId:(NSString *)fileId; + +// Method: drive.comments.patch +// Updates an existing comment. This method supports patch semantics. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveComment. ++ (id)queryForCommentsPatchWithObject:(GTLDriveComment *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId; + +// Method: drive.comments.update +// Updates an existing comment. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveComment. ++ (id)queryForCommentsUpdateWithObject:(GTLDriveComment *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId; + +#pragma mark - +#pragma mark "files" methods +// These create a GTLQueryDrive object. + +// Method: drive.files.copy +// Creates a copy of the specified file. +// Required: +// fileId: The ID of the file to copy. +// Optional: +// convert: Whether to convert this file to the corresponding Google Docs +// format. (Default false) +// ocr: Whether to attempt OCR on .jpg, .png, .gif, or .pdf uploads. (Default +// false) +// ocrLanguage: If ocr is true, hints at the language to use. Valid values are +// ISO 639-1 codes. +// pinned: Whether to pin the head revision of the new copy. A file can have a +// maximum of 200 pinned revisions. (Default false) +// timedTextLanguage: The language of the timed text. +// timedTextTrackName: The timed text track name. +// visibility: The visibility of the new file. This parameter is only relevant +// when the source is not a native Google Doc and convert=false. (Default +// kGTLDriveVisibilityDefault) +// kGTLDriveVisibilityDefault: The visibility of the new file is determined +// by the user's default visibility/sharing policies. +// kGTLDriveVisibilityPrivate: The new file will be visible to only the +// owner. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveFile. ++ (id)queryForFilesCopyWithObject:(GTLDriveFile *)object + fileId:(NSString *)fileId; + +// Method: drive.files.delete +// Permanently deletes a file by ID. Skips the trash. +// Required: +// fileId: The ID of the file to delete. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile ++ (id)queryForFilesDeleteWithFileId:(NSString *)fileId; + +// Method: drive.files.emptyTrash +// Permanently deletes all of the user's trashed files. +// Authorization scope(s): +// kGTLAuthScopeDrive ++ (id)queryForFilesEmptyTrash; + +// Method: drive.files.get +// Gets a file's metadata by ID. +// Required: +// fileId: The ID for the file in question. +// Optional: +// acknowledgeAbuse: Whether the user is acknowledging the risk of downloading +// known malware or other abusive files. (Default false) +// projection: This parameter is deprecated and has no function. +// kGTLDriveProjectionBasic: Deprecated +// kGTLDriveProjectionFull: Deprecated +// updateViewedDate: Whether to update the view date after successfully +// retrieving the file. (Default false) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveFile. ++ (id)queryForFilesGetWithFileId:(NSString *)fileId; + +// Method: drive.files.insert +// Insert a new file. +// Optional: +// convert: Whether to convert this file to the corresponding Google Docs +// format. (Default false) +// ocr: Whether to attempt OCR on .jpg, .png, .gif, or .pdf uploads. (Default +// false) +// ocrLanguage: If ocr is true, hints at the language to use. Valid values are +// ISO 639-1 codes. +// pinned: Whether to pin the head revision of the uploaded file. A file can +// have a maximum of 200 pinned revisions. (Default false) +// timedTextLanguage: The language of the timed text. +// timedTextTrackName: The timed text track name. +// useContentAsIndexableText: Whether to use the content as indexable text. +// (Default false) +// visibility: The visibility of the new file. This parameter is only relevant +// when convert=false. (Default kGTLDriveVisibilityDefault) +// kGTLDriveVisibilityDefault: The visibility of the new file is determined +// by the user's default visibility/sharing policies. +// kGTLDriveVisibilityPrivate: The new file will be visible to only the +// owner. +// Upload Parameters: +// Maximum size: 5120GB +// Accepted MIME type(s): */* +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveFile. ++ (id)queryForFilesInsertWithObject:(GTLDriveFile *)object + uploadParameters:(GTLUploadParameters *)uploadParametersOrNil; + +// Method: drive.files.list +// Lists the user's files. +// Optional: +// corpus: The body of items (files/documents) to which the query applies. +// kGTLDriveCorpusDefault: The items that the user has accessed. +// kGTLDriveCorpusDomain: Items shared to the user's domain. +// maxResults: Maximum number of files to return. (Default 100) +// pageToken: Page token for files. +// projection: This parameter is deprecated and has no function. +// kGTLDriveProjectionBasic: Deprecated +// kGTLDriveProjectionFull: Deprecated +// q: Query string for searching files. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveFileList. ++ (id)queryForFilesList; + +// Method: drive.files.patch +// Updates file metadata and/or content. This method supports patch semantics. +// Required: +// fileId: The ID of the file to update. +// Optional: +// addParents: Comma-separated list of parent IDs to add. +// convert: Whether to convert this file to the corresponding Google Docs +// format. (Default false) +// newRevision: Whether a blob upload should create a new revision. If false, +// the blob data in the current head revision is replaced. If true or not +// set, a new blob is created as head revision, and previous revisions are +// preserved (causing increased use of the user's data storage quota). +// (Default true) +// ocr: Whether to attempt OCR on .jpg, .png, .gif, or .pdf uploads. (Default +// false) +// ocrLanguage: If ocr is true, hints at the language to use. Valid values are +// ISO 639-1 codes. +// pinned: Whether to pin the new revision. A file can have a maximum of 200 +// pinned revisions. (Default false) +// removeParents: Comma-separated list of parent IDs to remove. +// setModifiedDate: Whether to set the modified date with the supplied +// modified date. (Default false) +// timedTextLanguage: The language of the timed text. +// timedTextTrackName: The timed text track name. +// updateViewedDate: Whether to update the view date after successfully +// updating the file. (Default true) +// useContentAsIndexableText: Whether to use the content as indexable text. +// (Default false) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveScripts +// Fetches a GTLDriveFile. ++ (id)queryForFilesPatchWithObject:(GTLDriveFile *)object + fileId:(NSString *)fileId; + +// Method: drive.files.touch +// Set the file's updated time to the current server time. +// Required: +// fileId: The ID of the file to update. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveFile. ++ (id)queryForFilesTouchWithFileId:(NSString *)fileId; + +// Method: drive.files.trash +// Moves a file to the trash. +// Required: +// fileId: The ID of the file to trash. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveFile. ++ (id)queryForFilesTrashWithFileId:(NSString *)fileId; + +// Method: drive.files.untrash +// Restores a file from the trash. +// Required: +// fileId: The ID of the file to untrash. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveFile. ++ (id)queryForFilesUntrashWithFileId:(NSString *)fileId; + +// Method: drive.files.update +// Updates file metadata and/or content. +// Required: +// fileId: The ID of the file to update. +// Optional: +// addParents: Comma-separated list of parent IDs to add. +// convert: Whether to convert this file to the corresponding Google Docs +// format. (Default false) +// newRevision: Whether a blob upload should create a new revision. If false, +// the blob data in the current head revision is replaced. If true or not +// set, a new blob is created as head revision, and previous revisions are +// preserved (causing increased use of the user's data storage quota). +// (Default true) +// ocr: Whether to attempt OCR on .jpg, .png, .gif, or .pdf uploads. (Default +// false) +// ocrLanguage: If ocr is true, hints at the language to use. Valid values are +// ISO 639-1 codes. +// pinned: Whether to pin the new revision. A file can have a maximum of 200 +// pinned revisions. (Default false) +// removeParents: Comma-separated list of parent IDs to remove. +// setModifiedDate: Whether to set the modified date with the supplied +// modified date. (Default false) +// timedTextLanguage: The language of the timed text. +// timedTextTrackName: The timed text track name. +// updateViewedDate: Whether to update the view date after successfully +// updating the file. (Default true) +// useContentAsIndexableText: Whether to use the content as indexable text. +// (Default false) +// Upload Parameters: +// Maximum size: 5120GB +// Accepted MIME type(s): */* +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveScripts +// Fetches a GTLDriveFile. ++ (id)queryForFilesUpdateWithObject:(GTLDriveFile *)object + fileId:(NSString *)fileId + uploadParameters:(GTLUploadParameters *)uploadParametersOrNil; + +// Method: drive.files.watch +// Subscribe to changes on a file +// Required: +// fileId: The ID for the file in question. +// Optional: +// acknowledgeAbuse: Whether the user is acknowledging the risk of downloading +// known malware or other abusive files. (Default false) +// projection: This parameter is deprecated and has no function. +// kGTLDriveProjectionBasic: Deprecated +// kGTLDriveProjectionFull: Deprecated +// updateViewedDate: Whether to update the view date after successfully +// retrieving the file. (Default false) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveChannel. ++ (id)queryForFilesWatchWithObject:(GTLDriveChannel *)object + fileId:(NSString *)fileId; + +#pragma mark - +#pragma mark "parents" methods +// These create a GTLQueryDrive object. + +// Method: drive.parents.delete +// Removes a parent from a file. +// Required: +// fileId: The ID of the file. +// parentId: The ID of the parent. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile ++ (id)queryForParentsDeleteWithFileId:(NSString *)fileId + parentId:(NSString *)parentId; + +// Method: drive.parents.get +// Gets a specific parent reference. +// Required: +// fileId: The ID of the file. +// parentId: The ID of the parent. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveParentReference. ++ (id)queryForParentsGetWithFileId:(NSString *)fileId + parentId:(NSString *)parentId; + +// Method: drive.parents.insert +// Adds a parent folder for a file. +// Required: +// fileId: The ID of the file. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveParentReference. ++ (id)queryForParentsInsertWithObject:(GTLDriveParentReference *)object + fileId:(NSString *)fileId; + +// Method: drive.parents.list +// Lists a file's parents. +// Required: +// fileId: The ID of the file. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveParentList. ++ (id)queryForParentsListWithFileId:(NSString *)fileId; + +#pragma mark - +#pragma mark "permissions" methods +// These create a GTLQueryDrive object. + +// Method: drive.permissions.delete +// Deletes a permission from a file. +// Required: +// fileId: The ID for the file. +// permissionId: The ID for the permission. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile ++ (id)queryForPermissionsDeleteWithFileId:(NSString *)fileId + permissionId:(NSString *)permissionId; + +// Method: drive.permissions.get +// Gets a permission by ID. +// Required: +// fileId: The ID for the file. +// permissionId: The ID for the permission. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDrivePermission. ++ (id)queryForPermissionsGetWithFileId:(NSString *)fileId + permissionId:(NSString *)permissionId; + +// Method: drive.permissions.getIdForEmail +// Returns the permission ID for an email address. +// Required: +// email: The email address for which to return a permission ID +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveAppsReadonly +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDrivePermissionId. ++ (id)queryForPermissionsGetIdForEmailWithEmail:(NSString *)email; + +// Method: drive.permissions.insert +// Inserts a permission for a file. +// Required: +// fileId: The ID for the file. +// Optional: +// emailMessage: A custom message to include in notification emails. +// sendNotificationEmails: Whether to send notification emails when sharing to +// users or groups. This parameter is ignored and an email is sent if the +// role is owner. (Default true) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDrivePermission. ++ (id)queryForPermissionsInsertWithObject:(GTLDrivePermission *)object + fileId:(NSString *)fileId; + +// Method: drive.permissions.list +// Lists a file's permissions. +// Required: +// fileId: The ID for the file. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDrivePermissionList. ++ (id)queryForPermissionsListWithFileId:(NSString *)fileId; + +// Method: drive.permissions.patch +// Updates a permission. This method supports patch semantics. +// Required: +// fileId: The ID for the file. +// permissionId: The ID for the permission. +// Optional: +// transferOwnership: Whether changing a role to 'owner' should also downgrade +// the current owners to writers. (Default false) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDrivePermission. ++ (id)queryForPermissionsPatchWithObject:(GTLDrivePermission *)object + fileId:(NSString *)fileId + permissionId:(NSString *)permissionId; + +// Method: drive.permissions.update +// Updates a permission. +// Required: +// fileId: The ID for the file. +// permissionId: The ID for the permission. +// Optional: +// transferOwnership: Whether changing a role to 'owner' should also downgrade +// the current owners to writers. (Default false) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDrivePermission. ++ (id)queryForPermissionsUpdateWithObject:(GTLDrivePermission *)object + fileId:(NSString *)fileId + permissionId:(NSString *)permissionId; + +#pragma mark - +#pragma mark "properties" methods +// These create a GTLQueryDrive object. + +// Method: drive.properties.delete +// Deletes a property. +// Required: +// fileId: The ID of the file. +// propertyKey: The key of the property. +// Optional: +// visibility: The visibility of the property. (Default private) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile ++ (id)queryForPropertiesDeleteWithFileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey; + +// Method: drive.properties.get +// Gets a property by its key. +// Required: +// fileId: The ID of the file. +// propertyKey: The key of the property. +// Optional: +// visibility: The visibility of the property. (Default private) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveProperty. ++ (id)queryForPropertiesGetWithFileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey; + +// Method: drive.properties.insert +// Adds a property to a file. +// Required: +// fileId: The ID of the file. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveProperty. ++ (id)queryForPropertiesInsertWithObject:(GTLDriveProperty *)object + fileId:(NSString *)fileId; + +// Method: drive.properties.list +// Lists a file's properties. +// Required: +// fileId: The ID of the file. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDrivePropertyList. ++ (id)queryForPropertiesListWithFileId:(NSString *)fileId; + +// Method: drive.properties.patch +// Updates a property. This method supports patch semantics. +// Required: +// fileId: The ID of the file. +// propertyKey: The key of the property. +// Optional: +// visibility: The visibility of the property. (Default private) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveProperty. ++ (id)queryForPropertiesPatchWithObject:(GTLDriveProperty *)object + fileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey; + +// Method: drive.properties.update +// Updates a property. +// Required: +// fileId: The ID of the file. +// propertyKey: The key of the property. +// Optional: +// visibility: The visibility of the property. (Default private) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveProperty. ++ (id)queryForPropertiesUpdateWithObject:(GTLDriveProperty *)object + fileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey; + +#pragma mark - +#pragma mark "realtime" methods +// These create a GTLQueryDrive object. + +// Method: drive.realtime.get +// Exports the contents of the Realtime API data model associated with this file +// as JSON. +// Required: +// fileId: The ID of the file that the Realtime API data model is associated +// with. +// Optional: +// revision: The revision of the Realtime API data model to export. Revisions +// start at 1 (the initial empty data model) and are incremented with each +// change. If this parameter is excluded, the most recent data model will be +// returned. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveReadonly ++ (id)queryForRealtimeGetWithFileId:(NSString *)fileId; + +// Method: drive.realtime.update +// Overwrites the Realtime API data model associated with this file with the +// provided JSON data model. +// Required: +// fileId: The ID of the file that the Realtime API data model is associated +// with. +// Optional: +// baseRevision: The revision of the model to diff the uploaded model against. +// If set, the uploaded model is diffed against the provided revision and +// those differences are merged with any changes made to the model after the +// provided revision. If not set, the uploaded model replaces the current +// model on the server. +// Upload Parameters: +// Maximum size: 10MB +// Accepted MIME type(s): */* +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile ++ (id)queryForRealtimeUpdateWithFileId:(NSString *)fileId + uploadParameters:(GTLUploadParameters *)uploadParametersOrNil; + +#pragma mark - +#pragma mark "replies" methods +// These create a GTLQueryDrive object. + +// Method: drive.replies.delete +// Deletes a reply. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// replyId: The ID of the reply. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile ++ (id)queryForRepliesDeleteWithFileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId; + +// Method: drive.replies.get +// Gets a reply. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// replyId: The ID of the reply. +// Optional: +// includeDeleted: If set, this will succeed when retrieving a deleted reply. +// (Default false) +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveCommentReply. ++ (id)queryForRepliesGetWithFileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId; + +// Method: drive.replies.insert +// Creates a new reply to the given comment. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveCommentReply. ++ (id)queryForRepliesInsertWithObject:(GTLDriveCommentReply *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId; + +// Method: drive.replies.list +// Lists all of the replies to a comment. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// Optional: +// includeDeleted: If set, all replies, including deleted replies (with +// content stripped) will be returned. (Default false) +// maxResults: The maximum number of replies to include in the response, used +// for paging. (0..100, default 20) +// pageToken: The continuation token, used to page through large result sets. +// To get the next page of results, set this parameter to the value of +// "nextPageToken" from the previous response. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveCommentReplyList. ++ (id)queryForRepliesListWithFileId:(NSString *)fileId + commentId:(NSString *)commentId; + +// Method: drive.replies.patch +// Updates an existing reply. This method supports patch semantics. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// replyId: The ID of the reply. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveCommentReply. ++ (id)queryForRepliesPatchWithObject:(GTLDriveCommentReply *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId; + +// Method: drive.replies.update +// Updates an existing reply. +// Required: +// fileId: The ID of the file. +// commentId: The ID of the comment. +// replyId: The ID of the reply. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveCommentReply. ++ (id)queryForRepliesUpdateWithObject:(GTLDriveCommentReply *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId; + +#pragma mark - +#pragma mark "revisions" methods +// These create a GTLQueryDrive object. + +// Method: drive.revisions.delete +// Removes a revision. +// Required: +// fileId: The ID of the file. +// revisionId: The ID of the revision. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile ++ (id)queryForRevisionsDeleteWithFileId:(NSString *)fileId + revisionId:(NSString *)revisionId; + +// Method: drive.revisions.get +// Gets a specific revision. +// Required: +// fileId: The ID of the file. +// revisionId: The ID of the revision. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveRevision. ++ (id)queryForRevisionsGetWithFileId:(NSString *)fileId + revisionId:(NSString *)revisionId; + +// Method: drive.revisions.list +// Lists a file's revisions. +// Required: +// fileId: The ID of the file. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// kGTLAuthScopeDriveMetadataReadonly +// kGTLAuthScopeDriveReadonly +// Fetches a GTLDriveRevisionList. ++ (id)queryForRevisionsListWithFileId:(NSString *)fileId; + +// Method: drive.revisions.patch +// Updates a revision. This method supports patch semantics. +// Required: +// fileId: The ID for the file. +// revisionId: The ID for the revision. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveRevision. ++ (id)queryForRevisionsPatchWithObject:(GTLDriveRevision *)object + fileId:(NSString *)fileId + revisionId:(NSString *)revisionId; + +// Method: drive.revisions.update +// Updates a revision. +// Required: +// fileId: The ID for the file. +// revisionId: The ID for the revision. +// Authorization scope(s): +// kGTLAuthScopeDrive +// kGTLAuthScopeDriveAppdata +// kGTLAuthScopeDriveFile +// Fetches a GTLDriveRevision. ++ (id)queryForRevisionsUpdateWithObject:(GTLDriveRevision *)object + fileId:(NSString *)fileId + revisionId:(NSString *)revisionId; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLQueryDrive.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLQueryDrive.m new file mode 100755 index 0000000..d4ef664 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLQueryDrive.m @@ -0,0 +1,774 @@ +/* Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLQueryDrive.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLQueryDrive (59 custom class methods, 45 custom properties) + +#import "GTLQueryDrive.h" + +#import "GTLDriveAbout.h" +#import "GTLDriveApp.h" +#import "GTLDriveAppList.h" +#import "GTLDriveChange.h" +#import "GTLDriveChangeList.h" +#import "GTLDriveChannel.h" +#import "GTLDriveChildList.h" +#import "GTLDriveChildReference.h" +#import "GTLDriveComment.h" +#import "GTLDriveCommentList.h" +#import "GTLDriveCommentReply.h" +#import "GTLDriveCommentReplyList.h" +#import "GTLDriveFile.h" +#import "GTLDriveFileList.h" +#import "GTLDriveParentList.h" +#import "GTLDriveParentReference.h" +#import "GTLDrivePermission.h" +#import "GTLDrivePermissionId.h" +#import "GTLDrivePermissionList.h" +#import "GTLDriveProperty.h" +#import "GTLDrivePropertyList.h" +#import "GTLDriveRevision.h" +#import "GTLDriveRevisionList.h" + +@implementation GTLQueryDrive + +@dynamic acknowledgeAbuse, addParents, appFilterExtensions, appFilterMimeTypes, + appId, baseRevision, changeId, childId, commentId, convert, corpus, + email, emailMessage, fields, fileId, folderId, includeDeleted, + includeSubscribed, languageCode, maxChangeIdCount, maxResults, + newRevision, ocr, ocrLanguage, pageToken, parentId, permissionId, + pinned, projection, propertyKey, q, removeParents, replyId, revision, + revisionId, sendNotificationEmails, setModifiedDate, startChangeId, + timedTextLanguage, timedTextTrackName, transferOwnership, updatedMin, + updateViewedDate, useContentAsIndexableText, visibility; + +#pragma mark - +#pragma mark "about" methods +// These create a GTLQueryDrive object. + ++ (id)queryForAboutGet { + NSString *methodName = @"drive.about.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.expectedObjectClass = [GTLDriveAbout class]; + return query; +} + +#pragma mark - +#pragma mark "apps" methods +// These create a GTLQueryDrive object. + ++ (id)queryForAppsGetWithAppId:(NSString *)appId { + NSString *methodName = @"drive.apps.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.appId = appId; + query.expectedObjectClass = [GTLDriveApp class]; + return query; +} + ++ (id)queryForAppsList { + NSString *methodName = @"drive.apps.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.expectedObjectClass = [GTLDriveAppList class]; + return query; +} + +#pragma mark - +#pragma mark "changes" methods +// These create a GTLQueryDrive object. + ++ (id)queryForChangesGetWithChangeId:(NSString *)changeId { + NSString *methodName = @"drive.changes.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.changeId = changeId; + query.expectedObjectClass = [GTLDriveChange class]; + return query; +} + ++ (id)queryForChangesList { + NSString *methodName = @"drive.changes.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.expectedObjectClass = [GTLDriveChangeList class]; + return query; +} + ++ (id)queryForChangesWatchWithObject:(GTLDriveChannel *)object { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.changes.watch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.expectedObjectClass = [GTLDriveChannel class]; + return query; +} + +#pragma mark - +#pragma mark "channels" methods +// These create a GTLQueryDrive object. + ++ (id)queryForChannelsStopWithObject:(GTLDriveChannel *)object { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.channels.stop"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + return query; +} + +#pragma mark - +#pragma mark "children" methods +// These create a GTLQueryDrive object. + ++ (id)queryForChildrenDeleteWithFolderId:(NSString *)folderId + childId:(NSString *)childId { + NSString *methodName = @"drive.children.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.folderId = folderId; + query.childId = childId; + return query; +} + ++ (id)queryForChildrenGetWithFolderId:(NSString *)folderId + childId:(NSString *)childId { + NSString *methodName = @"drive.children.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.folderId = folderId; + query.childId = childId; + query.expectedObjectClass = [GTLDriveChildReference class]; + return query; +} + ++ (id)queryForChildrenInsertWithObject:(GTLDriveChildReference *)object + folderId:(NSString *)folderId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.children.insert"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.folderId = folderId; + query.expectedObjectClass = [GTLDriveChildReference class]; + return query; +} + ++ (id)queryForChildrenListWithFolderId:(NSString *)folderId { + NSString *methodName = @"drive.children.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.folderId = folderId; + query.expectedObjectClass = [GTLDriveChildList class]; + return query; +} + +#pragma mark - +#pragma mark "comments" methods +// These create a GTLQueryDrive object. + ++ (id)queryForCommentsDeleteWithFileId:(NSString *)fileId + commentId:(NSString *)commentId { + NSString *methodName = @"drive.comments.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.commentId = commentId; + return query; +} + ++ (id)queryForCommentsGetWithFileId:(NSString *)fileId + commentId:(NSString *)commentId { + NSString *methodName = @"drive.comments.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.commentId = commentId; + query.expectedObjectClass = [GTLDriveComment class]; + return query; +} + ++ (id)queryForCommentsInsertWithObject:(GTLDriveComment *)object + fileId:(NSString *)fileId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.comments.insert"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveComment class]; + return query; +} + ++ (id)queryForCommentsListWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.comments.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveCommentList class]; + return query; +} + ++ (id)queryForCommentsPatchWithObject:(GTLDriveComment *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.comments.patch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.commentId = commentId; + query.expectedObjectClass = [GTLDriveComment class]; + return query; +} + ++ (id)queryForCommentsUpdateWithObject:(GTLDriveComment *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.comments.update"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.commentId = commentId; + query.expectedObjectClass = [GTLDriveComment class]; + return query; +} + +#pragma mark - +#pragma mark "files" methods +// These create a GTLQueryDrive object. + ++ (id)queryForFilesCopyWithObject:(GTLDriveFile *)object + fileId:(NSString *)fileId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.files.copy"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesDeleteWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.files.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + return query; +} + ++ (id)queryForFilesEmptyTrash { + NSString *methodName = @"drive.files.emptyTrash"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + return query; +} + ++ (id)queryForFilesGetWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.files.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesInsertWithObject:(GTLDriveFile *)object + uploadParameters:(GTLUploadParameters *)uploadParametersOrNil { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.files.insert"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.uploadParameters = uploadParametersOrNil; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesList { + NSString *methodName = @"drive.files.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.expectedObjectClass = [GTLDriveFileList class]; + return query; +} + ++ (id)queryForFilesPatchWithObject:(GTLDriveFile *)object + fileId:(NSString *)fileId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.files.patch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesTouchWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.files.touch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesTrashWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.files.trash"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesUntrashWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.files.untrash"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesUpdateWithObject:(GTLDriveFile *)object + fileId:(NSString *)fileId + uploadParameters:(GTLUploadParameters *)uploadParametersOrNil { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.files.update"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.uploadParameters = uploadParametersOrNil; + query.expectedObjectClass = [GTLDriveFile class]; + return query; +} + ++ (id)queryForFilesWatchWithObject:(GTLDriveChannel *)object + fileId:(NSString *)fileId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.files.watch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveChannel class]; + return query; +} + +#pragma mark - +#pragma mark "parents" methods +// These create a GTLQueryDrive object. + ++ (id)queryForParentsDeleteWithFileId:(NSString *)fileId + parentId:(NSString *)parentId { + NSString *methodName = @"drive.parents.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.parentId = parentId; + return query; +} + ++ (id)queryForParentsGetWithFileId:(NSString *)fileId + parentId:(NSString *)parentId { + NSString *methodName = @"drive.parents.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.parentId = parentId; + query.expectedObjectClass = [GTLDriveParentReference class]; + return query; +} + ++ (id)queryForParentsInsertWithObject:(GTLDriveParentReference *)object + fileId:(NSString *)fileId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.parents.insert"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveParentReference class]; + return query; +} + ++ (id)queryForParentsListWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.parents.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveParentList class]; + return query; +} + +#pragma mark - +#pragma mark "permissions" methods +// These create a GTLQueryDrive object. + ++ (id)queryForPermissionsDeleteWithFileId:(NSString *)fileId + permissionId:(NSString *)permissionId { + NSString *methodName = @"drive.permissions.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.permissionId = permissionId; + return query; +} + ++ (id)queryForPermissionsGetWithFileId:(NSString *)fileId + permissionId:(NSString *)permissionId { + NSString *methodName = @"drive.permissions.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.permissionId = permissionId; + query.expectedObjectClass = [GTLDrivePermission class]; + return query; +} + ++ (id)queryForPermissionsGetIdForEmailWithEmail:(NSString *)email { + NSString *methodName = @"drive.permissions.getIdForEmail"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.email = email; + query.expectedObjectClass = [GTLDrivePermissionId class]; + return query; +} + ++ (id)queryForPermissionsInsertWithObject:(GTLDrivePermission *)object + fileId:(NSString *)fileId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.permissions.insert"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.expectedObjectClass = [GTLDrivePermission class]; + return query; +} + ++ (id)queryForPermissionsListWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.permissions.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDrivePermissionList class]; + return query; +} + ++ (id)queryForPermissionsPatchWithObject:(GTLDrivePermission *)object + fileId:(NSString *)fileId + permissionId:(NSString *)permissionId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.permissions.patch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.permissionId = permissionId; + query.expectedObjectClass = [GTLDrivePermission class]; + return query; +} + ++ (id)queryForPermissionsUpdateWithObject:(GTLDrivePermission *)object + fileId:(NSString *)fileId + permissionId:(NSString *)permissionId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.permissions.update"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.permissionId = permissionId; + query.expectedObjectClass = [GTLDrivePermission class]; + return query; +} + +#pragma mark - +#pragma mark "properties" methods +// These create a GTLQueryDrive object. + ++ (id)queryForPropertiesDeleteWithFileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey { + NSString *methodName = @"drive.properties.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.propertyKey = propertyKey; + return query; +} + ++ (id)queryForPropertiesGetWithFileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey { + NSString *methodName = @"drive.properties.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.propertyKey = propertyKey; + query.expectedObjectClass = [GTLDriveProperty class]; + return query; +} + ++ (id)queryForPropertiesInsertWithObject:(GTLDriveProperty *)object + fileId:(NSString *)fileId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.properties.insert"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveProperty class]; + return query; +} + ++ (id)queryForPropertiesListWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.properties.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDrivePropertyList class]; + return query; +} + ++ (id)queryForPropertiesPatchWithObject:(GTLDriveProperty *)object + fileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.properties.patch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.propertyKey = propertyKey; + query.expectedObjectClass = [GTLDriveProperty class]; + return query; +} + ++ (id)queryForPropertiesUpdateWithObject:(GTLDriveProperty *)object + fileId:(NSString *)fileId + propertyKey:(NSString *)propertyKey { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.properties.update"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.propertyKey = propertyKey; + query.expectedObjectClass = [GTLDriveProperty class]; + return query; +} + +#pragma mark - +#pragma mark "realtime" methods +// These create a GTLQueryDrive object. + ++ (id)queryForRealtimeGetWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.realtime.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + return query; +} + ++ (id)queryForRealtimeUpdateWithFileId:(NSString *)fileId + uploadParameters:(GTLUploadParameters *)uploadParametersOrNil { + NSString *methodName = @"drive.realtime.update"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.uploadParameters = uploadParametersOrNil; + return query; +} + +#pragma mark - +#pragma mark "replies" methods +// These create a GTLQueryDrive object. + ++ (id)queryForRepliesDeleteWithFileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId { + NSString *methodName = @"drive.replies.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.commentId = commentId; + query.replyId = replyId; + return query; +} + ++ (id)queryForRepliesGetWithFileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId { + NSString *methodName = @"drive.replies.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.commentId = commentId; + query.replyId = replyId; + query.expectedObjectClass = [GTLDriveCommentReply class]; + return query; +} + ++ (id)queryForRepliesInsertWithObject:(GTLDriveCommentReply *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.replies.insert"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.commentId = commentId; + query.expectedObjectClass = [GTLDriveCommentReply class]; + return query; +} + ++ (id)queryForRepliesListWithFileId:(NSString *)fileId + commentId:(NSString *)commentId { + NSString *methodName = @"drive.replies.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.commentId = commentId; + query.expectedObjectClass = [GTLDriveCommentReplyList class]; + return query; +} + ++ (id)queryForRepliesPatchWithObject:(GTLDriveCommentReply *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.replies.patch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.commentId = commentId; + query.replyId = replyId; + query.expectedObjectClass = [GTLDriveCommentReply class]; + return query; +} + ++ (id)queryForRepliesUpdateWithObject:(GTLDriveCommentReply *)object + fileId:(NSString *)fileId + commentId:(NSString *)commentId + replyId:(NSString *)replyId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.replies.update"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.commentId = commentId; + query.replyId = replyId; + query.expectedObjectClass = [GTLDriveCommentReply class]; + return query; +} + +#pragma mark - +#pragma mark "revisions" methods +// These create a GTLQueryDrive object. + ++ (id)queryForRevisionsDeleteWithFileId:(NSString *)fileId + revisionId:(NSString *)revisionId { + NSString *methodName = @"drive.revisions.delete"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.revisionId = revisionId; + return query; +} + ++ (id)queryForRevisionsGetWithFileId:(NSString *)fileId + revisionId:(NSString *)revisionId { + NSString *methodName = @"drive.revisions.get"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.revisionId = revisionId; + query.expectedObjectClass = [GTLDriveRevision class]; + return query; +} + ++ (id)queryForRevisionsListWithFileId:(NSString *)fileId { + NSString *methodName = @"drive.revisions.list"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.fileId = fileId; + query.expectedObjectClass = [GTLDriveRevisionList class]; + return query; +} + ++ (id)queryForRevisionsPatchWithObject:(GTLDriveRevision *)object + fileId:(NSString *)fileId + revisionId:(NSString *)revisionId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.revisions.patch"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.revisionId = revisionId; + query.expectedObjectClass = [GTLDriveRevision class]; + return query; +} + ++ (id)queryForRevisionsUpdateWithObject:(GTLDriveRevision *)object + fileId:(NSString *)fileId + revisionId:(NSString *)revisionId { + if (object == nil) { + GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd)); + return nil; + } + NSString *methodName = @"drive.revisions.update"; + GTLQueryDrive *query = [self queryWithMethodName:methodName]; + query.bodyObject = object; + query.fileId = fileId; + query.revisionId = revisionId; + query.expectedObjectClass = [GTLDriveRevision class]; + return query; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLServiceDrive.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLServiceDrive.h new file mode 100755 index 0000000..d81141d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLServiceDrive.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLServiceDrive.h +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLServiceDrive (0 custom class methods, 0 custom properties) + +#if GTL_BUILT_AS_FRAMEWORK + #import "GTL/GTLService.h" +#else + #import "GTLService.h" +#endif + +@interface GTLServiceDrive : GTLService + +// No new methods + +// Clients should create a standard query with any of the class methods in +// GTLQueryDrive.h. The query can the be sent with GTLService's execute methods, +// +// - (GTLServiceTicket *)executeQuery:(GTLQuery *)query +// completionHandler:(void (^)(GTLServiceTicket *ticket, +// id object, NSError *error))handler; +// or +// - (GTLServiceTicket *)executeQuery:(GTLQuery *)query +// delegate:(id)delegate +// didFinishSelector:(SEL)finishedSelector; +// +// where finishedSelector has a signature of: +// +// - (void)serviceTicket:(GTLServiceTicket *)ticket +// finishedWithObject:(id)object +// error:(NSError *)error; +// +// The object passed to the completion handler or delegate method +// is a subclass of GTLObject, determined by the query method executed. + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLServiceDrive.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLServiceDrive.m new file mode 100755 index 0000000..9d32819 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Services/Drive/Generated/GTLServiceDrive.m @@ -0,0 +1,85 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLServiceDrive.m +// + +// ---------------------------------------------------------------------------- +// NOTE: This file is generated from Google APIs Discovery Service. +// Service: +// Drive API (drive/v2) +// Description: +// The API to interact with Drive. +// Documentation: +// https://developers.google.com/drive/ +// Classes: +// GTLServiceDrive (0 custom class methods, 0 custom properties) + +#import "GTLDrive.h" + +@implementation GTLServiceDrive + +#if DEBUG +// Method compiled in debug builds just to check that all the needed support +// classes are present at link time. ++ (NSArray *)checkClasses { + NSArray *classes = [NSArray arrayWithObjects: + [GTLQueryDrive class], + [GTLDriveAbout class], + [GTLDriveApp class], + [GTLDriveAppList class], + [GTLDriveChange class], + [GTLDriveChangeList class], + [GTLDriveChannel class], + [GTLDriveChildList class], + [GTLDriveChildReference class], + [GTLDriveComment class], + [GTLDriveCommentList class], + [GTLDriveCommentReply class], + [GTLDriveCommentReplyList class], + [GTLDriveFile class], + [GTLDriveFileList class], + [GTLDriveParentList class], + [GTLDriveParentReference class], + [GTLDrivePermission class], + [GTLDrivePermissionId class], + [GTLDrivePermissionList class], + [GTLDriveProperty class], + [GTLDrivePropertyList class], + [GTLDriveRevision class], + [GTLDriveRevisionList class], + [GTLDriveUser class], + nil]; + return classes; +} +#endif // DEBUG + +- (id)init { + self = [super init]; + if (self) { + // Version from discovery. + self.apiVersion = @"v2"; + + // From discovery. Where to send JSON-RPC. + // Turn off prettyPrint for this service to save bandwidth (especially on + // mobile). The fetcher logging will pretty print. + self.rpcURL = [NSURL URLWithString:@"https://www.googleapis.com/rpc?prettyPrint=false"]; + self.rpcUploadURL = [NSURL URLWithString:@"https://www.googleapis.com/upload/rpc?uploadType=resumable&prettyPrint=false"]; + } + return self; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLBase64.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLBase64.h new file mode 100755 index 0000000..fd0a051 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLBase64.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NSData *GTLDecodeBase64(NSString *base64Str); +NSString *GTLEncodeBase64(NSData *data); + +// "Web-safe" encoding substitutes - and _ for + and / in the encoding table, +// per http://www.ietf.org/rfc/rfc4648.txt section 5. + +NSData *GTLDecodeWebSafeBase64(NSString *base64Str); +NSString *GTLEncodeWebSafeBase64(NSData *data); diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLBase64.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLBase64.m new file mode 100755 index 0000000..e6c0362 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLBase64.m @@ -0,0 +1,139 @@ +/* Copyright (c) 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GTLBase64.h" + +// Based on Cyrus Najmabadi's elegent little encoder and decoder from +// http://www.cocoadev.com/index.pl?BaseSixtyFour + +static char gStandardEncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static char gWebSafeEncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +#pragma mark Encode + +static NSString *EncodeBase64StringCommon(NSData *data, const char *table) { + if (data == nil) return nil; + + const uint8_t* input = [data bytes]; + NSUInteger length = [data length]; + + NSUInteger bufferSize = ((length + 2) / 3) * 4; + NSMutableData* buffer = [NSMutableData dataWithLength:bufferSize]; + + int8_t *output = [buffer mutableBytes]; + + for (NSUInteger i = 0; i < length; i += 3) { + NSUInteger value = 0; + for (NSUInteger j = i; j < (i + 3); j++) { + value <<= 8; + + if (j < length) { + value |= (0xFF & input[j]); + } + } + + NSInteger idx = (i / 3) * 4; + output[idx + 0] = table[(value >> 18) & 0x3F]; + output[idx + 1] = table[(value >> 12) & 0x3F]; + output[idx + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '='; + output[idx + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '='; + } + + NSString *result = [[[NSString alloc] initWithData:buffer + encoding:NSASCIIStringEncoding] autorelease]; + return result; +} + +NSString *GTLEncodeBase64(NSData *data) { + return EncodeBase64StringCommon(data, gStandardEncodingTable); +} + +NSString *GTLEncodeWebSafeBase64(NSData *data) { + return EncodeBase64StringCommon(data, gWebSafeEncodingTable); +} + +#pragma mark Decode + +static void CreateDecodingTable(const char *encodingTable, + size_t encodingTableSize, char *decodingTable) { + memset(decodingTable, 0, 128); + for (unsigned int i = 0; i < encodingTableSize; i++) { + decodingTable[(unsigned int) encodingTable[i]] = (char)i; + } +} + +static NSData *DecodeBase64StringCommon(NSString *base64Str, + char *decodingTable) { + // The input string should be plain ASCII + const char *cString = [base64Str cStringUsingEncoding:NSASCIIStringEncoding]; + if (cString == nil) return nil; + + NSInteger inputLength = (NSInteger)strlen(cString); + if (inputLength % 4 != 0) return nil; + if (inputLength == 0) return [NSData data]; + + while (inputLength > 0 && cString[inputLength - 1] == '=') { + inputLength--; + } + + NSInteger outputLength = inputLength * 3 / 4; + NSMutableData* data = [NSMutableData dataWithLength:(NSUInteger)outputLength]; + uint8_t *output = [data mutableBytes]; + + NSInteger inputPoint = 0; + NSInteger outputPoint = 0; + char *table = decodingTable; + + while (inputPoint < inputLength) { + int i0 = cString[inputPoint++]; + int i1 = cString[inputPoint++]; + int i2 = inputPoint < inputLength ? cString[inputPoint++] : 'A'; // 'A' will decode to \0 + int i3 = inputPoint < inputLength ? cString[inputPoint++] : 'A'; + + output[outputPoint++] = (uint8_t)((table[i0] << 2) | (table[i1] >> 4)); + if (outputPoint < outputLength) { + output[outputPoint++] = (uint8_t)(((table[i1] & 0xF) << 4) | (table[i2] >> 2)); + } + if (outputPoint < outputLength) { + output[outputPoint++] = (uint8_t)(((table[i2] & 0x3) << 6) | table[i3]); + } + } + + return data; +} + +NSData *GTLDecodeBase64(NSString *base64Str) { + static char decodingTable[128]; + static BOOL hasInited = NO; + + if (!hasInited) { + CreateDecodingTable(gStandardEncodingTable, sizeof(gStandardEncodingTable), + decodingTable); + hasInited = YES; + } + return DecodeBase64StringCommon(base64Str, decodingTable); +} + +NSData *GTLDecodeWebSafeBase64(NSString *base64Str) { + static char decodingTable[128]; + static BOOL hasInited = NO; + + if (!hasInited) { + CreateDecodingTable(gWebSafeEncodingTable, sizeof(gWebSafeEncodingTable), + decodingTable); + hasInited = YES; + } + return DecodeBase64StringCommon(base64Str, decodingTable); +} diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLFramework.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLFramework.h new file mode 100755 index 0000000..106f420 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLFramework.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef _GTLFRAMEWORK_H_ +#define _GTLFRAMEWORK_H_ + +#import + +#import "GTLDefines.h" + + +// Returns the version of the framework. Major and minor should +// match the bundle version in the Info.plist file. +// +// Pass NULL to ignore any of the parameters. + +void GTLFrameworkVersion(NSUInteger* major, NSUInteger* minor, NSUInteger* release); + +// Returns the version in @"a.b" or @"a.b.c" format +NSString *GTLFrameworkVersionString(void); + +#endif diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLFramework.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLFramework.m new file mode 100755 index 0000000..6bfc7f2 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLFramework.m @@ -0,0 +1,40 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GTLFramework.h" + +void GTLFrameworkVersion(NSUInteger* major, NSUInteger* minor, NSUInteger* release) { + // version 2.0.0 + if (major) *major = 2; + if (minor) *minor = 0; + if (release) *release = 0; +} + +NSString *GTLFrameworkVersionString(void) { + NSUInteger major, minor, release; + NSString *libVersionString; + + GTLFrameworkVersion(&major, &minor, &release); + + // most library releases will have a release value of zero + if (release != 0) { + libVersionString = [NSString stringWithFormat:@"%d.%d.%d", + (int)major, (int)minor, (int)release]; + } else { + libVersionString = [NSString stringWithFormat:@"%d.%d", + (int)major, (int)minor]; + } + return libVersionString; +} diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLJSONParser.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLJSONParser.h new file mode 100755 index 0000000..d971529 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLJSONParser.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLJSONParser.h +// + +// This class is a thin wrapper around the JSON parser. It uses +// NSJSONSerialization when available, and SBJSON otherwise. + +#import + +#import "GTLDefines.h" + +@interface GTLJSONParser : NSObject ++ (NSString*)stringWithObject:(id)value + humanReadable:(BOOL)humanReadable + error:(NSError**)error; + ++ (NSData *)dataWithObject:(id)obj + humanReadable:(BOOL)humanReadable + error:(NSError**)error; + ++ (id)objectWithString:(NSString *)jsonStr + error:(NSError **)error; + ++ (id)objectWithData:(NSData *)jsonData + error:(NSError **)error; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLJSONParser.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLJSONParser.m new file mode 100755 index 0000000..bbbcc43 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLJSONParser.m @@ -0,0 +1,152 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTLJSONParser.m +// + +#import "GTLJSONParser.h" + +// We can assume NSJSONSerialization is present on Mac OS X 10.7 and iOS 5 +#if !defined(GTL_REQUIRES_NSJSONSERIALIZATION) +#if (!TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) || \ + (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) +#define GTL_REQUIRES_NSJSONSERIALIZATION 1 +#endif +#endif + +// If GTMNSJSONSerialization is available, it is used for parsing and +// formatting JSON +#if !GTL_REQUIRES_NSJSONSERIALIZATION +@interface GTMNSJSONSerialization : NSObject ++ (NSData *)dataWithJSONObject:(id)obj options:(NSUInteger)opt error:(NSError **)error; ++ (id)JSONObjectWithData:(NSData *)data options:(NSUInteger)opt error:(NSError **)error; +@end + +// As a fallback, SBJSON is used for parsing and formatting JSON +@interface GTLSBJSON +- (void)setHumanReadable:(BOOL)flag; +- (NSString*)stringWithObject:(id)value error:(NSError**)error; +- (id)objectWithString:(NSString*)jsonrep error:(NSError**)error; +@end +#endif // !GTL_REQUIRES_NSJSONSERIALIZATION + +@implementation GTLJSONParser + +#if DEBUG && !GTL_REQUIRES_NSJSONSERIALIZATION +// When compiling for iOS 4 compatibility, SBJSON must be available ++ (void)load { + Class writer = NSClassFromString(@"SBJsonWriter"); + Class parser = NSClassFromString(@"SBJsonParser"); + Class oldParser = NSClassFromString(@"SBJSON"); + GTL_ASSERT((oldParser != Nil) + || (writer != Nil && parser != Nil), + @"No parsing class found"); +} +#endif // DEBUG && !GTL_REQUIRES_NSJSONSERIALIZATION + ++ (NSString *)stringWithObject:(id)obj + humanReadable:(BOOL)humanReadable + error:(NSError **)error { + NSData *data = [self dataWithObject:obj + humanReadable:humanReadable + error:error]; + if (data) { + NSString *jsonStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + return jsonStr; + } + return nil; +} + ++ (NSData *)dataWithObject:(id)obj + humanReadable:(BOOL)humanReadable + error:(NSError **)error { + if (obj == nil) return nil; + + const NSUInteger kOpts = humanReadable ? (1UL << 0) : 0; // NSJSONWritingPrettyPrinted + +#if GTL_REQUIRES_NSJSONSERIALIZATION + NSData *data = [NSJSONSerialization dataWithJSONObject:obj + options:kOpts + error:error]; + return data; +#else + Class serializer = NSClassFromString(@"NSJSONSerialization"); + if (serializer) { + NSData *data = [serializer dataWithJSONObject:obj + options:kOpts + error:error]; + return data; + } else { + Class jsonWriteClass = NSClassFromString(@"SBJsonWriter"); + if (!jsonWriteClass) { + jsonWriteClass = NSClassFromString(@"SBJSON"); + } + + if (error) *error = nil; + + GTLSBJSON *writer = [[[jsonWriteClass alloc] init] autorelease]; + [writer setHumanReadable:humanReadable]; + NSString *jsonStr = [writer stringWithObject:obj + error:error]; + NSData *data = [jsonStr dataUsingEncoding:NSUTF8StringEncoding]; + return data; + } +#endif +} + ++ (id)objectWithString:(NSString *)jsonStr + error:(NSError **)error { + NSData *data = [jsonStr dataUsingEncoding:NSUTF8StringEncoding]; + return [self objectWithData:data + error:error]; +} + ++ (id)objectWithData:(NSData *)jsonData + error:(NSError **)error { +#if GTL_REQUIRES_NSJSONSERIALIZATION + NSMutableDictionary *obj = [NSJSONSerialization JSONObjectWithData:jsonData + options:NSJSONReadingMutableContainers + error:error]; + return obj; +#else + Class serializer = NSClassFromString(@"NSJSONSerialization"); + if (serializer) { + const NSUInteger kOpts = (1UL << 0); // NSJSONReadingMutableContainers + NSMutableDictionary *obj = [serializer JSONObjectWithData:jsonData + options:kOpts + error:error]; + return obj; + } else { + Class jsonParseClass = NSClassFromString(@"SBJsonParser"); + if (!jsonParseClass) { + jsonParseClass = NSClassFromString(@"SBJSON"); + } + + if (error) *error = nil; + + GTLSBJSON *parser = [[[jsonParseClass alloc] init] autorelease]; + + NSString *jsonrep = [[[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding] autorelease]; + id obj = [parser objectWithString:jsonrep + error:error]; + return obj; + } +#endif +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLTargetNamespace.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLTargetNamespace.h new file mode 100755 index 0000000..9e08a9e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLTargetNamespace.h @@ -0,0 +1,58 @@ +// +// Makes the value of GTL_TARGET_NAMESPACE a prefix for all GTL +// library class names +// + +// +// To avoid global namespace issues, define GTL_TARGET_NAMESPACE to a short +// string in your target if you are using the GTL library in a shared-code +// environment like a plug-in. +// +// For example: -DGTL_TARGET_NAMESPACE=MyPlugin +// + +// +// com.google.GTLFramework v. 2.0 (29 classes) 2011-10-25 19:25:36 -0700 +// + +#if defined(__OBJC__) && defined(GTL_TARGET_NAMESPACE) + + #define _GTL_NS_SYMBOL_INNER(ns, symbol) ns ## _ ## symbol + #define _GTL_NS_SYMBOL_MIDDLE(ns, symbol) _GTL_NS_SYMBOL_INNER(ns, symbol) + #define _GTL_NS_SYMBOL(symbol) _GTL_NS_SYMBOL_MIDDLE(GTL_TARGET_NAMESPACE, symbol) + + #define _GTL_NS_STRING_INNER(ns) #ns + #define _GTL_NS_STRING_MIDDLE(ns) _GTL_NS_STRING_INNER(ns) + #define GTL_TARGET_NAMESPACE_STRING _GTL_NS_STRING_MIDDLE(GTL_TARGET_NAMESPACE) + + #define GTLBatchQuery _GTL_NS_SYMBOL(GTLBatchQuery) + #define GTLBatchResult _GTL_NS_SYMBOL(GTLBatchResult) + #define GTLCollectionObject _GTL_NS_SYMBOL(GTLCollectionObject) + #define GTLDateTime _GTL_NS_SYMBOL(GTLDateTime) + #define GTLErrorObject _GTL_NS_SYMBOL(GTLErrorObject) + #define GTLErrorObjectData _GTL_NS_SYMBOL(GTLErrorObjectData) + #define GTLJSONParser _GTL_NS_SYMBOL(GTLJSONParser) + #define GTLObject _GTL_NS_SYMBOL(GTLObject) + #define GTLQuery _GTL_NS_SYMBOL(GTLQuery) + #define GTLRuntimeCommon _GTL_NS_SYMBOL(GTLRuntimeCommon) + #define GTLService _GTL_NS_SYMBOL(GTLService) + #define GTLServiceTicket _GTL_NS_SYMBOL(GTLServiceTicket) + #define GTLUploadParameters _GTL_NS_SYMBOL(GTLUploadParameters) + #define GTLUtilities _GTL_NS_SYMBOL(GTLUtilities) + #define GTMCachedURLResponse _GTL_NS_SYMBOL(GTMCachedURLResponse) + #define GTMCookieStorage _GTL_NS_SYMBOL(GTMCookieStorage) + #define GTMGatherInputStream _GTL_NS_SYMBOL(GTMGatherInputStream) + #define GTMHTTPFetcher _GTL_NS_SYMBOL(GTMHTTPFetcher) + #define GTMHTTPFetcherService _GTL_NS_SYMBOL(GTMHTTPFetcherService) + #define GTMHTTPFetchHistory _GTL_NS_SYMBOL(GTMHTTPFetchHistory) + #define GTMHTTPUploadFetcher _GTL_NS_SYMBOL(GTMHTTPUploadFetcher) + #define GTMMIMEDocument _GTL_NS_SYMBOL(GTMMIMEDocument) + #define GTMMIMEPart _GTL_NS_SYMBOL(GTMMIMEPart) + #define GTMOAuth2Authentication _GTL_NS_SYMBOL(GTMOAuth2Authentication) + #define GTMOAuth2AuthorizationArgs _GTL_NS_SYMBOL(GTMOAuth2AuthorizationArgs) + #define GTMOAuth2SignIn _GTL_NS_SYMBOL(GTMOAuth2SignIn) + #define GTMOAuth2WindowController _GTL_NS_SYMBOL(GTMOAuth2WindowController) + #define GTMReadMonitorInputStream _GTL_NS_SYMBOL(GTMReadMonitorInputStream) + #define GTMURLCache _GTL_NS_SYMBOL(GTMURLCache) + +#endif diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLUtilities.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLUtilities.h new file mode 100755 index 0000000..5d9a1cd --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLUtilities.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#ifndef SKIP_GTL_DEFINES + #import "GTLDefines.h" +#endif + +// helper functions for implementing isEqual: +BOOL GTL_AreEqualOrBothNil(id obj1, id obj2); +BOOL GTL_AreBoolsEqual(BOOL b1, BOOL b2); + +// Helper to ensure a number is a number. +// +// The GoogleAPI servers will send numbers >53 bits as strings to avoid +// bugs in some JavaScript implementations. Work around this by catching +// the string and turning it back into a number. +NSNumber *GTL_EnsureNSNumber(NSNumber *num); + +@interface GTLUtilities : NSObject + +// +// String encoding +// + +// URL encoding, different for parts of URLs and parts of URL parameters +// +// +stringByURLEncodingString just makes a string legal for a URL +// +// +stringByURLEncodingForURI also encodes some characters that are legal in +// URLs but should not be used in URIs, +// per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7 +// +// +stringByURLEncodingStringParameter is like +stringByURLEncodingForURI but +// replaces space characters with + characters rather than percent-escaping them +// ++ (NSString *)stringByURLEncodingString:(NSString *)str; ++ (NSString *)stringByURLEncodingForURI:(NSString *)str; ++ (NSString *)stringByURLEncodingStringParameter:(NSString *)str; + +// Percent-encoded UTF-8 ++ (NSString *)stringByPercentEncodingUTF8ForString:(NSString *)str; + +// Key-value coding searches in an array +// +// Utilities to get from an array objects having a known value (or nil) +// at a keyPath + ++ (NSArray *)objectsFromArray:(NSArray *)sourceArray + withValue:(id)desiredValue + forKeyPath:(NSString *)keyPath; + ++ (id)firstObjectFromArray:(NSArray *)sourceArray + withValue:(id)desiredValue + forKeyPath:(NSString *)keyPath; + +// +// Version helpers +// + ++ (NSComparisonResult)compareVersion:(NSString *)ver1 toVersion:(NSString *)ver2; + +// +// URL builder +// + +// If there are already query parameters on urlString, the new ones are simple +// appended after them. ++ (NSURL *)URLWithString:(NSString *)urlString + queryParameters:(NSDictionary *)queryParameters; + +// Walk up the class tree merging dictionaries and return the result. ++ (NSDictionary *)mergedClassDictionaryForSelector:(SEL)selector + startClass:(Class)startClass + ancestorClass:(Class)ancestorClass + cache:(NSMutableDictionary *)cache; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLUtilities.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLUtilities.m new file mode 100755 index 0000000..03c6437 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Google-API-Client/Source/Utilities/GTLUtilities.m @@ -0,0 +1,348 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GTLUtilities.h" + +#include + +@implementation GTLUtilities + +#pragma mark String encoding + +// URL Encoding + ++ (NSString *)stringByURLEncodingString:(NSString *)str { + NSString *result = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + return result; +} + +// NSURL's stringByAddingPercentEscapesUsingEncoding: does not escape +// some characters that should be escaped in URL parameters, like / and ?; +// we'll use CFURL to force the encoding of those +// +// Reference: http://www.ietf.org/rfc/rfc3986.txt + +const CFStringRef kCharsToForceEscape = CFSTR("!*'();:@&=+$,/?%#[]"); + ++ (NSString *)stringByURLEncodingForURI:(NSString *)str { + + NSString *resultStr = str; + + CFStringRef originalString = (CFStringRef) str; + CFStringRef leaveUnescaped = NULL; + + CFStringRef escapedStr; + escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, + originalString, + leaveUnescaped, + kCharsToForceEscape, + kCFStringEncodingUTF8); + if (escapedStr) { + resultStr = [(id)CFMakeCollectable(escapedStr) autorelease]; + } + return resultStr; +} + ++ (NSString *)stringByURLEncodingStringParameter:(NSString *)str { + // For parameters, we'll explicitly leave spaces unescaped now, and replace + // them with +'s + NSString *resultStr = str; + + CFStringRef originalString = (CFStringRef) str; + CFStringRef leaveUnescaped = CFSTR(" "); + + CFStringRef escapedStr; + escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, + originalString, + leaveUnescaped, + kCharsToForceEscape, + kCFStringEncodingUTF8); + + if (escapedStr) { + NSMutableString *mutableStr = [NSMutableString stringWithString:(NSString *)escapedStr]; + CFRelease(escapedStr); + + // replace spaces with plusses + [mutableStr replaceOccurrencesOfString:@" " + withString:@"+" + options:0 + range:NSMakeRange(0, [mutableStr length])]; + resultStr = mutableStr; + } + return resultStr; +} + ++ (NSString *)stringByPercentEncodingUTF8ForString:(NSString *)inputStr { + + // Encode per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7 + // + // This is used for encoding upload slug headers + // + // Step through the string as UTF-8, and replace characters outside 20..7E + // (and the percent symbol itself, 25) with percent-encodings + // + // We avoid creating an encoding string unless we encounter some characters + // that require it + const char* utf8 = [inputStr UTF8String]; + if (utf8 == NULL) { + return nil; + } + + NSMutableString *encoded = nil; + + for (unsigned int idx = 0; utf8[idx] != '\0'; idx++) { + + unsigned char currChar = (unsigned char)utf8[idx]; + if (currChar < 0x20 || currChar == 0x25 || currChar > 0x7E) { + + if (encoded == nil) { + // Start encoding and catch up on the character skipped so far + encoded = [[[NSMutableString alloc] initWithBytes:utf8 + length:idx + encoding:NSUTF8StringEncoding] autorelease]; + } + + // append this byte as a % and then uppercase hex + [encoded appendFormat:@"%%%02X", currChar]; + + } else { + // This character does not need encoding + // + // Encoded is nil here unless we've encountered a previous character + // that needed encoding + [encoded appendFormat:@"%c", currChar]; + } + } + + if (encoded) { + return encoded; + } + + return inputStr; +} + +#pragma mark Key-Value Coding Searches in an Array + ++ (NSArray *)objectsFromArray:(NSArray *)sourceArray + withValue:(id)desiredValue + forKeyPath:(NSString *)keyPath { + // Step through all entries, get the value from + // the key path, and see if it's equal to the + // desired value + NSMutableArray *results = [NSMutableArray array]; + + for(id obj in sourceArray) { + id val = [obj valueForKeyPath:keyPath]; + if (GTL_AreEqualOrBothNil(val, desiredValue)) { + + // found a match; add it to the results array + [results addObject:obj]; + } + } + return results; +} + ++ (id)firstObjectFromArray:(NSArray *)sourceArray + withValue:(id)desiredValue + forKeyPath:(NSString *)keyPath { + for (id obj in sourceArray) { + id val = [obj valueForKeyPath:keyPath]; + if (GTL_AreEqualOrBothNil(val, desiredValue)) { + // found a match; return it + return obj; + } + } + return nil; +} + +#pragma mark Version helpers + +// compareVersion compares two strings in 1.2.3.4 format +// missing fields are interpreted as zeros, so 1.2 = 1.2.0.0 ++ (NSComparisonResult)compareVersion:(NSString *)ver1 toVersion:(NSString *)ver2 { + + static NSCharacterSet* dotSet = nil; + if (dotSet == nil) { + dotSet = [[NSCharacterSet characterSetWithCharactersInString:@"."] retain]; + } + + if (ver1 == nil) ver1 = @""; + if (ver2 == nil) ver2 = @""; + + NSScanner* scanner1 = [NSScanner scannerWithString:ver1]; + NSScanner* scanner2 = [NSScanner scannerWithString:ver2]; + + [scanner1 setCharactersToBeSkipped:dotSet]; + [scanner2 setCharactersToBeSkipped:dotSet]; + + int partA1 = 0, partA2 = 0, partB1 = 0, partB2 = 0; + int partC1 = 0, partC2 = 0, partD1 = 0, partD2 = 0; + + if ([scanner1 scanInt:&partA1] && [scanner1 scanInt:&partB1] + && [scanner1 scanInt:&partC1] && [scanner1 scanInt:&partD1]) { + } + if ([scanner2 scanInt:&partA2] && [scanner2 scanInt:&partB2] + && [scanner2 scanInt:&partC2] && [scanner2 scanInt:&partD2]) { + } + + if (partA1 != partA2) return ((partA1 < partA2) ? NSOrderedAscending : NSOrderedDescending); + if (partB1 != partB2) return ((partB1 < partB2) ? NSOrderedAscending : NSOrderedDescending); + if (partC1 != partC2) return ((partC1 < partC2) ? NSOrderedAscending : NSOrderedDescending); + if (partD1 != partD2) return ((partD1 < partD2) ? NSOrderedAscending : NSOrderedDescending); + return NSOrderedSame; +} + +#pragma mark URL builder + ++ (NSURL *)URLWithString:(NSString *)urlString + queryParameters:(NSDictionary *)queryParameters { + if ([urlString length] == 0) return nil; + + NSString *fullURLString; + if ([queryParameters count] > 0) { + NSMutableArray *queryItems = [NSMutableArray arrayWithCapacity:[queryParameters count]]; + + // sort the custom parameter keys so that we have deterministic parameter + // order for unit tests + NSArray *queryKeys = [queryParameters allKeys]; + NSArray *sortedQueryKeys = [queryKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + + for (NSString *paramKey in sortedQueryKeys) { + NSString *paramValue = [queryParameters valueForKey:paramKey]; + + NSString *paramItem = [NSString stringWithFormat:@"%@=%@", + [self stringByURLEncodingStringParameter:paramKey], + [self stringByURLEncodingStringParameter:paramValue]]; + + [queryItems addObject:paramItem]; + } + + NSString *paramStr = [queryItems componentsJoinedByString:@"&"]; + + BOOL hasQMark = ([urlString rangeOfString:@"?"].location == NSNotFound); + char joiner = hasQMark ? '?' : '&'; + fullURLString = [NSString stringWithFormat:@"%@%c%@", + urlString, joiner, paramStr]; + } else { + fullURLString = urlString; + } + NSURL *result = [NSURL URLWithString:fullURLString]; + return result; +} + +#pragma mark Collections + ++ (NSDictionary *)mergedClassDictionaryForSelector:(SEL)selector + startClass:(Class)startClass + ancestorClass:(Class)ancestorClass + cache:(NSMutableDictionary *)cache { + NSDictionary *result; + @synchronized(cache) { + result = [cache objectForKey:startClass]; + if (result == nil) { + // Collect the class's dictionary. + NSDictionary *classDict = [startClass performSelector:selector]; + + // Collect the parent class's merged dictionary. + NSDictionary *parentClassMergedDict; + if ([startClass isEqual:ancestorClass]) { + parentClassMergedDict = nil; + } else { + Class parentClass = class_getSuperclass(startClass); + parentClassMergedDict = + [GTLUtilities mergedClassDictionaryForSelector:selector + startClass:parentClass + ancestorClass:ancestorClass + cache:cache]; + } + + // Merge this class's into the parent's so things properly override. + NSMutableDictionary *mergeDict; + if (parentClassMergedDict != nil) { + mergeDict = + [NSMutableDictionary dictionaryWithDictionary:parentClassMergedDict]; + } else { + mergeDict = [NSMutableDictionary dictionary]; + } + if (classDict != nil) { + [mergeDict addEntriesFromDictionary:classDict]; + } + + // Make an immutable version. + result = [NSDictionary dictionaryWithDictionary:mergeDict]; + + // Save it. + [cache setObject:result forKey:(id)startClass]; + } + } + return result; +} + +@end + +// isEqual: has the fatal flaw that it doesn't deal well with the receiver +// being nil. We'll use this utility instead. +BOOL GTL_AreEqualOrBothNil(id obj1, id obj2) { + if (obj1 == obj2) { + return YES; + } + if (obj1 && obj2) { + BOOL areEqual = [obj1 isEqual:obj2]; + return areEqual; + } + return NO; +} + +BOOL GTL_AreBoolsEqual(BOOL b1, BOOL b2) { + // avoid comparison problems with boolean types by negating + // both booleans + return (!b1 == !b2); +} + +NSNumber *GTL_EnsureNSNumber(NSNumber *num) { + // If the server returned a string object where we expect a number, try + // to make a number object. + if ([num isKindOfClass:[NSString class]]) { + NSNumber *newNum; + NSString *str = (NSString *)num; + if ([str rangeOfString:@"."].location != NSNotFound) { + // This is a floating-point number. + // Force the parser to use '.' as the decimal separator. + static NSLocale *usLocale = nil; + @synchronized([GTLUtilities class]) { + if (usLocale == nil) { + usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + } + newNum = [NSDecimalNumber decimalNumberWithString:(NSString*)num + locale:(id)usLocale]; + } + } else { + // NSDecimalNumber +decimalNumberWithString:locale: + // does not correctly create an NSNumber for large values like + // 71100000000007780. + if ([str hasPrefix:@"-"]) { + newNum = [NSNumber numberWithLongLong:[str longLongValue]]; + } else { + const char *utf8 = [str UTF8String]; + unsigned long long ull = strtoull(utf8, NULL, 10); + newNum = [NSNumber numberWithUnsignedLongLong:ull]; + } + } + if (newNum) { + num = newNum; + } + } + return num; +} diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBase64.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBase64.h new file mode 120000 index 0000000..aa0c368 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBase64.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Utilities/GTLBase64.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBatchQuery.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBatchQuery.h new file mode 120000 index 0000000..0123a0a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBatchQuery.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLBatchQuery.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBatchResult.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBatchResult.h new file mode 120000 index 0000000..8e741a5 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLBatchResult.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLBatchResult.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDateTime.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDateTime.h new file mode 120000 index 0000000..e68220f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDateTime.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLDateTime.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDefines.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDefines.h new file mode 120000 index 0000000..b84ca45 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDefines.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/GTLDefines.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrive.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrive.h new file mode 120000 index 0000000..be4c9cc --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrive.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDrive.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveAbout.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveAbout.h new file mode 120000 index 0000000..b75b460 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveAbout.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveAbout.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveApp.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveApp.h new file mode 120000 index 0000000..dd87d29 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveApp.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveApp.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveAppList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveAppList.h new file mode 120000 index 0000000..a38936a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveAppList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveAppList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChange.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChange.h new file mode 120000 index 0000000..049d992 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChange.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveChange.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChangeList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChangeList.h new file mode 120000 index 0000000..4d18f3a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChangeList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveChangeList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChannel.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChannel.h new file mode 120000 index 0000000..f1f7f08 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChannel.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveChannel.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChildList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChildList.h new file mode 120000 index 0000000..2f7c585 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChildList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChildReference.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChildReference.h new file mode 120000 index 0000000..b8af77d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveChildReference.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveChildReference.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveComment.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveComment.h new file mode 120000 index 0000000..8848883 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveComment.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveComment.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentList.h new file mode 120000 index 0000000..fc49553 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentReply.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentReply.h new file mode 120000 index 0000000..4538114 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentReply.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReply.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentReplyList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentReplyList.h new file mode 120000 index 0000000..8ea429e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveCommentReplyList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveCommentReplyList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveConstants.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveConstants.h new file mode 120000 index 0000000..2d0da92 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveConstants.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveConstants.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveFile.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveFile.h new file mode 120000 index 0000000..0773065 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveFile.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveFile.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveFileList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveFileList.h new file mode 120000 index 0000000..8019104 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveFileList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveFileList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveParentList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveParentList.h new file mode 120000 index 0000000..41842a5 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveParentList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveParentReference.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveParentReference.h new file mode 120000 index 0000000..41b7b56 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveParentReference.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveParentReference.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermission.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermission.h new file mode 120000 index 0000000..b1656f5 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermission.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermission.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermissionId.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermissionId.h new file mode 120000 index 0000000..76d1ef4 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermissionId.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionId.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermissionList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermissionList.h new file mode 120000 index 0000000..992194e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePermissionList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDrivePermissionList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveProperty.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveProperty.h new file mode 120000 index 0000000..fb880b7 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveProperty.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveProperty.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePropertyList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePropertyList.h new file mode 120000 index 0000000..d6be200 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDrivePropertyList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDrivePropertyList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveRevision.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveRevision.h new file mode 120000 index 0000000..a8fc279 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveRevision.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevision.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveRevisionList.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveRevisionList.h new file mode 120000 index 0000000..ce3474a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveRevisionList.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveRevisionList.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveUser.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveUser.h new file mode 120000 index 0000000..78ffc22 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLDriveUser.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLDriveUser.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLErrorObject.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLErrorObject.h new file mode 120000 index 0000000..e5b909b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLErrorObject.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLErrorObject.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLFramework.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLFramework.h new file mode 120000 index 0000000..425bd0d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLFramework.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Utilities/GTLFramework.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLJSONParser.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLJSONParser.h new file mode 120000 index 0000000..ec217ff --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLJSONParser.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Utilities/GTLJSONParser.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLObject.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLObject.h new file mode 120000 index 0000000..44512ab --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLObject.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLObject.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLQuery.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLQuery.h new file mode 120000 index 0000000..81a394e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLQuery.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLQuery.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLQueryDrive.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLQueryDrive.h new file mode 120000 index 0000000..f85d3ef --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLQueryDrive.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLQueryDrive.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLRuntimeCommon.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLRuntimeCommon.h new file mode 120000 index 0000000..d7f752d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLRuntimeCommon.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLRuntimeCommon.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLService.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLService.h new file mode 120000 index 0000000..050a89f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLService.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLService.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLServiceDrive.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLServiceDrive.h new file mode 120000 index 0000000..de3959c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLServiceDrive.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Services/Drive/Generated/GTLServiceDrive.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLTargetNamespace.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLTargetNamespace.h new file mode 120000 index 0000000..f58beea --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLTargetNamespace.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Utilities/GTLTargetNamespace.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLUploadParameters.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLUploadParameters.h new file mode 120000 index 0000000..de34fd6 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLUploadParameters.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Objects/GTLUploadParameters.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLUtilities.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLUtilities.h new file mode 120000 index 0000000..23a7614 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/Google-API-Client/GTLUtilities.h @@ -0,0 +1 @@ +../../../Google-API-Client/Source/Utilities/GTLUtilities.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMGatherInputStream.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMGatherInputStream.h new file mode 120000 index 0000000..1f7adcd --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMGatherInputStream.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMGatherInputStream.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetchHistory.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetchHistory.h new file mode 120000 index 0000000..172b468 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetchHistory.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMHTTPFetchHistory.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcher.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcher.h new file mode 120000 index 0000000..8c84e35 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcher.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMHTTPFetcher.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherLogViewController.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherLogViewController.h new file mode 120000 index 0000000..1e4b31e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherLogViewController.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMHTTPFetcherLogViewController.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherLogging.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherLogging.h new file mode 120000 index 0000000..023fee8 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherLogging.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMHTTPFetcherLogging.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherService.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherService.h new file mode 120000 index 0000000..2615384 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPFetcherService.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMHTTPFetcherService.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPUploadFetcher.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPUploadFetcher.h new file mode 120000 index 0000000..abf05fa --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMHTTPUploadFetcher.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMHTTPUploadFetcher.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMMIMEDocument.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMMIMEDocument.h new file mode 120000 index 0000000..2d430cd --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMMIMEDocument.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMMIMEDocument.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMReadMonitorInputStream.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMReadMonitorInputStream.h new file mode 120000 index 0000000..ebac3a6 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-http-fetcher/GTMReadMonitorInputStream.h @@ -0,0 +1 @@ +../../../gtm-http-fetcher/Source/GTMReadMonitorInputStream.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2Authentication.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2Authentication.h new file mode 120000 index 0000000..867af0f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2Authentication.h @@ -0,0 +1 @@ +../../../gtm-oauth2/Source/GTMOAuth2Authentication.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2SignIn.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2SignIn.h new file mode 120000 index 0000000..9c6dce8 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2SignIn.h @@ -0,0 +1 @@ +../../../gtm-oauth2/Source/GTMOAuth2SignIn.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2ViewControllerTouch.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2ViewControllerTouch.h new file mode 120000 index 0000000..460d972 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Headers/Public/gtm-oauth2/GTMOAuth2ViewControllerTouch.h @@ -0,0 +1 @@ +../../../gtm-oauth2/Source/Touch/GTMOAuth2ViewControllerTouch.h \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Manifest.lock b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Manifest.lock new file mode 100755 index 0000000..d8bdd94 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Manifest.lock @@ -0,0 +1,21 @@ +PODS: + - Google-API-Client/Common (1.0.422): + - gtm-http-fetcher (~> 1.0.141) + - gtm-oauth2 (~> 1.0.125) + - Google-API-Client/Drive (1.0.422): + - Google-API-Client/Common + - gtm-http-fetcher (~> 1.0.141) + - gtm-oauth2 (~> 1.0.125) + - gtm-http-fetcher (1.0.141) + - gtm-oauth2 (1.0.126): + - gtm-http-fetcher (~> 1.0.141) + +DEPENDENCIES: + - Google-API-Client/Drive (~> 1.0) + +SPEC CHECKSUMS: + Google-API-Client: 94e15390b2f5507e81a9a8c0edd58a02d2ab464b + gtm-http-fetcher: 6d4617e7d343b6e4c082b777541c334eb6f5d81e + gtm-oauth2: 60651b37376fa8fa5d1b92c9a631bd36ba093fd3 + +COCOAPODS: 0.35.0 diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Pods.xcodeproj/project.pbxproj b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Pods.xcodeproj/project.pbxproj new file mode 100755 index 0000000..c8e34cf --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,4578 @@ + + + + + archiveVersion + 1 + classes + + objectVersion + 46 + objects + + 00DF624361E82AB3A76D8151 + + fileRef + 3C4AAC1C66BCBD3A7ECE47C3 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 014C40719B958268E8C9CC6A + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveProperty.m + path + Source/Services/Drive/Generated/GTLDriveProperty.m + sourceTree + <group> + + 03E8499C67AFB451D8553C37 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveChildList.h + path + Source/Services/Drive/Generated/GTLDriveChildList.h + sourceTree + <group> + + 044E0069CBF77966D3B923EF + + fileRef + 29962679DC176F19469B9CF9 + isa + PBXBuildFile + + 04BB767B56A0B4177A345946 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + Pods-gtm-oauth2-prefix.pch + sourceTree + <group> + + 055131DB2F8B9353CBEB1630 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods-gtm-oauth2-Private.xcconfig + sourceTree + <group> + + 05EFBA718EC011E3A69D9B96 + + children + + 8D58CF01087F4EB7E2914F66 + E1551A38A5BED43BD5B89B74 + FEF578F969D055A88889DC8F + 3BAD3B3199895D09A06C6F91 + 7F6664AC146B057BB679BD02 + E1612C74185CAAAEB6DFBC71 + 41411994CB0A44CE885FB50E + 84D92F036455F259CA4FCFA0 + + isa + PBXGroup + name + gtm-oauth2 + path + gtm-oauth2 + sourceTree + <group> + + 074CB1E0069F2CCE9A2D0ECD + + fileRef + FB9D94EF5248754F25A45269 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 0785415E7DD2A39727C20AFB + + fileRef + FEF578F969D055A88889DC8F + isa + PBXBuildFile + + 07946DA53AAC9A1762F0A832 + + fileRef + 70A94B55280C47F0EB0BB722 + isa + PBXBuildFile + + 07A519422911046E98F01593 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLJSONParser.h + path + Source/Utilities/GTLJSONParser.h + sourceTree + <group> + + 08989B50638BFB83DE8BCE23 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMHTTPFetcherLogging.m + path + Source/GTMHTTPFetcherLogging.m + sourceTree + <group> + + 08F6ABDC218F31086ED0A4E6 + + fileRef + BBA41A9760B2E1F92922CB28 + isa + PBXBuildFile + + 095BDD86B342747142E1FD51 + + fileRef + 781E5826C2799D2409AB134F + isa + PBXBuildFile + + 0A13DAC37BB990D3ABD0A288 + + fileRef + 7FC3133D861CC24F6DA18214 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 0AB55F7F90C329519FE7F44E + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods.release.xcconfig + sourceTree + <group> + + 0B664C08EFEB80FC55E554DE + + fileRef + 8A8E9622D087343D3CE0306A + isa + PBXBuildFile + + 0C5CCE940F3DF18307C0621B + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLObject.m + path + Source/Objects/GTLObject.m + sourceTree + <group> + + 0E1A2DC8CF5133FF6DD5F089 + + fileRef + 4131CC211ADCE7F537D60B77 + isa + PBXBuildFile + + 0E3B3B2F52EC1F83601FD0A6 + + fileRef + 6353EE08DCACD566DA2E0788 + isa + PBXBuildFile + + 0E89AC2784062681E66C4195 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveProperty.h + path + Source/Services/Drive/Generated/GTLDriveProperty.h + sourceTree + <group> + + 0EB676B3DDD843C27D9EC409 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDefines.h + path + Source/GTLDefines.h + sourceTree + <group> + + 10B35DEDE6A1C206E1620AC3 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveAppList.h + path + Source/Services/Drive/Generated/GTLDriveAppList.h + sourceTree + <group> + + 10D42D84A4D868A94674CC51 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods.debug.xcconfig + sourceTree + <group> + + 10FCAF49CF667F665EF8AF48 + + buildActionMask + 2147483647 + files + + 044E0069CBF77966D3B923EF + 20E5CA51B66F50204406CA7D + 07946DA53AAC9A1762F0A832 + 9F4EF8B51AC61EDF7D10632C + 9E8AFD1B93AB1C765A03B47D + 0B664C08EFEB80FC55E554DE + 08F6ABDC218F31086ED0A4E6 + 14DB5E6823A5950C7DECD78B + B5209E5568BE6B55BA5F66E7 + + isa + PBXHeadersBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 11A589EDE19AF418BD4BCFAE + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDrivePermissionList.h + path + Source/Services/Drive/Generated/GTLDrivePermissionList.h + sourceTree + <group> + + 1213708E485E4DDD5B619CA5 + + children + + 1351EDF2CE25884344936483 + 457355172648E5554031F31E + 59333724CED46BEA8A81805F + A71A00303E92E1DEC27F9091 + E636E4C345FFD2A7782B5275 + 10D42D84A4D868A94674CC51 + 0AB55F7F90C329519FE7F44E + + isa + PBXGroup + name + Pods + path + Target Support Files/Pods + sourceTree + <group> + + 1284BDECDFC0D7C41B0D4739 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveConstants.h + path + Source/Services/Drive/Generated/GTLDriveConstants.h + sourceTree + <group> + + 1351EDF2CE25884344936483 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text + path + Pods-acknowledgements.markdown + sourceTree + <group> + + 1449DE99AF5D2C313B14CCA9 + + fileRef + 44183B8EAD00AE7C82394ECB + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 14DB5E6823A5950C7DECD78B + + fileRef + ED783139D6FB2B5DCA03B872 + isa + PBXBuildFile + + 15020587BAB1B332F42D7503 + + buildConfigurations + + 4437150C7884806F09497FD5 + DD6D27D0E4698D7A1E13460B + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + 150FF5698D38AFDE528BFB03 + + fileRef + F73316961E013D5A9CBB5AEE + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 16543F7AC304D070621BF1DE + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods-Google-API-Client-Private.xcconfig + sourceTree + <group> + + 165BF6488CB3D2DFBEB300A3 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveFileList.h + path + Source/Services/Drive/Generated/GTLDriveFileList.h + sourceTree + <group> + + 16BB7C693BCB983961820507 + + fileRef + E1551A38A5BED43BD5B89B74 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 177F8A7FAE00DE93FD89237A + + fileRef + 38C58D9349529227967743D6 + isa + PBXBuildFile + + 1783A2B5E0DC44C6A4D0B76A + + fileRef + 03E8499C67AFB451D8553C37 + isa + PBXBuildFile + + 1B1F92DCC3D9477B9FA283C6 + + containerPortal + 69F5A1152BC2D0A8D62C83CF + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + D86F34FDA732FE2D376159FA + remoteInfo + Pods-gtm-http-fetcher + + 1B8D72FA2287FB1825008643 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLFramework.h + path + Source/Utilities/GTLFramework.h + sourceTree + <group> + + 1B8F47E6D7E8F330AE0DF8A2 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveChannel.m + path + Source/Services/Drive/Generated/GTLDriveChannel.m + sourceTree + <group> + + 1B91617FB5A041BA4753BBF4 + + fileRef + 44F59DD503176281165B97D7 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 1D15E8028576F08F1BE84101 + + fileRef + CB7331611930E34323709C2F + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 1E2BCA5EA4D7F1951B8F4FAF + + fileRef + 7EEDA886BAC2DC50006FBE5D + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 1F2697AF69C81C4358D90876 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveChildReference.m + path + Source/Services/Drive/Generated/GTLDriveChildReference.m + sourceTree + <group> + + 204402C110C36194F0C5BFE9 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMHTTPFetcherLogViewController.h + path + Source/GTMHTTPFetcherLogViewController.h + sourceTree + <group> + + 20B286BA202182EA197508B7 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveRevisionList.m + path + Source/Services/Drive/Generated/GTLDriveRevisionList.m + sourceTree + <group> + + 20E5CA51B66F50204406CA7D + + fileRef + D55D394D7A2F801C936C1EB2 + isa + PBXBuildFile + + 2295289C54CB40BC89BB15DD + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveChannel.h + path + Source/Services/Drive/Generated/GTLDriveChannel.h + sourceTree + <group> + + 2297FB94509CCE69C12B677E + + baseConfigurationReference + 16543F7AC304D070621BF1DE + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + YES + DSTROOT + /tmp/xcodeproj.dst + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-prefix.pch + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_CFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_CPLUSPLUSFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + VALIDATE_PRODUCT + YES + + isa + XCBuildConfiguration + name + Release + + 23A31A288D5BD29BA6EC4585 + + fileRef + F00EF8294F0E25A9116B874F + isa + PBXBuildFile + + 243AF22950254C1BAAAA2628 + + fileRef + 1284BDECDFC0D7C41B0D4739 + isa + PBXBuildFile + + 24BB3C1FE76098CD9B74404D + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + Security.framework + path + Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/Security.framework + sourceTree + DEVELOPER_DIR + + 288DF28E51C3A244CF5310CF + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDrive.h + path + Source/Services/Drive/Generated/GTLDrive.h + sourceTree + <group> + + 29962679DC176F19469B9CF9 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMGatherInputStream.h + path + Source/GTMGatherInputStream.h + sourceTree + <group> + + 29A939D6F0A258A65314DE24 + + explicitFileType + archive.ar + includeInIndex + 0 + isa + PBXFileReference + path + libPods-gtm-oauth2.a + sourceTree + BUILT_PRODUCTS_DIR + + 2A6F6D2CAA4739FC6292429F + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDrivePermission.m + path + Source/Services/Drive/Generated/GTLDrivePermission.m + sourceTree + <group> + + 2C372A2BBF81DF8EA735AF65 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + file.xib + name + GTMOAuth2ViewTouch.xib + path + Source/Touch/GTMOAuth2ViewTouch.xib + sourceTree + <group> + + 2F4A85D5EE487FD592B6C374 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveCommentList.h + path + Source/Services/Drive/Generated/GTLDriveCommentList.h + sourceTree + <group> + + 2FA0F376D8A29FF1F2EF0F0F + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + UIKit.framework + path + Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/UIKit.framework + sourceTree + DEVELOPER_DIR + + 3049D4328F3DF05125B811AD + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveFile.m + path + Source/Services/Drive/Generated/GTLDriveFile.m + sourceTree + <group> + + 308D84327136BAB820823D02 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLUploadParameters.h + path + Source/Objects/GTLUploadParameters.h + sourceTree + <group> + + 31A24E345DA43AD6B12CA97A + + buildActionMask + 2147483647 + files + + A635890121A5E93CF19B2217 + 51349BDAB0CCF6B19F12E856 + 5CE910DEC5733D2B7F10EA1F + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 33273ADC926C6411DA4E3A19 + + children + + FD64C8E7BD98E2E64DCE1405 + 3D4E7C4E87FA48DE20B8CABB + 4131CC211ADCE7F537D60B77 + 624F308B8BD0D8E91370F016 + + isa + PBXGroup + name + Support Files + path + ../Target Support Files/Pods-gtm-http-fetcher + sourceTree + <group> + + 34856CBC5B135FD2F8F4DAC5 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveChange.h + path + Source/Services/Drive/Generated/GTLDriveChange.h + sourceTree + <group> + + 3614F0AFCA6B3D8E00818E88 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveAbout.m + path + Source/Services/Drive/Generated/GTLDriveAbout.m + sourceTree + <group> + + 38A0640E2342435BB5ECF035 + + fileRef + B90613105B7B81CDBCB607E8 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 38C58D9349529227967743D6 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDrivePermissionId.h + path + Source/Services/Drive/Generated/GTLDrivePermissionId.h + sourceTree + <group> + + 3956DD03A66BB4081BE86B6E + + fileRef + 3BAD3B3199895D09A06C6F91 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 395776CDFF6F07633C2E7979 + + fileRef + 2A6F6D2CAA4739FC6292429F + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 3B1DAD98FEBD57166795F770 + + fileRef + F41E360666FB045C62B806AC + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 3BAD3B3199895D09A06C6F91 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMOAuth2SignIn.m + path + Source/GTMOAuth2SignIn.m + sourceTree + <group> + + 3BDD54B9BC9ED35B680E5E8E + + fileRef + D4856A2A9B29FE9F37E3E4F3 + isa + PBXBuildFile + + 3BEBA6961BB2D04C334EDEE6 + + buildConfigurationList + 15020587BAB1B332F42D7503 + buildPhases + + DF0243F8EDC5CF63EE388B3B + 31A24E345DA43AD6B12CA97A + CF73775F029486F44090CB0A + + buildRules + + dependencies + + 62B39A94038E7C7A5D196D7B + + isa + PBXNativeTarget + name + Pods-gtm-oauth2 + productName + Pods-gtm-oauth2 + productReference + 29A939D6F0A258A65314DE24 + productType + com.apple.product-type.library.static + + 3C4AAC1C66BCBD3A7ECE47C3 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveCommentList.m + path + Source/Services/Drive/Generated/GTLDriveCommentList.m + sourceTree + <group> + + 3D064287543D1194C7B7D428 + + fileRef + F2E81095DFC87262E092E5F8 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 3D1280177A8CD98931B232A0 + + isa + PBXTargetDependency + name + Pods-gtm-oauth2 + target + 3BEBA6961BB2D04C334EDEE6 + targetProxy + D116C7044C76C6FCC6D595BC + + 3D4E7C4E87FA48DE20B8CABB + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods-gtm-http-fetcher-Private.xcconfig + sourceTree + <group> + + 3DA39D02457D80989262E62E + + buildActionMask + 2147483647 + files + + 9B17DBE2B307B123FF1D3546 + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 3E2EA59A13338C676C34BDD0 + + fileRef + E0EFDFF8AEBC4539B22AF2B0 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 409F24F08FE354BF89B76FDA + + baseConfigurationReference + 3D4E7C4E87FA48DE20B8CABB + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + NO + DSTROOT + /tmp/xcodeproj.dst + GCC_DYNAMIC_NO_PIC + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-prefix.pch + GCC_PREPROCESSOR_DEFINITIONS + + DEBUG=1 + $(inherited) + + GCC_SYMBOLS_PRIVATE_EXTERN + NO + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + + isa + XCBuildConfiguration + name + Debug + + 410ADF54900D18731106E14F + + fileRef + 5513F5993143CC993DB5AA77 + isa + PBXBuildFile + + 4131CC211ADCE7F537D60B77 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + Pods-gtm-http-fetcher-dummy.m + sourceTree + <group> + + 41411994CB0A44CE885FB50E + + children + + 2C372A2BBF81DF8EA735AF65 + + isa + PBXGroup + name + Resources + sourceTree + <group> + + 4243BE6C5541AF7981A75CE1 + + fileRef + C3DC945EC39932528A867F51 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 4383A2D59079CC83BD8907E9 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLQueryDrive.h + path + Source/Services/Drive/Generated/GTLQueryDrive.h + sourceTree + <group> + + 44183B8EAD00AE7C82394ECB + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveCommentReply.m + path + Source/Services/Drive/Generated/GTLDriveCommentReply.m + sourceTree + <group> + + 4437150C7884806F09497FD5 + + baseConfigurationReference + 055131DB2F8B9353CBEB1630 + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + NO + DSTROOT + /tmp/xcodeproj.dst + GCC_DYNAMIC_NO_PIC + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-prefix.pch + GCC_PREPROCESSOR_DEFINITIONS + + DEBUG=1 + $(inherited) + + GCC_SYMBOLS_PRIVATE_EXTERN + NO + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + + isa + XCBuildConfiguration + name + Debug + + 44F59DD503176281165B97D7 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMHTTPFetcherService.m + path + Source/GTMHTTPFetcherService.m + sourceTree + <group> + + 457355172648E5554031F31E + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.plist.xml + path + Pods-acknowledgements.plist + sourceTree + <group> + + 459C7B03A59C67253EA2D81D + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLUtilities.m + path + Source/Utilities/GTLUtilities.m + sourceTree + <group> + + 4848B159F64A39D9F50D8CFF + + buildActionMask + 2147483647 + files + + 7E6E441A2D41F387B9B059E7 + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 4BFA5B38158ACEEFE9FCB935 + + fileRef + 749FD7B69998A7F3EA6B7254 + isa + PBXBuildFile + + 4C38697F4C2EC71AF708E8F7 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLBatchResult.h + path + Source/Objects/GTLBatchResult.h + sourceTree + <group> + + 4D18DEEDB5318B07F1196794 + + fileRef + F9F67BFF4082560243606B31 + isa + PBXBuildFile + + 4D1E10E91930FDEC8545219F + + children + + 662C62A3FA7F133A74D24B9C + 65E3832CB796B0F9B8A8B250 + 5513F5993143CC993DB5AA77 + BE66489E7194AB23C1DB916B + 4C38697F4C2EC71AF708E8F7 + B3BDFDD9AD46D74E0A46E708 + 995957ABD7231EDD072ADD59 + DD07BE9506DB9EE185AAFECD + 0EB676B3DDD843C27D9EC409 + 5494424660F3333C46B7D2D4 + D7614DE3AF2ECABF84DEEF4F + 1B8D72FA2287FB1825008643 + C001C6DEC321279DCE5E7EBB + 07A519422911046E98F01593 + 7EEDA886BAC2DC50006FBE5D + 8C0B530302835BD114BE03EB + 0C5CCE940F3DF18307C0621B + 781E5826C2799D2409AB134F + FF33B6F9780C733B7F91C760 + F9F67BFF4082560243606B31 + CE1757246566510818FD161E + CA4FC6C8A66851CC6C3E8171 + C0CB8C2587E399A7717BDF25 + DF180F8D611667C30C568493 + 308D84327136BAB820823D02 + 5CE1491F4045A6F1C0520BF2 + A8F0C8538E1971CF36BCAB6C + 459C7B03A59C67253EA2D81D + + isa + PBXGroup + name + Common + sourceTree + <group> + + 4D42829D01D2E4D7DA755330 + + fileRef + B3BDFDD9AD46D74E0A46E708 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 4D514D2233430A94AAA58A43 + + fileRef + D3C61BFB6592AE150E7C8D48 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 50B6902EB8FAF094A6ED99D7 + + fileRef + 0EB676B3DDD843C27D9EC409 + isa + PBXBuildFile + + 51349BDAB0CCF6B19F12E856 + + fileRef + 24BB3C1FE76098CD9B74404D + isa + PBXBuildFile + + 5184F7693DDCDD6618E9538E + + isa + PBXTargetDependency + name + Pods-Google-API-Client + target + B31A978BEFBC46D180B885C0 + targetProxy + AF31E816054D83719E180C51 + + 51891E116BB27015724F9FE3 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMHTTPUploadFetcher.m + path + Source/GTMHTTPUploadFetcher.m + sourceTree + <group> + + 52AB1EBC58A4FE681BCAA53D + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveAbout.h + path + Source/Services/Drive/Generated/GTLDriveAbout.h + sourceTree + <group> + + 53786FB7150AD3D8ADA2A247 + + fileRef + 84AD87C60F4DFB3666BA4527 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 5494424660F3333C46B7D2D4 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLErrorObject.h + path + Source/Objects/GTLErrorObject.h + sourceTree + <group> + + 5513F5993143CC993DB5AA77 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLBatchQuery.h + path + Source/Objects/GTLBatchQuery.h + sourceTree + <group> + + 56A6E3713CCCC0F5597755C6 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveCommentReplyList.m + path + Source/Services/Drive/Generated/GTLDriveCommentReplyList.m + sourceTree + <group> + + 580DEC254A90D2F752A954FA + + fileRef + 2FA0F376D8A29FF1F2EF0F0F + isa + PBXBuildFile + + 59333724CED46BEA8A81805F + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + Pods-dummy.m + sourceTree + <group> + + 598CB8AE9DE3B4B86D8DFC3C + + fileRef + 014C40719B958268E8C9CC6A + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 59BABEAC33285F8EF28960F9 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMHTTPFetcher.m + path + Source/GTMHTTPFetcher.m + sourceTree + <group> + + 5ACDEA45FE92C379DC6064ED + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveAppList.m + path + Source/Services/Drive/Generated/GTLDriveAppList.m + sourceTree + <group> + + 5AD1D445614D3E7209AB6970 + + fileRef + E1C96240D32F0F991DAC7D72 + isa + PBXBuildFile + + 5B47B2E475B0593845980297 + + buildActionMask + 2147483647 + files + + C3E1561785167FE2A8A86216 + 580DEC254A90D2F752A954FA + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 5B7E5328ECA708D316791AD5 + + containerPortal + 69F5A1152BC2D0A8D62C83CF + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + 3BEBA6961BB2D04C334EDEE6 + remoteInfo + Pods-gtm-oauth2 + + 5BBD7D96B17766394C40E894 + + fileRef + C233B5ACEFCDE1ECB6479590 + isa + PBXBuildFile + + 5CE1491F4045A6F1C0520BF2 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLUploadParameters.m + path + Source/Objects/GTLUploadParameters.m + sourceTree + <group> + + 5CE910DEC5733D2B7F10EA1F + + fileRef + 773BF4EABF5B2AAF0BC79E40 + isa + PBXBuildFile + + 5DAB834EC7647CB0EFF6151C + + children + + B5CC86FFB137EB5ACB41C4B8 + B3EEF1B83BBB9EE9AAF22CF2 + 779804940A84DF8926ACF5B5 + C85E7E5A1D590769D439F299 + A59A5A089E0FC47F82D69BF3 + + isa + PBXGroup + sourceTree + <group> + + 5EAC417C5E6D73A7A9D4D01D + + fileRef + FDA4FC120EA341D2BCA83936 + isa + PBXBuildFile + + 612D64B2188810D7EC3E8351 + + fileRef + 3614F0AFCA6B3D8E00818E88 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 61DE6F6823A0FFB2B047A878 + + fileRef + BE66489E7194AB23C1DB916B + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 62453F52B2B3EDF6475155EB + + fileRef + FF33B6F9780C733B7F91C760 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 624F308B8BD0D8E91370F016 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + Pods-gtm-http-fetcher-prefix.pch + sourceTree + <group> + + 62B39A94038E7C7A5D196D7B + + isa + PBXTargetDependency + name + Pods-gtm-http-fetcher + target + D86F34FDA732FE2D376159FA + targetProxy + 77C38DBC6B9922DA56C6916F + + 6353EE08DCACD566DA2E0788 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + Pods-Google-API-Client-dummy.m + sourceTree + <group> + + 643317E3A992B91AAD0E3115 + + fileRef + F440729C22759252486D7975 + isa + PBXBuildFile + + 65E3832CB796B0F9B8A8B250 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLBase64.m + path + Source/Utilities/GTLBase64.m + sourceTree + <group> + + 662C62A3FA7F133A74D24B9C + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLBase64.h + path + Source/Utilities/GTLBase64.h + sourceTree + <group> + + 66EA661D472BAB1B72036219 + + fileRef + 11A589EDE19AF418BD4BCFAE + isa + PBXBuildFile + + 67A934691C27CE181AF74158 + + fileRef + 8D58CF01087F4EB7E2914F66 + isa + PBXBuildFile + + 67EE726A874DB868FF2D20A8 + + fileRef + E1612C74185CAAAEB6DFBC71 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 68254BCB4312805D575DDDA3 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMHTTPFetchHistory.m + path + Source/GTMHTTPFetchHistory.m + sourceTree + <group> + + 68336E20B92E7F05659EA895 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveChangeList.h + path + Source/Services/Drive/Generated/GTLDriveChangeList.h + sourceTree + <group> + + 69C44D2DF7BD4EF2144EA3D1 + + fileRef + 93746BF7D4C282E03D437321 + isa + PBXBuildFile + + 69F5A1152BC2D0A8D62C83CF + + attributes + + LastUpgradeCheck + 0510 + + buildConfigurationList + C970ABE9988D06FD5C7C262D + compatibilityVersion + Xcode 3.2 + developmentRegion + English + hasScannedForEncodings + 0 + isa + PBXProject + knownRegions + + en + + mainGroup + 5DAB834EC7647CB0EFF6151C + productRefGroup + C85E7E5A1D590769D439F299 + projectDirPath + + projectReferences + + projectRoot + + targets + + 6AF7E9A5AE3CBEE5AE4C2844 + B31A978BEFBC46D180B885C0 + D86F34FDA732FE2D376159FA + 3BEBA6961BB2D04C334EDEE6 + + + 6AF7E9A5AE3CBEE5AE4C2844 + + buildConfigurationList + 9810C629EE98C85FA8B6BCE2 + buildPhases + + 4848B159F64A39D9F50D8CFF + 3DA39D02457D80989262E62E + + buildRules + + dependencies + + 5184F7693DDCDD6618E9538E + 7C2EBE95DF688A5FC30A47FB + 87D9E1F90F26E4D45EC6B5E2 + + isa + PBXNativeTarget + name + Pods + productName + Pods + productReference + F7B94161AFDC1DF5FBADACDD + productType + com.apple.product-type.library.static + + 6D7C5423C133717783489190 + + fileRef + FCB308CE73A15075E7DE8751 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 703F21EF1B2CD011162A136E + + buildActionMask + 2147483647 + files + + DC457F971743611484650EC5 + 61DE6F6823A0FFB2B047A878 + 4D42829D01D2E4D7DA755330 + B471863524822D13DF05AEF8 + 612D64B2188810D7EC3E8351 + DA29918FF7BB8F5050B0C729 + BF7820D32D70C05A7BDE3E2A + FC5281ABA6C81AB9E980125F + B3888D210AA8016C0E06538C + 8BAFD3AD10A15C61D8602C9C + 3B1DAD98FEBD57166795F770 + EFC83A41398305ADBB80AC8A + 4243BE6C5541AF7981A75CE1 + 00DF624361E82AB3A76D8151 + 1449DE99AF5D2C313B14CCA9 + D4980BC40E1052DFCC188C81 + 6D7C5423C133717783489190 + DEA6BBE54C1516AD46FA96DE + A15ABB81E7BD34AFB140A716 + 074CB1E0069F2CCE9A2D0ECD + 0A13DAC37BB990D3ABD0A288 + 395776CDFF6F07633C2E7979 + C22699B6399794582E9E42AD + FFEC08358BBF198A740FAC85 + 598CB8AE9DE3B4B86D8DFC3C + 3E2EA59A13338C676C34BDD0 + 83ADF4701723C2688D413104 + 7AED16C6BA8B922F76053C18 + 1D15E8028576F08F1BE84101 + FCDE5D0BC42131531DB198E3 + E0117D16F81E149991E6CE1E + 1E2BCA5EA4D7F1951B8F4FAF + 751EFDCE4AD2B91CF95522A8 + 62453F52B2B3EDF6475155EB + 150FF5698D38AFDE528BFB03 + 912AEDBFD3A9ECE8A6F151F2 + EFF0FF3D4FBAFA07EB1F8FB7 + 53786FB7150AD3D8ADA2A247 + AF352CB592C3F49450D34DA1 + F65850DE68118953B1578F91 + 0E3B3B2F52EC1F83601FD0A6 + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 70A94B55280C47F0EB0BB722 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMHTTPFetcher.h + path + Source/GTMHTTPFetcher.h + sourceTree + <group> + + 71FBC2E910A20A392835B5B1 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDrivePermissionId.m + path + Source/Services/Drive/Generated/GTLDrivePermissionId.m + sourceTree + <group> + + 749FD7B69998A7F3EA6B7254 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveRevisionList.h + path + Source/Services/Drive/Generated/GTLDriveRevisionList.h + sourceTree + <group> + + 74A2110920EC8CF0AC2804E0 + + fileRef + CA4FC6C8A66851CC6C3E8171 + isa + PBXBuildFile + + 751EFDCE4AD2B91CF95522A8 + + fileRef + 0C5CCE940F3DF18307C0621B + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 773BF4EABF5B2AAF0BC79E40 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + SystemConfiguration.framework + path + Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/SystemConfiguration.framework + sourceTree + DEVELOPER_DIR + + 777E98A5BFB951891A3E6137 + + fileRef + C8BBA82F4963899A0FC9F065 + isa + PBXBuildFile + + 779804940A84DF8926ACF5B5 + + children + + A8D177CA4365278DC1691CDA + 7D48ABE7B929B0F0F4E953B8 + 05EFBA718EC011E3A69D9B96 + + isa + PBXGroup + name + Pods + sourceTree + <group> + + 77C38DBC6B9922DA56C6916F + + containerPortal + 69F5A1152BC2D0A8D62C83CF + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + D86F34FDA732FE2D376159FA + remoteInfo + Pods-gtm-http-fetcher + + 781E5826C2799D2409AB134F + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLQuery.h + path + Source/Objects/GTLQuery.h + sourceTree + <group> + + 78ACB0DF0FA52F05AF50C70F + + fileRef + 308D84327136BAB820823D02 + isa + PBXBuildFile + + 7AED16C6BA8B922F76053C18 + + fileRef + 20B286BA202182EA197508B7 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 7C2EBE95DF688A5FC30A47FB + + isa + PBXTargetDependency + name + Pods-gtm-http-fetcher + target + D86F34FDA732FE2D376159FA + targetProxy + A8083538F141A18F422BE7A0 + + 7CDFBB89E85A58C547D4978A + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDrivePropertyList.h + path + Source/Services/Drive/Generated/GTLDrivePropertyList.h + sourceTree + <group> + + 7D48ABE7B929B0F0F4E953B8 + + children + + 29962679DC176F19469B9CF9 + B90613105B7B81CDBCB607E8 + D55D394D7A2F801C936C1EB2 + 68254BCB4312805D575DDDA3 + 70A94B55280C47F0EB0BB722 + 59BABEAC33285F8EF28960F9 + 204402C110C36194F0C5BFE9 + F2E81095DFC87262E092E5F8 + E72708D844C731DEAB7C851C + 08989B50638BFB83DE8BCE23 + 8A8E9622D087343D3CE0306A + 44F59DD503176281165B97D7 + BBA41A9760B2E1F92922CB28 + 51891E116BB27015724F9FE3 + ED783139D6FB2B5DCA03B872 + D3C61BFB6592AE150E7C8D48 + A0FD87073D31D4A9CA5106E8 + DEB494912FD9267C6BC0AE62 + 33273ADC926C6411DA4E3A19 + + isa + PBXGroup + name + gtm-http-fetcher + path + gtm-http-fetcher + sourceTree + <group> + + 7E6E441A2D41F387B9B059E7 + + fileRef + 59333724CED46BEA8A81805F + isa + PBXBuildFile + + 7EEDA886BAC2DC50006FBE5D + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLJSONParser.m + path + Source/Utilities/GTLJSONParser.m + sourceTree + <group> + + 7F2DB1F48EFE738410AF1AFC + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveRevision.m + path + Source/Services/Drive/Generated/GTLDriveRevision.m + sourceTree + <group> + + 7F6664AC146B057BB679BD02 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMOAuth2ViewControllerTouch.h + path + Source/Touch/GTMOAuth2ViewControllerTouch.h + sourceTree + <group> + + 7FC3133D861CC24F6DA18214 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveParentReference.m + path + Source/Services/Drive/Generated/GTLDriveParentReference.m + sourceTree + <group> + + 7FDBB5B3BB5A2AD53E911ECF + + fileRef + B1714354A8A314969314FFCA + isa + PBXBuildFile + + 8114EB2A5D8F241BAD7AA476 + + fileRef + 7CDFBB89E85A58C547D4978A + isa + PBXBuildFile + + 83064B4F29F7FD5D3C4DC804 + + fileRef + 34856CBC5B135FD2F8F4DAC5 + isa + PBXBuildFile + + 83A8F088C964704466851C4F + + buildConfigurations + + 409F24F08FE354BF89B76FDA + B693A41E4D27042FC2EA51BB + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + 83ADF4701723C2688D413104 + + fileRef + 7F2DB1F48EFE738410AF1AFC + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 843A392158489311B2F2D75A + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveFileList.m + path + Source/Services/Drive/Generated/GTLDriveFileList.m + sourceTree + <group> + + 84AD87C60F4DFB3666BA4527 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLServiceDrive.m + path + Source/Services/Drive/Generated/GTLServiceDrive.m + sourceTree + <group> + + 84D92F036455F259CA4FCFA0 + + children + + 865207C7943AA448EA7E1023 + 055131DB2F8B9353CBEB1630 + C0E3D4284CC2C86883C32F32 + 04BB767B56A0B4177A345946 + + isa + PBXGroup + name + Support Files + path + ../Target Support Files/Pods-gtm-oauth2 + sourceTree + <group> + + 865207C7943AA448EA7E1023 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods-gtm-oauth2.xcconfig + sourceTree + <group> + + 8767D1B85636EEAAE5BEDECE + + fileRef + 0E89AC2784062681E66C4195 + isa + PBXBuildFile + + 87D9E1F90F26E4D45EC6B5E2 + + isa + PBXTargetDependency + name + Pods-gtm-oauth2 + target + 3BEBA6961BB2D04C334EDEE6 + targetProxy + 5B7E5328ECA708D316791AD5 + + 89FA0CCE470AFE1443FCEA8C + + fileRef + 52AB1EBC58A4FE681BCAA53D + isa + PBXBuildFile + + 8A8E9622D087343D3CE0306A + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMHTTPFetcherService.h + path + Source/GTMHTTPFetcherService.h + sourceTree + <group> + + 8BAFD3AD10A15C61D8602C9C + + fileRef + 1B8F47E6D7E8F330AE0DF8A2 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 8BC358B5D5C066BE1B18E79D + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveComment.h + path + Source/Services/Drive/Generated/GTLDriveComment.h + sourceTree + <group> + + 8BF9ED5B66BE3358A636E8B7 + + fileRef + 5494424660F3333C46B7D2D4 + isa + PBXBuildFile + + 8BFBAF271A63684EA714A2C0 + + fileRef + 4C38697F4C2EC71AF708E8F7 + isa + PBXBuildFile + + 8C0B530302835BD114BE03EB + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLObject.h + path + Source/Objects/GTLObject.h + sourceTree + <group> + + 8D58CF01087F4EB7E2914F66 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMOAuth2Authentication.h + path + Source/GTMOAuth2Authentication.h + sourceTree + <group> + + 8D610B71D1A7C7A3E9227B74 + + fileRef + 59BABEAC33285F8EF28960F9 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 912AEDBFD3A9ECE8A6F151F2 + + fileRef + CE1757246566510818FD161E + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 914A194D74DBA71D909DA4C5 + + fileRef + 08989B50638BFB83DE8BCE23 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 91837E982F3912DDE283358D + + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + CLANG_CXX_LANGUAGE_STANDARD + gnu++0x + CLANG_CXX_LIBRARY + libc++ + CLANG_ENABLE_MODULES + YES + CLANG_ENABLE_OBJC_ARC + YES + CLANG_WARN_BOOL_CONVERSION + YES + CLANG_WARN_CONSTANT_CONVERSION + YES + CLANG_WARN_DIRECT_OBJC_ISA_USAGE + YES + CLANG_WARN_EMPTY_BODY + YES + CLANG_WARN_ENUM_CONVERSION + YES + CLANG_WARN_INT_CONVERSION + YES + CLANG_WARN_OBJC_ROOT_CLASS + YES + COPY_PHASE_STRIP + NO + ENABLE_NS_ASSERTIONS + NO + GCC_C_LANGUAGE_STANDARD + gnu99 + GCC_PREPROCESSOR_DEFINITIONS + + RELEASE=1 + + GCC_WARN_64_TO_32_BIT_CONVERSION + YES + GCC_WARN_ABOUT_RETURN_TYPE + YES + GCC_WARN_UNDECLARED_SELECTOR + YES + GCC_WARN_UNINITIALIZED_AUTOS + YES + GCC_WARN_UNUSED_FUNCTION + YES + GCC_WARN_UNUSED_VARIABLE + YES + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + STRIP_INSTALLED_PRODUCT + NO + VALIDATE_PRODUCT + YES + + isa + XCBuildConfiguration + name + Release + + 92830449E40969227AC60F1D + + explicitFileType + archive.ar + includeInIndex + 0 + isa + PBXFileReference + path + libPods-gtm-http-fetcher.a + sourceTree + BUILT_PRODUCTS_DIR + + 92DA4AD8E8DFA22DE1F6D6F3 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods-Google-API-Client.xcconfig + sourceTree + <group> + + 93746BF7D4C282E03D437321 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveChildReference.h + path + Source/Services/Drive/Generated/GTLDriveChildReference.h + sourceTree + <group> + + 95B2CB70C43EF35562E169CD + + fileRef + 2295289C54CB40BC89BB15DD + isa + PBXBuildFile + + 96215DF99F80B11DAA7C266E + + fileRef + 07A519422911046E98F01593 + isa + PBXBuildFile + + 979CC85B91CAE464866E3DD1 + + fileRef + 68254BCB4312805D575DDDA3 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + 9810C629EE98C85FA8B6BCE2 + + buildConfigurations + + F3C4F9917A860C9166554B34 + F47E258E21EF049AFBAC4451 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + 981C41096FC5C7661091D929 + + fileRef + 10B35DEDE6A1C206E1620AC3 + isa + PBXBuildFile + + 98EB6F6A8B1A1A24A0515B88 + + fileRef + 995957ABD7231EDD072ADD59 + isa + PBXBuildFile + + 995957ABD7231EDD072ADD59 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDateTime.h + path + Source/Objects/GTLDateTime.h + sourceTree + <group> + + 99D5EBAC09D9B56E880A94C5 + + fileRef + 165BF6488CB3D2DFBEB300A3 + isa + PBXBuildFile + + 9B17DBE2B307B123FF1D3546 + + fileRef + B9C4F4D3C4C547301C375A6E + isa + PBXBuildFile + + 9C2CB0ACC1037A477930DFA9 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveChangeList.m + path + Source/Services/Drive/Generated/GTLDriveChangeList.m + sourceTree + <group> + + 9CA08D6704BCF0B8263F5002 + + explicitFileType + archive.ar + includeInIndex + 0 + isa + PBXFileReference + path + libPods-Google-API-Client.a + sourceTree + BUILT_PRODUCTS_DIR + + 9CBE29C112F25DE11AE3F6CC + + fileRef + 7F6664AC146B057BB679BD02 + isa + PBXBuildFile + + 9E8AFD1B93AB1C765A03B47D + + fileRef + E72708D844C731DEAB7C851C + isa + PBXBuildFile + + 9F4EF8B51AC61EDF7D10632C + + fileRef + 204402C110C36194F0C5BFE9 + isa + PBXBuildFile + + A0BC037B46AE415AD994EFB9 + + fileRef + 1B8D72FA2287FB1825008643 + isa + PBXBuildFile + + A0FD87073D31D4A9CA5106E8 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMReadMonitorInputStream.h + path + Source/GTMReadMonitorInputStream.h + sourceTree + <group> + + A15ABB81E7BD34AFB140A716 + + fileRef + 843A392158489311B2F2D75A + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + A3DE18FB689014E31A80700A + + children + + 92DA4AD8E8DFA22DE1F6D6F3 + 16543F7AC304D070621BF1DE + 6353EE08DCACD566DA2E0788 + BA43CC92309F623C37A55B7A + + isa + PBXGroup + name + Support Files + path + ../Target Support Files/Pods-Google-API-Client + sourceTree + <group> + + A4498293B7F79189F313CDB7 + + isa + PBXTargetDependency + name + Pods-gtm-http-fetcher + target + D86F34FDA732FE2D376159FA + targetProxy + 1B1F92DCC3D9477B9FA283C6 + + A59A5A089E0FC47F82D69BF3 + + children + + 1213708E485E4DDD5B619CA5 + + isa + PBXGroup + name + Targets Support Files + sourceTree + <group> + + A635890121A5E93CF19B2217 + + fileRef + B9C4F4D3C4C547301C375A6E + isa + PBXBuildFile + + A71A00303E92E1DEC27F9091 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + Pods-environment.h + sourceTree + <group> + + A8083538F141A18F422BE7A0 + + containerPortal + 69F5A1152BC2D0A8D62C83CF + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + D86F34FDA732FE2D376159FA + remoteInfo + Pods-gtm-http-fetcher + + A8D177CA4365278DC1691CDA + + children + + 4D1E10E91930FDEC8545219F + DC3AB683DA0B47CA32820A9C + A3DE18FB689014E31A80700A + + isa + PBXGroup + name + Google-API-Client + path + Google-API-Client + sourceTree + <group> + + A8F0C8538E1971CF36BCAB6C + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLUtilities.h + path + Source/Utilities/GTLUtilities.h + sourceTree + <group> + + A93EB22E9F910C64BA3166BF + + fileRef + C57FD8D229ACA88153706630 + isa + PBXBuildFile + + ABCFA353277BC5D14B12A72E + + fileRef + 51891E116BB27015724F9FE3 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + ADF5289C17BFF8EF837C3EDD + + buildConfigurations + + BC04CB18398A354AEFE21072 + 2297FB94509CCE69C12B677E + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + AF31E816054D83719E180C51 + + containerPortal + 69F5A1152BC2D0A8D62C83CF + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + B31A978BEFBC46D180B885C0 + remoteInfo + Pods-Google-API-Client + + AF352CB592C3F49450D34DA1 + + fileRef + 5CE1491F4045A6F1C0520BF2 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + B1714354A8A314969314FFCA + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveFile.h + path + Source/Services/Drive/Generated/GTLDriveFile.h + sourceTree + <group> + + B31A978BEFBC46D180B885C0 + + buildConfigurationList + ADF5289C17BFF8EF837C3EDD + buildPhases + + 703F21EF1B2CD011162A136E + EC06DC774BA50EA3719AEB15 + D2F1E3FC221ECDE7BD3D3972 + + buildRules + + dependencies + + A4498293B7F79189F313CDB7 + 3D1280177A8CD98931B232A0 + + isa + PBXNativeTarget + name + Pods-Google-API-Client + productName + Pods-Google-API-Client + productReference + 9CA08D6704BCF0B8263F5002 + productType + com.apple.product-type.library.static + + B3888D210AA8016C0E06538C + + fileRef + 9C2CB0ACC1037A477930DFA9 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + B3BDFDD9AD46D74E0A46E708 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLBatchResult.m + path + Source/Objects/GTLBatchResult.m + sourceTree + <group> + + B3EEF1B83BBB9EE9AAF22CF2 + + children + + F554A9C2596AB1239F3868D2 + + isa + PBXGroup + name + Frameworks + sourceTree + <group> + + B471863524822D13DF05AEF8 + + fileRef + DD07BE9506DB9EE185AAFECD + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + B5209E5568BE6B55BA5F66E7 + + fileRef + A0FD87073D31D4A9CA5106E8 + isa + PBXBuildFile + + B5CC86FFB137EB5ACB41C4B8 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text + name + Podfile + path + ../Podfile + sourceTree + SOURCE_ROOT + xcLanguageSpecificationIdentifier + xcode.lang.ruby + + B693A41E4D27042FC2EA51BB + + baseConfigurationReference + 3D4E7C4E87FA48DE20B8CABB + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + YES + DSTROOT + /tmp/xcodeproj.dst + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-prefix.pch + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_CFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_CPLUSPLUSFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + VALIDATE_PRODUCT + YES + + isa + XCBuildConfiguration + name + Release + + B90613105B7B81CDBCB607E8 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMGatherInputStream.m + path + Source/GTMGatherInputStream.m + sourceTree + <group> + + B9C4F4D3C4C547301C375A6E + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + Foundation.framework + path + Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/Foundation.framework + sourceTree + DEVELOPER_DIR + + BA43CC92309F623C37A55B7A + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + Pods-Google-API-Client-prefix.pch + sourceTree + <group> + + BBA41A9760B2E1F92922CB28 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMHTTPUploadFetcher.h + path + Source/GTMHTTPUploadFetcher.h + sourceTree + <group> + + BC04CB18398A354AEFE21072 + + baseConfigurationReference + 16543F7AC304D070621BF1DE + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + NO + DSTROOT + /tmp/xcodeproj.dst + GCC_DYNAMIC_NO_PIC + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-prefix.pch + GCC_PREPROCESSOR_DEFINITIONS + + DEBUG=1 + $(inherited) + + GCC_SYMBOLS_PRIVATE_EXTERN + NO + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + + isa + XCBuildConfiguration + name + Debug + + BCDD154A126401DCA7FC536B + + fileRef + DF180F8D611667C30C568493 + isa + PBXBuildFile + + BCEEF3DB19A5BA6D47C1BD14 + + fileRef + B9C4F4D3C4C547301C375A6E + isa + PBXBuildFile + + BDF22827C0AEC9504825C719 + + fileRef + C0E3D4284CC2C86883C32F32 + isa + PBXBuildFile + + BE66489E7194AB23C1DB916B + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLBatchQuery.m + path + Source/Objects/GTLBatchQuery.m + sourceTree + <group> + + BF7820D32D70C05A7BDE3E2A + + fileRef + 5ACDEA45FE92C379DC6064ED + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + C001C6DEC321279DCE5E7EBB + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLFramework.m + path + Source/Utilities/GTLFramework.m + sourceTree + <group> + + C0CB8C2587E399A7717BDF25 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLService.m + path + Source/Objects/GTLService.m + sourceTree + <group> + + C0E3D4284CC2C86883C32F32 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + Pods-gtm-oauth2-dummy.m + sourceTree + <group> + + C22699B6399794582E9E42AD + + fileRef + 71FBC2E910A20A392835B5B1 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + C233B5ACEFCDE1ECB6479590 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveCommentReplyList.h + path + Source/Services/Drive/Generated/GTLDriveCommentReplyList.h + sourceTree + <group> + + C2BF1140A5D4C24E85D0B5E2 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveApp.m + path + Source/Services/Drive/Generated/GTLDriveApp.m + sourceTree + <group> + + C3DC945EC39932528A867F51 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveComment.m + path + Source/Services/Drive/Generated/GTLDriveComment.m + sourceTree + <group> + + C3E1561785167FE2A8A86216 + + fileRef + B9C4F4D3C4C547301C375A6E + isa + PBXBuildFile + + C418564018C8590C5C60F7F1 + + fileRef + 8C0B530302835BD114BE03EB + isa + PBXBuildFile + + C4A4028A1486E91DE74EC4C6 + + fileRef + 288DF28E51C3A244CF5310CF + isa + PBXBuildFile + + C57FD8D229ACA88153706630 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveRevision.h + path + Source/Services/Drive/Generated/GTLDriveRevision.h + sourceTree + <group> + + C6BC0F696323529F93CD5602 + + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + CLANG_CXX_LANGUAGE_STANDARD + gnu++0x + CLANG_CXX_LIBRARY + libc++ + CLANG_ENABLE_MODULES + YES + CLANG_ENABLE_OBJC_ARC + YES + CLANG_WARN_BOOL_CONVERSION + YES + CLANG_WARN_CONSTANT_CONVERSION + YES + CLANG_WARN_DIRECT_OBJC_ISA_USAGE + YES + CLANG_WARN_EMPTY_BODY + YES + CLANG_WARN_ENUM_CONVERSION + YES + CLANG_WARN_INT_CONVERSION + YES + CLANG_WARN_OBJC_ROOT_CLASS + YES + COPY_PHASE_STRIP + YES + GCC_C_LANGUAGE_STANDARD + gnu99 + GCC_DYNAMIC_NO_PIC + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_PREPROCESSOR_DEFINITIONS + + DEBUG=1 + $(inherited) + + GCC_SYMBOLS_PRIVATE_EXTERN + NO + GCC_WARN_64_TO_32_BIT_CONVERSION + YES + GCC_WARN_ABOUT_RETURN_TYPE + YES + GCC_WARN_UNDECLARED_SELECTOR + YES + GCC_WARN_UNINITIALIZED_AUTOS + YES + GCC_WARN_UNUSED_FUNCTION + YES + GCC_WARN_UNUSED_VARIABLE + YES + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + ONLY_ACTIVE_ARCH + YES + STRIP_INSTALLED_PRODUCT + NO + + isa + XCBuildConfiguration + name + Debug + + C85E7E5A1D590769D439F299 + + children + + F7B94161AFDC1DF5FBADACDD + 9CA08D6704BCF0B8263F5002 + 92830449E40969227AC60F1D + 29A939D6F0A258A65314DE24 + + isa + PBXGroup + name + Products + sourceTree + <group> + + C8BBA82F4963899A0FC9F065 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveParentReference.h + path + Source/Services/Drive/Generated/GTLDriveParentReference.h + sourceTree + <group> + + C970ABE9988D06FD5C7C262D + + buildConfigurations + + C6BC0F696323529F93CD5602 + 91837E982F3912DDE283358D + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + CA4FC6C8A66851CC6C3E8171 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLService.h + path + Source/Objects/GTLService.h + sourceTree + <group> + + CB7331611930E34323709C2F + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveUser.m + path + Source/Services/Drive/Generated/GTLDriveUser.m + sourceTree + <group> + + CC9B476A4751377E348CB5C8 + + fileRef + DEB494912FD9267C6BC0AE62 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + CD607DF08D72FEEEB4089B58 + + fileRef + 4383A2D59079CC83BD8907E9 + isa + PBXBuildFile + + CE1757246566510818FD161E + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLRuntimeCommon.m + path + Source/Objects/GTLRuntimeCommon.m + sourceTree + <group> + + CF73775F029486F44090CB0A + + buildActionMask + 2147483647 + files + + 67A934691C27CE181AF74158 + 0785415E7DD2A39727C20AFB + 9CBE29C112F25DE11AE3F6CC + + isa + PBXHeadersBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + D116C7044C76C6FCC6D595BC + + containerPortal + 69F5A1152BC2D0A8D62C83CF + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + 3BEBA6961BB2D04C334EDEE6 + remoteInfo + Pods-gtm-oauth2 + + D14CAA8D7254FC1A337A2683 + + fileRef + 2F4A85D5EE487FD592B6C374 + isa + PBXBuildFile + + D2F1E3FC221ECDE7BD3D3972 + + buildActionMask + 2147483647 + files + + F179A162F5A38E98FD3382D2 + 410ADF54900D18731106E14F + 8BFBAF271A63684EA714A2C0 + 98EB6F6A8B1A1A24A0515B88 + 50B6902EB8FAF094A6ED99D7 + C4A4028A1486E91DE74EC4C6 + 89FA0CCE470AFE1443FCEA8C + 3BDD54B9BC9ED35B680E5E8E + 981C41096FC5C7661091D929 + 83064B4F29F7FD5D3C4DC804 + FA04465F6317CB983FBCC35A + 95B2CB70C43EF35562E169CD + 1783A2B5E0DC44C6A4D0B76A + 69C44D2DF7BD4EF2144EA3D1 + DFFDD04ACDDE43DA57DBD8E0 + D14CAA8D7254FC1A337A2683 + 5AD1D445614D3E7209AB6970 + 5BBD7D96B17766394C40E894 + 243AF22950254C1BAAAA2628 + 7FDBB5B3BB5A2AD53E911ECF + 99D5EBAC09D9B56E880A94C5 + FA1027F74A01A696F6F9D051 + 777E98A5BFB951891A3E6137 + 5EAC417C5E6D73A7A9D4D01D + 177F8A7FAE00DE93FD89237A + 66EA661D472BAB1B72036219 + 8767D1B85636EEAAE5BEDECE + 8114EB2A5D8F241BAD7AA476 + A93EB22E9F910C64BA3166BF + 4BFA5B38158ACEEFE9FCB935 + 23A31A288D5BD29BA6EC4585 + 8BF9ED5B66BE3358A636E8B7 + A0BC037B46AE415AD994EFB9 + 96215DF99F80B11DAA7C266E + C418564018C8590C5C60F7F1 + 095BDD86B342747142E1FD51 + CD607DF08D72FEEEB4089B58 + 4D18DEEDB5318B07F1196794 + 74A2110920EC8CF0AC2804E0 + 643317E3A992B91AAD0E3115 + BCDD154A126401DCA7FC536B + 78ACB0DF0FA52F05AF50C70F + F475DF4CB88CA998F5E6A41C + + isa + PBXHeadersBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + D3C61BFB6592AE150E7C8D48 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMMIMEDocument.m + path + Source/GTMMIMEDocument.m + sourceTree + <group> + + D4856A2A9B29FE9F37E3E4F3 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveApp.h + path + Source/Services/Drive/Generated/GTLDriveApp.h + sourceTree + <group> + + D4980BC40E1052DFCC188C81 + + fileRef + 56A6E3713CCCC0F5597755C6 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + D55D394D7A2F801C936C1EB2 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMHTTPFetchHistory.h + path + Source/GTMHTTPFetchHistory.h + sourceTree + <group> + + D7614DE3AF2ECABF84DEEF4F + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLErrorObject.m + path + Source/Objects/GTLErrorObject.m + sourceTree + <group> + + D86F34FDA732FE2D376159FA + + buildConfigurationList + 83A8F088C964704466851C4F + buildPhases + + F4B12EA6D775ACB167E1B846 + 5B47B2E475B0593845980297 + 10FCAF49CF667F665EF8AF48 + + buildRules + + dependencies + + isa + PBXNativeTarget + name + Pods-gtm-http-fetcher + productName + Pods-gtm-http-fetcher + productReference + 92830449E40969227AC60F1D + productType + com.apple.product-type.library.static + + DA29918FF7BB8F5050B0C729 + + fileRef + C2BF1140A5D4C24E85D0B5E2 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + DC3AB683DA0B47CA32820A9C + + children + + 288DF28E51C3A244CF5310CF + 52AB1EBC58A4FE681BCAA53D + 3614F0AFCA6B3D8E00818E88 + D4856A2A9B29FE9F37E3E4F3 + C2BF1140A5D4C24E85D0B5E2 + 10B35DEDE6A1C206E1620AC3 + 5ACDEA45FE92C379DC6064ED + 34856CBC5B135FD2F8F4DAC5 + E4B57D125EB3F5A3151DB3F6 + 68336E20B92E7F05659EA895 + 9C2CB0ACC1037A477930DFA9 + 2295289C54CB40BC89BB15DD + 1B8F47E6D7E8F330AE0DF8A2 + 03E8499C67AFB451D8553C37 + F41E360666FB045C62B806AC + 93746BF7D4C282E03D437321 + 1F2697AF69C81C4358D90876 + 8BC358B5D5C066BE1B18E79D + C3DC945EC39932528A867F51 + 2F4A85D5EE487FD592B6C374 + 3C4AAC1C66BCBD3A7ECE47C3 + E1C96240D32F0F991DAC7D72 + 44183B8EAD00AE7C82394ECB + C233B5ACEFCDE1ECB6479590 + 56A6E3713CCCC0F5597755C6 + 1284BDECDFC0D7C41B0D4739 + FCB308CE73A15075E7DE8751 + B1714354A8A314969314FFCA + 3049D4328F3DF05125B811AD + 165BF6488CB3D2DFBEB300A3 + 843A392158489311B2F2D75A + DD812784DA7F8BB475BF1944 + FB9D94EF5248754F25A45269 + C8BBA82F4963899A0FC9F065 + 7FC3133D861CC24F6DA18214 + FDA4FC120EA341D2BCA83936 + 2A6F6D2CAA4739FC6292429F + 38C58D9349529227967743D6 + 71FBC2E910A20A392835B5B1 + 11A589EDE19AF418BD4BCFAE + FB86C544D6AA3923838D2BF0 + 0E89AC2784062681E66C4195 + 014C40719B958268E8C9CC6A + 7CDFBB89E85A58C547D4978A + E0EFDFF8AEBC4539B22AF2B0 + C57FD8D229ACA88153706630 + 7F2DB1F48EFE738410AF1AFC + 749FD7B69998A7F3EA6B7254 + 20B286BA202182EA197508B7 + F00EF8294F0E25A9116B874F + CB7331611930E34323709C2F + 4383A2D59079CC83BD8907E9 + F73316961E013D5A9CBB5AEE + F440729C22759252486D7975 + 84AD87C60F4DFB3666BA4527 + + isa + PBXGroup + name + Drive + sourceTree + <group> + + DC457F971743611484650EC5 + + fileRef + 65E3832CB796B0F9B8A8B250 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + DD07BE9506DB9EE185AAFECD + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDateTime.m + path + Source/Objects/GTLDateTime.m + sourceTree + <group> + + DD6D27D0E4698D7A1E13460B + + baseConfigurationReference + 055131DB2F8B9353CBEB1630 + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + YES + DSTROOT + /tmp/xcodeproj.dst + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-prefix.pch + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_CFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_CPLUSPLUSFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + VALIDATE_PRODUCT + YES + + isa + XCBuildConfiguration + name + Release + + DD812784DA7F8BB475BF1944 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveParentList.h + path + Source/Services/Drive/Generated/GTLDriveParentList.h + sourceTree + <group> + + DEA6BBE54C1516AD46FA96DE + + fileRef + 3049D4328F3DF05125B811AD + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + DEB494912FD9267C6BC0AE62 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMReadMonitorInputStream.m + path + Source/GTMReadMonitorInputStream.m + sourceTree + <group> + + DF0243F8EDC5CF63EE388B3B + + buildActionMask + 2147483647 + files + + 16BB7C693BCB983961820507 + 3956DD03A66BB4081BE86B6E + 67EE726A874DB868FF2D20A8 + BDF22827C0AEC9504825C719 + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + DF180F8D611667C30C568493 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLTargetNamespace.h + path + Source/Utilities/GTLTargetNamespace.h + sourceTree + <group> + + DFFDD04ACDDE43DA57DBD8E0 + + fileRef + 8BC358B5D5C066BE1B18E79D + isa + PBXBuildFile + + E0117D16F81E149991E6CE1E + + fileRef + C001C6DEC321279DCE5E7EBB + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + E0EFDFF8AEBC4539B22AF2B0 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDrivePropertyList.m + path + Source/Services/Drive/Generated/GTLDrivePropertyList.m + sourceTree + <group> + + E1551A38A5BED43BD5B89B74 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMOAuth2Authentication.m + path + Source/GTMOAuth2Authentication.m + sourceTree + <group> + + E1612C74185CAAAEB6DFBC71 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMOAuth2ViewControllerTouch.m + path + Source/Touch/GTMOAuth2ViewControllerTouch.m + sourceTree + <group> + + E1C96240D32F0F991DAC7D72 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveCommentReply.h + path + Source/Services/Drive/Generated/GTLDriveCommentReply.h + sourceTree + <group> + + E4B57D125EB3F5A3151DB3F6 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveChange.m + path + Source/Services/Drive/Generated/GTLDriveChange.m + sourceTree + <group> + + E636E4C345FFD2A7782B5275 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.script.sh + path + Pods-resources.sh + sourceTree + <group> + + E72708D844C731DEAB7C851C + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMHTTPFetcherLogging.h + path + Source/GTMHTTPFetcherLogging.h + sourceTree + <group> + + EC06DC774BA50EA3719AEB15 + + buildActionMask + 2147483647 + files + + BCEEF3DB19A5BA6D47C1BD14 + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + ED783139D6FB2B5DCA03B872 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMMIMEDocument.h + path + Source/GTMMIMEDocument.h + sourceTree + <group> + + EFC83A41398305ADBB80AC8A + + fileRef + 1F2697AF69C81C4358D90876 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + EFF0FF3D4FBAFA07EB1F8FB7 + + fileRef + C0CB8C2587E399A7717BDF25 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + F00EF8294F0E25A9116B874F + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDriveUser.h + path + Source/Services/Drive/Generated/GTLDriveUser.h + sourceTree + <group> + + F179A162F5A38E98FD3382D2 + + fileRef + 662C62A3FA7F133A74D24B9C + isa + PBXBuildFile + + F2E81095DFC87262E092E5F8 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTMHTTPFetcherLogViewController.m + path + Source/GTMHTTPFetcherLogViewController.m + sourceTree + <group> + + F3C4F9917A860C9166554B34 + + baseConfigurationReference + 10D42D84A4D868A94674CC51 + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + NO + DSTROOT + /tmp/xcodeproj.dst + GCC_DYNAMIC_NO_PIC + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREPROCESSOR_DEFINITIONS + + DEBUG=1 + $(inherited) + + GCC_SYMBOLS_PRIVATE_EXTERN + NO + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + + isa + XCBuildConfiguration + name + Debug + + F41E360666FB045C62B806AC + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveChildList.m + path + Source/Services/Drive/Generated/GTLDriveChildList.m + sourceTree + <group> + + F440729C22759252486D7975 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLServiceDrive.h + path + Source/Services/Drive/Generated/GTLServiceDrive.h + sourceTree + <group> + + F475DF4CB88CA998F5E6A41C + + fileRef + A8F0C8538E1971CF36BCAB6C + isa + PBXBuildFile + + F47E258E21EF049AFBAC4451 + + baseConfigurationReference + 0AB55F7F90C329519FE7F44E + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + COPY_PHASE_STRIP + YES + DSTROOT + /tmp/xcodeproj.dst + GCC_PRECOMPILE_PREFIX_HEADER + YES + INSTALL_PATH + $(BUILT_PRODUCTS_DIR) + IPHONEOS_DEPLOYMENT_TARGET + 7.0 + OTHER_CFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_CPLUSPLUSFLAGS + + -DNS_BLOCK_ASSERTIONS=1 + $(inherited) + + OTHER_LDFLAGS + + OTHER_LIBTOOLFLAGS + + PRODUCT_NAME + $(TARGET_NAME) + PUBLIC_HEADERS_FOLDER_PATH + $(TARGET_NAME) + SDKROOT + iphoneos + SKIP_INSTALL + YES + VALIDATE_PRODUCT + YES + + isa + XCBuildConfiguration + name + Release + + F4B12EA6D775ACB167E1B846 + + buildActionMask + 2147483647 + files + + 38A0640E2342435BB5ECF035 + 979CC85B91CAE464866E3DD1 + 8D610B71D1A7C7A3E9227B74 + 3D064287543D1194C7B7D428 + 914A194D74DBA71D909DA4C5 + 1B91617FB5A041BA4753BBF4 + ABCFA353277BC5D14B12A72E + 4D514D2233430A94AAA58A43 + CC9B476A4751377E348CB5C8 + 0E1A2DC8CF5133FF6DD5F089 + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + F554A9C2596AB1239F3868D2 + + children + + B9C4F4D3C4C547301C375A6E + 24BB3C1FE76098CD9B74404D + 773BF4EABF5B2AAF0BC79E40 + 2FA0F376D8A29FF1F2EF0F0F + + isa + PBXGroup + name + iOS + sourceTree + <group> + + F65850DE68118953B1578F91 + + fileRef + 459C7B03A59C67253EA2D81D + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + F73316961E013D5A9CBB5AEE + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLQueryDrive.m + path + Source/Services/Drive/Generated/GTLQueryDrive.m + sourceTree + <group> + + F7B94161AFDC1DF5FBADACDD + + explicitFileType + archive.ar + includeInIndex + 0 + isa + PBXFileReference + path + libPods.a + sourceTree + BUILT_PRODUCTS_DIR + + F9F67BFF4082560243606B31 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLRuntimeCommon.h + path + Source/Objects/GTLRuntimeCommon.h + sourceTree + <group> + + FA04465F6317CB983FBCC35A + + fileRef + 68336E20B92E7F05659EA895 + isa + PBXBuildFile + + FA1027F74A01A696F6F9D051 + + fileRef + DD812784DA7F8BB475BF1944 + isa + PBXBuildFile + + FB86C544D6AA3923838D2BF0 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDrivePermissionList.m + path + Source/Services/Drive/Generated/GTLDrivePermissionList.m + sourceTree + <group> + + FB9D94EF5248754F25A45269 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveParentList.m + path + Source/Services/Drive/Generated/GTLDriveParentList.m + sourceTree + <group> + + FC5281ABA6C81AB9E980125F + + fileRef + E4B57D125EB3F5A3151DB3F6 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + FCB308CE73A15075E7DE8751 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLDriveConstants.m + path + Source/Services/Drive/Generated/GTLDriveConstants.m + sourceTree + <group> + + FCDE5D0BC42131531DB198E3 + + fileRef + D7614DE3AF2ECABF84DEEF4F + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + FD64C8E7BD98E2E64DCE1405 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Pods-gtm-http-fetcher.xcconfig + sourceTree + <group> + + FDA4FC120EA341D2BCA83936 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTLDrivePermission.h + path + Source/Services/Drive/Generated/GTLDrivePermission.h + sourceTree + <group> + + FEF578F969D055A88889DC8F + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + GTMOAuth2SignIn.h + path + Source/GTMOAuth2SignIn.h + sourceTree + <group> + + FF33B6F9780C733B7F91C760 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + name + GTLQuery.m + path + Source/Objects/GTLQuery.m + sourceTree + <group> + + FFEC08358BBF198A740FAC85 + + fileRef + FB86C544D6AA3923838D2BF0 + isa + PBXBuildFile + settings + + COMPILER_FLAGS + -fno-objc-arc + + + + rootObject + 69F5A1152BC2D0A8D62C83CF + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-Private.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-Private.xcconfig new file mode 100755 index 0000000..9afde2b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-Private.xcconfig @@ -0,0 +1,5 @@ +#include "Pods-Google-API-Client.xcconfig" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/Google-API-Client" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Google-API-Client" "${PODS_ROOT}/Headers/Public/gtm-http-fetcher" "${PODS_ROOT}/Headers/Public/gtm-oauth2" +OTHER_LDFLAGS = -ObjC +PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-dummy.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-dummy.m new file mode 100755 index 0000000..9038c74 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_Google_API_Client : NSObject +@end +@implementation PodsDummy_Pods_Google_API_Client +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-prefix.pch b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-prefix.pch new file mode 100755 index 0000000..95cf11d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client-prefix.pch @@ -0,0 +1,5 @@ +#ifdef __OBJC__ +#import +#endif + +#import "Pods-environment.h" diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-Google-API-Client/Pods-Google-API-Client.xcconfig new file mode 100755 index 0000000..e69de29 diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-Private.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-Private.xcconfig new file mode 100755 index 0000000..ec5e36e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-Private.xcconfig @@ -0,0 +1,5 @@ +#include "Pods-gtm-http-fetcher.xcconfig" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/gtm-http-fetcher" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Google-API-Client" "${PODS_ROOT}/Headers/Public/gtm-http-fetcher" "${PODS_ROOT}/Headers/Public/gtm-oauth2" +OTHER_LDFLAGS = ${PODS_GTM_HTTP_FETCHER_OTHER_LDFLAGS} -ObjC +PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-dummy.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-dummy.m new file mode 100755 index 0000000..792653b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_gtm_http_fetcher : NSObject +@end +@implementation PodsDummy_Pods_gtm_http_fetcher +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-prefix.pch b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-prefix.pch new file mode 100755 index 0000000..95cf11d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher-prefix.pch @@ -0,0 +1,5 @@ +#ifdef __OBJC__ +#import +#endif + +#import "Pods-environment.h" diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher.xcconfig new file mode 100755 index 0000000..8fe2afa --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-http-fetcher/Pods-gtm-http-fetcher.xcconfig @@ -0,0 +1 @@ +PODS_GTM_HTTP_FETCHER_OTHER_LDFLAGS = -framework "UIKit" \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-Private.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-Private.xcconfig new file mode 100755 index 0000000..6092bff --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-Private.xcconfig @@ -0,0 +1,5 @@ +#include "Pods-gtm-oauth2.xcconfig" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/gtm-oauth2" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Google-API-Client" "${PODS_ROOT}/Headers/Public/gtm-http-fetcher" "${PODS_ROOT}/Headers/Public/gtm-oauth2" +OTHER_LDFLAGS = ${PODS_GTM_OAUTH__OTHER_LDFLAGS} -ObjC +PODS_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-dummy.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-dummy.m new file mode 100755 index 0000000..73d0955 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_gtm_oauth2 : NSObject +@end +@implementation PodsDummy_Pods_gtm_oauth2 +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-prefix.pch b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-prefix.pch new file mode 100755 index 0000000..95cf11d --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2-prefix.pch @@ -0,0 +1,5 @@ +#ifdef __OBJC__ +#import +#endif + +#import "Pods-environment.h" diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2.xcconfig new file mode 100755 index 0000000..caa371c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods-gtm-oauth2/Pods-gtm-oauth2.xcconfig @@ -0,0 +1 @@ +PODS_GTM_OAUTH__OTHER_LDFLAGS = -framework "Security" -framework "SystemConfiguration" \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown new file mode 100755 index 0000000..c7b3bdb --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown @@ -0,0 +1,54 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## Google-API-Client + +Copyright (c) 2011 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +## gtm-http-fetcher + +Copyright (c) 2011 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +## gtm-oauth2 + +Copyright (c) 2010 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Generated by CocoaPods - http://cocoapods.org diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-acknowledgements.plist b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-acknowledgements.plist new file mode 100755 index 0000000..90878f6 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-acknowledgements.plist @@ -0,0 +1,92 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + Title + Google-API-Client + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + Title + gtm-http-fetcher + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2010 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + Title + gtm-oauth2 + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - http://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-dummy.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-dummy.m new file mode 100755 index 0000000..ade64bd --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods : NSObject +@end +@implementation PodsDummy_Pods +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-environment.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-environment.h new file mode 100755 index 0000000..c200614 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-environment.h @@ -0,0 +1,32 @@ + +// To check if a library is compiled with CocoaPods you +// can use the `COCOAPODS` macro definition which is +// defined in the xcconfigs so it is available in +// headers also when they are imported in the client +// project. + + +// Google-API-Client/Common +#define COCOAPODS_POD_AVAILABLE_Google_API_Client_Common +#define COCOAPODS_VERSION_MAJOR_Google_API_Client_Common 1 +#define COCOAPODS_VERSION_MINOR_Google_API_Client_Common 0 +#define COCOAPODS_VERSION_PATCH_Google_API_Client_Common 422 + +// Google-API-Client/Drive +#define COCOAPODS_POD_AVAILABLE_Google_API_Client_Drive +#define COCOAPODS_VERSION_MAJOR_Google_API_Client_Drive 1 +#define COCOAPODS_VERSION_MINOR_Google_API_Client_Drive 0 +#define COCOAPODS_VERSION_PATCH_Google_API_Client_Drive 422 + +// gtm-http-fetcher +#define COCOAPODS_POD_AVAILABLE_gtm_http_fetcher +#define COCOAPODS_VERSION_MAJOR_gtm_http_fetcher 1 +#define COCOAPODS_VERSION_MINOR_gtm_http_fetcher 0 +#define COCOAPODS_VERSION_PATCH_gtm_http_fetcher 141 + +// gtm-oauth2 +#define COCOAPODS_POD_AVAILABLE_gtm_oauth2 +#define COCOAPODS_VERSION_MAJOR_gtm_oauth2 1 +#define COCOAPODS_VERSION_MINOR_gtm_oauth2 0 +#define COCOAPODS_VERSION_PATCH_gtm_oauth2 126 + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-resources.sh b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-resources.sh new file mode 100755 index 0000000..e0eccbf --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods-resources.sh @@ -0,0 +1,75 @@ +#!/bin/sh +set -e + +mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +install_resource() +{ + case $1 in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" + ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" + ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" + ;; + *.framework) + echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" + xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" + xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" + xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ;; + /*) + echo "$1" + echo "$1" >> "$RESOURCES_TO_COPY" + ;; + *) + echo "${PODS_ROOT}/$1" + echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" + ;; + esac +} + install_resource "gtm-oauth2/Source/Touch/GTMOAuth2ViewTouch.xib" + +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]]; then + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ] +then + case "${TARGETED_DEVICE_FAMILY}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; + esac + find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods.debug.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods.debug.xcconfig new file mode 100755 index 0000000..1c8e590 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods.debug.xcconfig @@ -0,0 +1,6 @@ +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Google-API-Client" "${PODS_ROOT}/Headers/Public/gtm-http-fetcher" "${PODS_ROOT}/Headers/Public/gtm-oauth2" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Google-API-Client" -isystem "${PODS_ROOT}/Headers/Public/gtm-http-fetcher" -isystem "${PODS_ROOT}/Headers/Public/gtm-oauth2" +OTHER_LDFLAGS = -ObjC -l"Pods-Google-API-Client" -l"Pods-gtm-http-fetcher" -l"Pods-gtm-oauth2" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" +OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) +PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods.release.xcconfig b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods.release.xcconfig new file mode 100755 index 0000000..1c8e590 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/Target Support Files/Pods/Pods.release.xcconfig @@ -0,0 +1,6 @@ +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Google-API-Client" "${PODS_ROOT}/Headers/Public/gtm-http-fetcher" "${PODS_ROOT}/Headers/Public/gtm-oauth2" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Google-API-Client" -isystem "${PODS_ROOT}/Headers/Public/gtm-http-fetcher" -isystem "${PODS_ROOT}/Headers/Public/gtm-oauth2" +OTHER_LDFLAGS = -ObjC -l"Pods-Google-API-Client" -l"Pods-gtm-http-fetcher" -l"Pods-gtm-oauth2" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" +OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) +PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/README.txt b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/README.txt new file mode 100755 index 0000000..6f218d5 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/README.txt @@ -0,0 +1,4 @@ +Information on using the Google Toolbox for Mac HTTP Fetcher project +is available at + +http://code.google.com/p/gtm-http-fetcher/ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMGatherInputStream.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMGatherInputStream.h new file mode 100755 index 0000000..280ff97 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMGatherInputStream.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// The GTMGatherInput stream is an input stream implementation that is to be +// instantiated with an NSArray of NSData objects. It works in the traditional +// scatter/gather vector I/O model. Rather than allocating a big NSData object +// to hold all of the data and performing a copy into that object, the +// GTMGatherInputStream will maintain a reference to the NSArray and read from +// each NSData in turn as the read method is called. You should not alter the +// underlying set of NSData objects until all read operations on this input +// stream have completed. + +#import + +#if defined(GTL_TARGET_NAMESPACE) + // we need NSInteger for the 10.4 SDK, or we're using target namespace macros + #import "GTLDefines.h" +#elif defined(GDATA_TARGET_NAMESPACE) + #import "GDataDefines.h" +#endif + +// Define only for Mac OS X 10.6+ or iPhone OS 4.0+. +#undef GTM_NSSTREAM_DELEGATE +#if (TARGET_OS_MAC && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \ + (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000)) + #define GTM_NSSTREAM_DELEGATE +#else + #define GTM_NSSTREAM_DELEGATE +#endif + +@interface GTMGatherInputStream : NSInputStream GTM_NSSTREAM_DELEGATE { + + NSArray* dataArray_; // NSDatas that should be "gathered" and streamed. + NSUInteger arrayIndex_; // Index in the array of the current NSData. + long long dataOffset_; // Offset in the current NSData we are processing. + + id delegate_; // WEAK, stream delegate, defaults to self + + // Since various undocumented methods get called on a stream, we'll + // use a 1-byte dummy stream object to handle all unexpected messages. + // Actual reads from the stream we will perform using the data array, not + // from the dummy stream. + NSInputStream* dummyStream_; + NSData* dummyData_; +} + ++ (NSInputStream *)streamWithArray:(NSArray *)dataArray; + +- (id)initWithArray:(NSArray *)dataArray; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMGatherInputStream.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMGatherInputStream.m new file mode 100755 index 0000000..7713982 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMGatherInputStream.m @@ -0,0 +1,197 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GTMGatherInputStream.h" + +@implementation GTMGatherInputStream + ++ (NSInputStream *)streamWithArray:(NSArray *)dataArray { + return [[[self alloc] initWithArray:dataArray] autorelease]; +} + +- (id)initWithArray:(NSArray *)dataArray { + self = [super init]; + if (self) { + dataArray_ = [dataArray retain]; + arrayIndex_ = 0; + dataOffset_ = 0; + + [self setDelegate:self]; // An NSStream's default delegate should be self. + + // We use a dummy input stream to handle all the various undocumented + // messages the system sends to an input stream. + // + // Contrary to documentation, inputStreamWithData neither copies nor + // retains the data in Mac OS X 10.4, so we must retain it. + // (Radar 5167591) + + dummyData_ = [[NSData alloc] initWithBytes:"x" length:1]; + dummyStream_ = [[NSInputStream alloc] initWithData:dummyData_]; + } + return self; +} + +- (void)dealloc { + [dataArray_ release]; + [dummyStream_ release]; + [dummyData_ release]; + + [super dealloc]; +} + +- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len { + + NSInteger bytesRead = 0; + NSUInteger bytesRemaining = len; + + // read bytes from the currently-indexed array + while ((bytesRemaining > 0) && (arrayIndex_ < [dataArray_ count])) { + + NSData* data = [dataArray_ objectAtIndex:arrayIndex_]; + + NSUInteger dataLen = [data length]; + NSUInteger dataBytesLeft = dataLen - (NSUInteger)dataOffset_; + + NSUInteger bytesToCopy = MIN(bytesRemaining, dataBytesLeft); + NSRange range = NSMakeRange((NSUInteger) dataOffset_, bytesToCopy); + + [data getBytes:(buffer + bytesRead) range:range]; + + bytesRead += bytesToCopy; + dataOffset_ += bytesToCopy; + bytesRemaining -= bytesToCopy; + + if (dataOffset_ == (long long)dataLen) { + dataOffset_ = 0; + arrayIndex_++; + } + } + + if (bytesRead == 0) { + // We are at the end our our stream, so we read all of the data on our + // dummy input stream to make sure it is in the "fully read" state. + uint8_t leftOverBytes[2]; + (void) [dummyStream_ read:leftOverBytes maxLength:sizeof(leftOverBytes)]; + } + + return bytesRead; +} + +- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len { + return NO; // We don't support this style of reading. +} + +- (BOOL)hasBytesAvailable { + // if we return no, the read never finishes, even if we've already + // delivered all the bytes + return YES; +} + +#pragma mark - + +// Pass other expected messages on to the dummy input stream + +- (void)open { + [dummyStream_ open]; +} + +- (void)close { + [dummyStream_ close]; + + // 10.4's NSURLConnection tends to retain streams needlessly, + // so we'll free up the data array right away + [dataArray_ release]; + dataArray_ = nil; +} + +- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { + if (delegate_ != self) { + [delegate_ stream:self handleEvent:streamEvent]; + } +} + +- (id)delegate { + return delegate_; +} + +- (void)setDelegate:(id)delegate { + if (delegate == nil) { + delegate_ = self; + [dummyStream_ setDelegate:nil]; + } else { + delegate_ = delegate; + [dummyStream_ setDelegate:self]; + } +} + +- (id)propertyForKey:(NSString *)key { + return [dummyStream_ propertyForKey:key]; +} + +- (BOOL)setProperty:(id)property forKey:(NSString *)key { + return [dummyStream_ setProperty:property forKey:key]; +} + +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { + [dummyStream_ scheduleInRunLoop:aRunLoop forMode:mode]; +} + +- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { + [dummyStream_ removeFromRunLoop:aRunLoop forMode:mode]; +} + +- (NSStreamStatus)streamStatus { + return [dummyStream_ streamStatus]; +} +- (NSError *)streamError { + return [dummyStream_ streamError]; +} + +#pragma mark - + +// We'll forward all unexpected messages to our dummy stream + ++ (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { + return [NSInputStream methodSignatureForSelector:selector]; +} + ++ (void)forwardInvocation:(NSInvocation*)invocation { + [invocation invokeWithTarget:[NSInputStream class]]; +} + +- (BOOL)respondsToSelector:(SEL)selector { + return [dummyStream_ respondsToSelector:selector]; +} + +- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { + return [dummyStream_ methodSignatureForSelector:selector]; +} + +- (void)forwardInvocation:(NSInvocation*)invocation { + +#if 0 + // uncomment this section to see the messages the NSInputStream receives + SEL selector; + NSString *selName; + + selector=[invocation selector]; + selName=NSStringFromSelector(selector); + NSLog(@"-forwardInvocation: %@",selName); +#endif + + [invocation invokeWithTarget:dummyStream_]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetchHistory.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetchHistory.h new file mode 100755 index 0000000..9c7eed9 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetchHistory.h @@ -0,0 +1,175 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPFetchHistory.h +// + +// +// Users of the GTMHTTPFetcher class may optionally create and set a fetch +// history object. The fetch history provides "memory" between subsequent +// fetches, including: +// +// - For fetch responses with Etag headers, the fetch history +// remembers the response headers. Future fetcher requests to the same URL +// will be given an "If-None-Match" header, telling the server to return +// a 304 Not Modified status if the response is unchanged, reducing the +// server load and network traffic. +// +// - Optionally, the fetch history can cache the ETagged data that was returned +// in the responses that contained Etag headers. If a later fetch +// results in a 304 status, the fetcher will return the cached ETagged data +// to the client along with a 200 status, hiding the 304. +// +// - The fetch history can track cookies. +// + +#pragma once + +#import + +#import "GTMHTTPFetcher.h" + +// default data cache size for when we're caching responses to handle "not +// modified" errors for the client + +#ifdef __cplusplus +extern "C" { +#endif + +extern const NSUInteger kGTMDefaultETaggedDataCacheMemoryCapacity; + +#ifdef __cplusplus +} +#endif + +// forward declarations +@class GTMURLCache; +@class GTMCookieStorage; + +@interface GTMHTTPFetchHistory : NSObject { + @private + GTMURLCache *etaggedDataCache_; + BOOL shouldRememberETags_; + BOOL shouldCacheETaggedData_; // if NO, then only headers are cached + GTMCookieStorage *cookieStorage_; +} + +// With caching enabled, previously-cached data will be returned instead of +// 304 Not Modified responses when repeating a fetch of an URL that previously +// included an ETag header in its response +@property (assign) BOOL shouldRememberETags; // default: NO +@property (assign) BOOL shouldCacheETaggedData; // default: NO + +// the default ETag data cache capacity is kGTMDefaultETaggedDataCacheMemoryCapacity +@property (assign) NSUInteger memoryCapacity; + +@property (retain) GTMCookieStorage *cookieStorage; + +- (id)initWithMemoryCapacity:(NSUInteger)totalBytes + shouldCacheETaggedData:(BOOL)shouldCacheETaggedData; + +- (void)updateRequest:(NSMutableURLRequest *)request isHTTPGet:(BOOL)isHTTPGet; + +- (void)clearETaggedDataCache; +- (void)clearHistory; + +- (void)removeAllCookies; + +@end + + +// GTMURLCache and GTMCachedURLResponse have interfaces similar to their +// NSURLCache counterparts, in hopes that someday the NSURLCache versions +// can be used. But in 10.5.8, those are not reliable enough except when +// used with +setSharedURLCache. Our goal here is just to cache +// responses for handling If-None-Match requests that return +// "Not Modified" responses, not for replacing the general URL +// caches. + +@interface GTMCachedURLResponse : NSObject { + @private + NSURLResponse *response_; + NSData *data_; + NSDate *useDate_; // date this response was last saved or used + NSDate *reservationDate_; // date this response's ETag was used +} + +@property (readonly) NSURLResponse* response; +@property (readonly) NSData* data; + +// date the response was saved or last accessed +@property (retain) NSDate *useDate; + +// date the response's ETag header was last used for a fetch request +@property (retain) NSDate *reservationDate; + +- (id)initWithResponse:(NSURLResponse *)response data:(NSData *)data; +@end + +@interface GTMURLCache : NSObject { + NSMutableDictionary *responses_; // maps request URL to GTMCachedURLResponse + NSUInteger memoryCapacity_; // capacity of NSDatas in the responses + NSUInteger totalDataSize_; // sum of sizes of NSDatas of all responses + NSTimeInterval reservationInterval_; // reservation expiration interval +} + +@property (assign) NSUInteger memoryCapacity; + +- (id)initWithMemoryCapacity:(NSUInteger)totalBytes; + +- (GTMCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request; +- (void)storeCachedResponse:(GTMCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request; +- (void)removeCachedResponseForRequest:(NSURLRequest *)request; +- (void)removeAllCachedResponses; + +// for unit testing +- (void)setReservationInterval:(NSTimeInterval)secs; +- (NSDictionary *)responses; +- (NSUInteger)totalDataSize; +@end + +@interface GTMCookieStorage : NSObject { + @private + // The cookie storage object manages an array holding cookies, but the array + // is allocated externally (it may be in a fetcher object or the static + // fetcher cookie array.) See the fetcher's setCookieStorageMethod: + // for allocation of this object and assignment of its cookies array. + NSMutableArray *cookies_; +} + +// add all NSHTTPCookies in the supplied array to the storage array, +// replacing cookies in the storage array as appropriate +// Side effect: removes expired cookies from the storage array +- (void)setCookies:(NSArray *)newCookies; + +// retrieve all cookies appropriate for the given URL, considering +// domain, path, cookie name, expiration, security setting. +// Side effect: removes expired cookies from the storage array +- (NSArray *)cookiesForURL:(NSURL *)theURL; + +// return a cookie with the same name, domain, and path as the +// given cookie, or else return nil if none found +// +// Both the cookie being tested and all stored cookies should +// be valid (non-nil name, domains, paths) +- (NSHTTPCookie *)cookieMatchingCookie:(NSHTTPCookie *)cookie; + +// remove any expired cookies, excluding cookies with nil expirations +- (void)removeExpiredCookies; + +- (void)removeAllCookies; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetchHistory.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetchHistory.m new file mode 100755 index 0000000..cc78ea6 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetchHistory.m @@ -0,0 +1,612 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPFetchHistory.m +// + +#import "GTMHTTPFetchHistory.h" + +static const NSTimeInterval kCachedURLReservationInterval = 60.0; // 1 minute +static NSString* const kGTMIfNoneMatchHeader = @"If-None-Match"; +static NSString* const kGTMETagHeader = @"Etag"; + +#if GTM_IPHONE +// iPhone: up to 1MB memory +const NSUInteger kGTMDefaultETaggedDataCacheMemoryCapacity = 1 * 1024 * 1024; +#else +// Mac OS X: up to 15MB memory +const NSUInteger kGTMDefaultETaggedDataCacheMemoryCapacity = 15 * 1024 * 1024; +#endif + + +@implementation GTMCookieStorage + +- (id)init { + self = [super init]; + if (self != nil) { + cookies_ = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)dealloc { + [cookies_ release]; + [super dealloc]; +} + +// Add all cookies in the new cookie array to the storage, +// replacing stored cookies as appropriate. +// +// Side effect: removes expired cookies from the storage array. +- (void)setCookies:(NSArray *)newCookies { + + @synchronized(cookies_) { + [self removeExpiredCookies]; + + for (NSHTTPCookie *newCookie in newCookies) { + if ([[newCookie name] length] > 0 + && [[newCookie domain] length] > 0 + && [[newCookie path] length] > 0) { + + // remove the cookie if it's currently in the array + NSHTTPCookie *oldCookie = [self cookieMatchingCookie:newCookie]; + if (oldCookie) { + [cookies_ removeObjectIdenticalTo:oldCookie]; + } + + // make sure the cookie hasn't already expired + NSDate *expiresDate = [newCookie expiresDate]; + if ((!expiresDate) || [expiresDate timeIntervalSinceNow] > 0) { + [cookies_ addObject:newCookie]; + } + + } else { + NSAssert1(NO, @"Cookie incomplete: %@", newCookie); + } + } + } +} + +- (void)deleteCookie:(NSHTTPCookie *)cookie { + @synchronized(cookies_) { + NSHTTPCookie *foundCookie = [self cookieMatchingCookie:cookie]; + if (foundCookie) { + [cookies_ removeObjectIdenticalTo:foundCookie]; + } + } +} + +// Retrieve all cookies appropriate for the given URL, considering +// domain, path, cookie name, expiration, security setting. +// Side effect: removed expired cookies from the storage array. +- (NSArray *)cookiesForURL:(NSURL *)theURL { + + NSMutableArray *foundCookies = nil; + + @synchronized(cookies_) { + [self removeExpiredCookies]; + + // We'll prepend "." to the desired domain, since we want the + // actual domain "nytimes.com" to still match the cookie domain + // ".nytimes.com" when we check it below with hasSuffix. + NSString *host = [[theURL host] lowercaseString]; + NSString *path = [theURL path]; + NSString *scheme = [theURL scheme]; + + NSString *domain = nil; + BOOL isLocalhostRetrieval = NO; + + if ([host isEqual:@"localhost"]) { + isLocalhostRetrieval = YES; + } else { + if (host) { + domain = [@"." stringByAppendingString:host]; + } + } + + NSUInteger numberOfCookies = [cookies_ count]; + for (NSUInteger idx = 0; idx < numberOfCookies; idx++) { + + NSHTTPCookie *storedCookie = [cookies_ objectAtIndex:idx]; + + NSString *cookieDomain = [[storedCookie domain] lowercaseString]; + NSString *cookiePath = [storedCookie path]; + BOOL cookieIsSecure = [storedCookie isSecure]; + + BOOL isDomainOK; + + if (isLocalhostRetrieval) { + // prior to 10.5.6, the domain stored into NSHTTPCookies for localhost + // is "localhost.local" + isDomainOK = [cookieDomain isEqual:@"localhost"] + || [cookieDomain isEqual:@"localhost.local"]; + } else { + isDomainOK = [domain hasSuffix:cookieDomain]; + } + + BOOL isPathOK = [cookiePath isEqual:@"/"] || [path hasPrefix:cookiePath]; + BOOL isSecureOK = (!cookieIsSecure) || [scheme isEqual:@"https"]; + + if (isDomainOK && isPathOK && isSecureOK) { + if (foundCookies == nil) { + foundCookies = [NSMutableArray arrayWithCapacity:1]; + } + [foundCookies addObject:storedCookie]; + } + } + } + return foundCookies; +} + +// Return a cookie from the array with the same name, domain, and path as the +// given cookie, or else return nil if none found. +// +// Both the cookie being tested and all cookies in the storage array should +// be valid (non-nil name, domains, paths). +// +// Note: this should only be called from inside a @synchronized(cookies_) block +- (NSHTTPCookie *)cookieMatchingCookie:(NSHTTPCookie *)cookie { + + NSUInteger numberOfCookies = [cookies_ count]; + NSString *name = [cookie name]; + NSString *domain = [cookie domain]; + NSString *path = [cookie path]; + + NSAssert3(name && domain && path, @"Invalid cookie (name:%@ domain:%@ path:%@)", + name, domain, path); + + for (NSUInteger idx = 0; idx < numberOfCookies; idx++) { + + NSHTTPCookie *storedCookie = [cookies_ objectAtIndex:idx]; + + if ([[storedCookie name] isEqual:name] + && [[storedCookie domain] isEqual:domain] + && [[storedCookie path] isEqual:path]) { + + return storedCookie; + } + } + return nil; +} + + +// Internal routine to remove any expired cookies from the array, excluding +// cookies with nil expirations. +// +// Note: this should only be called from inside a @synchronized(cookies_) block +- (void)removeExpiredCookies { + + // count backwards since we're deleting items from the array + for (NSInteger idx = (NSInteger)[cookies_ count] - 1; idx >= 0; idx--) { + + NSHTTPCookie *storedCookie = [cookies_ objectAtIndex:(NSUInteger)idx]; + + NSDate *expiresDate = [storedCookie expiresDate]; + if (expiresDate && [expiresDate timeIntervalSinceNow] < 0) { + [cookies_ removeObjectAtIndex:(NSUInteger)idx]; + } + } +} + +- (void)removeAllCookies { + @synchronized(cookies_) { + [cookies_ removeAllObjects]; + } +} +@end + +// +// GTMCachedURLResponse +// + +@implementation GTMCachedURLResponse + +@synthesize response = response_; +@synthesize data = data_; +@synthesize reservationDate = reservationDate_; +@synthesize useDate = useDate_; + +- (id)initWithResponse:(NSURLResponse *)response data:(NSData *)data { + self = [super init]; + if (self != nil) { + response_ = [response retain]; + data_ = [data retain]; + useDate_ = [[NSDate alloc] init]; + } + return self; +} + +- (void)dealloc { + [response_ release]; + [data_ release]; + [useDate_ release]; + [reservationDate_ release]; + [super dealloc]; +} + +- (NSString *)description { + NSString *reservationStr = reservationDate_ ? + [NSString stringWithFormat:@" resDate:%@", reservationDate_] : @""; + + return [NSString stringWithFormat:@"%@ %p: {bytes:%@ useDate:%@%@}", + [self class], self, + data_ ? [NSNumber numberWithInt:(int)[data_ length]] : nil, + useDate_, + reservationStr]; +} + +- (NSComparisonResult)compareUseDate:(GTMCachedURLResponse *)other { + return [useDate_ compare:[other useDate]]; +} + +@end + +// +// GTMURLCache +// + +@implementation GTMURLCache + +@dynamic memoryCapacity; + +- (id)init { + return [self initWithMemoryCapacity:kGTMDefaultETaggedDataCacheMemoryCapacity]; +} + +- (id)initWithMemoryCapacity:(NSUInteger)totalBytes { + self = [super init]; + if (self != nil) { + memoryCapacity_ = totalBytes; + + responses_ = [[NSMutableDictionary alloc] initWithCapacity:5]; + + reservationInterval_ = kCachedURLReservationInterval; + } + return self; +} + +- (void)dealloc { + [responses_ release]; + [super dealloc]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p: {responses:%@}", + [self class], self, [responses_ allValues]]; +} + +// Setters/getters + +- (void)pruneCacheResponses { + // Internal routine to remove the least-recently-used responses when the + // cache has grown too large + if (memoryCapacity_ >= totalDataSize_) return; + + // Sort keys by date + SEL sel = @selector(compareUseDate:); + NSArray *sortedKeys = [responses_ keysSortedByValueUsingSelector:sel]; + + // The least-recently-used keys are at the beginning of the sorted array; + // remove those (except ones still reserved) until the total data size is + // reduced sufficiently + for (NSURL *key in sortedKeys) { + GTMCachedURLResponse *response = [responses_ objectForKey:key]; + + NSDate *resDate = [response reservationDate]; + BOOL isResponseReserved = (resDate != nil) + && ([resDate timeIntervalSinceNow] > -reservationInterval_); + + if (!isResponseReserved) { + // We can remove this response from the cache + NSUInteger storedSize = [[response data] length]; + totalDataSize_ -= storedSize; + [responses_ removeObjectForKey:key]; + } + + // If we've removed enough response data, then we're done + if (memoryCapacity_ >= totalDataSize_) break; + } +} + +- (void)storeCachedResponse:(GTMCachedURLResponse *)cachedResponse + forRequest:(NSURLRequest *)request { + @synchronized(self) { + // Remove any previous entry for this request + [self removeCachedResponseForRequest:request]; + + // cache this one only if it's not bigger than our cache + NSUInteger storedSize = [[cachedResponse data] length]; + if (storedSize < memoryCapacity_) { + + NSURL *key = [request URL]; + [responses_ setObject:cachedResponse forKey:key]; + totalDataSize_ += storedSize; + + [self pruneCacheResponses]; + } + } +} + +- (GTMCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request { + GTMCachedURLResponse *response; + + @synchronized(self) { + NSURL *key = [request URL]; + response = [[[responses_ objectForKey:key] retain] autorelease]; + + // Touch the date to indicate this was recently retrieved + [response setUseDate:[NSDate date]]; + } + return response; +} + +- (void)removeCachedResponseForRequest:(NSURLRequest *)request { + @synchronized(self) { + NSURL *key = [request URL]; + totalDataSize_ -= [[[responses_ objectForKey:key] data] length]; + [responses_ removeObjectForKey:key]; + } +} + +- (void)removeAllCachedResponses { + @synchronized(self) { + [responses_ removeAllObjects]; + totalDataSize_ = 0; + } +} + +- (NSUInteger)memoryCapacity { + return memoryCapacity_; +} + +- (void)setMemoryCapacity:(NSUInteger)totalBytes { + @synchronized(self) { + BOOL didShrink = (totalBytes < memoryCapacity_); + memoryCapacity_ = totalBytes; + + if (didShrink) { + [self pruneCacheResponses]; + } + } +} + +// Methods for unit testing. +- (void)setReservationInterval:(NSTimeInterval)secs { + reservationInterval_ = secs; +} + +- (NSDictionary *)responses { + return responses_; +} + +- (NSUInteger)totalDataSize { + return totalDataSize_; +} + +@end + +// +// GTMHTTPFetchHistory +// + +@interface GTMHTTPFetchHistory () +- (NSString *)cachedETagForRequest:(NSURLRequest *)request; +- (void)removeCachedDataForRequest:(NSURLRequest *)request; +@end + +@implementation GTMHTTPFetchHistory + +@synthesize cookieStorage = cookieStorage_; + +@dynamic shouldRememberETags; +@dynamic shouldCacheETaggedData; +@dynamic memoryCapacity; + +- (id)init { + return [self initWithMemoryCapacity:kGTMDefaultETaggedDataCacheMemoryCapacity + shouldCacheETaggedData:NO]; +} + +- (id)initWithMemoryCapacity:(NSUInteger)totalBytes + shouldCacheETaggedData:(BOOL)shouldCacheETaggedData { + self = [super init]; + if (self != nil) { + etaggedDataCache_ = [[GTMURLCache alloc] initWithMemoryCapacity:totalBytes]; + shouldRememberETags_ = shouldCacheETaggedData; + shouldCacheETaggedData_ = shouldCacheETaggedData; + cookieStorage_ = [[GTMCookieStorage alloc] init]; + } + return self; +} + +- (void)dealloc { + [etaggedDataCache_ release]; + [cookieStorage_ release]; + [super dealloc]; +} + +- (void)updateRequest:(NSMutableURLRequest *)request isHTTPGet:(BOOL)isHTTPGet { + @synchronized(self) { + if ([self shouldRememberETags]) { + // If this URL is in the history, and no ETag has been set, then + // set the ETag header field + + // If we have a history, we're tracking across fetches, so we don't + // want to pull results from any other cache + [request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; + + if (isHTTPGet) { + // We'll only add an ETag if there's no ETag specified in the user's + // request + NSString *specifiedETag = [request valueForHTTPHeaderField:kGTMIfNoneMatchHeader]; + if (specifiedETag == nil) { + // No ETag: extract the previous ETag for this request from the + // fetch history, and add it to the request + NSString *cachedETag = [self cachedETagForRequest:request]; + + if (cachedETag != nil) { + [request addValue:cachedETag forHTTPHeaderField:kGTMIfNoneMatchHeader]; + } + } else { + // Has an ETag: remove any stored response in the fetch history + // for this request, as the If-None-Match header could lead to + // a 304 Not Modified, and we want that error delivered to the + // user since they explicitly specified the ETag + [self removeCachedDataForRequest:request]; + } + } + } + } +} + +- (void)updateFetchHistoryWithRequest:(NSURLRequest *)request + response:(NSURLResponse *)response + downloadedData:(NSData *)downloadedData { + @synchronized(self) { + if (![self shouldRememberETags]) return; + + if (![response respondsToSelector:@selector(allHeaderFields)]) return; + + NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; + + if (statusCode != kGTMHTTPFetcherStatusNotModified) { + // Save this ETag string for successful results (<300) + // If there's no last modified string, clear the dictionary + // entry for this URL. Also cache or delete the data, if appropriate + // (when etaggedDataCache is non-nil.) + NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields]; + NSString* etag = [headers objectForKey:kGTMETagHeader]; + + if (etag != nil && statusCode < 300) { + + // we want to cache responses for the headers, even if the client + // doesn't want the response body data caches + NSData *dataToStore = shouldCacheETaggedData_ ? downloadedData : nil; + + GTMCachedURLResponse *cachedResponse; + cachedResponse = [[[GTMCachedURLResponse alloc] initWithResponse:response + data:dataToStore] autorelease]; + [etaggedDataCache_ storeCachedResponse:cachedResponse + forRequest:request]; + } else { + [etaggedDataCache_ removeCachedResponseForRequest:request]; + } + } + } +} + +- (NSString *)cachedETagForRequest:(NSURLRequest *)request { + // Internal routine. + GTMCachedURLResponse *cachedResponse; + cachedResponse = [etaggedDataCache_ cachedResponseForRequest:request]; + + NSURLResponse *response = [cachedResponse response]; + NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields]; + NSString *cachedETag = [headers objectForKey:kGTMETagHeader]; + if (cachedETag) { + // Since the request having an ETag implies this request is about + // to be fetched again, reserve the cached response to ensure that + // that it will be around at least until the fetch completes. + // + // When the fetch completes, either the cached response will be replaced + // with a new response, or the cachedDataForRequest: method below will + // clear the reservation. + [cachedResponse setReservationDate:[NSDate date]]; + } + return cachedETag; +} + +- (NSData *)cachedDataForRequest:(NSURLRequest *)request { + @synchronized(self) { + GTMCachedURLResponse *cachedResponse; + cachedResponse = [etaggedDataCache_ cachedResponseForRequest:request]; + + NSData *cachedData = [cachedResponse data]; + + // Since the data for this cached request is being obtained from the cache, + // we can clear the reservation as the fetch has completed. + [cachedResponse setReservationDate:nil]; + + return cachedData; + } +} + +- (void)removeCachedDataForRequest:(NSURLRequest *)request { + @synchronized(self) { + [etaggedDataCache_ removeCachedResponseForRequest:request]; + } +} + +- (void)clearETaggedDataCache { + @synchronized(self) { + [etaggedDataCache_ removeAllCachedResponses]; + } +} + +- (void)clearHistory { + @synchronized(self) { + [self clearETaggedDataCache]; + [cookieStorage_ removeAllCookies]; + } +} + +- (void)removeAllCookies { + @synchronized(self) { + [cookieStorage_ removeAllCookies]; + } +} + +- (BOOL)shouldRememberETags { + return shouldRememberETags_; +} + +- (void)setShouldRememberETags:(BOOL)flag { + BOOL wasRemembering = shouldRememberETags_; + shouldRememberETags_ = flag; + + if (wasRemembering && !flag) { + // Free up the cache memory + [self clearETaggedDataCache]; + } +} + +- (BOOL)shouldCacheETaggedData { + return shouldCacheETaggedData_; +} + +- (void)setShouldCacheETaggedData:(BOOL)flag { + BOOL wasCaching = shouldCacheETaggedData_; + shouldCacheETaggedData_ = flag; + + if (flag) { + self.shouldRememberETags = YES; + } + + if (wasCaching && !flag) { + // users expect turning off caching to free up the cache memory + [self clearETaggedDataCache]; + } +} + +- (NSUInteger)memoryCapacity { + return [etaggedDataCache_ memoryCapacity]; +} + +- (void)setMemoryCapacity:(NSUInteger)totalBytes { + [etaggedDataCache_ setMemoryCapacity:totalBytes]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcher.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcher.h new file mode 100755 index 0000000..8cf6121 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcher.h @@ -0,0 +1,847 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPFetcher.h +// + +// This is essentially a wrapper around NSURLConnection for POSTs and GETs. +// If setPostData: is called, then POST is assumed. +// +// When would you use this instead of NSURLConnection? +// +// - When you just want the result from a GET, POST, or PUT +// - When you want the "standard" behavior for connections (redirection handling +// an so on) +// - When you want automatic retry on failures +// - When you want to avoid cookie collisions with Safari and other applications +// - When you are fetching resources with ETags and want to avoid the overhead +// of repeated fetches of unchanged data +// - When you need to set a credential for the http operation +// +// This is assumed to be a one-shot fetch request; don't reuse the object +// for a second fetch. +// +// The fetcher may be created auto-released, in which case it will release +// itself after the fetch completion callback. The fetcher is implicitly +// retained as long as a connection is pending. +// +// But if you may need to cancel the fetcher, retain it and have the delegate +// release the fetcher in the callbacks. +// +// Sample usage: +// +// NSURLRequest *request = [NSURLRequest requestWithURL:myURL]; +// GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request]; +// +// // optional upload body data +// [myFetcher setPostData:[postString dataUsingEncoding:NSUTF8StringEncoding]]; +// +// [myFetcher beginFetchWithDelegate:self +// didFinishSelector:@selector(myFetcher:finishedWithData:error:)]; +// +// Upon fetch completion, the callback selector is invoked; it should have +// this signature (you can use any callback method name you want so long as +// the signature matches this): +// +// - (void)myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)retrievedData error:(NSError *)error; +// +// The block callback version looks like: +// +// [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) { +// if (error != nil) { +// // status code or network error +// } else { +// // succeeded +// } +// }]; + +// +// NOTE: Fetches may retrieve data from the server even though the server +// returned an error. The failure selector is called when the server +// status is >= 300, with an NSError having domain +// kGTMHTTPFetcherStatusDomain and code set to the server status. +// +// Status codes are at +// +// +// Threading and queue support: +// +// Callbacks require either that the thread used to start the fetcher have a run +// loop spinning (typically the main thread), or that an NSOperationQueue be +// provided upon which the delegate callbacks will be called. Starting with +// iOS 6 and Mac OS X 10.7, clients may simply create an operation queue for +// callbacks on a background thread: +// +// NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; +// [queue setMaxConcurrentOperationCount:1]; +// fetcher.delegateQueue = queue; +// +// or specify the main queue for callbacks on the main thread: +// +// fetcher.delegateQueue = [NSOperationQueue mainQueue]; +// +// The client may also re-dispatch from the callbacks and notifications to +// a known dispatch queue: +// +// [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) { +// if (error == nil) { +// dispatch_async(myDispatchQueue, ^{ +// ... +// }); +// } +// }]; +// +// +// +// Downloading to disk: +// +// To have downloaded data saved directly to disk, specify either a path for the +// downloadPath property, or a file handle for the downloadFileHandle property. +// When downloading to disk, callbacks will be passed a nil for the NSData* +// arguments. +// +// +// HTTP methods and headers: +// +// Alternative HTTP methods, like PUT, and custom headers can be specified by +// creating the fetcher with an appropriate NSMutableURLRequest +// +// +// Proxies: +// +// Proxy handling is invisible so long as the system has a valid credential in +// the keychain, which is normally true (else most NSURL-based apps would have +// difficulty.) But when there is a proxy authetication error, the the fetcher +// will call the failedWithError: method with the NSURLChallenge in the error's +// userInfo. The error method can get the challenge info like this: +// +// NSURLAuthenticationChallenge *challenge +// = [[error userInfo] objectForKey:kGTMHTTPFetcherErrorChallengeKey]; +// BOOL isProxyChallenge = [[challenge protectionSpace] isProxy]; +// +// If a proxy error occurs, you can ask the user for the proxy username/password +// and call fetcher's setProxyCredential: to provide those for the +// next attempt to fetch. +// +// +// Cookies: +// +// There are three supported mechanisms for remembering cookies between fetches. +// +// By default, GTMHTTPFetcher uses a mutable array held statically to track +// cookies for all instantiated fetchers. This avoids server cookies being set +// by servers for the application from interfering with Safari cookie settings, +// and vice versa. The fetcher cookies are lost when the application quits. +// +// To rely instead on WebKit's global NSHTTPCookieStorage, call +// setCookieStorageMethod: with kGTMHTTPFetcherCookieStorageMethodSystemDefault. +// +// If the fetcher is created from a GTMHTTPFetcherService object +// then the cookie storage mechanism is set to use the cookie storage in the +// service object rather than the static storage. +// +// +// Fetching for periodic checks: +// +// The fetcher object tracks ETag headers from responses and +// provide an "If-None-Match" header. This allows the server to save +// bandwidth by providing a status message instead of repeated response +// data. +// +// To get this behavior, create the fetcher from an GTMHTTPFetcherService object +// and look for a fetch callback error with code 304 +// (kGTMHTTPFetcherStatusNotModified) like this: +// +// - (void)myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error { +// if ([error code] == kGTMHTTPFetcherStatusNotModified) { +// // |data| is empty; use the data from the previous finishedWithData: for this URL +// } else { +// // handle other server status code +// } +// } +// +// +// Monitoring received data +// +// The optional received data selector can be set with setReceivedDataSelector: +// and should have the signature +// +// - (void)myFetcher:(GTMHTTPFetcher *)fetcher receivedData:(NSData *)dataReceivedSoFar; +// +// The number bytes received so far is available as [fetcher downloadedLength]. +// This number may go down if a redirect causes the download to begin again from +// a new server. +// +// If supplied by the server, the anticipated total download size is available +// as [[myFetcher response] expectedContentLength] (and may be -1 for unknown +// download sizes.) +// +// +// Automatic retrying of fetches +// +// The fetcher can optionally create a timer and reattempt certain kinds of +// fetch failures (status codes 408, request timeout; 503, service unavailable; +// 504, gateway timeout; networking errors NSURLErrorTimedOut and +// NSURLErrorNetworkConnectionLost.) The user may set a retry selector to +// customize the type of errors which will be retried. +// +// Retries are done in an exponential-backoff fashion (that is, after 1 second, +// 2, 4, 8, and so on.) +// +// Enabling automatic retries looks like this: +// [myFetcher setRetryEnabled:YES]; +// +// With retries enabled, the success or failure callbacks are called only +// when no more retries will be attempted. Calling the fetcher's stopFetching +// method will terminate the retry timer, without the finished or failure +// selectors being invoked. +// +// Optionally, the client may set the maximum retry interval: +// [myFetcher setMaxRetryInterval:60.0]; // in seconds; default is 60 seconds +// // for downloads, 600 for uploads +// +// Also optionally, the client may provide a callback selector to determine +// if a status code or other error should be retried. +// [myFetcher setRetrySelector:@selector(myFetcher:willRetry:forError:)]; +// +// If set, the retry selector should have the signature: +// -(BOOL)fetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error +// and return YES to set the retry timer or NO to fail without additional +// fetch attempts. +// +// The retry method may return the |suggestedWillRetry| argument to get the +// default retry behavior. Server status codes are present in the +// error argument, and have the domain kGTMHTTPFetcherStatusDomain. The +// user's method may look something like this: +// +// -(BOOL)myFetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error { +// +// // perhaps examine [error domain] and [error code], or [fetcher retryCount] +// // +// // return YES to start the retry timer, NO to proceed to the failure +// // callback, or |suggestedWillRetry| to get default behavior for the +// // current error domain and code values. +// return suggestedWillRetry; +// } + + + +#pragma once + +#import + +#if defined(GTL_TARGET_NAMESPACE) + // we're using target namespace macros + #import "GTLDefines.h" +#elif defined(GDATA_TARGET_NAMESPACE) + #import "GDataDefines.h" +#else + #if TARGET_OS_IPHONE + #ifndef GTM_FOUNDATION_ONLY + #define GTM_FOUNDATION_ONLY 1 + #endif + #ifndef GTM_IPHONE + #define GTM_IPHONE 1 + #endif + #endif +#endif + +#if TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000) + #define GTM_BACKGROUND_FETCHING 1 +#endif + +#ifndef GTM_ALLOW_INSECURE_REQUESTS + // For builds prior to the iOS 8/10.10 SDKs, default to ignoring insecure requests for backwards + // compatibility unless the project has smartly set GTM_ALLOW_INSECURE_REQUESTS explicitly. + #if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0) + #define GTM_ALLOW_INSECURE_REQUESTS 0 + #else + #define GTM_ALLOW_INSECURE_REQUESTS 1 + #endif +#endif + +#if !defined(GTMBridgeFetcher) + // These bridge macros should be identical in GTMHTTPFetcher.h and GTMSessionFetcher.h + #if GTM_USE_SESSION_FETCHER + // Macros to new fetcher class. + #define GTMBridgeFetcher GTMSessionFetcher + #define GTMBridgeFetcherService GTMSessionFetcherService + #define GTMBridgeFetcherServiceProtocol GTMSessionFetcherServiceProtocol + #define GTMBridgeAssertValidSelector GTMSessionFetcherAssertValidSelector + #define GTMBridgeCookieStorage GTMSessionCookieStorage + #define GTMBridgeCleanedUserAgentString GTMFetcherCleanedUserAgentString + #define GTMBridgeSystemVersionString GTMFetcherSystemVersionString + #define GTMBridgeApplicationIdentifier GTMFetcherApplicationIdentifier + #define kGTMBridgeFetcherStatusDomain kGTMSessionFetcherStatusDomain + #define kGTMBridgeFetcherStatusBadRequest kGTMSessionFetcherStatusBadRequest + #else + // Macros to old fetcher class. + #define GTMBridgeFetcher GTMHTTPFetcher + #define GTMBridgeFetcherService GTMHTTPFetcherService + #define GTMBridgeFetcherServiceProtocol GTMHTTPFetcherServiceProtocol + #define GTMBridgeAssertValidSelector GTMAssertSelectorNilOrImplementedWithArgs + #define GTMBridgeCookieStorage GTMCookieStorage + #define GTMBridgeCleanedUserAgentString GTMCleanedUserAgentString + #define GTMBridgeSystemVersionString GTMSystemVersionString + #define GTMBridgeApplicationIdentifier GTMApplicationIdentifier + #define kGTMBridgeFetcherStatusDomain kGTMHTTPFetcherStatusDomain + #define kGTMBridgeFetcherStatusBadRequest kGTMHTTPFetcherStatusBadRequest + #endif // GTM_USE_SESSION_FETCHER +#endif // !defined(GTMBridgeFetcher) + +#ifdef __cplusplus +extern "C" { +#endif + +// notifications +// +// fetch started and stopped, and fetch retry delay started and stopped +extern NSString *const kGTMHTTPFetcherStartedNotification; +extern NSString *const kGTMHTTPFetcherStoppedNotification; +extern NSString *const kGTMHTTPFetcherRetryDelayStartedNotification; +extern NSString *const kGTMHTTPFetcherRetryDelayStoppedNotification; + +// callback constants + +extern NSString *const kGTMHTTPFetcherErrorDomain; +extern NSString *const kGTMHTTPFetcherStatusDomain; +extern NSString *const kGTMHTTPFetcherErrorChallengeKey; +extern NSString *const kGTMHTTPFetcherStatusDataKey; // data returned with a kGTMHTTPFetcherStatusDomain error + +#ifdef __cplusplus +} +#endif + +enum { + kGTMHTTPFetcherErrorDownloadFailed = -1, + kGTMHTTPFetcherErrorAuthenticationChallengeFailed = -2, + kGTMHTTPFetcherErrorChunkUploadFailed = -3, + kGTMHTTPFetcherErrorFileHandleException = -4, + kGTMHTTPFetcherErrorBackgroundExpiration = -6, + + // The code kGTMHTTPFetcherErrorAuthorizationFailed (-5) has been removed; + // look for status 401 instead. + + kGTMHTTPFetcherStatusNotModified = 304, + kGTMHTTPFetcherStatusBadRequest = 400, + kGTMHTTPFetcherStatusUnauthorized = 401, + kGTMHTTPFetcherStatusForbidden = 403, + kGTMHTTPFetcherStatusPreconditionFailed = 412 +}; + +// cookie storage methods +enum { + kGTMHTTPFetcherCookieStorageMethodStatic = 0, + kGTMHTTPFetcherCookieStorageMethodFetchHistory = 1, + kGTMHTTPFetcherCookieStorageMethodSystemDefault = 2, + kGTMHTTPFetcherCookieStorageMethodNone = 3 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void GTMAssertSelectorNilOrImplementedWithArgs(id obj, SEL sel, ...); + +// Utility functions for applications self-identifying to servers via a +// user-agent header + +// Make a proper app name without whitespace from the given string, removing +// whitespace and other characters that may be special parsed marks of +// the full user-agent string. +NSString *GTMCleanedUserAgentString(NSString *str); + +// Make an identifier like "MacOSX/10.7.1" or "iPod_Touch/4.1 hw/iPod1_1" +NSString *GTMSystemVersionString(void); + +// Make a generic name and version for the current application, like +// com.example.MyApp/1.2.3 relying on the bundle identifier and the +// CFBundleShortVersionString or CFBundleVersion. +// +// The bundle ID may be overridden as the base identifier string by +// adding to the bundle's Info.plist a "GTMUserAgentID" key. +// +// If no bundle ID or override is available, the process name preceded +// by "proc_" is used. +NSString *GTMApplicationIdentifier(NSBundle *bundle); + +#ifdef __cplusplus +} // extern "C" +#endif + +@class GTMHTTPFetcher; + +@protocol GTMCookieStorageProtocol +// This protocol allows us to call into the service without requiring +// GTMCookieStorage sources in this project +// +// The public interface for cookie handling is the GTMCookieStorage class, +// accessible from a fetcher service object's fetchHistory or from the fetcher's +// +staticCookieStorage method. +- (NSArray *)cookiesForURL:(NSURL *)theURL; +- (void)setCookies:(NSArray *)newCookies; +@end + +@protocol GTMHTTPFetchHistoryProtocol +// This protocol allows us to call the fetch history object without requiring +// GTMHTTPFetchHistory sources in this project +- (void)updateRequest:(NSMutableURLRequest *)request isHTTPGet:(BOOL)isHTTPGet; +- (BOOL)shouldCacheETaggedData; +- (NSData *)cachedDataForRequest:(NSURLRequest *)request; +- (id )cookieStorage; +- (void)updateFetchHistoryWithRequest:(NSURLRequest *)request + response:(NSURLResponse *)response + downloadedData:(NSData *)downloadedData; +- (void)removeCachedDataForRequest:(NSURLRequest *)request; +@end + +#if GTM_USE_SESSION_FETCHER +@protocol GTMSessionFetcherServiceProtocol; +#endif + +@protocol GTMHTTPFetcherServiceProtocol +// This protocol allows us to call into the service without requiring +// GTMHTTPFetcherService sources in this project + +@property (retain) NSOperationQueue *delegateQueue; + +- (BOOL)fetcherShouldBeginFetching:(GTMHTTPFetcher *)fetcher; +- (void)fetcherDidStop:(GTMHTTPFetcher *)fetcher; + +- (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request; +- (BOOL)isDelayingFetcher:(GTMHTTPFetcher *)fetcher; +@end + +#if !defined(GTM_FETCHER_AUTHORIZATION_PROTOCOL) +#define GTM_FETCHER_AUTHORIZATION_PROTOCOL 1 +@protocol GTMFetcherAuthorizationProtocol +@required +// This protocol allows us to call the authorizer without requiring its sources +// in this project. +- (void)authorizeRequest:(NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel; + +- (void)stopAuthorization; + +- (void)stopAuthorizationForRequest:(NSURLRequest *)request; + +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request; + +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request; + +@property (retain, readonly) NSString *userEmail; + +@optional + +// Indicate if authorization may be attempted. Even if this succeeds, +// authorization may fail if the user's permissions have been revoked. +@property (readonly) BOOL canAuthorize; + +// For development only, allow authorization of non-SSL requests, allowing +// transmission of the bearer token unencrypted. +@property (assign) BOOL shouldAuthorizeAllRequests; + +#if NS_BLOCKS_AVAILABLE +- (void)authorizeRequest:(NSMutableURLRequest *)request + completionHandler:(void (^)(NSError *error))handler; +#endif + +#if GTM_USE_SESSION_FETCHER +@property (assign) id fetcherService; // WEAK +#else +@property (assign) id fetcherService; // WEAK +#endif + +- (BOOL)primeForRefresh; + +@end +#endif // !defined(GTM_FETCHER_AUTHORIZATION_PROTOCOL) + + +// GTMHTTPFetcher objects are used for async retrieval of an http get or post +// +// See additional comments at the beginning of this file +@interface GTMHTTPFetcher : NSObject { + @protected + NSMutableURLRequest *request_; + NSURLConnection *connection_; + NSMutableData *downloadedData_; + NSString *downloadPath_; + NSString *temporaryDownloadPath_; + NSFileHandle *downloadFileHandle_; + unsigned long long downloadedLength_; + NSArray *allowedInsecureSchemes_; + BOOL allowLocalhostRequest_; + NSURLCredential *credential_; // username & password + NSURLCredential *proxyCredential_; // credential supplied to proxy servers + NSData *postData_; + NSInputStream *postStream_; + NSMutableData *loggedStreamData_; + NSURLResponse *response_; // set in connection:didReceiveResponse: + id delegate_; + SEL finishedSel_; // should by implemented by delegate + SEL sentDataSel_; // optional, set with setSentDataSelector + SEL receivedDataSel_; // optional, set with setReceivedDataSelector +#if NS_BLOCKS_AVAILABLE + void (^completionBlock_)(NSData *, NSError *); + void (^receivedDataBlock_)(NSData *); + void (^sentDataBlock_)(NSInteger, NSInteger, NSInteger); + BOOL (^retryBlock_)(BOOL, NSError *); +#elif !__LP64__ + // placeholders: for 32-bit builds, keep the size of the object's ivar section + // the same with and without blocks + id completionPlaceholder_; + id receivedDataPlaceholder_; + id sentDataPlaceholder_; + id retryPlaceholder_; +#endif + BOOL hasConnectionEnded_; // set if the connection need not be cancelled + BOOL isCancellingChallenge_; // set only when cancelling an auth challenge + BOOL isStopNotificationNeeded_; // set when start notification has been sent + BOOL shouldFetchInBackground_; +#if GTM_BACKGROUND_FETCHING + NSUInteger backgroundTaskIdentifer_; // UIBackgroundTaskIdentifier +#endif + id userData_; // retained, if set by caller + NSMutableDictionary *properties_; // more data retained for caller + NSArray *runLoopModes_; // optional + NSOperationQueue *delegateQueue_; // optional; available iOS 6/10.7 and later + id fetchHistory_; // if supplied by the caller, used for Last-Modified-Since checks and cookies + NSInteger cookieStorageMethod_; // constant from above + id cookieStorage_; + + id authorizer_; + + // the service object that created and monitors this fetcher, if any + id service_; + NSString *serviceHost_; + NSInteger servicePriority_; + NSThread *thread_; + + BOOL isRetryEnabled_; // user wants auto-retry + SEL retrySel_; // optional; set with setRetrySelector + NSTimer *retryTimer_; + NSUInteger retryCount_; + NSTimeInterval maxRetryInterval_; // default 600 seconds + NSTimeInterval minRetryInterval_; // random between 1 and 2 seconds + NSTimeInterval retryFactor_; // default interval multiplier is 2 + NSTimeInterval lastRetryInterval_; + NSDate *initialRequestDate_; + BOOL hasAttemptedAuthRefresh_; + + NSString *comment_; // comment for log + NSString *log_; +#if !STRIP_GTM_FETCH_LOGGING + NSURL *redirectedFromURL_; + NSString *logRequestBody_; + NSString *logResponseBody_; + BOOL hasLoggedError_; + BOOL shouldDeferResponseBodyLogging_; +#endif +} + +// Create a fetcher +// +// fetcherWithRequest will return an autoreleased fetcher, but if +// the connection is successfully created, the connection should retain the +// fetcher for the life of the connection as well. So the caller doesn't have +// to retain the fetcher explicitly unless they want to be able to cancel it. ++ (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request; + +// Convenience methods that make a request, like +fetcherWithRequest ++ (GTMHTTPFetcher *)fetcherWithURL:(NSURL *)requestURL; ++ (GTMHTTPFetcher *)fetcherWithURLString:(NSString *)requestURLString; + +// Designated initializer +- (id)initWithRequest:(NSURLRequest *)request; + +// Fetcher request +// +// The underlying request is mutable and may be modified by the caller +@property (retain) NSMutableURLRequest *mutableRequest; + +// By default, the fetcher allows only secure (https) schemes unless this +// property is set, or the GTM_ALLOW_INSECURE_REQUESTS build flag is set. +// +// For example, during debugging when fetching from a development server that lacks SSL support, +// this may be set to @[ @"http" ], or when the fetcher is used to retrieve local files, +// this may be set to @[ @"file" ]. +// +// This should be left as nil for release builds to avoid creating the opportunity for +// leaking private user behavior and data. If a server is providing insecure URLs +// for fetching by the client app, report the problem as server security & privacy bug. +@property(copy) NSArray *allowedInsecureSchemes; + +// By default, the fetcher prohibits localhost requests unless this property is set, +// or the GTM_ALLOW_INSECURE_REQUESTS build flag is set. +// +// For localhost requests, the URL scheme is not checked when this property is set. +@property(assign) BOOL allowLocalhostRequest; + +// Setting the credential is optional; it is used if the connection receives +// an authentication challenge +@property (retain) NSURLCredential *credential; + +// Setting the proxy credential is optional; it is used if the connection +// receives an authentication challenge from a proxy +@property (retain) NSURLCredential *proxyCredential; + +// If post data or stream is not set, then a GET retrieval method is assumed +@property (retain) NSData *postData; +@property (retain) NSInputStream *postStream; + +// The default cookie storage method is kGTMHTTPFetcherCookieStorageMethodStatic +// without a fetch history set, and kGTMHTTPFetcherCookieStorageMethodFetchHistory +// with a fetch history set +// +// Applications needing control of cookies across a sequence of fetches should +// create fetchers from a GTMHTTPFetcherService object (which encapsulates +// fetch history) for a well-defined cookie store +@property (assign) NSInteger cookieStorageMethod; + ++ (id )staticCookieStorage; + +// Object to add authorization to the request, if needed +@property (retain) id authorizer; + +// The service object that created and monitors this fetcher, if any +@property (retain) id service; + +// The host, if any, used to classify this fetcher in the fetcher service +@property (copy) NSString *serviceHost; + +// The priority, if any, used for starting fetchers in the fetcher service +// +// Lower values are higher priority; the default is 0, and values may +// be negative or positive. This priority affects only the start order of +// fetchers that are being delayed by a fetcher service. +@property (assign) NSInteger servicePriority; + +// The thread used to run this fetcher in the fetcher service when no operation +// queue is provided. +@property (retain) NSThread *thread; + +// The delegate is retained during the connection +@property (retain) id delegate; + +// On iOS 4 and later, the fetch may optionally continue while the app is in the +// background until finished or stopped by OS expiration +// +// The default value is NO +// +// For Mac OS X, background fetches are always supported, and this property +// is ignored +@property (assign) BOOL shouldFetchInBackground; + +// The delegate's optional sentData selector may be used to monitor upload +// progress. It should have a signature like: +// - (void)myFetcher:(GTMHTTPFetcher *)fetcher +// didSendBytes:(NSInteger)bytesSent +// totalBytesSent:(NSInteger)totalBytesSent +// totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend; +// +// +doesSupportSentDataCallback indicates if this delegate method is supported ++ (BOOL)doesSupportSentDataCallback; + +@property (assign) SEL sentDataSelector; + +// The delegate's optional receivedData selector may be used to monitor download +// progress. It should have a signature like: +// - (void)myFetcher:(GTMHTTPFetcher *)fetcher +// receivedData:(NSData *)dataReceivedSoFar; +// +// The dataReceived argument will be nil when downloading to a path or to a +// file handle. +// +// Applications should not use this method to accumulate the received data; +// the callback method or block supplied to the beginFetch call will have +// the complete NSData received. +@property (assign) SEL receivedDataSelector; + +#if NS_BLOCKS_AVAILABLE +// The full interface to the block is provided rather than just a typedef for +// its parameter list in order to get more useful code completion in the Xcode +// editor +@property (copy) void (^sentDataBlock)(NSInteger bytesSent, NSInteger totalBytesSent, NSInteger bytesExpectedToSend); + +// The dataReceived argument will be nil when downloading to a path or to +// a file handle +@property (copy) void (^receivedDataBlock)(NSData *dataReceivedSoFar); +#endif + +// retrying; see comments at the top of the file. Calling +// setRetryEnabled(YES) resets the min and max retry intervals. +@property (assign, getter=isRetryEnabled) BOOL retryEnabled; + +// Retry selector or block is optional for retries. +// +// If present, it should have the signature: +// -(BOOL)fetcher:(GTMHTTPFetcher *)fetcher willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error +// and return YES to cause a retry. See comments at the top of this file. +@property (assign) SEL retrySelector; + +#if NS_BLOCKS_AVAILABLE +@property (copy) BOOL (^retryBlock)(BOOL suggestedWillRetry, NSError *error); +#endif + +// Retry intervals must be strictly less than maxRetryInterval, else +// they will be limited to maxRetryInterval and no further retries will +// be attempted. Setting maxRetryInterval to 0.0 will reset it to the +// default value, 600 seconds. + +@property (assign) NSTimeInterval maxRetryInterval; + +// Starting retry interval. Setting minRetryInterval to 0.0 will reset it +// to a random value between 1.0 and 2.0 seconds. Clients should normally not +// call this except for unit testing. +@property (assign) NSTimeInterval minRetryInterval; + +// Multiplier used to increase the interval between retries, typically 2.0. +// Clients should not need to call this. +@property (assign) double retryFactor; + +// Number of retries attempted +@property (readonly) NSUInteger retryCount; + +// interval delay to precede next retry +@property (readonly) NSTimeInterval nextRetryInterval; + +// Begin fetching the request +// +// The delegate can optionally implement the finished selectors or pass NULL +// for it. +// +// Returns YES if the fetch is initiated. The delegate is retained between +// the beginFetch call until after the finish callback. +// +// An error is passed to the callback for server statuses 300 or +// higher, with the status stored as the error object's code. +// +// finishedSEL has a signature like: +// - (void)fetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error; +// +// If the application has specified a downloadPath or downloadFileHandle +// for the fetcher, the data parameter passed to the callback will be nil. + +- (BOOL)beginFetchWithDelegate:(id)delegate + didFinishSelector:(SEL)finishedSEL; + +#if NS_BLOCKS_AVAILABLE +- (BOOL)beginFetchWithCompletionHandler:(void (^)(NSData *data, NSError *error))handler; +#endif + + +// Returns YES if this is in the process of fetching a URL +- (BOOL)isFetching; + +// Cancel the fetch of the request that's currently in progress +- (void)stopFetching; + +// Return the status code from the server response +@property (readonly) NSInteger statusCode; + +// Return the http headers from the response +@property (retain, readonly) NSDictionary *responseHeaders; + +// The response, once it's been received +@property (retain) NSURLResponse *response; + +// Bytes downloaded so far +@property (readonly) unsigned long long downloadedLength; + +// Buffer of currently-downloaded data +@property (readonly, retain) NSData *downloadedData; + +// Path in which to non-atomically create a file for storing the downloaded data +// +// The path must be set before fetching begins. The download file handle +// will be created for the path, and can be used to monitor progress. If a file +// already exists at the path, it will be overwritten. +@property (copy) NSString *downloadPath; + +// If downloadFileHandle is set, data received is immediately appended to +// the file handle rather than being accumulated in the downloadedData property +// +// The file handle supplied must allow writing and support seekToFileOffset:, +// and must be set before fetching begins. Setting a download path will +// override the file handle property. +@property (retain) NSFileHandle *downloadFileHandle; + +// The optional fetchHistory object is used for a sequence of fetchers to +// remember ETags, cache ETagged data, and store cookies. Typically, this +// is set by a GTMFetcherService object when it creates a fetcher. +// +// Side effect: setting fetch history implicitly calls setCookieStorageMethod: +@property (retain) id fetchHistory; + +// userData is retained for the convenience of the caller +@property (retain) id userData; + +// Stored property values are retained for the convenience of the caller +@property (copy) NSMutableDictionary *properties; + +- (void)setProperty:(id)obj forKey:(NSString *)key; // pass nil obj to remove property +- (id)propertyForKey:(NSString *)key; + +- (void)addPropertiesFromDictionary:(NSDictionary *)dict; + +// Comments are useful for logging +@property (copy) NSString *comment; + +- (void)setCommentWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); + +// Log of request and response, if logging is enabled +@property (copy) NSString *log; + +// Callbacks can be invoked on an operation queue rather than via the run loop, +// starting on 10.7 and iOS 6. If a delegate queue is supplied. the run loop +// modes are ignored. If no delegateQueue is supplied, and run loop modes are +// not supplied, and the fetcher is started off of the main thread, then a +// delegateQueue of [NSOperationQueue mainQueue] is assumed. +@property (retain) NSOperationQueue *delegateQueue; + +// Using the fetcher while a modal dialog is displayed requires setting the +// run-loop modes to include NSModalPanelRunLoopMode +@property (retain) NSArray *runLoopModes; + +// Users who wish to replace GTMHTTPFetcher's use of NSURLConnection +// can do so globally here. The replacement should be a subclass of +// NSURLConnection. ++ (Class)connectionClass; ++ (void)setConnectionClass:(Class)theClass; + +// +// Method for compatibility with GTMSessionFetcher +// +@property (retain) NSData *bodyData; + +// Spin the run loop, discarding events, until the fetch has completed +// +// This is only for use in testing or in tools without a user interface. +// +// Synchronous fetches should never be done by shipping apps; they are +// sufficient reason for rejection from the app store. +- (void)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds; + +#if STRIP_GTM_FETCH_LOGGING +// if logging is stripped, provide a stub for the main method +// for controlling logging ++ (void)setLoggingEnabled:(BOOL)flag; +#endif // STRIP_GTM_FETCH_LOGGING + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcher.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcher.m new file mode 100755 index 0000000..99e1892 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcher.m @@ -0,0 +1,2156 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPFetcher.m +// + +#import "GTMHTTPFetcher.h" + +#if GTM_BACKGROUND_FETCHING +#import +#endif + +#import + +static id gGTMFetcherStaticCookieStorage = nil; +static Class gGTMFetcherConnectionClass = nil; + + +NSString *const kGTMHTTPFetcherStartedNotification = @"kGTMHTTPFetcherStartedNotification"; +NSString *const kGTMHTTPFetcherStoppedNotification = @"kGTMHTTPFetcherStoppedNotification"; +NSString *const kGTMHTTPFetcherRetryDelayStartedNotification = @"kGTMHTTPFetcherRetryDelayStartedNotification"; +NSString *const kGTMHTTPFetcherRetryDelayStoppedNotification = @"kGTMHTTPFetcherRetryDelayStoppedNotification"; + +NSString *const kGTMHTTPFetcherErrorDomain = @"com.google.GTMHTTPFetcher"; +NSString *const kGTMHTTPFetcherStatusDomain = @"com.google.HTTPStatus"; +NSString *const kGTMHTTPFetcherErrorChallengeKey = @"challenge"; +NSString *const kGTMHTTPFetcherStatusDataKey = @"data"; // data returned with a kGTMHTTPFetcherStatusDomain error + +// The default max retry interview is 10 minutes for uploads (POST/PUT/PATCH), +// 1 minute for downloads. +static const NSTimeInterval kUnsetMaxRetryInterval = -1; +static const NSTimeInterval kDefaultMaxDownloadRetryInterval = 60.0; +static const NSTimeInterval kDefaultMaxUploadRetryInterval = 60.0 * 10.; + +// delegateQueue callback parameters +static NSString *const kCallbackTarget = @"target"; +static NSString *const kCallbackSelector = @"sel"; +static NSString *const kCallbackBlock = @"block"; +static NSString *const kCallbackData = @"data"; +static NSString *const kCallbackError = @"error"; + +// +// GTMHTTPFetcher +// + +@interface GTMHTTPFetcher () + +@property (copy) NSString *temporaryDownloadPath; +@property (retain) id cookieStorage; +@property (readwrite, retain) NSData *downloadedData; +#if NS_BLOCKS_AVAILABLE +@property (copy) void (^completionBlock)(NSData *, NSError *); +#endif + +- (BOOL)beginFetchMayDelay:(BOOL)mayDelay + mayAuthorize:(BOOL)mayAuthorize; +- (void)failToBeginFetchWithError:(NSError *)error; +- (void)failToBeginFetchDeferWithError:(NSError *)error; + +#if GTM_BACKGROUND_FETCHING +- (void)endBackgroundTask; +- (void)backgroundFetchExpired; +#endif + +- (BOOL)authorizeRequest; +- (void)authorizer:(id )auth + request:(NSMutableURLRequest *)request + finishedWithError:(NSError *)error; + +- (NSString *)createTempDownloadFilePathForPath:(NSString *)targetPath; +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks; +- (BOOL)shouldReleaseCallbacksUponCompletion; + +- (void)addCookiesToRequest:(NSMutableURLRequest *)request; +- (void)handleCookiesForResponse:(NSURLResponse *)response; + +- (void)invokeFetchCallbacksWithData:(NSData *)data + error:(NSError *)error; +- (void)invokeFetchCallbacksWithTarget:(id)target + selector:(SEL)sel + block:(id)block + data:(NSData *)data + error:(NSError *)error; +- (void)invokeFetchCallback:(SEL)sel + target:(id)target + data:(NSData *)data + error:(NSError *)error; +- (void)invokeFetchCallbacksOnDelegateQueueWithData:(NSData *)data + error:(NSError *)error; +- (void)invokeOnQueueWithDictionary:(NSDictionary *)dict; +- (void)releaseCallbacks; + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; + +- (BOOL)shouldRetryNowForStatus:(NSInteger)status error:(NSError *)error; +- (void)destroyRetryTimer; +- (void)beginRetryTimer; +- (void)primeRetryTimerWithNewTimeInterval:(NSTimeInterval)secs; +- (void)sendStopNotificationIfNeeded; +- (void)retryFetch; +- (void)retryTimerFired:(NSTimer *)timer; +@end + +@interface GTMHTTPFetcher (GTMHTTPFetcherLoggingInternal) +- (void)setupStreamLogging; +- (void)logFetchWithError:(NSError *)error; +- (void)logNowWithError:(NSError *)error; +@end + +@implementation GTMHTTPFetcher + ++ (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request { + return [[[[self class] alloc] initWithRequest:request] autorelease]; +} + ++ (GTMHTTPFetcher *)fetcherWithURL:(NSURL *)requestURL { + return [self fetcherWithRequest:[NSURLRequest requestWithURL:requestURL]]; +} + ++ (GTMHTTPFetcher *)fetcherWithURLString:(NSString *)requestURLString { + return [self fetcherWithURL:[NSURL URLWithString:requestURLString]]; +} + ++ (void)initialize { + // initialize is guaranteed by the runtime to be called in a + // thread-safe manner + if (!gGTMFetcherStaticCookieStorage) { + Class cookieStorageClass = NSClassFromString(@"GTMCookieStorage"); + if (cookieStorageClass) { + gGTMFetcherStaticCookieStorage = [[cookieStorageClass alloc] init]; + } + } +} + +- (id)init { + return [self initWithRequest:nil]; +} + +- (id)initWithRequest:(NSURLRequest *)request { + self = [super init]; + if (self) { + request_ = [request mutableCopy]; + + if (gGTMFetcherStaticCookieStorage != nil) { + // The user has compiled with the cookie storage class available; + // default to static cookie storage, so our cookies are independent + // of the cookies of other apps. + [self setCookieStorageMethod:kGTMHTTPFetcherCookieStorageMethodStatic]; + } else { + // Default to system default cookie storage + [self setCookieStorageMethod:kGTMHTTPFetcherCookieStorageMethodSystemDefault]; + } +#if !STRIP_GTM_FETCH_LOGGING + // Encourage developers to set the comment property or use + // setCommentWithFormat: by providing a default string. + comment_ = @"(No fetcher comment set)"; +#endif + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + // disallow use of fetchers in a copy property + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p (%@)", + [self class], self, [self.mutableRequest URL]]; +} + +#if !GTM_IPHONE +- (void)finalize { + [self stopFetchReleasingCallbacks:YES]; // releases connection_, destroys timers + [super finalize]; +} +#endif + +- (void)dealloc { +#if DEBUG + NSAssert(!isStopNotificationNeeded_, + @"unbalanced fetcher notification for %@", [request_ URL]); +#endif + + // Note: if a connection or a retry timer was pending, then this instance + // would be retained by those so it wouldn't be getting dealloc'd, + // hence we don't need to stopFetch here + [request_ release]; + [connection_ release]; + [downloadedData_ release]; + [downloadPath_ release]; + [temporaryDownloadPath_ release]; + [downloadFileHandle_ release]; + [credential_ release]; + [proxyCredential_ release]; + [postData_ release]; + [postStream_ release]; + [loggedStreamData_ release]; + [response_ release]; +#if NS_BLOCKS_AVAILABLE + [completionBlock_ release]; + [receivedDataBlock_ release]; + [sentDataBlock_ release]; + [retryBlock_ release]; +#endif + [userData_ release]; + [properties_ release]; + [delegateQueue_ release]; + [runLoopModes_ release]; + [fetchHistory_ release]; + [cookieStorage_ release]; + [authorizer_ release]; + [service_ release]; + [serviceHost_ release]; + [thread_ release]; + [retryTimer_ release]; + [initialRequestDate_ release]; + [comment_ release]; + [log_ release]; +#if !STRIP_GTM_FETCH_LOGGING + [redirectedFromURL_ release]; + [logRequestBody_ release]; + [logResponseBody_ release]; +#endif + + [super dealloc]; +} + +#pragma mark - + +// Begin fetching the URL (or begin a retry fetch). The delegate is retained +// for the duration of the fetch connection. + +- (BOOL)beginFetchWithDelegate:(id)delegate + didFinishSelector:(SEL)finishedSelector { + GTMAssertSelectorNilOrImplementedWithArgs(delegate, finishedSelector, @encode(GTMHTTPFetcher *), @encode(NSData *), @encode(NSError *), 0); + GTMAssertSelectorNilOrImplementedWithArgs(delegate, receivedDataSel_, @encode(GTMHTTPFetcher *), @encode(NSData *), 0); + GTMAssertSelectorNilOrImplementedWithArgs(delegate, retrySel_, @encode(GTMHTTPFetcher *), @encode(BOOL), @encode(NSError *), 0); + + // We'll retain the delegate only during the outstanding connection (similar + // to what Cocoa does with performSelectorOnMainThread:) and during + // authorization or delays, since the app would crash + // if the delegate was released before the fetch calls back + [self setDelegate:delegate]; + finishedSel_ = finishedSelector; + + return [self beginFetchMayDelay:YES + mayAuthorize:YES]; +} + +- (BOOL)beginFetchMayDelay:(BOOL)mayDelay + mayAuthorize:(BOOL)mayAuthorize { + // This is the internal entry point for re-starting fetches + NSError *error = nil; + + if (connection_ != nil) { + NSAssert1(connection_ != nil, @"fetch object %@ being reused; this should never happen", self); + goto CannotBeginFetch; + } + + NSURL *requestURL = [request_ URL]; + if (request_ == nil || requestURL == nil) { + NSAssert(request_ != nil, @"beginFetchWithDelegate requires a request with a URL"); + goto CannotBeginFetch; + } + +#if !GTM_ALLOW_INSECURE_REQUESTS + if (requestURL != nil) { + // Allow https only for requests, unless overridden by the client. + // + // Non-https requests may too easily be snooped, so we disallow them by default. + // + // file: and data: schemes are usually safe if they are hardcoded in the client or provided + // by a trusted source, but since it's fairly rare to need them, it's safest to make clients + // explicitly whitelist them. + NSString *requestScheme = [requestURL scheme]; + BOOL isSecure = ([requestScheme caseInsensitiveCompare:@"https"] == NSOrderedSame); + if (!isSecure) { + BOOL allowRequest = NO; + NSString *host = [requestURL host]; + BOOL isLocalhost = ([host caseInsensitiveCompare:@"localhost"] == NSOrderedSame + || [host isEqual:@"::1"] + || [host isEqual:@"127.0.0.1"]); + if (isLocalhost) { + if (allowLocalhostRequest_) { + allowRequest = YES; + } else { + // To fetch from localhost, the fetcher must specifically have the allowLocalhostRequest + // property set. +#if DEBUG + NSAssert(NO, @"Fetch request for localhost but fetcher allowLocalhostRequest" + @" is not set: %@", requestURL); +#else + NSLog(@"Localhost fetch disallowed for %@", requestURL); +#endif + } + } else { + // Not localhost; check schemes. + for (NSString *allowedScheme in allowedInsecureSchemes_) { + if ([requestScheme caseInsensitiveCompare:allowedScheme] == NSOrderedSame) { + allowRequest = YES; + break; + } + } + if (!allowRequest) { + // To make a request other than https:, the client must specify an array for the + // allowedInsecureSchemes property. +#if DEBUG + NSAssert(NO, @"Insecure fetch request has a scheme (%@)" + @" not found in fetcher allowedInsecureSchemes (%@): %@", + requestScheme, allowedInsecureSchemes_, requestURL); +#else + NSLog(@"Fetch disallowed for %@", requestURL); +#endif + } + } + if (!allowRequest) { + goto CannotBeginFetch; + } + } // !isSecure + } // requestURL != nil +#endif // GTM_ALLOW_INSECURE_REQUESTS + + self.downloadedData = nil; + downloadedLength_ = 0; + + if (mayDelay && service_) { + BOOL shouldFetchNow = [service_ fetcherShouldBeginFetching:self]; + if (!shouldFetchNow) { + // the fetch is deferred, but will happen later + return YES; + } + } + + NSString *effectiveHTTPMethod = [request_ valueForHTTPHeaderField:@"X-HTTP-Method-Override"]; + if (effectiveHTTPMethod == nil) { + effectiveHTTPMethod = [request_ HTTPMethod]; + } + BOOL isEffectiveHTTPGet = (effectiveHTTPMethod == nil + || [effectiveHTTPMethod isEqual:@"GET"]); + + if (postData_ || postStream_) { + if (isEffectiveHTTPGet) { + [request_ setHTTPMethod:@"POST"]; + isEffectiveHTTPGet = NO; + } + + if (postData_) { + [request_ setHTTPBody:postData_]; + } else { + if ([self respondsToSelector:@selector(setupStreamLogging)]) { + [self performSelector:@selector(setupStreamLogging)]; + } + + [request_ setHTTPBodyStream:postStream_]; + } + } + + // We authorize after setting up the http method and body in the request + // because OAuth 1 may need to sign the request body + if (mayAuthorize && authorizer_) { + BOOL isAuthorized = [authorizer_ isAuthorizedRequest:request_]; + if (!isAuthorized) { + // authorization needed + return [self authorizeRequest]; + } + } + + [fetchHistory_ updateRequest:request_ isHTTPGet:isEffectiveHTTPGet]; + + // set the default upload or download retry interval, if necessary + if (isRetryEnabled_ + && maxRetryInterval_ <= kUnsetMaxRetryInterval) { + if (isEffectiveHTTPGet || [effectiveHTTPMethod isEqual:@"HEAD"]) { + [self setMaxRetryInterval:kDefaultMaxDownloadRetryInterval]; + } else { + [self setMaxRetryInterval:kDefaultMaxUploadRetryInterval]; + } + } + + [self addCookiesToRequest:request_]; + + if (downloadPath_ != nil) { + // downloading to a path, so create a temporary file and a file handle for + // downloading + NSString *tempPath = [self createTempDownloadFilePathForPath:downloadPath_]; + + BOOL didCreate = [[NSData data] writeToFile:tempPath + options:0 + error:&error]; + if (!didCreate) goto CannotBeginFetch; + + [self setTemporaryDownloadPath:tempPath]; + + NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:tempPath]; + if (fh == nil) goto CannotBeginFetch; + + [self setDownloadFileHandle:fh]; + } + + // finally, start the connection + + Class connectionClass = [[self class] connectionClass]; + + NSOperationQueue *delegateQueue = delegateQueue_; + if (delegateQueue && + ![connectionClass instancesRespondToSelector:@selector(setDelegateQueue:)]) { + // NSURLConnection has no setDelegateQueue: on iOS 4 and Mac OS X 10.5. + delegateQueue = nil; + self.delegateQueue = nil; + } else if (delegateQueue == nil && runLoopModes_ == nil && ![NSThread isMainThread]) { + // Neither a delegate queue nor runLoopModes were supplied, and we're not on the + // main thread, so assume the user really wants callbacks and provide a queue. + // + // We don't have a way to verify that this thread has a run loop spinning, but + // it's fairly rare that a background thread does have one. A client that + // does want to rely on spinning a run loop should specify run loop modes. + delegateQueue = [NSOperationQueue mainQueue]; + self.delegateQueue = delegateQueue; + } + +#if DEBUG && TARGET_OS_IPHONE + BOOL isPreIOS6 = (NSFoundationVersionNumber <= 890.1); + if (isPreIOS6 && delegateQueue) { + NSLog(@"GTMHTTPFetcher delegateQueue not safe in iOS 5"); + } +#endif + + if (downloadFileHandle_ != nil) { + // Downloading to a file, so downloadedData_ remains nil. + } else { + self.downloadedData = [NSMutableData data]; + } + + hasConnectionEnded_ = NO; + if ([runLoopModes_ count] == 0 && delegateQueue == nil) { + // No custom callback modes or queue were specified, so start the connection + // on the current run loop in the current mode + connection_ = [[connectionClass connectionWithRequest:request_ + delegate:self] retain]; + } else { + // Specify callbacks be on an operation queue or on the current run loop + // in the specified modes + connection_ = [[connectionClass alloc] initWithRequest:request_ + delegate:self + startImmediately:NO]; + if (delegateQueue) { + [connection_ performSelector:@selector(setDelegateQueue:) + withObject:delegateQueue]; + } else if (runLoopModes_) { + NSRunLoop *rl = [NSRunLoop currentRunLoop]; + for (NSString *mode in runLoopModes_) { + [connection_ scheduleInRunLoop:rl forMode:mode]; + } + } + [connection_ start]; + } + + if (!connection_) { + NSAssert(connection_ != nil, @"beginFetchWithDelegate could not create a connection"); + self.downloadedData = nil; + goto CannotBeginFetch; + } + +#if GTM_BACKGROUND_FETCHING + backgroundTaskIdentifer_ = 0; // UIBackgroundTaskInvalid is 0 on iOS 4 + if (shouldFetchInBackground_) { + // For iOS 3 compatibility, ensure that UIApp supports backgrounding + UIApplication *app = [UIApplication sharedApplication]; + if ([app respondsToSelector:@selector(beginBackgroundTaskWithExpirationHandler:)]) { + // Tell UIApplication that we want to continue even when the app is in the + // background. + NSThread *thread = delegateQueue_ ? nil : [NSThread currentThread]; + backgroundTaskIdentifer_ = [app beginBackgroundTaskWithExpirationHandler:^{ + // Background task expiration callback - this block is always invoked by + // UIApplication on the main thread. + if (thread) { + // Run the user's callbacks on the thread used to start the + // fetch. + [self performSelector:@selector(backgroundFetchExpired) + onThread:thread + withObject:nil + waitUntilDone:YES]; + } else { + // backgroundFetchExpired invokes callbacks on the provided delegate + // queue. + [self backgroundFetchExpired]; + } + }]; + } + } +#endif + + if (!initialRequestDate_) { + initialRequestDate_ = [[NSDate alloc] init]; + } + +#if DEBUG + // For testing only, look for a property indicating the fetch should immediately fail. + if ([self propertyForKey:@"_CannotBeginFetch"] != nil) { + goto CannotBeginFetch; + } +#endif + + // Once connection_ is non-nil we can send the start notification + isStopNotificationNeeded_ = YES; + NSNotificationCenter *defaultNC = [NSNotificationCenter defaultCenter]; + [defaultNC postNotificationName:kGTMHTTPFetcherStartedNotification + object:self]; + return YES; + +CannotBeginFetch: + [self failToBeginFetchDeferWithError:error]; + return NO; +} + +- (void)failToBeginFetchDeferWithError:(NSError *)error { + if (delegateQueue_) { + // Deferring will happen by the callback being invoked on the specified + // queue. + [self failToBeginFetchWithError:error]; + } else { + // No delegate queue has been specified, so put the callback + // on an appropriate run loop. + NSArray *modes = (runLoopModes_ ? runLoopModes_ : + [NSArray arrayWithObject:NSRunLoopCommonModes]); + [self performSelector:@selector(failToBeginFetchWithError:) + onThread:[NSThread currentThread] + withObject:error + waitUntilDone:NO + modes:modes]; + } +} + +- (void)failToBeginFetchWithError:(NSError *)error { + if (error == nil) { + error = [NSError errorWithDomain:kGTMHTTPFetcherErrorDomain + code:kGTMHTTPFetcherErrorDownloadFailed + userInfo:nil]; + } + + [[self retain] autorelease]; // In case the callback releases us + + [self invokeFetchCallbacksOnDelegateQueueWithData:nil + error:error]; + + [self releaseCallbacks]; + + [service_ fetcherDidStop:self]; + + self.authorizer = nil; + + if (temporaryDownloadPath_) { + [[NSFileManager defaultManager] removeItemAtPath:temporaryDownloadPath_ + error:NULL]; + self.temporaryDownloadPath = nil; + } +} + +#if GTM_BACKGROUND_FETCHING +- (void)backgroundFetchExpired { + // On background expiration, we stop the fetch and invoke the callbacks + NSError *error = [NSError errorWithDomain:kGTMHTTPFetcherErrorDomain + code:kGTMHTTPFetcherErrorBackgroundExpiration + userInfo:nil]; + [self invokeFetchCallbacksOnDelegateQueueWithData:nil + error:error]; + @synchronized(self) { + // Stopping the fetch here will indirectly call endBackgroundTask + [self stopFetchReleasingCallbacks:NO]; + + [self releaseCallbacks]; + self.authorizer = nil; + } +} + +- (void)endBackgroundTask { + @synchronized(self) { + // Whenever the connection stops or background execution expires, + // we need to tell UIApplication we're done + if (backgroundTaskIdentifer_) { + // If backgroundTaskIdentifer_ is non-zero, we know we're on iOS 4 + UIApplication *app = [UIApplication sharedApplication]; + [app endBackgroundTask:backgroundTaskIdentifer_]; + + backgroundTaskIdentifer_ = 0; + } + } +} +#endif // GTM_BACKGROUND_FETCHING + +- (BOOL)authorizeRequest { + id authorizer = self.authorizer; + SEL asyncAuthSel = @selector(authorizeRequest:delegate:didFinishSelector:); + if ([authorizer respondsToSelector:asyncAuthSel]) { + SEL callbackSel = @selector(authorizer:request:finishedWithError:); + [authorizer authorizeRequest:request_ + delegate:self + didFinishSelector:callbackSel]; + return YES; + } else { + NSAssert(authorizer == nil, @"invalid authorizer for fetch"); + + // No authorizing possible, and authorizing happens only after any delay; + // just begin fetching + return [self beginFetchMayDelay:NO + mayAuthorize:NO]; + } +} + +- (void)authorizer:(id )auth + request:(NSMutableURLRequest *)request + finishedWithError:(NSError *)error { + if (error != nil) { + // We can't fetch without authorization + [self failToBeginFetchDeferWithError:error]; + } else { + [self beginFetchMayDelay:NO + mayAuthorize:NO]; + } +} + +#if NS_BLOCKS_AVAILABLE +- (BOOL)beginFetchWithCompletionHandler:(void (^)(NSData *data, NSError *error))handler { + self.completionBlock = handler; + + // The user may have called setDelegate: earlier if they want to use other + // delegate-style callbacks during the fetch; otherwise, the delegate is nil, + // which is fine. + return [self beginFetchWithDelegate:[self delegate] + didFinishSelector:nil]; +} +#endif + +- (NSString *)createTempDownloadFilePathForPath:(NSString *)targetPath { + NSString *tempDir = nil; + +#if (!TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) + // Find an appropriate directory for the download, ideally on the same disk + // as the final target location so the temporary file won't have to be moved + // to a different disk. + // + // Available in SDKs for 10.6 and iOS 4 + // + // Oct 2011: We previously also used URLForDirectory for + // (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000)) + // but that is returning a non-temporary directory for iOS, unfortunately + + SEL sel = @selector(URLForDirectory:inDomain:appropriateForURL:create:error:); + if ([NSFileManager instancesRespondToSelector:sel]) { + NSError *error = nil; + NSURL *targetURL = [NSURL fileURLWithPath:targetPath]; + NSFileManager *fileMgr = [NSFileManager defaultManager]; + + NSURL *tempDirURL = [fileMgr URLForDirectory:NSItemReplacementDirectory + inDomain:NSUserDomainMask + appropriateForURL:targetURL + create:YES + error:&error]; + tempDir = [tempDirURL path]; + } +#endif + + if (tempDir == nil) { + tempDir = NSTemporaryDirectory(); + } + + static unsigned int counter = 0; + NSString *name = [NSString stringWithFormat:@"gtmhttpfetcher_%u_%u", + ++counter, (unsigned int) arc4random()]; + NSString *result = [tempDir stringByAppendingPathComponent:name]; + return result; +} + +- (void)addCookiesToRequest:(NSMutableURLRequest *)request { + // Get cookies for this URL from our storage array, if + // we have a storage array + if (cookieStorageMethod_ != kGTMHTTPFetcherCookieStorageMethodSystemDefault + && cookieStorageMethod_ != kGTMHTTPFetcherCookieStorageMethodNone) { + + NSArray *cookies = [cookieStorage_ cookiesForURL:[request URL]]; + if ([cookies count] > 0) { + + NSDictionary *headerFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies]; + NSString *cookieHeader = [headerFields objectForKey:@"Cookie"]; // key used in header dictionary + if (cookieHeader) { + [request addValue:cookieHeader forHTTPHeaderField:@"Cookie"]; // header name + } + } + } +} + +// Returns YES if this is in the process of fetching a URL, or waiting to +// retry, or waiting for authorization, or waiting to be issued by the +// service object +- (BOOL)isFetching { + if (connection_ != nil || retryTimer_ != nil) return YES; + + BOOL isAuthorizing = [authorizer_ isAuthorizingRequest:request_]; + if (isAuthorizing) return YES; + + BOOL isDelayed = [service_ isDelayingFetcher:self]; + return isDelayed; +} + +// Returns the status code set in connection:didReceiveResponse: +- (NSInteger)statusCode { + + NSInteger statusCode; + + if (response_ != nil + && [response_ respondsToSelector:@selector(statusCode)]) { + + statusCode = [(NSHTTPURLResponse *)response_ statusCode]; + } else { + // Default to zero, in hopes of hinting "Unknown" (we can't be + // sure that things are OK enough to use 200). + statusCode = 0; + } + return statusCode; +} + +- (NSDictionary *)responseHeaders { + if (response_ != nil + && [response_ respondsToSelector:@selector(allHeaderFields)]) { + + NSDictionary *headers = [(NSHTTPURLResponse *)response_ allHeaderFields]; + return headers; + } + return nil; +} + +- (void)releaseCallbacks { + [delegate_ autorelease]; + delegate_ = nil; + + [delegateQueue_ autorelease]; + delegateQueue_ = nil; + +#if NS_BLOCKS_AVAILABLE + self.completionBlock = nil; + self.sentDataBlock = nil; + self.receivedDataBlock = nil; + self.retryBlock = nil; +#endif +} + +// Cancel the fetch of the URL that's currently in progress. +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks { + id service; + + // if the connection or the retry timer is all that's retaining the fetcher, + // we want to be sure this instance survives stopping at least long enough for + // the stack to unwind + [[self retain] autorelease]; + + [self destroyRetryTimer]; + + @synchronized(self) { + service = [[service_ retain] autorelease]; + + if (connection_) { + // in case cancelling the connection calls this recursively, we want + // to ensure that we'll only release the connection and delegate once, + // so first set connection_ to nil + NSURLConnection* oldConnection = connection_; + connection_ = nil; + + if (!hasConnectionEnded_) { + [oldConnection cancel]; + } + + // this may be called in a callback from the connection, so use autorelease + [oldConnection autorelease]; + } + } // @synchronized(self) + + // send the stopped notification + [self sendStopNotificationIfNeeded]; + + @synchronized(self) { + [authorizer_ stopAuthorizationForRequest:request_]; + + if (shouldReleaseCallbacks) { + [self releaseCallbacks]; + + self.authorizer = nil; + } + + if (temporaryDownloadPath_) { + [[NSFileManager defaultManager] removeItemAtPath:temporaryDownloadPath_ + error:NULL]; + self.temporaryDownloadPath = nil; + } + } // @synchronized(self) + + [service fetcherDidStop:self]; + +#if GTM_BACKGROUND_FETCHING + [self endBackgroundTask]; +#endif +} + +// External stop method +- (void)stopFetching { + [self stopFetchReleasingCallbacks:YES]; +} + +- (void)sendStopNotificationIfNeeded { + BOOL sendNow = NO; + @synchronized(self) { + if (isStopNotificationNeeded_) { + isStopNotificationNeeded_ = NO; + sendNow = YES; + } + } + + if (sendNow) { + NSNotificationCenter *defaultNC = [NSNotificationCenter defaultCenter]; + [defaultNC postNotificationName:kGTMHTTPFetcherStoppedNotification + object:self]; + } +} + +- (void)retryFetch { + [self stopFetchReleasingCallbacks:NO]; + + [self beginFetchWithDelegate:delegate_ + didFinishSelector:finishedSel_]; +} + +- (void)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds { + NSDate* giveUpDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + + // Loop until the callbacks have been called and released, and until + // the connection is no longer pending, or until the timeout has expired + BOOL isMainThread = [NSThread isMainThread]; + + while ((!hasConnectionEnded_ +#if NS_BLOCKS_AVAILABLE + || completionBlock_ != nil +#endif + || delegate_ != nil) + && [giveUpDate timeIntervalSinceNow] > 0) { + + // Run the current run loop 1/1000 of a second to give the networking + // code a chance to work + if (isMainThread || delegateQueue_ == nil) { + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:0.001]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + [NSThread sleepForTimeInterval:0.001]; + } + } +} + +#pragma mark NSURLConnection Delegate Methods + +// +// NSURLConnection Delegate Methods +// + +// This method just says "follow all redirects", which _should_ be the default behavior, +// According to file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Conceptual/URLLoadingSystem +// but the redirects were not being followed until I added this method. May be +// a bug in the NSURLConnection code, or the documentation. +// +// In OS X 10.4.8 and earlier, the redirect request doesn't +// get the original's headers and body. This causes POSTs to fail. +// So we construct a new request, a copy of the original, with overrides from the +// redirect. +// +// Docs say that if redirectResponse is nil, just return the redirectRequest. + +- (NSURLRequest *)connection:(NSURLConnection *)connection + willSendRequest:(NSURLRequest *)redirectRequest + redirectResponse:(NSURLResponse *)redirectResponse { + @synchronized(self) { + if (redirectRequest && redirectResponse) { + // save cookies from the response + [self handleCookiesForResponse:redirectResponse]; + + NSMutableURLRequest *newRequest = [[request_ mutableCopy] autorelease]; + // copy the URL + NSURL *redirectURL = [redirectRequest URL]; + NSURL *url = [newRequest URL]; + + // disallow scheme changes (say, from https to http) + NSString *redirectScheme = [url scheme]; + NSString *newScheme = [redirectURL scheme]; + NSString *newResourceSpecifier = [redirectURL resourceSpecifier]; + + if ([redirectScheme caseInsensitiveCompare:@"http"] == NSOrderedSame + && newScheme != nil + && [newScheme caseInsensitiveCompare:@"https"] == NSOrderedSame) { + + // allow the change from http to https + redirectScheme = newScheme; + } + + NSString *newUrlString = [NSString stringWithFormat:@"%@:%@", + redirectScheme, newResourceSpecifier]; + + NSURL *newURL = [NSURL URLWithString:newUrlString]; + [newRequest setURL:newURL]; + + // any headers in the redirect override headers in the original. + NSDictionary *redirectHeaders = [redirectRequest allHTTPHeaderFields]; + for (NSString *key in redirectHeaders) { + NSString *value = [redirectHeaders objectForKey:key]; + [newRequest setValue:value forHTTPHeaderField:key]; + } + + [self addCookiesToRequest:newRequest]; + + redirectRequest = newRequest; + + // log the response we just received + [self setResponse:redirectResponse]; + [self logNowWithError:nil]; + + // update the request for future logging + NSMutableURLRequest *mutable = [[redirectRequest mutableCopy] autorelease]; + [self setMutableRequest:mutable]; + } + return redirectRequest; + } // @synchronized(self) +} + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + @synchronized(self) { + // This method is called when the server has determined that it + // has enough information to create the NSURLResponse + // it can be called multiple times, for example in the case of a + // redirect, so each time we reset the data. + [downloadedData_ setLength:0]; + [downloadFileHandle_ truncateFileAtOffset:0]; + downloadedLength_ = 0; + + [self setResponse:response]; + + // Save cookies from the response + [self handleCookiesForResponse:response]; + } +} + + +// handleCookiesForResponse: handles storage of cookies for responses passed to +// connection:willSendRequest:redirectResponse: and connection:didReceiveResponse: +- (void)handleCookiesForResponse:(NSURLResponse *)response { + + if (cookieStorageMethod_ == kGTMHTTPFetcherCookieStorageMethodSystemDefault + || cookieStorageMethod_ == kGTMHTTPFetcherCookieStorageMethodNone) { + + // do nothing special for NSURLConnection's default storage mechanism + // or when we're ignoring cookies + + } else if ([response respondsToSelector:@selector(allHeaderFields)]) { + + // grab the cookies from the header as NSHTTPCookies and store them either + // into our static array or into the fetchHistory + + NSDictionary *responseHeaderFields = [(NSHTTPURLResponse *)response allHeaderFields]; + if (responseHeaderFields) { + + NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseHeaderFields + forURL:[response URL]]; + if ([cookies count] > 0) { + [cookieStorage_ setCookies:cookies]; + } + } + } +} + +-(void)connection:(NSURLConnection *)connection +didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { + @synchronized(self) { + if ([challenge previousFailureCount] <= 2) { + + NSURLCredential *credential = credential_; + + if ([[challenge protectionSpace] isProxy] && proxyCredential_ != nil) { + credential = proxyCredential_; + } + + // Here, if credential is still nil, then we *could* try to get it from + // NSURLCredentialStorage's defaultCredentialForProtectionSpace:. + // We don't, because we're assuming: + // + // - for server credentials, we only want ones supplied by the program + // calling http fetcher + // - for proxy credentials, if one were necessary and available in the + // keychain, it would've been found automatically by NSURLConnection + // and this challenge delegate method never would've been called + // anyway + + if (credential) { + // try the credential + [[challenge sender] useCredential:credential + forAuthenticationChallenge:challenge]; + return; + } + } // @synchronized(self) + + // If we don't have credentials, or we've already failed auth 3x, + // report the error, putting the challenge as a value in the userInfo + // dictionary. +#if DEBUG + NSAssert(!isCancellingChallenge_, @"isCancellingChallenge_ unexpected"); +#endif + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:challenge + forKey:kGTMHTTPFetcherErrorChallengeKey]; + NSError *error = [NSError errorWithDomain:kGTMHTTPFetcherErrorDomain + code:kGTMHTTPFetcherErrorAuthenticationChallengeFailed + userInfo:userInfo]; + + // cancelAuthenticationChallenge seems to indirectly call + // connection:didFailWithError: now, though that isn't documented + // + // We'll use an ivar to make the indirect invocation of the + // delegate method do nothing. + isCancellingChallenge_ = YES; + [[challenge sender] cancelAuthenticationChallenge:challenge]; + isCancellingChallenge_ = NO; + + [self connection:connection didFailWithError:error]; + } +} + +- (void)invokeFetchCallbacksWithData:(NSData *)data + error:(NSError *)error { + // To avoid deadlocks, this should not be called inside of @synchronized(self) + id target; + SEL sel; +#if NS_BLOCKS_AVAILABLE + void (^block)(NSData *, NSError *); +#else + id block = nil; +#endif + + // If -stopFetching is called in another thread directly after this @synchronized stanza finishes + // on this thread, then target and block could be released before being used in this method. So + // retain each until this method is done with them. + @synchronized(self) { + target = [[delegate_ retain] autorelease]; + sel = finishedSel_; +#if NS_BLOCKS_AVAILABLE + block = [[completionBlock_ retain] autorelease]; +#endif + } + [self invokeFetchCallbacksWithTarget:target + selector:sel + block:block + data:data + error:error]; +} + +- (void)invokeFetchCallbacksWithTarget:(id)target + selector:(SEL)sel + block:(id)block + data:(NSData *)data + error:(NSError *)error { + [[self retain] autorelease]; // In case the callback releases us + + [self invokeFetchCallback:sel + target:target + data:data + error:error]; + +#if NS_BLOCKS_AVAILABLE + if (block) { + ((void (^)(NSData *, NSError *))block)(data, error); + } +#endif +} + +- (void)invokeFetchCallback:(SEL)sel + target:(id)target + data:(NSData *)data + error:(NSError *)error { + // This method is available to subclasses which may provide a customized + // target pointer. + if (target && sel) { + NSMethodSignature *sig = [target methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:target]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&data atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + } +} + +- (void)invokeFetchCallbacksOnDelegateQueueWithData:(NSData *)data + error:(NSError *)error { + // This is called by methods that are not already on the delegateQueue + // (as NSURLConnection callbacks should already be, but other failures + // are not.) + if (!delegateQueue_) { + [self invokeFetchCallbacksWithData:data error:error]; + } + + // Values may be nil. + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:2]; + [dict setValue:data forKey:kCallbackData]; + [dict setValue:error forKey:kCallbackError]; + + // If -stopFetching is called in another thread directly after this @synchronized stanza finishes + // on this thread, then target and block could be released before being used in this method. So + // retain each until this method is done with them. + @synchronized(self) { + id target = delegate_; + NSString *sel = finishedSel_ ? NSStringFromSelector(finishedSel_) : nil; +#if NS_BLOCKS_AVAILABLE + void (^block)(NSData *, NSError *) = completionBlock_; +#else + id block = nil; +#endif + [dict setValue:target forKey:kCallbackTarget]; + [dict setValue:sel forKey:kCallbackSelector]; + [dict setValue:block forKey:kCallbackBlock]; + } + + NSInvocationOperation *op = + [[[NSInvocationOperation alloc] initWithTarget:self + selector:@selector(invokeOnQueueWithDictionary:) + object:dict] autorelease]; + [delegateQueue_ addOperation:op]; +} + +- (void)invokeOnQueueWithDictionary:(NSDictionary *)dict { + id target = [dict objectForKey:kCallbackTarget]; + NSString *selStr = [dict objectForKey:kCallbackSelector]; + SEL sel = selStr ? NSSelectorFromString(selStr) : NULL; + id block = [dict objectForKey:kCallbackBlock]; + + NSData *data = [dict objectForKey:kCallbackData]; + NSError *error = [dict objectForKey:kCallbackError]; + + [self invokeFetchCallbacksWithTarget:target + selector:sel + block:block + data:data + error:error]; +} + +- (void)invokeSentDataCallback:(SEL)sel + target:(id)target + didSendBodyData:(NSInteger)bytesWritten + totalBytesWritten:(NSInteger)totalBytesWritten + totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { + if (target && sel) { + NSMethodSignature *sig = [target methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:target]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&bytesWritten atIndex:3]; + [invocation setArgument:&totalBytesWritten atIndex:4]; + [invocation setArgument:&totalBytesExpectedToWrite atIndex:5]; + [invocation invoke]; + } +} + +- (BOOL)invokeRetryCallback:(SEL)sel + target:(id)target + willRetry:(BOOL)willRetry + error:(NSError *)error { + if (target && sel) { + NSMethodSignature *sig = [target methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:target]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&willRetry atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + + [invocation getReturnValue:&willRetry]; + } + return willRetry; +} + +- (void)connection:(NSURLConnection *)connection + didSendBodyData:(NSInteger)bytesWritten + totalBytesWritten:(NSInteger)totalBytesWritten +totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { + @synchronized(self) { + SEL sel = [self sentDataSelector]; + [self invokeSentDataCallback:sel + target:delegate_ + didSendBodyData:bytesWritten + totalBytesWritten:totalBytesWritten + totalBytesExpectedToWrite:totalBytesExpectedToWrite]; + +#if NS_BLOCKS_AVAILABLE + if (sentDataBlock_) { + sentDataBlock_(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); + } +#endif + } +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + @synchronized(self) { +#if DEBUG + NSAssert(!hasConnectionEnded_, @"Connection received data after ending"); + + // The download file handle should be set or the data object allocated + // before the fetch is started. + NSAssert((downloadFileHandle_ == nil) != (downloadedData_ == nil), + @"received data accumulates as either NSData (%d) or" + @" NSFileHandle (%d)", + (downloadedData_ != nil), (downloadFileHandle_ != nil)); +#endif + // Hopefully, we'll never see this execute out-of-order, receiving data + // after we've received the finished or failed callback. + if (hasConnectionEnded_) return; + + if (downloadFileHandle_ != nil) { + // Append to file + @try { + [downloadFileHandle_ writeData:data]; + + downloadedLength_ = [downloadFileHandle_ offsetInFile]; + } + @catch (NSException *exc) { + // Couldn't write to file, probably due to a full disk + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[exc reason] + forKey:NSLocalizedDescriptionKey]; + NSError *error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain + code:kGTMHTTPFetcherErrorFileHandleException + userInfo:userInfo]; + [self connection:connection didFailWithError:error]; + return; + } + } else { + // append to mutable data + [downloadedData_ appendData:data]; + + downloadedLength_ = [downloadedData_ length]; + } + + if (receivedDataSel_) { + [delegate_ performSelector:receivedDataSel_ + withObject:self + withObject:downloadedData_]; + } + +#if NS_BLOCKS_AVAILABLE + if (receivedDataBlock_) { + receivedDataBlock_(downloadedData_); + } +#endif + } // @synchronized(self) +} + +// For error 304's ("Not Modified") where we've cached the data, return +// status 200 ("OK") to the caller (but leave the fetcher status as 304) +// and copy the cached data. +// +// For other errors or if there's no cached data, just return the actual status. +- (NSData *)cachedDataForStatus { + if ([self statusCode] == kGTMHTTPFetcherStatusNotModified + && [fetchHistory_ shouldCacheETaggedData]) { + NSData *cachedData = [fetchHistory_ cachedDataForRequest:request_]; + return cachedData; + } + return nil; +} + +- (NSInteger)statusAfterHandlingNotModifiedError { + NSInteger status = [self statusCode]; + NSData *cachedData = [self cachedDataForStatus]; + if (cachedData) { + // Forge the status to pass on to the delegate + status = 200; + + // Copy our stored data + if (downloadFileHandle_ != nil) { + @try { + // Downloading to a file handle won't save to the cache (the data is + // likely inappropriately large for caching), but will still read from + // the cache, on the unlikely chance that the response was Not Modified + // and the URL response was indeed present in the cache. + [downloadFileHandle_ truncateFileAtOffset:0]; + [downloadFileHandle_ writeData:cachedData]; + downloadedLength_ = [downloadFileHandle_ offsetInFile]; + } + @catch (NSException *) { + // Failed to write data, likely due to lack of disk space + status = kGTMHTTPFetcherErrorFileHandleException; + } + } else { + [downloadedData_ setData:cachedData]; + downloadedLength_ = [cachedData length]; + } + } + return status; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + BOOL shouldStopFetching = YES; + BOOL shouldSendStopNotification = NO; + NSError *error = nil; + NSData *downloadedData; +#if !STRIP_GTM_FETCH_LOGGING + BOOL shouldDeferLogging = NO; +#endif + BOOL shouldBeginRetryTimer = NO; + + @synchronized(self) { + // We no longer need to cancel the connection + hasConnectionEnded_ = YES; + + // Skip caching ETagged results when the data is being saved to a file + if (downloadFileHandle_ == nil) { + [fetchHistory_ updateFetchHistoryWithRequest:request_ + response:response_ + downloadedData:downloadedData_]; + } else { + [fetchHistory_ removeCachedDataForRequest:request_]; + } + + [[self retain] autorelease]; // in case the callback releases us + + NSInteger status = [self statusCode]; + if ([self cachedDataForStatus] != nil) { +#if !STRIP_GTM_FETCH_LOGGING + // Log the pre-cache response. + [self logNowWithError:nil]; + hasLoggedError_ = YES; +#endif + status = [self statusAfterHandlingNotModifiedError]; + } + + shouldSendStopNotification = YES; + + if (status >= 0 && status < 300) { + // success + if (downloadPath_) { + // Avoid deleting the downloaded file when the fetch stops + [downloadFileHandle_ closeFile]; + self.downloadFileHandle = nil; + + NSFileManager *fileMgr = [NSFileManager defaultManager]; + [fileMgr removeItemAtPath:downloadPath_ + error:NULL]; + + if ([fileMgr moveItemAtPath:temporaryDownloadPath_ + toPath:downloadPath_ + error:&error]) { + self.temporaryDownloadPath = nil; + } + } + } else { + // unsuccessful +#if !STRIP_GTM_FETCH_LOGGING + if (!hasLoggedError_) { + [self logNowWithError:nil]; + hasLoggedError_ = YES; + } +#endif + // Status over 300; retry or notify the delegate of failure + if ([self shouldRetryNowForStatus:status error:nil]) { + // retrying + shouldBeginRetryTimer = YES; + shouldStopFetching = NO; + } else { + NSDictionary *userInfo = nil; + if ([downloadedData_ length] > 0) { + userInfo = [NSDictionary dictionaryWithObject:downloadedData_ + forKey:kGTMHTTPFetcherStatusDataKey]; + } + error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain + code:status + userInfo:userInfo]; + } + } + downloadedData = downloadedData_; +#if !STRIP_GTM_FETCH_LOGGING + shouldDeferLogging = shouldDeferResponseBodyLogging_; +#endif + } // @synchronized(self) + + if (shouldBeginRetryTimer) { + [self beginRetryTimer]; + } + + if (shouldSendStopNotification) { + // We want to send the stop notification before calling the delegate's + // callback selector, since the callback selector may release all of + // the fetcher properties that the client is using to track the fetches. + // + // We'll also stop now so that, to any observers watching the notifications, + // it doesn't look like our wait for a retry (which may be long, + // 30 seconds or more) is part of the network activity. + [self sendStopNotificationIfNeeded]; + } + + if (shouldStopFetching) { + // Call the callbacks (outside of the @synchronized to avoid deadlocks.) + [self invokeFetchCallbacksWithData:downloadedData + error:error]; + BOOL shouldRelease = [self shouldReleaseCallbacksUponCompletion]; + [self stopFetchReleasingCallbacks:shouldRelease]; + } + +#if !STRIP_GTM_FETCH_LOGGING + @synchronized(self) { + if (!shouldDeferLogging && !hasLoggedError_) { + [self logNowWithError:nil]; + } + } +#endif +} + +- (BOOL)shouldReleaseCallbacksUponCompletion { + // A subclass can override this to keep callbacks around after the + // connection has finished successfully + return YES; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + @synchronized(self) { + // Prevent the failure callback from being called twice, since the stopFetch + // call below (either the explicit one at the end of this method, or the + // implicit one when the retry occurs) will release the delegate. + if (connection_ == nil) return; + + // If this method was invoked indirectly by cancellation of an authentication + // challenge, defer this until it is called again with the proper error object + if (isCancellingChallenge_) return; + + // We no longer need to cancel the connection + hasConnectionEnded_ = YES; + + [self logNowWithError:error]; + } + + // See comment about sendStopNotificationIfNeeded + // in connectionDidFinishLoading: + [self sendStopNotificationIfNeeded]; + + if ([self shouldRetryNowForStatus:0 error:error]) { + [self beginRetryTimer]; + } else { + [[self retain] autorelease]; // in case the callback releases us + + [self invokeFetchCallbacksWithData:nil + error:error]; + + [self stopFetchReleasingCallbacks:YES]; + } +} + +- (void)logNowWithError:(NSError *)error { + // If the logging category is available, then log the current request, + // response, data, and error + if ([self respondsToSelector:@selector(logFetchWithError:)]) { + [self performSelector:@selector(logFetchWithError:) withObject:error]; + } +} + +#pragma mark Retries + +- (BOOL)isRetryError:(NSError *)error { + + struct retryRecord { + NSString *const domain; + int code; + }; + + struct retryRecord retries[] = { + { kGTMHTTPFetcherStatusDomain, 408 }, // request timeout + { kGTMHTTPFetcherStatusDomain, 503 }, // service unavailable + { kGTMHTTPFetcherStatusDomain, 504 }, // request timeout + { NSURLErrorDomain, NSURLErrorTimedOut }, + { NSURLErrorDomain, NSURLErrorNetworkConnectionLost }, + { nil, 0 } + }; + + // NSError's isEqual always returns false for equal but distinct instances + // of NSError, so we have to compare the domain and code values explicitly + + for (int idx = 0; retries[idx].domain != nil; idx++) { + + if ([[error domain] isEqual:retries[idx].domain] + && [error code] == retries[idx].code) { + + return YES; + } + } + return NO; +} + + +// shouldRetryNowForStatus:error: returns YES if the user has enabled retries +// and the status or error is one that is suitable for retrying. "Suitable" +// means either the isRetryError:'s list contains the status or error, or the +// user's retrySelector: is present and returns YES when called, or the +// authorizer may be able to fix. +- (BOOL)shouldRetryNowForStatus:(NSInteger)status + error:(NSError *)error { + // Determine if a refreshed authorizer may avoid an authorization error + BOOL shouldRetryForAuthRefresh = NO; + BOOL isFirstAuthError = (authorizer_ != nil) + && !hasAttemptedAuthRefresh_ + && (status == kGTMHTTPFetcherStatusUnauthorized); // 401 + + if (isFirstAuthError) { + if ([authorizer_ respondsToSelector:@selector(primeForRefresh)]) { + BOOL hasPrimed = [authorizer_ primeForRefresh]; + if (hasPrimed) { + shouldRetryForAuthRefresh = YES; + hasAttemptedAuthRefresh_ = YES; + [request_ setValue:nil forHTTPHeaderField:@"Authorization"]; + } + } + } + + // Determine if we're doing exponential backoff retries + BOOL shouldDoIntervalRetry = [self isRetryEnabled] + && ([self nextRetryInterval] < [self maxRetryInterval]); + + if (shouldDoIntervalRetry) { + // If an explicit max retry interval was set, we expect repeated backoffs to take + // up to roughly twice that for repeated fast failures. If the initial attempt is + // already more than 3 times the max retry interval, then failures have taken a long time + // (such as from network timeouts) so don't retry again to avoid the app becoming + // unexpectedly unresponsive. + if (maxRetryInterval_ > kUnsetMaxRetryInterval) { + NSTimeInterval maxAllowedIntervalBeforeRetry = maxRetryInterval_ * 3; + NSTimeInterval timeSinceInitialRequest = -[initialRequestDate_ timeIntervalSinceNow]; + if (timeSinceInitialRequest > maxAllowedIntervalBeforeRetry) { + shouldDoIntervalRetry = NO; + } + } + } + + BOOL willRetry = NO; + BOOL canRetry = shouldRetryForAuthRefresh || shouldDoIntervalRetry; + if (canRetry) { + // Check if this is a retryable error + if (error == nil) { + // Make an error for the status + NSDictionary *userInfo = nil; + if ([downloadedData_ length] > 0) { + userInfo = [NSDictionary dictionaryWithObject:downloadedData_ + forKey:kGTMHTTPFetcherStatusDataKey]; + } + error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain + code:status + userInfo:userInfo]; + } + + willRetry = shouldRetryForAuthRefresh || [self isRetryError:error]; + + // If the user has installed a retry callback, consult that + willRetry = [self invokeRetryCallback:retrySel_ + target:delegate_ + willRetry:willRetry + error:error]; +#if NS_BLOCKS_AVAILABLE + if (retryBlock_) { + willRetry = retryBlock_(willRetry, error); + } +#endif + } + return willRetry; +} + +- (void)beginRetryTimer { + @synchronized(self) { + if (delegateQueue_ != nil && ![NSThread isMainThread]) { + // A delegate queue is set, so the thread we're running on may not + // have a run loop. We'll defer creating and starting the timer + // until we're on the main thread to ensure it has a run loop. + // (If we weren't supporting 10.5, we could use dispatch_after instead + // of an NSTimer.) + [self performSelectorOnMainThread:_cmd + withObject:nil + waitUntilDone:NO]; + return; + } + } + + NSTimeInterval nextInterval = [self nextRetryInterval]; + NSTimeInterval maxInterval = [self maxRetryInterval]; + NSTimeInterval newInterval = MIN(nextInterval, maxInterval); + + [self primeRetryTimerWithNewTimeInterval:newInterval]; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMHTTPFetcherRetryDelayStartedNotification + object:self]; +} + +- (void)primeRetryTimerWithNewTimeInterval:(NSTimeInterval)secs { + + [self destroyRetryTimer]; + + @synchronized(self) { + lastRetryInterval_ = secs; + + retryTimer_ = [NSTimer timerWithTimeInterval:secs + target:self + selector:@selector(retryTimerFired:) + userInfo:nil + repeats:NO]; + [retryTimer_ retain]; + + NSRunLoop *timerRL = (self.delegateQueue ? + [NSRunLoop mainRunLoop] : [NSRunLoop currentRunLoop]); + [timerRL addTimer:retryTimer_ + forMode:NSDefaultRunLoopMode]; + } +} + +- (void)retryTimerFired:(NSTimer *)timer { + [self destroyRetryTimer]; + + @synchronized(self) { + retryCount_++; + + [self retryFetch]; + } +} + +- (void)destroyRetryTimer { + BOOL shouldNotify = NO; + @synchronized(self) { + if (retryTimer_) { + [retryTimer_ invalidate]; + [retryTimer_ autorelease]; + retryTimer_ = nil; + shouldNotify = YES; + } + } // @synchronized(self) + + if (shouldNotify) { + NSNotificationCenter *defaultNC = [NSNotificationCenter defaultCenter]; + [defaultNC postNotificationName:kGTMHTTPFetcherRetryDelayStoppedNotification + object:self]; + } +} + +- (NSUInteger)retryCount { + return retryCount_; +} + +- (NSTimeInterval)nextRetryInterval { + // The next wait interval is the factor (2.0) times the last interval, + // but never less than the minimum interval. + NSTimeInterval secs = lastRetryInterval_ * retryFactor_; + secs = MIN(secs, maxRetryInterval_); + secs = MAX(secs, minRetryInterval_); + + return secs; +} + +- (BOOL)isRetryEnabled { + return isRetryEnabled_; +} + +- (void)setRetryEnabled:(BOOL)flag { + + if (flag && !isRetryEnabled_) { + // We defer initializing these until the user calls setRetryEnabled + // to avoid using the random number generator if it's not needed. + // However, this means min and max intervals for this fetcher are reset + // as a side effect of calling setRetryEnabled. + // + // Make an initial retry interval random between 1.0 and 2.0 seconds + [self setMinRetryInterval:0.0]; + [self setMaxRetryInterval:kUnsetMaxRetryInterval]; + [self setRetryFactor:2.0]; + lastRetryInterval_ = 0.0; + } + isRetryEnabled_ = flag; +}; + +- (NSTimeInterval)maxRetryInterval { + return maxRetryInterval_; +} + +- (void)setMaxRetryInterval:(NSTimeInterval)secs { + if (secs > 0) { + maxRetryInterval_ = secs; + } else { + maxRetryInterval_ = kUnsetMaxRetryInterval; + } +} + +- (double)minRetryInterval { + return minRetryInterval_; +} + +- (void)setMinRetryInterval:(NSTimeInterval)secs { + if (secs > 0) { + minRetryInterval_ = secs; + } else { + // Set min interval to a random value between 1.0 and 2.0 seconds + // so that if multiple clients start retrying at the same time, they'll + // repeat at different times and avoid overloading the server + minRetryInterval_ = 1.0 + ((double)(arc4random() & 0x0FFFF) / (double) 0x0FFFF); + } +} + +#pragma mark Getters and Setters + +@dynamic cookieStorageMethod, + retryEnabled, + maxRetryInterval, + minRetryInterval, + retryCount, + nextRetryInterval, + statusCode, + responseHeaders, + fetchHistory, + userData, + properties; + +@synthesize mutableRequest = request_, + allowedInsecureSchemes = allowedInsecureSchemes_, + allowLocalhostRequest = allowLocalhostRequest_, + credential = credential_, + proxyCredential = proxyCredential_, + postData = postData_, + postStream = postStream_, + delegate = delegate_, + authorizer = authorizer_, + service = service_, + serviceHost = serviceHost_, + servicePriority = servicePriority_, + thread = thread_, + sentDataSelector = sentDataSel_, + receivedDataSelector = receivedDataSel_, + retrySelector = retrySel_, + retryFactor = retryFactor_, + response = response_, + downloadedLength = downloadedLength_, + downloadedData = downloadedData_, + downloadPath = downloadPath_, + temporaryDownloadPath = temporaryDownloadPath_, + downloadFileHandle = downloadFileHandle_, + delegateQueue = delegateQueue_, + runLoopModes = runLoopModes_, + comment = comment_, + log = log_, + cookieStorage = cookieStorage_; + +#if NS_BLOCKS_AVAILABLE +@synthesize completionBlock = completionBlock_, + sentDataBlock = sentDataBlock_, + receivedDataBlock = receivedDataBlock_, + retryBlock = retryBlock_; +#endif + +@synthesize shouldFetchInBackground = shouldFetchInBackground_; + +- (NSInteger)cookieStorageMethod { + return cookieStorageMethod_; +} + +- (void)setCookieStorageMethod:(NSInteger)method { + + cookieStorageMethod_ = method; + + if (method == kGTMHTTPFetcherCookieStorageMethodSystemDefault) { + // System default + [request_ setHTTPShouldHandleCookies:YES]; + + // No need for a cookie storage object + self.cookieStorage = nil; + + } else { + // Not system default + [request_ setHTTPShouldHandleCookies:NO]; + + if (method == kGTMHTTPFetcherCookieStorageMethodStatic) { + // Store cookies in the static array + NSAssert(gGTMFetcherStaticCookieStorage != nil, + @"cookie storage requires GTMHTTPFetchHistory"); + + self.cookieStorage = gGTMFetcherStaticCookieStorage; + } else if (method == kGTMHTTPFetcherCookieStorageMethodFetchHistory) { + // store cookies in the fetch history + self.cookieStorage = [fetchHistory_ cookieStorage]; + } else { + // kGTMHTTPFetcherCookieStorageMethodNone - ignore cookies + self.cookieStorage = nil; + } + } +} + ++ (id )staticCookieStorage { + return gGTMFetcherStaticCookieStorage; +} + ++ (BOOL)doesSupportSentDataCallback { +#if GTM_IPHONE + // NSURLConnection's didSendBodyData: delegate support appears to be + // available starting in iPhone OS 3.0 + return (NSFoundationVersionNumber >= 678.47); +#else + // Per WebKit's MaxFoundationVersionWithoutdidSendBodyDataDelegate + // + // Indicates if NSURLConnection will invoke the didSendBodyData: delegate + // method + return (NSFoundationVersionNumber > 677.21); +#endif +} + +- (id )fetchHistory { + return fetchHistory_; +} + +- (void)setFetchHistory:(id )fetchHistory { + [fetchHistory_ autorelease]; + fetchHistory_ = [fetchHistory retain]; + + if (fetchHistory_ != nil) { + // set the fetch history's cookie array to be the cookie store + [self setCookieStorageMethod:kGTMHTTPFetcherCookieStorageMethodFetchHistory]; + + } else { + // The fetch history was removed + if (cookieStorageMethod_ == kGTMHTTPFetcherCookieStorageMethodFetchHistory) { + // Fall back to static storage + [self setCookieStorageMethod:kGTMHTTPFetcherCookieStorageMethodStatic]; + } + } +} + +- (id)userData { + @synchronized(self) { + return [[userData_ retain] autorelease]; + } +} + +- (void)setUserData:(id)theObj { + @synchronized(self) { + [userData_ autorelease]; + userData_ = [theObj retain]; + } +} + +- (void)setProperties:(NSMutableDictionary *)dict { + @synchronized(self) { + [properties_ autorelease]; + + // This copies rather than retains the parameter for compatiblity with + // an earlier version that took an immutable parameter and copied it. + properties_ = [dict mutableCopy]; + } +} + +- (NSMutableDictionary *)properties { + @synchronized(self) { + return [[properties_ retain] autorelease]; + } +} + +- (void)setProperty:(id)obj forKey:(NSString *)key { + @synchronized(self) { + if (properties_ == nil && obj != nil) { + [self setProperties:[NSMutableDictionary dictionary]]; + } + [properties_ setValue:obj forKey:key]; + } +} + +- (id)propertyForKey:(NSString *)key { + @synchronized(self) { + return [[[properties_ objectForKey:key] retain] autorelease]; + } +} + +- (void)addPropertiesFromDictionary:(NSDictionary *)dict { + @synchronized(self) { + if (properties_ == nil && dict != nil) { + [self setProperties:[[dict mutableCopy] autorelease]]; + } else { + [properties_ addEntriesFromDictionary:dict]; + } + } +} + +- (NSData *)bodyData { + return self.postData; +} + +- (void)setBodyData:(NSData *)postData { + self.postData = postData; +} + +- (void)setCommentWithFormat:(id)format, ... { +#if !STRIP_GTM_FETCH_LOGGING + NSString *result = format; + if (format) { + va_list argList; + va_start(argList, format); + + result = [[[NSString alloc] initWithFormat:format + arguments:argList] autorelease]; + va_end(argList); + } + [self setComment:result]; +#endif +} + ++ (Class)connectionClass { + if (gGTMFetcherConnectionClass == nil) { + gGTMFetcherConnectionClass = [NSURLConnection class]; + } + return gGTMFetcherConnectionClass; +} + ++ (void)setConnectionClass:(Class)theClass { + gGTMFetcherConnectionClass = theClass; +} + +#if STRIP_GTM_FETCH_LOGGING ++ (void)setLoggingEnabled:(BOOL)flag { +} +#endif // STRIP_GTM_FETCH_LOGGING + +@end + +void GTMAssertSelectorNilOrImplementedWithArgs(id obj, SEL sel, ...) { + + // Verify that the object's selector is implemented with the proper + // number and type of arguments +#if DEBUG + va_list argList; + va_start(argList, sel); + + if (obj && sel) { + // Check that the selector is implemented + if (![obj respondsToSelector:sel]) { + NSLog(@"\"%@\" selector \"%@\" is unimplemented or misnamed", + NSStringFromClass([obj class]), + NSStringFromSelector(sel)); + NSCAssert(0, @"callback selector unimplemented or misnamed"); + } else { + const char *expectedArgType; + unsigned int argCount = 2; // skip self and _cmd + NSMethodSignature *sig = [obj methodSignatureForSelector:sel]; + + // Check that each expected argument is present and of the correct type + while ((expectedArgType = va_arg(argList, const char*)) != 0) { + + if ([sig numberOfArguments] > argCount) { + const char *foundArgType = [sig getArgumentTypeAtIndex:argCount]; + + if(0 != strncmp(foundArgType, expectedArgType, strlen(expectedArgType))) { + NSLog(@"\"%@\" selector \"%@\" argument %d should be type %s", + NSStringFromClass([obj class]), + NSStringFromSelector(sel), (argCount - 2), expectedArgType); + NSCAssert(0, @"callback selector argument type mistake"); + } + } + argCount++; + } + + // Check that the proper number of arguments are present in the selector + if (argCount != [sig numberOfArguments]) { + NSLog( @"\"%@\" selector \"%@\" should have %d arguments", + NSStringFromClass([obj class]), + NSStringFromSelector(sel), (argCount - 2)); + NSCAssert(0, @"callback selector arguments incorrect"); + } + } + } + + va_end(argList); +#endif +} + +NSString *GTMCleanedUserAgentString(NSString *str) { + // Reference http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html + // and http://www-archive.mozilla.org/build/user-agent-strings.html + + if (str == nil) return nil; + + NSMutableString *result = [NSMutableString stringWithString:str]; + + // Replace spaces and commas with underscores + [result replaceOccurrencesOfString:@" " + withString:@"_" + options:0 + range:NSMakeRange(0, [result length])]; + [result replaceOccurrencesOfString:@"," + withString:@"_" + options:0 + range:NSMakeRange(0, [result length])]; + + // Delete http token separators and remaining whitespace + static NSCharacterSet *charsToDelete = nil; + if (charsToDelete == nil) { + // Make a set of unwanted characters + NSString *const kSeparators = @"()<>@;:\\\"/[]?={}"; + + NSMutableCharacterSet *mutableChars; + mutableChars = [[[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy] autorelease]; + [mutableChars addCharactersInString:kSeparators]; + charsToDelete = [mutableChars copy]; // hang on to an immutable copy + } + + while (1) { + NSRange separatorRange = [result rangeOfCharacterFromSet:charsToDelete]; + if (separatorRange.location == NSNotFound) break; + + [result deleteCharactersInRange:separatorRange]; + }; + + return result; +} + +NSString *GTMSystemVersionString(void) { + NSString *systemString = @""; + +#if TARGET_OS_MAC && !TARGET_OS_IPHONE + // Mac build + static NSString *savedSystemString = nil; + if (savedSystemString == nil) { + // With Gestalt inexplicably deprecated in 10.8, we're reduced to reading + // the system plist file. + NSString *const kPath = @"/System/Library/CoreServices/SystemVersion.plist"; + NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:kPath]; + NSString *versString = [plist objectForKey:@"ProductVersion"]; + if ([versString length] == 0) { + versString = @"10.?.?"; + } + savedSystemString = [[NSString alloc] initWithFormat:@"MacOSX/%@", versString]; + } + systemString = savedSystemString; +#elif TARGET_OS_IPHONE + // Compiling against the iPhone SDK + + static NSString *savedSystemString = nil; + if (savedSystemString == nil) { + // Avoid the slowness of calling currentDevice repeatedly on the iPhone + UIDevice* currentDevice = [UIDevice currentDevice]; + + NSString *model = [currentDevice model]; + NSString *cleanedModel = GTMCleanedUserAgentString(model); + NSString *systemVersion = [currentDevice systemVersion]; + +#if TARGET_IPHONE_SIMULATOR + NSString *hardwareModel = @"sim"; +#else + NSString *hardwareModel; + struct utsname unameRecord; + if (uname(&unameRecord) == 0) { + NSString *machineName = [NSString stringWithCString:unameRecord.machine + encoding:NSUTF8StringEncoding]; + hardwareModel = GTMCleanedUserAgentString(machineName); + } else { + hardwareModel = @"unk"; + } +#endif + savedSystemString = [[NSString alloc] initWithFormat:@"%@/%@ hw/%@", + cleanedModel, systemVersion, hardwareModel]; + // Example: iPod_Touch/2.2 hw/iPod1_1 + } + systemString = savedSystemString; + +#elif (GTL_IPHONE || GDATA_IPHONE) + // Compiling iOS libraries against the Mac SDK + systemString = @"iPhone/x.x"; + +#elif defined(_SYS_UTSNAME_H) + // Foundation-only build + struct utsname unameRecord; + uname(&unameRecord); + + systemString = [NSString stringWithFormat:@"%s/%s", + unameRecord.sysname, unameRecord.release]; // "Darwin/8.11.1" +#endif + + return systemString; +} + +// Return a generic name and version for the current application; this avoids +// anonymous server transactions. +NSString *GTMApplicationIdentifier(NSBundle *bundle) { + @synchronized([GTMHTTPFetcher class]) { + static NSMutableDictionary *sAppIDMap = nil; + + // If there's a bundle ID, use that; otherwise, use the process name + if (bundle == nil) { + bundle = [NSBundle mainBundle]; + } + NSString *bundleID = [bundle bundleIdentifier]; + if (bundleID == nil) { + bundleID = @""; + } + + NSString *identifier = [sAppIDMap objectForKey:bundleID]; + if (identifier) return identifier; + + // Apps may add a string to the info.plist to uniquely identify different builds. + identifier = [bundle objectForInfoDictionaryKey:@"GTMUserAgentID"]; + if ([identifier length] == 0) { + if ([bundleID length] > 0) { + identifier = bundleID; + } else { + // Fall back on the procname, prefixed by "proc" to flag that it's + // autogenerated and perhaps unreliable + NSString *procName = [[NSProcessInfo processInfo] processName]; + identifier = [NSString stringWithFormat:@"proc_%@", procName]; + } + } + + // Clean up whitespace and special characters + identifier = GTMCleanedUserAgentString(identifier); + + // If there's a version number, append that + NSString *version = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + if ([version length] == 0) { + version = [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]; + } + + // Clean up whitespace and special characters + version = GTMCleanedUserAgentString(version); + + // Glue the two together (cleanup done above or else cleanup would strip the + // slash) + if ([version length] > 0) { + identifier = [identifier stringByAppendingFormat:@"/%@", version]; + } + + if (sAppIDMap == nil) { + sAppIDMap = [[NSMutableDictionary alloc] init]; + } + [sAppIDMap setObject:identifier forKey:bundleID]; + return identifier; + } +} diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogViewController.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogViewController.h new file mode 100755 index 0000000..6549412 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogViewController.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !STRIP_GTM_FETCH_LOGGING && !STRIP_GTM_HTTPLOGVIEWCONTROLLER + +#import + +// GTMHTTPFetcherLogViewController allows browsing of GTMHTTPFetcher's logs on +// the iOS device. Logging must have been enabled with +// +// [GTMHTTPFetcher setLoggingEnabled:YES]; +// +// A table will display one entry for each run of the app, with the most recent +// run's log listed first. A simple web view is used to browse the contents of +// an individual run's log. +// +// To use, push the view controller onto your app's navigation controller. +// +// GTMHTTPFetcherLogViewController *logViewController = +// [[[GTMHTTPFetcherLogViewController alloc] init] autorelease]; +// [navController pushViewController:logViewController +// animated:YES]; +// +// Apps without a UINavigationController may use controllerWithTarget:selector: +// convenience method to make one. For example: +// +// UINavigationController *nc = +// [GTMHTTPFetcherLogViewController controllerWithTarget:self +// selector:@selector(logsDone:)]; +// [self presentViewController:nc animated:YES completion:NULL]; +// +// - (void)logsDone:(UINavigationController *)navController { +// [self dismissViewControllerAnimated:YES completion:NULL]; +// } + +@interface GTMHTTPFetcherLogViewController : UITableViewController + +/// Sets whether to automatically scroll to the bottom of a run's log when viewed, to show the most +/// recent entry (a run log's entries are written in chronological order). Default is NO. +- (void)setOpensScrolledToEnd:(BOOL)opensScrolledToEnd; + +// This optional convenience method created a nav controller for use +// by apps that do not have a standard UINavigationController, as shown +// in the code snippet above. +// +// The selector should be for a method with a signature matching +// - (void)logsDone:(UINavigationController *)navController +// +// The target and selector may be nil. ++ (UINavigationController *)controllerWithTarget:(id)target + selector:(SEL)selector; +@end + +#endif diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogViewController.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogViewController.m new file mode 100755 index 0000000..43b3133 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogViewController.m @@ -0,0 +1,275 @@ +/* Copyright (c) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(__has_feature) && __has_feature(objc_arc) +#error "This file uses manual reference counting. Compile with -fno-objc-arc" +#endif + +#import "GTMHTTPFetcherLogViewController.h" + +#if !STRIP_GTM_FETCH_LOGGING && !STRIP_GTM_HTTPLOGVIEWCONTROLLER + +#import + +#import "GTMHTTPFetcher.h" +#import "GTMHTTPFetcherLogging.h" + +static NSString *const kHTTPLogsCell = @"kGTMHTTPLogsCell"; + +// A minimal controller will be used to wrap a web view for displaying the +// log files. +@interface GTMHTTPFetcherLoggingWebViewController : UIViewController +- (id)initWithURL:(NSURL *)htmlURL title:(NSString *)title opensScrolledToEnd:(BOOL)opensScrolled; +@end + +#pragma mark - Table View Controller + +@interface GTMHTTPFetcherLogViewController () +@property (nonatomic, copy) void (^callbackBlock)(void); +@end + +@implementation GTMHTTPFetcherLogViewController { + NSArray *logsFolderURLs_; + BOOL opensScrolledToEnd_; +} + +@synthesize callbackBlock = callbackBlock_; + +- (instancetype)initWithStyle:(UITableViewStyle)style { + self = [super initWithStyle:style]; + if (self) { + self.title = @"HTTP Logs"; + + // Find all folders containing logs. + NSError *error; + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *logsFolderPath = [GTMHTTPFetcher loggingDirectory]; + NSString *processName = [GTMHTTPFetcher loggingProcessName]; + + NSURL *logsURL = [NSURL fileURLWithPath:logsFolderPath]; + NSMutableArray *mutableURLs = + [[fm contentsOfDirectoryAtURL:logsURL + includingPropertiesForKeys:@[ NSURLCreationDateKey ] + options:0 + error:&error] mutableCopy]; + + // Remove non-log files that lack the process name prefix, + // and remove the "newest" symlink. + NSString *symlinkSuffix = [GTMHTTPFetcher symlinkNameSuffix]; + NSIndexSet *nonLogIndexes = [mutableURLs indexesOfObjectsPassingTest: + ^BOOL(id obj, NSUInteger idx, BOOL *stop) { + NSString *name = [obj lastPathComponent]; + return (![name hasPrefix:processName] + || [name hasSuffix:symlinkSuffix]); + }]; + [mutableURLs removeObjectsAtIndexes:nonLogIndexes]; + + // Sort to put the newest logs at the top of the list. + [mutableURLs sortUsingComparator:^NSComparisonResult(NSURL *url1, + NSURL *url2) { + NSDate *date1, *date2; + [url1 getResourceValue:&date1 forKey:NSURLCreationDateKey error:NULL]; + [url2 getResourceValue:&date2 forKey:NSURLCreationDateKey error:NULL]; + return [date2 compare:date1]; + }]; + logsFolderURLs_ = mutableURLs; + } + return self; +} + +- (void)dealloc { + [logsFolderURLs_ release]; + [super dealloc]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Avoid silent failure if this was not added to a UINavigationController. + // + // The method +controllerWithTarget:selector: can be used to create a + // temporary UINavigationController. + NSAssert(self.navigationController != nil, @"Need a UINavigationController"); +} + +- (void)setOpensScrolledToEnd:(BOOL)opensScrolledToEnd { + opensScrolledToEnd_ = opensScrolledToEnd; +} + +#pragma mark - + +- (NSString *)shortenedNameForURL:(NSURL *)url { + // Remove "Processname_log_" from the start of the file name. + NSString *name = [url lastPathComponent]; + NSString *prefix = [GTMHTTPFetcher processNameLogPrefix]; + if ([name hasPrefix:prefix]) { + name = [name substringFromIndex:[prefix length]]; + } + return name; +} + +#pragma mark - Table view data source + +- (NSInteger)tableView:(UITableView *)tableView + numberOfRowsInSection:(NSInteger)section { + return [logsFolderURLs_ count]; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView + cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = + [tableView dequeueReusableCellWithIdentifier:kHTTPLogsCell]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:kHTTPLogsCell] autorelease]; + [cell.textLabel setAdjustsFontSizeToFitWidth:YES]; + } + + NSURL *url = [logsFolderURLs_ objectAtIndex:indexPath.row]; + cell.textLabel.text = [self shortenedNameForURL:url]; + + return cell; +} + +#pragma mark - Table view delegate + +- (void)tableView:(UITableView *)tableView + didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSURL *folderURL = [logsFolderURLs_ objectAtIndex:indexPath.row]; + NSString *htmlName = [GTMHTTPFetcher htmlFileName]; + NSURL *htmlURL = [folderURL URLByAppendingPathComponent:htmlName]; + + // Show the webview controller. + NSString *title = [self shortenedNameForURL:folderURL]; + UIViewController *webViewController = + [[[GTMHTTPFetcherLoggingWebViewController alloc] initWithURL:htmlURL + title:title + opensScrolledToEnd:opensScrolledToEnd_] autorelease]; + + UINavigationController *navController = [self navigationController]; + [navController pushViewController:webViewController animated:YES]; + + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +#pragma mark - + ++ (UINavigationController *)controllerWithTarget:(id)target + selector:(SEL)selector { + UINavigationController *navController = + [[[UINavigationController alloc] init] autorelease]; + GTMHTTPFetcherLogViewController *logViewController = + [[[GTMHTTPFetcherLogViewController alloc] init] autorelease]; + UIBarButtonItem *barButtonItem = + [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:logViewController + action:@selector(doneButtonClicked:)] autorelease]; + logViewController.navigationItem.leftBarButtonItem = barButtonItem; + + // Make a block to capture the callback and nav controller. + void (^block)(void) = ^{ + if (target && selector) { + [target performSelector:selector withObject:navController]; + } + }; + logViewController.callbackBlock = block; + + navController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; + + [navController pushViewController:logViewController animated:NO]; + return navController; +} + +- (void)doneButtonClicked:(UIBarButtonItem *)barButtonItem { + void (^block)() = self.callbackBlock; + block(); + self.callbackBlock = nil; +} + +@end + +#pragma mark - Minimal WebView Controller + +@implementation GTMHTTPFetcherLoggingWebViewController { + BOOL opensScrolledToEnd_; + NSURL *htmlURL_; +} + +- (instancetype)initWithURL:(NSURL *)htmlURL + title:(NSString *)title + opensScrolledToEnd:(BOOL)opensScrolledToEnd { + self = [super initWithNibName:nil bundle:nil]; + if (self) { + self.title = title; + htmlURL_ = [htmlURL retain]; + opensScrolledToEnd_ = opensScrolledToEnd; + } + return self; +} + +- (void)dealloc { + [htmlURL_ release]; + [super dealloc]; +} + +- (void)loadView { + UIWebView *webView = [[UIWebView alloc] init]; + webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth + | UIViewAutoresizingFlexibleHeight); + webView.delegate = self; + self.view = webView; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + NSURLRequest *request = [NSURLRequest requestWithURL:htmlURL_]; + [[self webView] loadRequest:request]; +} + +- (void)didTapBackButton:(UIButton *)button { + [[self webView] goBack]; +} + +- (UIWebView *)webView { + return (UIWebView *)self.view; +} + +#pragma mark - WebView delegate + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + if (opensScrolledToEnd_) { + // Scroll to the bottom, because the most recent entry is at the end. + NSString* javascript = [NSString stringWithFormat:@"window.scrollBy(0, %ld);", NSIntegerMax]; + [[self webView] stringByEvaluatingJavaScriptFromString:javascript]; + opensScrolledToEnd_ = NO; + } + + // Instead of the nav controller's back button, provide a simple + // webview back button when it's needed. + BOOL canGoBack = [webView canGoBack]; + UIBarButtonItem *backItem = nil; + if (canGoBack) { + // This hides the nav back button. + backItem = [[[UIBarButtonItem alloc] initWithTitle:@"⏎" + style:UIBarButtonItemStylePlain + target:self + action:@selector(didTapBackButton:)] autorelease]; + } + self.navigationItem.leftBarButtonItem = backItem; +} + +@end + +#endif // !STRIP_GTM_FETCH_LOGGING && !STRIP_GTM_HTTPLOGVIEWCONTROLLER diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogging.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogging.h new file mode 100755 index 0000000..93ca24c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogging.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GTMHTTPFetcher.h" + +// GTM HTTP Logging +// +// All traffic using GTMHTTPFetcher can be easily logged. Call +// +// [GTMHTTPFetcher setLoggingEnabled:YES]; +// +// to begin generating log files. +// +// Log files are put into a folder on the desktop called "GTMHTTPDebugLogs" +// unless another directory is specified with +setLoggingDirectory. +// +// In the iPhone simulator, the default logs location is the user's home +// directory in ~/Library/Application Support. On the iPhone device, the +// default logs location is the application's documents directory on the device. +// +// Tip: use the Finder's "Sort By Date" to find the most recent logs. +// +// Each run of an application gets a separate set of log files. An html +// file is generated to simplify browsing the run's http transactions. +// The html file includes javascript links for inline viewing of uploaded +// and downloaded data. +// +// A symlink is created in the logs folder to simplify finding the html file +// for the latest run of the application; the symlink is called +// +// AppName_http_log_newest.html +// +// For better viewing of XML logs, use Camino or Firefox rather than Safari. +// +// Each fetcher may be given a comment to be inserted as a label in the logs, +// such as +// [fetcher setCommentWithFormat:@"retrieve item %@", itemName]; +// +// Projects may define STRIP_GTM_FETCH_LOGGING to remove logging code. + +#if !STRIP_GTM_FETCH_LOGGING + +@interface GTMHTTPFetcher (GTMHTTPFetcherLogging) + +// Note: the default logs directory is ~/Desktop/GTMHTTPDebugLogs; it will be +// created as needed. If a custom directory is set, the directory should +// already exist. ++ (void)setLoggingDirectory:(NSString *)path; ++ (NSString *)loggingDirectory; + +// client apps can turn logging on and off ++ (void)setLoggingEnabled:(BOOL)flag; ++ (BOOL)isLoggingEnabled; + +// client apps can turn off logging to a file if they want to only check +// the fetcher's log property ++ (void)setLoggingToFileEnabled:(BOOL)flag; ++ (BOOL)isLoggingToFileEnabled; + +// client apps can optionally specify process name and date string used in +// log file names ++ (void)setLoggingProcessName:(NSString *)str; ++ (NSString *)loggingProcessName; + ++ (void)setLoggingDateStamp:(NSString *)str; ++ (NSString *)loggingDateStamp; + +// internal; called by fetcher +- (void)logFetchWithError:(NSError *)error; +- (BOOL)logCapturePostStream; + +// internal; accessors useful for viewing logs ++ (NSString *)processNameLogPrefix; ++ (NSString *)symlinkNameSuffix; ++ (NSString *)htmlFileName; + +// Applications may provide alternative body strings to be displayed in the +// log, such as for binary requests or responses. If deferring is turned +// on, the response log will not be sent until deferring is turned off, +// allowing the application to write the response body after the response +// data has been parsed. +- (void)setLogRequestBody:(NSString *)bodyString; +- (NSString *)logRequestBody; +- (void)setLogResponseBody:(NSString *)bodyString; +- (NSString *)logResponseBody; +- (void)setShouldDeferResponseBodyLogging:(BOOL)flag; +- (BOOL)shouldDeferResponseBodyLogging; + +@end + +#endif // !STRIP_GTM_FETCH_LOGGING diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogging.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogging.m new file mode 100755 index 0000000..54a4d95 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherLogging.m @@ -0,0 +1,1134 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !STRIP_GTM_FETCH_LOGGING + +#include +#include + +#import "GTMHTTPFetcherLogging.h" + +// Sensitive credential strings are replaced in logs with _snip_ +// +// Apps that must see the contents of sensitive tokens can set this to 1 +#ifndef SKIP_GTM_FETCH_LOGGING_SNIPPING +#define SKIP_GTM_FETCH_LOGGING_SNIPPING 0 +#endif + +// If GTMReadMonitorInputStream is available, it can be used for +// capturing uploaded streams of data +// +// We locally declare methods of GTMReadMonitorInputStream so we +// do not need to import the header, as some projects may not have it available +#ifndef GTM_NSSTREAM_DELEGATE +@interface GTMReadMonitorInputStream : NSInputStream ++ (id)inputStreamWithStream:(NSInputStream *)input; +@property (assign) id readDelegate; +@property (assign) SEL readSelector; +@property (retain) NSArray *runLoopModes; +@end +#endif + +// If GTMNSJSONSerialization is available, it is used for formatting JSON +#if (TARGET_OS_MAC && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED < 1070)) || \ + (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED < 50000)) +@interface GTMNSJSONSerialization : NSObject ++ (NSData *)dataWithJSONObject:(id)obj options:(NSUInteger)opt error:(NSError **)error; ++ (id)JSONObjectWithData:(NSData *)data options:(NSUInteger)opt error:(NSError **)error; +@end +#endif + +// Otherwise, if SBJSON is available, it is used for formatting JSON +@interface GTMFetcherSBJSON +- (void)setHumanReadable:(BOOL)flag; +- (NSString*)stringWithObject:(id)value error:(NSError**)error; +- (id)objectWithString:(NSString*)jsonrep error:(NSError**)error; +@end + +@interface GTMHTTPFetcher (GTMHTTPFetcherLoggingUtilities) ++ (NSString *)headersStringForDictionary:(NSDictionary *)dict; + +- (void)inputStream:(GTMReadMonitorInputStream *)stream + readIntoBuffer:(void *)buffer + length:(NSUInteger)length; + +// internal file utilities for logging ++ (BOOL)fileOrDirExistsAtPath:(NSString *)path; ++ (BOOL)makeDirectoryUpToPath:(NSString *)path; ++ (BOOL)removeItemAtPath:(NSString *)path; ++ (BOOL)createSymbolicLinkAtPath:(NSString *)newPath + withDestinationPath:(NSString *)targetPath; + ++ (NSString *)snipSubstringOfString:(NSString *)originalStr + betweenStartString:(NSString *)startStr + endString:(NSString *)endStr; + ++ (id)JSONObjectWithData:(NSData *)data; ++ (id)stringWithJSONObject:(id)obj; +@end + +@implementation GTMHTTPFetcher (GTMHTTPFetcherLogging) + +// fetchers come and fetchers go, but statics are forever +static BOOL gIsLoggingEnabled = NO; +static BOOL gIsLoggingToFile = YES; +static NSString *gLoggingDirectoryPath = nil; +static NSString *gLoggingDateStamp = nil; +static NSString* gLoggingProcessName = nil; + ++ (void)setLoggingDirectory:(NSString *)path { + [gLoggingDirectoryPath autorelease]; + gLoggingDirectoryPath = [path copy]; +} + ++ (NSString *)loggingDirectory { + + if (!gLoggingDirectoryPath) { + NSArray *arr = nil; +#if GTM_IPHONE && TARGET_IPHONE_SIMULATOR + // default to a directory called GTMHTTPDebugLogs into a sandbox-safe + // directory that a developer can find easily, the application home + arr = [NSArray arrayWithObject:NSHomeDirectory()]; +#elif GTM_IPHONE + // Neither ~/Desktop nor ~/Home is writable on an actual iPhone device. + // Put it in ~/Documents. + arr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, + NSUserDomainMask, YES); +#else + // default to a directory called GTMHTTPDebugLogs in the desktop folder + arr = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, + NSUserDomainMask, YES); +#endif + + if ([arr count] > 0) { + NSString *const kGTMLogFolderName = @"GTMHTTPDebugLogs"; + + NSString *desktopPath = [arr objectAtIndex:0]; + NSString *logsFolderPath = [desktopPath stringByAppendingPathComponent:kGTMLogFolderName]; + + BOOL doesFolderExist = [[self class] fileOrDirExistsAtPath:logsFolderPath]; + + if (!doesFolderExist) { + // make the directory + doesFolderExist = [self makeDirectoryUpToPath:logsFolderPath]; + } + + if (doesFolderExist) { + // it's there; store it in the global + gLoggingDirectoryPath = [logsFolderPath copy]; + } + } + } + return gLoggingDirectoryPath; +} + ++ (void)setLoggingEnabled:(BOOL)flag { + gIsLoggingEnabled = flag; +} + ++ (BOOL)isLoggingEnabled { + return gIsLoggingEnabled; +} + ++ (void)setLoggingToFileEnabled:(BOOL)flag { + gIsLoggingToFile = flag; +} + ++ (BOOL)isLoggingToFileEnabled { + return gIsLoggingToFile; +} + ++ (void)setLoggingProcessName:(NSString *)str { + [gLoggingProcessName release]; + gLoggingProcessName = [str copy]; +} + ++ (NSString *)loggingProcessName { + + // get the process name (once per run) replacing spaces with underscores + if (!gLoggingProcessName) { + + NSString *procName = [[NSProcessInfo processInfo] processName]; + NSMutableString *loggingProcessName; + loggingProcessName = [[NSMutableString alloc] initWithString:procName]; + + [loggingProcessName replaceOccurrencesOfString:@" " + withString:@"_" + options:0 + range:NSMakeRange(0, [loggingProcessName length])]; + gLoggingProcessName = loggingProcessName; + } + return gLoggingProcessName; +} + ++ (void)setLoggingDateStamp:(NSString *)str { + [gLoggingDateStamp release]; + gLoggingDateStamp = [str copy]; +} + ++ (NSString *)loggingDateStamp { + // we'll pick one date stamp per run, so a run that starts at a later second + // will get a unique results html file + if (!gLoggingDateStamp) { + // produce a string like 08-21_01-41-23PM + + NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; + [formatter setFormatterBehavior:NSDateFormatterBehavior10_4]; + [formatter setDateFormat:@"M-dd_hh-mm-ssa"]; + + gLoggingDateStamp = [[formatter stringFromDate:[NSDate date]] retain] ; + } + return gLoggingDateStamp; +} + ++ (NSString *)processNameLogPrefix { + static NSString *prefix = nil; + if (!prefix) { + NSString *processName = [[self class] loggingProcessName]; + prefix = [[NSString alloc] initWithFormat:@"%@_log_", processName]; + } + return prefix; +} + ++ (NSString *)symlinkNameSuffix { + return @"_log_newest.html"; +} + ++ (NSString *)htmlFileName { + return @"aperçu_http_log.html"; +} + +// formattedStringFromData returns a prettyprinted string for XML or JSON input, +// and a plain string for other input data +- (NSString *)formattedStringFromData:(NSData *)inputData + contentType:(NSString *)contentType + JSON:(NSDictionary **)outJSON { + if (inputData == nil) return nil; + + // if the content type is JSON and we have the parsing class available, + // use that + if ([contentType hasPrefix:@"application/json"] + && [inputData length] > 5) { + // convert from JSON string to NSObjects and back to a formatted string + NSMutableDictionary *obj = [[self class] JSONObjectWithData:inputData]; + if (obj) { + if (outJSON) *outJSON = obj; + if ([obj isKindOfClass:[NSMutableDictionary class]]) { + // for security and privacy, omit OAuth 2 response access and refresh + // tokens + if ([obj valueForKey:@"refresh_token"] != nil) { + [obj setObject:@"_snip_" forKey:@"refresh_token"]; + } + if ([obj valueForKey:@"access_token"] != nil) { + [obj setObject:@"_snip_" forKey:@"access_token"]; + } + } + NSString *formatted = [[self class] stringWithJSONObject:obj]; + if (formatted) return formatted; + } + } + +#if !GTM_FOUNDATION_ONLY && !GTM_SKIP_LOG_XMLFORMAT + // verify that this data starts with the bytes indicating XML + + NSString *const kXMLLintPath = @"/usr/bin/xmllint"; + static BOOL hasCheckedAvailability = NO; + static BOOL isXMLLintAvailable; + + if (!hasCheckedAvailability) { + isXMLLintAvailable = [[self class] fileOrDirExistsAtPath:kXMLLintPath]; + hasCheckedAvailability = YES; + } + + if (isXMLLintAvailable + && [inputData length] > 5 + && strncmp([inputData bytes], " 0) { + // success + inputData = formattedData; + } + } +#else + // we can't call external tasks on the iPhone; leave the XML unformatted +#endif + + NSString *dataStr = [[[NSString alloc] initWithData:inputData + encoding:NSUTF8StringEncoding] autorelease]; + return dataStr; +} + +- (void)setupStreamLogging { + // if logging is enabled, it needs a buffer to accumulate data from any + // NSInputStream used for uploading. Logging will wrap the input + // stream with a stream that lets us keep a copy the data being read. + if ([GTMHTTPFetcher isLoggingEnabled] + && loggedStreamData_ == nil + && postStream_ != nil) { + loggedStreamData_ = [[NSMutableData alloc] init]; + + BOOL didCapture = [self logCapturePostStream]; + if (!didCapture) { + // upload stream logging requires the class + // GTMReadMonitorInputStream be available + NSString const *str = @"<>"; + [loggedStreamData_ setData:[str dataUsingEncoding:NSUTF8StringEncoding]]; + } + } +} + +- (void)setLogRequestBody:(NSString *)bodyString { + @synchronized(self) { + [logRequestBody_ release]; + logRequestBody_ = [bodyString copy]; + } +} + +- (NSString *)logRequestBody { + @synchronized(self) { + return logRequestBody_; + } +} + +- (void)setLogResponseBody:(NSString *)bodyString { + @synchronized(self) { + [logResponseBody_ release]; + logResponseBody_ = [bodyString copy]; + } +} + +- (NSString *)logResponseBody { + @synchronized(self) { + return logResponseBody_; + } +} + +- (void)setShouldDeferResponseBodyLogging:(BOOL)flag { + @synchronized(self) { + if (flag != shouldDeferResponseBodyLogging_) { + shouldDeferResponseBodyLogging_ = flag; + if (!flag && !hasLoggedError_) { + [self performSelectorOnMainThread:@selector(logFetchWithError:) + withObject:nil + waitUntilDone:NO]; + } + } + } +} + +- (BOOL)shouldDeferResponseBodyLogging { + @synchronized(self) { + return shouldDeferResponseBodyLogging_; + } +} + +// stringFromStreamData creates a string given the supplied data +// +// If NSString can create a UTF-8 string from the data, then that is returned. +// +// Otherwise, this routine tries to find a MIME boundary at the beginning of +// the data block, and uses that to break up the data into parts. Each part +// will be used to try to make a UTF-8 string. For parts that fail, a +// replacement string showing the part header and <> is supplied +// in place of the binary data. + +- (NSString *)stringFromStreamData:(NSData *)data + contentType:(NSString *)contentType { + + if (data == nil) return nil; + + // optimistically, see if the whole data block is UTF-8 + NSString *streamDataStr = [self formattedStringFromData:data + contentType:contentType + JSON:NULL]; + if (streamDataStr) return streamDataStr; + + // Munge a buffer by replacing non-ASCII bytes with underscores, + // and turn that munged buffer an NSString. That gives us a string + // we can use with NSScanner. + NSMutableData *mutableData = [NSMutableData dataWithData:data]; + unsigned char *bytes = [mutableData mutableBytes]; + + for (unsigned int idx = 0; idx < [mutableData length]; idx++) { + if (bytes[idx] > 0x7F || bytes[idx] == 0) { + bytes[idx] = '_'; + } + } + + NSString *mungedStr = [[[NSString alloc] initWithData:mutableData + encoding:NSUTF8StringEncoding] autorelease]; + if (mungedStr != nil) { + + // scan for the boundary string + NSString *boundary = nil; + NSScanner *scanner = [NSScanner scannerWithString:mungedStr]; + + if ([scanner scanUpToString:@"\r\n" intoString:&boundary] + && [boundary hasPrefix:@"--"]) { + + // we found a boundary string; use it to divide the string into parts + NSArray *mungedParts = [mungedStr componentsSeparatedByString:boundary]; + + // look at each of the munged parts in the original string, and try to + // convert those into UTF-8 + NSMutableArray *origParts = [NSMutableArray array]; + NSUInteger offset = 0; + for (NSString *mungedPart in mungedParts) { + NSUInteger partSize = [mungedPart length]; + + NSRange range = NSMakeRange(offset, partSize); + NSData *origPartData = [data subdataWithRange:range]; + + NSString *origPartStr = [[[NSString alloc] initWithData:origPartData + encoding:NSUTF8StringEncoding] autorelease]; + if (origPartStr) { + // we could make this original part into UTF-8; use the string + [origParts addObject:origPartStr]; + } else { + // this part can't be made into UTF-8; scan the header, if we can + NSString *header = nil; + NSScanner *headerScanner = [NSScanner scannerWithString:mungedPart]; + if (![headerScanner scanUpToString:@"\r\n\r\n" intoString:&header]) { + // we couldn't find a header + header = @""; + } + + // make a part string with the header and <> + NSString *binStr = [NSString stringWithFormat:@"\r%@\r<<%lu bytes>>\r", + header, (long)(partSize - [header length])]; + [origParts addObject:binStr]; + } + offset += partSize + [boundary length]; + } + + // rejoin the original parts + streamDataStr = [origParts componentsJoinedByString:boundary]; + } + } + + if (!streamDataStr) { + // give up; just make a string showing the uploaded bytes + streamDataStr = [NSString stringWithFormat:@"<<%u bytes>>", + (unsigned int)[data length]]; + } + return streamDataStr; +} + +// logFetchWithError is called following a successful or failed fetch attempt +// +// This method does all the work for appending to and creating log files + +- (void)logFetchWithError:(NSError *)error { + + if (![[self class] isLoggingEnabled]) return; + + // TODO: (grobbins) add Javascript to display response data formatted in hex + + NSString *parentDir = [[self class] loggingDirectory]; + NSString *processName = [[self class] loggingProcessName]; + NSString *dateStamp = [[self class] loggingDateStamp]; + NSString *logNamePrefix = [[self class] processNameLogPrefix]; + + // make a directory for this run's logs, like + // SyncProto_logs_10-16_01-56-58PM + NSString *dirName = [NSString stringWithFormat:@"%@%@", + logNamePrefix, dateStamp]; + NSString *logDirectory = [parentDir stringByAppendingPathComponent:dirName]; + + if (gIsLoggingToFile) { + // be sure that the first time this app runs, it's not writing to + // a preexisting folder + static BOOL shouldReuseFolder = NO; + if (!shouldReuseFolder) { + shouldReuseFolder = YES; + NSString *origLogDir = logDirectory; + for (int ctr = 2; ctr < 20; ctr++) { + if (![[self class] fileOrDirExistsAtPath:logDirectory]) break; + + // append a digit + logDirectory = [origLogDir stringByAppendingFormat:@"_%d", ctr]; + } + } + if (![[self class] makeDirectoryUpToPath:logDirectory]) return; + } + // each response's NSData goes into its own xml or txt file, though all + // responses for this run of the app share a main html file. This + // counter tracks all fetch responses for this run of the app. + // + // we'll use a local variable since this routine may be reentered while + // waiting for XML formatting to be completed by an external task + static int zResponseCounter = 0; + int responseCounter = ++zResponseCounter; + + // file name for an image data file + NSString *responseDataFileName = nil; + NSUInteger responseDataLength; + if (downloadFileHandle_) { + responseDataLength = (NSUInteger) [downloadFileHandle_ offsetInFile]; + } else { + responseDataLength = [downloadedData_ length]; + } + + NSURLResponse *response = [self response]; + NSDictionary *responseHeaders = [self responseHeaders]; + + NSString *responseBaseName = nil; + NSString *responseDataStr = nil; + NSDictionary *responseJSON = nil; + + // if there's response data, decide what kind of file to put it in based + // on the first bytes of the file or on the mime type supplied by the server + NSString *responseMIMEType = [response MIMEType]; + BOOL isResponseImage = NO; + NSData *dataToWrite = nil; + + if (responseDataLength > 0) { + NSString *responseDataExtn = nil; + + // generate a response file base name like + responseBaseName = [NSString stringWithFormat:@"fetch_%d_response", + responseCounter]; + + NSString *responseType = [responseHeaders valueForKey:@"Content-Type"]; + responseDataStr = [self formattedStringFromData:downloadedData_ + contentType:responseType + JSON:&responseJSON]; + if (responseDataStr) { + // we were able to make a UTF-8 string from the response data + if ([responseMIMEType isEqual:@"application/atom+xml"] + || [responseMIMEType hasSuffix:@"/xml"]) { + responseDataExtn = @"xml"; + dataToWrite = [responseDataStr dataUsingEncoding:NSUTF8StringEncoding]; + } + } else if ([responseMIMEType isEqual:@"image/jpeg"]) { + responseDataExtn = @"jpg"; + dataToWrite = downloadedData_; + isResponseImage = YES; + } else if ([responseMIMEType isEqual:@"image/gif"]) { + responseDataExtn = @"gif"; + dataToWrite = downloadedData_; + isResponseImage = YES; + } else if ([responseMIMEType isEqual:@"image/png"]) { + responseDataExtn = @"png"; + dataToWrite = downloadedData_; + isResponseImage = YES; + } else { + // add more non-text types here + } + + // if we have an extension, save the raw data in a file with that + // extension + if (responseDataExtn && dataToWrite) { + responseDataFileName = [responseBaseName stringByAppendingPathExtension:responseDataExtn]; + NSString *responseDataFilePath = [logDirectory stringByAppendingPathComponent:responseDataFileName]; + + NSError *downloadedError = nil; + if (gIsLoggingToFile + && ![dataToWrite writeToFile:responseDataFilePath + options:0 + error:&downloadedError]) { + NSLog(@"%@ logging write error:%@ (%@)", + [self class], downloadedError, responseDataFileName); + } + } + } + + // we'll have one main html file per run of the app + NSString *htmlName = [[self class] htmlFileName]; + NSString *htmlPath =[logDirectory stringByAppendingPathComponent:htmlName]; + + // if the html file exists (from logging previous fetches) we don't need + // to re-write the header or the scripts + BOOL didFileExist = [[self class] fileOrDirExistsAtPath:htmlPath]; + + NSMutableString* outputHTML = [NSMutableString string]; + NSURLRequest *request = [self mutableRequest]; + + // we need a header to say we'll have UTF-8 text + if (!didFileExist) { + [outputHTML appendFormat:@"%@ HTTP fetch log %@", + processName, dateStamp]; + } + + // now write the visible html elements + NSString *copyableFileName = [NSString stringWithFormat:@"fetch_%d.txt", + responseCounter]; + + // write the date & time, the comment, and the link to the plain-text + // (copyable) log + NSString *const dateLineFormat = @"%@      "; + [outputHTML appendFormat:dateLineFormat, [NSDate date]]; + + NSString *comment = [self comment]; + if (comment) { + NSString *const commentFormat = @"%@      "; + [outputHTML appendFormat:commentFormat, comment]; + } + + NSString *const reqRespFormat = @"request/response log
"; + [outputHTML appendFormat:reqRespFormat, copyableFileName]; + + // write the request URL + NSString *requestMethod = [request HTTPMethod]; + NSURL *requestURL = [request URL]; + + NSURL *redirectedFromHost = [[[redirectedFromURL_ host] copy] autorelease]; + // Save the request URL for next time in case this redirects. + [redirectedFromURL_ release]; + redirectedFromURL_ = [requestURL copy]; + if (redirectedFromHost) { + [outputHTML appendFormat:@"redirected from %@
", + redirectedFromHost]; + } + + [outputHTML appendFormat:@"request: %@ %@
\n", + requestMethod, requestURL]; + + // write the request headers + NSDictionary *requestHeaders = [request allHTTPHeaderFields]; + NSUInteger numberOfRequestHeaders = [requestHeaders count]; + if (numberOfRequestHeaders > 0) { + // Indicate if the request is authorized; warn if the request is + // authorized but non-SSL + NSString *auth = [requestHeaders objectForKey:@"Authorization"]; + NSString *headerDetails = @""; + if (auth) { + headerDetails = @"   authorized"; + BOOL isInsecure = [[requestURL scheme] isEqual:@"http"]; + if (isInsecure) { + headerDetails = @"   authorized, non-SSL" + " "; // 26A0 = ⚠ + } + } + NSString *cookiesHdr = [requestHeaders objectForKey:@"Cookie"]; + if (cookiesHdr) { + headerDetails = [headerDetails stringByAppendingString: + @"   cookies"]; + } + NSString *matchHdr = [requestHeaders objectForKey:@"If-Match"]; + if (matchHdr) { + headerDetails = [headerDetails stringByAppendingString: + @"   if-match"]; + } + matchHdr = [requestHeaders objectForKey:@"If-None-Match"]; + if (matchHdr) { + headerDetails = [headerDetails stringByAppendingString: + @"   if-none-match"]; + } + [outputHTML appendFormat:@"   headers: %d %@
", + (int)numberOfRequestHeaders, headerDetails]; + } else { + [outputHTML appendFormat:@"   headers: none
"]; + } + + // write the request post data, toggleable + NSData *postData; + if (loggedStreamData_) { + postData = loggedStreamData_; + } else if (postData_) { + postData = postData_; + } else { + postData = [request_ HTTPBody]; + } + + NSString *postDataStr = nil; + NSUInteger postDataLength = [postData length]; + NSString *postType = [requestHeaders valueForKey:@"Content-Type"]; + + if (postDataLength > 0) { + [outputHTML appendFormat:@"   data: %d bytes, %@
\n", + (int)postDataLength, postType ? postType : @""]; + + if (logRequestBody_) { + postDataStr = [[logRequestBody_ copy] autorelease]; + [logRequestBody_ release]; + logRequestBody_ = nil; + } else { + postDataStr = [self stringFromStreamData:postData + contentType:postType]; + if (postDataStr) { + // remove OAuth 2 client secret and refresh token + postDataStr = [[self class] snipSubstringOfString:postDataStr + betweenStartString:@"client_secret=" + endString:@"&"]; + + postDataStr = [[self class] snipSubstringOfString:postDataStr + betweenStartString:@"refresh_token=" + endString:@"&"]; + + // remove ClientLogin password + postDataStr = [[self class] snipSubstringOfString:postDataStr + betweenStartString:@"&Passwd=" + endString:@"&"]; + } + } + } else { + // no post data + } + + // write the response status, MIME type, URL + NSInteger status = [self statusCode]; + if (response) { + NSString *statusString = @""; + if (status != 0) { + if (status == 200 || status == 201) { + statusString = [NSString stringWithFormat:@"%ld", (long)status]; + + // report any JSON-RPC error + if ([responseJSON isKindOfClass:[NSDictionary class]]) { + NSDictionary *jsonError = [responseJSON objectForKey:@"error"]; + if ([jsonError isKindOfClass:[NSDictionary class]]) { + NSString *jsonCode = [[jsonError valueForKey:@"code"] description]; + NSString *jsonMessage = [jsonError valueForKey:@"message"]; + if (jsonCode || jsonMessage) { + NSString *const jsonErrFmt = @"   JSON error: %@ %@  ⚑"; // 2691 = ⚑ + statusString = [statusString stringByAppendingFormat:jsonErrFmt, + jsonCode ? jsonCode : @"", + jsonMessage ? jsonMessage : @""]; + } + } + } + } else { + // purple for anything other than 200 or 201 + NSString *flag = (status >= 400 ? @" ⚑" : @""); // 2691 = ⚑ + NSString *const statusFormat = @"%ld %@"; + statusString = [NSString stringWithFormat:statusFormat, + (long)status, flag]; + } + } + + // show the response URL only if it's different from the request URL + NSString *responseURLStr = @""; + NSURL *responseURL = [response URL]; + + if (responseURL && ![responseURL isEqual:[request URL]]) { + NSString *const responseURLFormat = @"response URL:" + " %@
\n"; + responseURLStr = [NSString stringWithFormat:responseURLFormat, + [responseURL absoluteString]]; + } + + [outputHTML appendFormat:@"response:  status %@
\n%@", + statusString, responseURLStr]; + + // Write the response headers + NSUInteger numberOfResponseHeaders = [responseHeaders count]; + if (numberOfResponseHeaders > 0) { + // Indicate if the server is setting cookies + NSString *cookiesSet = [responseHeaders valueForKey:@"Set-Cookie"]; + NSString *cookiesStr = (cookiesSet ? @"  " + "sets cookies" : @""); + // Indicate if the server is redirecting + NSString *location = [responseHeaders valueForKey:@"Location"]; + BOOL isRedirect = (status >= 300 && status <= 399 && location != nil); + NSString *redirectsStr = (isRedirect ? @"  " + "redirects" : @""); + + [outputHTML appendFormat:@"   headers: %d %@ %@
\n", + (int)numberOfResponseHeaders, cookiesStr, redirectsStr]; + } else { + [outputHTML appendString:@"   headers: none
\n"]; + } + } + + // error + if (error) { + [outputHTML appendFormat:@"Error: %@
\n", [error description]]; + } + + // Write the response data + if (responseDataFileName) { + NSString *escapedResponseFile = [responseDataFileName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + if (isResponseImage) { + // Make a small inline image that links to the full image file + [outputHTML appendFormat:@"   data: %d bytes, %@
", + (int)responseDataLength, responseMIMEType]; + NSString *const fmt = @"image\n"; + [outputHTML appendFormat:fmt, + escapedResponseFile, escapedResponseFile]; + } else { + // The response data was XML; link to the xml file + NSString *const fmt = @"   data: %d bytes, " + "%@   %@\n"; + [outputHTML appendFormat:fmt, + (int)responseDataLength, responseMIMEType, + escapedResponseFile, [escapedResponseFile pathExtension]]; + } + } else { + // The response data was not an image; just show the length and MIME type + [outputHTML appendFormat:@"   data: %d bytes, %@\n", + (int)responseDataLength, responseMIMEType]; + } + + // Make a single string of the request and response, suitable for copying + // to the clipboard and pasting into a bug report + NSMutableString *copyable = [NSMutableString string]; + if (comment) { + [copyable appendFormat:@"%@\n\n", comment]; + } + [copyable appendFormat:@"%@\n", [NSDate date]]; + if (redirectedFromHost) { + [copyable appendFormat:@"Redirected from %@\n", redirectedFromHost]; + } + [copyable appendFormat:@"Request: %@ %@\n", requestMethod, requestURL]; + if ([requestHeaders count] > 0) { + [copyable appendFormat:@"Request headers:\n%@\n", + [[self class] headersStringForDictionary:requestHeaders]]; + } + + if (postDataLength > 0) { + [copyable appendFormat:@"Request body: (%u bytes)\n", + (unsigned int) postDataLength]; + if (postDataStr) { + [copyable appendFormat:@"%@\n", postDataStr]; + } + [copyable appendString:@"\n"]; + } + + if (response) { + [copyable appendFormat:@"Response: status %d\n", (int) status]; + [copyable appendFormat:@"Response headers:\n%@\n", + [[self class] headersStringForDictionary:responseHeaders]]; + [copyable appendFormat:@"Response body: (%u bytes)\n", + (unsigned int) responseDataLength]; + if (responseDataLength > 0) { + if (logResponseBody_) { + responseDataStr = [[logResponseBody_ copy] autorelease]; + [logResponseBody_ release]; + logResponseBody_ = nil; + } + if (responseDataStr != nil) { + [copyable appendFormat:@"%@\n", responseDataStr]; + } else if (status >= 400 && [temporaryDownloadPath_ length] > 0) { + // Try to read in the saved data, which is probably a server error + // message + NSStringEncoding enc; + responseDataStr = [NSString stringWithContentsOfFile:temporaryDownloadPath_ + usedEncoding:&enc + error:NULL]; + if ([responseDataStr length] > 0) { + [copyable appendFormat:@"%@\n", responseDataStr]; + } else { + [copyable appendFormat:@"<<%u bytes to file>>\n", + (unsigned int) responseDataLength]; + } + } else { + // Even though it's redundant, we'll put in text to indicate that all + // the bytes are binary + [copyable appendFormat:@"<<%u bytes>>\n", + (unsigned int) responseDataLength]; + } + } + } + + if (error) { + [copyable appendFormat:@"Error: %@\n", error]; + } + + // Save to log property before adding the separator + self.log = copyable; + + [copyable appendString:@"-----------------------------------------------------------\n"]; + + + // Write the copyable version to another file (linked to at the top of the + // html file, above) + // + // Ideally, something to just copy this to the clipboard like + // Copy here." + // would work everywhere, but it only works in Safari as of 8/2010 + if (gIsLoggingToFile) { + NSString *copyablePath = [logDirectory stringByAppendingPathComponent:copyableFileName]; + NSError *copyableError = nil; + if (![copyable writeToFile:copyablePath + atomically:NO + encoding:NSUTF8StringEncoding + error:©ableError]) { + // Error writing to file + NSLog(@"%@ logging write error:%@ (%@)", + [self class], copyableError, copyablePath); + } + + [outputHTML appendString:@"

"]; + + // Append the HTML to the main output file + const char* htmlBytes = [outputHTML UTF8String]; + NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:htmlPath + append:YES]; + [stream open]; + [stream write:(const uint8_t *) htmlBytes maxLength:strlen(htmlBytes)]; + [stream close]; + + // Make a symlink to the latest html + NSString *const symlinkNameSuffix = [[self class] symlinkNameSuffix]; + NSString *symlinkName = [processName stringByAppendingString:symlinkNameSuffix]; + NSString *symlinkPath = [parentDir stringByAppendingPathComponent:symlinkName]; + + [[self class] removeItemAtPath:symlinkPath]; + [[self class] createSymbolicLinkAtPath:symlinkPath + withDestinationPath:htmlPath]; + +#if GTM_IPHONE + static BOOL gReportedLoggingPath = NO; + if (!gReportedLoggingPath) { + gReportedLoggingPath = YES; + NSLog(@"GTMHTTPFetcher logging to \"%@\"", parentDir); + } +#endif + } +} + +- (BOOL)logCapturePostStream { + // This is called when beginning a fetch. The caller should have already + // verified that logging is enabled, and should have allocated + // loggedStreamData_ as a mutable object. + + // If the class GTMReadMonitorInputStream is not available, bail now, since + // we cannot capture this upload stream + Class monitorClass = NSClassFromString(@"GTMReadMonitorInputStream"); + if (!monitorClass) return NO; + + // If we're logging, we need to wrap the upload stream with our monitor + // stream that will call us back with the bytes being read from the stream + + // Our wrapper will retain the old post stream + [postStream_ autorelease]; + + postStream_ = [monitorClass inputStreamWithStream:postStream_]; + [postStream_ retain]; + + [(GTMReadMonitorInputStream *)postStream_ setReadDelegate:self]; + [(GTMReadMonitorInputStream *)postStream_ setRunLoopModes:[self runLoopModes]]; + + SEL readSel = @selector(inputStream:readIntoBuffer:length:); + [(GTMReadMonitorInputStream *)postStream_ setReadSelector:readSel]; + + return YES; +} + +@end + +@implementation GTMHTTPFetcher (GTMHTTPFetcherLoggingUtilities) + +- (void)inputStream:(GTMReadMonitorInputStream *)stream + readIntoBuffer:(void *)buffer + length:(NSUInteger)length { + // append the captured data + [loggedStreamData_ appendBytes:buffer length:length]; +} + +#pragma mark Internal file routines + +// We implement plain Unix versions of NSFileManager methods to avoid +// NSFileManager's issues with being used from multiple threads + ++ (BOOL)fileOrDirExistsAtPath:(NSString *)path { + struct stat buffer; + int result = stat([path fileSystemRepresentation], &buffer); + return (result == 0); +} + ++ (BOOL)makeDirectoryUpToPath:(NSString *)path { + int result = 0; + + // Recursively create the parent directory of the requested path + NSString *parent = [path stringByDeletingLastPathComponent]; + if (![self fileOrDirExistsAtPath:parent]) { + result = [self makeDirectoryUpToPath:parent]; + } + + // Make the leaf directory + if (result == 0 && ![self fileOrDirExistsAtPath:path]) { + result = mkdir([path fileSystemRepresentation], S_IRWXU); // RWX for owner + } + return (result == 0); +} + ++ (BOOL)removeItemAtPath:(NSString *)path { + int result = unlink([path fileSystemRepresentation]); + return (result == 0); +} + ++ (BOOL)createSymbolicLinkAtPath:(NSString *)newPath + withDestinationPath:(NSString *)targetPath { + int result = symlink([targetPath fileSystemRepresentation], + [newPath fileSystemRepresentation]); + return (result == 0); +} + +#pragma mark Fomatting Utilities + ++ (NSString *)snipSubstringOfString:(NSString *)originalStr + betweenStartString:(NSString *)startStr + endString:(NSString *)endStr { +#if SKIP_GTM_FETCH_LOGGING_SNIPPING + return originalStr; +#else + if (originalStr == nil) return nil; + + // Find the start string, and replace everything between it + // and the end string (or the end of the original string) with "_snip_" + NSRange startRange = [originalStr rangeOfString:startStr]; + if (startRange.location == NSNotFound) return originalStr; + + // We found the start string + NSUInteger originalLength = [originalStr length]; + NSUInteger startOfTarget = NSMaxRange(startRange); + NSRange targetAndRest = NSMakeRange(startOfTarget, + originalLength - startOfTarget); + NSRange endRange = [originalStr rangeOfString:endStr + options:0 + range:targetAndRest]; + NSRange replaceRange; + if (endRange.location == NSNotFound) { + // Found no end marker so replace to end of string + replaceRange = targetAndRest; + } else { + // Replace up to the endStr + replaceRange = NSMakeRange(startOfTarget, + endRange.location - startOfTarget); + } + + NSString *result = [originalStr stringByReplacingCharactersInRange:replaceRange + withString:@"_snip_"]; + return result; +#endif // SKIP_GTM_FETCH_LOGGING_SNIPPING +} + ++ (NSString *)headersStringForDictionary:(NSDictionary *)dict { + // Format the dictionary in http header style, like + // Accept: application/json + // Cache-Control: no-cache + // Content-Type: application/json; charset=utf-8 + // + // Pad the key names, but not beyond 16 chars, since long custom header + // keys just create too much whitespace + NSArray *keys = [[dict allKeys] sortedArrayUsingSelector:@selector(compare:)]; + + NSMutableString *str = [NSMutableString string]; + for (NSString *key in keys) { + NSString *value = [dict valueForKey:key]; + if ([key isEqual:@"Authorization"]) { + // Remove OAuth 1 token + value = [[self class] snipSubstringOfString:value + betweenStartString:@"oauth_token=\"" + endString:@"\""]; + + // Remove OAuth 2 bearer token (draft 16, and older form) + value = [[self class] snipSubstringOfString:value + betweenStartString:@"Bearer " + endString:@"\n"]; + value = [[self class] snipSubstringOfString:value + betweenStartString:@"OAuth " + endString:@"\n"]; + + // Remove Google ClientLogin + value = [[self class] snipSubstringOfString:value + betweenStartString:@"GoogleLogin auth=" + endString:@"\n"]; + } + [str appendFormat:@" %@: %@\n", key, value]; + } + return str; +} + ++ (id)JSONObjectWithData:(NSData *)data { + Class serializer = NSClassFromString(@"NSJSONSerialization"); + if (serializer) { + const NSUInteger kOpts = (1UL << 0); // NSJSONReadingMutableContainers + NSMutableDictionary *obj; + obj = [serializer JSONObjectWithData:data + options:kOpts + error:NULL]; + return obj; + } else { + // Try SBJsonParser or SBJSON + Class jsonParseClass = NSClassFromString(@"SBJsonParser"); + if (!jsonParseClass) { + jsonParseClass = NSClassFromString(@"SBJSON"); + } + if (jsonParseClass) { + GTMFetcherSBJSON *parser = [[[jsonParseClass alloc] init] autorelease]; + NSString *jsonStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + if (jsonStr) { + NSMutableDictionary *obj = [parser objectWithString:jsonStr error:NULL]; + return obj; + } + } + } + return nil; +} + ++ (id)stringWithJSONObject:(id)obj { + Class serializer = NSClassFromString(@"NSJSONSerialization"); + if (serializer) { + const NSUInteger kOpts = (1UL << 0); // NSJSONWritingPrettyPrinted + NSData *data; + data = [serializer dataWithJSONObject:obj + options:kOpts + error:NULL]; + if (data) { + NSString *jsonStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + return jsonStr; + } + } else { + // Try SBJsonParser or SBJSON + Class jsonWriterClass = NSClassFromString(@"SBJsonWriter"); + if (!jsonWriterClass) { + jsonWriterClass = NSClassFromString(@"SBJSON"); + } + if (jsonWriterClass) { + GTMFetcherSBJSON *writer = [[[jsonWriterClass alloc] init] autorelease]; + [writer setHumanReadable:YES]; + NSString *jsonStr = [writer stringWithObject:obj error:NULL]; + return jsonStr; + } + } + return nil; +} + +@end + +#endif // !STRIP_GTM_FETCH_LOGGING diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherService.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherService.h new file mode 100755 index 0000000..94912b6 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherService.h @@ -0,0 +1,130 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPFetcherService.h +// + +// The fetcher service class maintains a history to be used by a sequence +// of fetchers objects generated by the service. +// +// Fetchers that do not need to share a history may be generated independently, +// like +// +// GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request]; +// +// Fetchers that should share cookies or an ETagged data cache should be +// generated by a common GTMHTTPFetcherService instance, like +// +// GTMHTTPFetcherService *myFetcherService = [[GTMHTTPFetcherService alloc] init]; +// GTMHTTPFetcher* myFirstFetcher = [myFetcherService fetcherWithRequest:request1]; +// GTMHTTPFetcher* mySecondFetcher = [myFetcherService fetcherWithRequest:request2]; + +#import "GTMHTTPFetcher.h" +#import "GTMHTTPFetchHistory.h" + +@interface GTMHTTPFetcherService : NSObject { + @private + NSMutableDictionary *delayedHosts_; + NSMutableDictionary *runningHosts_; + NSUInteger maxRunningFetchersPerHost_; + + GTMHTTPFetchHistory *fetchHistory_; + NSOperationQueue *delegateQueue_; + NSArray *runLoopModes_; + NSString *userAgent_; + NSTimeInterval timeout_; + NSURLCredential *credential_; // username & password + NSURLCredential *proxyCredential_; // credential supplied to proxy servers + NSInteger cookieStorageMethod_; + + NSArray *allowedInsecureSchemes_; + BOOL allowLocalhostRequest_; + + BOOL shouldFetchInBackground_; + + id authorizer_; +} + +// Create a fetcher +// +// These methods will return an autoreleased fetcher, but if +// the fetcher is successfully created, the connection will retain the +// fetcher for the life of the connection as well. So the caller doesn't have +// to retain the fetcher explicitly unless they want to be able to monitor +// or cancel it. +- (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request; +- (GTMHTTPFetcher *)fetcherWithURL:(NSURL *)requestURL; +- (GTMHTTPFetcher *)fetcherWithURLString:(NSString *)requestURLString; +- (id)fetcherWithRequest:(NSURLRequest *)request + fetcherClass:(Class)fetcherClass; + +// Queues of delayed and running fetchers. Each dictionary contains arrays +// of fetchers, keyed by host +// +// A max value of 0 means no fetchers should be delayed. +// +// The default limit is 10 simultaneous fetchers targeting each host. +@property (assign) NSUInteger maxRunningFetchersPerHost; +@property (retain, readonly) NSDictionary *delayedHosts; +@property (retain, readonly) NSDictionary *runningHosts; + +- (BOOL)isDelayingFetcher:(GTMHTTPFetcher *)fetcher; + +- (NSUInteger)numberOfFetchers; // running + delayed fetchers +- (NSUInteger)numberOfRunningFetchers; +- (NSUInteger)numberOfDelayedFetchers; + +// Search for running or delayed fetchers with the specified URL. +// +// Returns an array of fetcher objects found, or nil if none found. +- (NSArray *)issuedFetchersWithRequestURL:(NSURL *)requestURL; + +- (void)stopAllFetchers; + +// Properties to be applied to each fetcher; +// see GTMHTTPFetcher.h for descriptions +@property (copy) NSString *userAgent; +@property (assign) NSTimeInterval timeout; +@property (retain) NSOperationQueue *delegateQueue; +@property (retain) NSArray *runLoopModes; +@property (retain) NSURLCredential *credential; +@property (retain) NSURLCredential *proxyCredential; +@property (assign) BOOL shouldFetchInBackground; +@property (copy) NSArray *allowedInsecureSchemes; +@property (assign) BOOL allowLocalhostRequest; + +// Fetch history +@property (retain) GTMHTTPFetchHistory *fetchHistory; + +@property (assign) NSInteger cookieStorageMethod; +@property (assign) BOOL shouldRememberETags; // default: NO +@property (assign) BOOL shouldCacheETaggedData; // default: NO + +- (void)clearETaggedDataCache; +- (void)clearHistory; + +@property (nonatomic, retain) id authorizer; + +// Spin the run loop, discarding events, until all running and delayed fetchers +// have completed +// +// This is only for use in testing or in tools without a user interface. +// +// Synchronous fetches should never be done by shipping apps; they are +// sufficient reason for rejection from the app store. +- (void)waitForCompletionOfAllFetchersWithTimeout:(NSTimeInterval)timeoutInSeconds; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherService.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherService.m new file mode 100755 index 0000000..4a00e58 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPFetcherService.m @@ -0,0 +1,507 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPFetcherService.m +// + +#import "GTMHTTPFetcherService.h" + +@interface GTMHTTPFetcher (ServiceMethods) +- (BOOL)beginFetchMayDelay:(BOOL)mayDelay + mayAuthorize:(BOOL)mayAuthorize; +@end + +@interface GTMHTTPFetcherService () +@property (retain, readwrite) NSDictionary *delayedHosts; +@property (retain, readwrite) NSDictionary *runningHosts; + +- (void)detachAuthorizer; +@end + +@implementation GTMHTTPFetcherService + +@synthesize maxRunningFetchersPerHost = maxRunningFetchersPerHost_, + userAgent = userAgent_, + timeout = timeout_, + delegateQueue = delegateQueue_, + runLoopModes = runLoopModes_, + credential = credential_, + proxyCredential = proxyCredential_, + cookieStorageMethod = cookieStorageMethod_, + shouldFetchInBackground = shouldFetchInBackground_, + allowedInsecureSchemes = allowedInsecureSchemes_, + allowLocalhostRequest = allowLocalhostRequest_, + fetchHistory = fetchHistory_; + +- (id)init { + self = [super init]; + if (self) { + fetchHistory_ = [[GTMHTTPFetchHistory alloc] init]; + delayedHosts_ = [[NSMutableDictionary alloc] init]; + runningHosts_ = [[NSMutableDictionary alloc] init]; + cookieStorageMethod_ = kGTMHTTPFetcherCookieStorageMethodFetchHistory; + + maxRunningFetchersPerHost_ = 10; +} + return self; +} + +- (void)dealloc { + [self detachAuthorizer]; + + [delayedHosts_ release]; + [runningHosts_ release]; + [fetchHistory_ release]; + [userAgent_ release]; + [delegateQueue_ release]; + [runLoopModes_ release]; + [credential_ release]; + [proxyCredential_ release]; + [authorizer_ release]; + + [super dealloc]; +} + +#pragma mark Generate a new fetcher + +- (id)fetcherWithRequest:(NSURLRequest *)request + fetcherClass:(Class)fetcherClass { + GTMHTTPFetcher *fetcher = [fetcherClass fetcherWithRequest:request]; + + fetcher.fetchHistory = self.fetchHistory; + fetcher.delegateQueue = self.delegateQueue; + fetcher.runLoopModes = self.runLoopModes; + fetcher.cookieStorageMethod = self.cookieStorageMethod; + fetcher.credential = self.credential; + fetcher.proxyCredential = self.proxyCredential; + fetcher.shouldFetchInBackground = self.shouldFetchInBackground; + fetcher.allowedInsecureSchemes = self.allowedInsecureSchemes; + fetcher.allowLocalhostRequest = self.allowLocalhostRequest; + fetcher.authorizer = self.authorizer; + fetcher.service = self; + + NSString *userAgent = self.userAgent; + if ([userAgent length] > 0 + && [request valueForHTTPHeaderField:@"User-Agent"] == nil) { + [fetcher.mutableRequest setValue:userAgent + forHTTPHeaderField:@"User-Agent"]; + } + + NSTimeInterval timeout = self.timeout; + if (timeout > 0.0) { + [fetcher.mutableRequest setTimeoutInterval:timeout]; + } + + return fetcher; +} + +- (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request { + return [self fetcherWithRequest:request + fetcherClass:[GTMHTTPFetcher class]]; +} + +- (GTMHTTPFetcher *)fetcherWithURL:(NSURL *)requestURL { + return [self fetcherWithRequest:[NSURLRequest requestWithURL:requestURL]]; +} + +- (GTMHTTPFetcher *)fetcherWithURLString:(NSString *)requestURLString { + return [self fetcherWithURL:[NSURL URLWithString:requestURLString]]; +} + +#pragma mark Queue Management + +- (void)addRunningFetcher:(GTMHTTPFetcher *)fetcher + forHost:(NSString *)host { + // Add to the array of running fetchers for this host, creating the array + // if needed + NSMutableArray *runningForHost = [runningHosts_ objectForKey:host]; + if (runningForHost == nil) { + runningForHost = [NSMutableArray arrayWithObject:fetcher]; + [runningHosts_ setObject:runningForHost forKey:host]; + } else { + [runningForHost addObject:fetcher]; + } +} + +- (void)addDelayedFetcher:(GTMHTTPFetcher *)fetcher + forHost:(NSString *)host { + // Add to the array of delayed fetchers for this host, creating the array + // if needed + NSMutableArray *delayedForHost = [delayedHosts_ objectForKey:host]; + if (delayedForHost == nil) { + delayedForHost = [NSMutableArray arrayWithObject:fetcher]; + [delayedHosts_ setObject:delayedForHost forKey:host]; + } else { + [delayedForHost addObject:fetcher]; + } +} + +- (BOOL)isDelayingFetcher:(GTMHTTPFetcher *)fetcher { + @synchronized(self) { + NSString *host = [[[fetcher mutableRequest] URL] host]; + NSArray *delayedForHost = [delayedHosts_ objectForKey:host]; + NSUInteger idx = [delayedForHost indexOfObjectIdenticalTo:fetcher]; + BOOL isDelayed = (delayedForHost != nil) && (idx != NSNotFound); + return isDelayed; + } +} + +- (BOOL)fetcherShouldBeginFetching:(GTMHTTPFetcher *)fetcher { + // Entry point from the fetcher + @synchronized(self) { + NSURL *requestURL = [[fetcher mutableRequest] URL]; + NSString *host = [requestURL host]; + + // Addresses "file:///path" case where localhost is the implicit host. + if ([host length] == 0 && [requestURL isFileURL]) { + host = @"localhost"; + } + + if ([host length] == 0) { +#if DEBUG + // Data URIs legitimately have no host, reject other hostless URLs. + NSAssert1([[requestURL scheme] isEqual:@"data"], @"%@ lacks host", fetcher); +#endif + return YES; + } + + NSMutableArray *runningForHost = [runningHosts_ objectForKey:host]; + if (runningForHost != nil + && [runningForHost indexOfObjectIdenticalTo:fetcher] != NSNotFound) { +#if DEBUG + NSAssert1(0, @"%@ was already running", fetcher); +#endif + return YES; + } + + // We'll save the host that serves as the key for this fetcher's array + // to avoid any chance of the underlying request changing, stranding + // the fetcher in the wrong array + fetcher.serviceHost = host; + fetcher.thread = [NSThread currentThread]; + + if (maxRunningFetchersPerHost_ == 0 + || maxRunningFetchersPerHost_ > [runningForHost count]) { + [self addRunningFetcher:fetcher forHost:host]; + return YES; + } else { + [self addDelayedFetcher:fetcher forHost:host]; + return NO; + } + } + return YES; +} + +// Fetcher start and stop methods, invoked on the appropriate thread for +// the fetcher +- (void)performSelector:(SEL)sel onStartThreadForFetcher:(GTMHTTPFetcher *)fetcher { + NSOperationQueue *delegateQueue = fetcher.delegateQueue; + NSThread *thread = fetcher.thread; + if (delegateQueue != nil || [thread isEqual:[NSThread currentThread]]) { + // The fetcher should run on the thread we're on now, or there's a delegate + // queue specified so it doesn't matter what thread the fetcher is started + // on, since it will call back on the queue. + [self performSelector:sel withObject:fetcher]; + } else { + // Fetcher must run on a specified thread (and that thread must have a + // run loop.) + [self performSelector:sel + onThread:thread + withObject:fetcher + waitUntilDone:NO]; + } +} + +- (void)startFetcherOnCurrentThread:(GTMHTTPFetcher *)fetcher { + [fetcher beginFetchMayDelay:NO + mayAuthorize:YES]; +} + +- (void)startFetcher:(GTMHTTPFetcher *)fetcher { + [self performSelector:@selector(startFetcherOnCurrentThread:) + onStartThreadForFetcher:fetcher]; +} + +- (void)stopFetcherOnCurrentThread:(GTMHTTPFetcher *)fetcher { + [fetcher stopFetching]; +} + +- (void)stopFetcher:(GTMHTTPFetcher *)fetcher { + [self performSelector:@selector(stopFetcherOnCurrentThread:) + onStartThreadForFetcher:fetcher]; +} + +- (void)fetcherDidStop:(GTMHTTPFetcher *)fetcher { + // Entry point from the fetcher + @synchronized(self) { + NSString *host = fetcher.serviceHost; + if (!host) { + // fetcher has been stopped previously + return; + } + + NSMutableArray *runningForHost = [runningHosts_ objectForKey:host]; + [runningForHost removeObject:fetcher]; + + NSMutableArray *delayedForHost = [delayedHosts_ objectForKey:host]; + [delayedForHost removeObject:fetcher]; + + while ([delayedForHost count] > 0 + && [runningForHost count] < maxRunningFetchersPerHost_) { + // Start another delayed fetcher running, scanning for the minimum + // priority value, defaulting to FIFO for equal priorities + GTMHTTPFetcher *nextFetcher = nil; + for (GTMHTTPFetcher *delayedFetcher in delayedForHost) { + if (nextFetcher == nil + || delayedFetcher.servicePriority < nextFetcher.servicePriority) { + nextFetcher = delayedFetcher; + } + } + + if (nextFetcher) { + [self addRunningFetcher:nextFetcher forHost:host]; + runningForHost = [runningHosts_ objectForKey:host]; + + [delayedForHost removeObjectIdenticalTo:nextFetcher]; + [self startFetcher:nextFetcher]; + } + } + + if ([runningForHost count] == 0) { + // None left; remove the empty array + [runningHosts_ removeObjectForKey:host]; + } + + if ([delayedForHost count] == 0) { + [delayedHosts_ removeObjectForKey:host]; + } + + // The fetcher is no longer in the running or the delayed array, + // so remove its host and thread properties + fetcher.serviceHost = nil; + fetcher.thread = nil; + } +} + +- (NSUInteger)numberOfFetchers { + @synchronized(self) { + NSUInteger running = [self numberOfRunningFetchers]; + NSUInteger delayed = [self numberOfDelayedFetchers]; + return running + delayed; + } +} + +- (NSUInteger)numberOfRunningFetchers { + @synchronized(self) { + NSUInteger sum = 0; + for (NSString *host in runningHosts_) { + NSArray *fetchers = [runningHosts_ objectForKey:host]; + sum += [fetchers count]; + } + return sum; + } +} + +- (NSUInteger)numberOfDelayedFetchers { + @synchronized(self) { + NSUInteger sum = 0; + for (NSString *host in delayedHosts_) { + NSArray *fetchers = [delayedHosts_ objectForKey:host]; + sum += [fetchers count]; + } + return sum; + } +} + +- (NSArray *)issuedFetchersWithRequestURL:(NSURL *)requestURL { + @synchronized(self) { + NSMutableArray *array = nil; + NSString *host = [requestURL host]; + if ([host length] == 0) return nil; + + NSURL *absRequestURL = [requestURL absoluteURL]; + + NSArray *runningForHost = [runningHosts_ objectForKey:host]; + for (GTMHTTPFetcher *fetcher in runningForHost) { + NSURL *fetcherURL = [[[fetcher mutableRequest] URL] absoluteURL]; + if ([fetcherURL isEqual:absRequestURL]) { + if (array == nil) { + array = [NSMutableArray array]; + } + [array addObject:fetcher]; + } + } + + NSArray *delayedForHost = [delayedHosts_ objectForKey:host]; + for (GTMHTTPFetcher *fetcher in delayedForHost) { + NSURL *fetcherURL = [[[fetcher mutableRequest] URL] absoluteURL]; + if ([fetcherURL isEqual:absRequestURL]) { + if (array == nil) { + array = [NSMutableArray array]; + } + [array addObject:fetcher]; + } + } + return array; + } +} + +- (void)stopAllFetchers { + @synchronized(self) { + // Remove fetchers from the delayed list to avoid fetcherDidStop: from + // starting more fetchers running as a side effect of stopping one + NSArray *delayedForHosts = [delayedHosts_ allValues]; + [delayedHosts_ removeAllObjects]; + + for (NSArray *delayedForHost in delayedForHosts) { + for (GTMHTTPFetcher *fetcher in delayedForHost) { + [self stopFetcher:fetcher]; + } + } + + NSArray *runningForHosts = [runningHosts_ allValues]; + [runningHosts_ removeAllObjects]; + + for (NSArray *runningForHost in runningForHosts) { + for (GTMHTTPFetcher *fetcher in runningForHost) { + [self stopFetcher:fetcher]; + } + } + } +} + +#pragma mark Fetch History Settings + +// Turn on data caching to receive a copy of previously-retrieved objects. +// Otherwise, fetches may return status 304 (No Change) rather than actual data +- (void)setShouldCacheETaggedData:(BOOL)flag { + self.fetchHistory.shouldCacheETaggedData = flag; +} + +- (BOOL)shouldCacheETaggedData { + return self.fetchHistory.shouldCacheETaggedData; +} + +- (void)setETaggedDataCacheCapacity:(NSUInteger)totalBytes { + self.fetchHistory.memoryCapacity = totalBytes; +} + +- (NSUInteger)ETaggedDataCacheCapacity { + return self.fetchHistory.memoryCapacity; +} + +- (void)setShouldRememberETags:(BOOL)flag { + self.fetchHistory.shouldRememberETags = flag; +} + +- (BOOL)shouldRememberETags { + return self.fetchHistory.shouldRememberETags; +} + +// reset the ETag cache to avoid getting a Not Modified status +// based on prior queries +- (void)clearETaggedDataCache { + [self.fetchHistory clearETaggedDataCache]; +} + +- (void)clearHistory { + [self clearETaggedDataCache]; + [self.fetchHistory removeAllCookies]; +} + +#pragma mark Synchronous Wait for Unit Testing + +- (void)waitForCompletionOfAllFetchersWithTimeout:(NSTimeInterval)timeoutInSeconds { + NSDate* giveUpDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + BOOL isMainThread = [NSThread isMainThread]; + + while ([self numberOfFetchers] > 0 + && [giveUpDate timeIntervalSinceNow] > 0) { + // Run the current run loop 1/1000 of a second to give the networking + // code a chance to work + if (isMainThread || delegateQueue_ == nil) { + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:0.001]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + // Sleep on the delegate queue's background thread. + [NSThread sleepForTimeInterval:0.001]; + } + } +} + +#pragma mark Accessors + +- (NSDictionary *)runningHosts { + return runningHosts_; +} + +- (void)setRunningHosts:(NSDictionary *)dict { + [runningHosts_ autorelease]; + runningHosts_ = [dict mutableCopy]; +} + +- (NSDictionary *)delayedHosts { + return delayedHosts_; +} + +- (void)setDelayedHosts:(NSDictionary *)dict { + [delayedHosts_ autorelease]; + delayedHosts_ = [dict mutableCopy]; +} + +- (id )authorizer { + return authorizer_; +} + +- (void)setAuthorizer:(id )obj { + if (obj != authorizer_) { + [self detachAuthorizer]; + } + + [authorizer_ autorelease]; + authorizer_ = [obj retain]; + + // Use the fetcher service for the authorization fetches if the auth + // object supports fetcher services + if ([authorizer_ respondsToSelector:@selector(setFetcherService:)]) { +#if GTM_USE_SESSION_FETCHER + [authorizer_ setFetcherService:(id)self]; +#else + [authorizer_ setFetcherService:self]; +#endif + } +} + +- (void)detachAuthorizer { + // This method is called by the fetcher service's dealloc and setAuthorizer: + // methods; do not override. + // + // The fetcher service retains the authorizer, and the authorizer has a + // weak pointer to the fetcher service (a non-zeroing pointer for + // compatibility with iOS 4 and Mac OS X 10.5/10.6.) + // + // When this fetcher service no longer uses the authorizer, we want to remove + // the authorizer's dependence on the fetcher service. Authorizers can still + // function without a fetcher service. + if ([authorizer_ respondsToSelector:@selector(fetcherService)]) { + id authFetcherService = [authorizer_ fetcherService]; + if (authFetcherService == self) { + [authorizer_ setFetcherService:nil]; + } + } +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPUploadFetcher.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPUploadFetcher.h new file mode 100755 index 0000000..b0ce3b6 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPUploadFetcher.h @@ -0,0 +1,139 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPUploadFetcher.h +// + +#if (!GDATA_REQUIRE_SERVICE_INCLUDES) || GDATA_INCLUDE_DOCS_SERVICE || \ + GDATA_INCLUDE_YOUTUBE_SERVICE || GDATA_INCLUDE_PHOTOS_SERVICE + +// +// This subclass of GTMHTTPFetcher simulates the series of fetches +// needed for chunked upload as a single fetch operation. +// +// Protocol document: +// http://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal +// +// To the client, the only fetcher that exists is this class; the subsidiary +// fetchers needed for uploading chunks are not visible (though the most recent +// chunk fetcher may be accessed via the -activeFetcher method, and +// -responseHeaders and -statusCode reflect results from the most recent chunk +// fetcher.) +// +// Chunk fetchers are discarded as soon as they have completed. +// + +#pragma once + +#import "GTMHTTPFetcher.h" +#import "GTMHTTPFetcherService.h" + +// async retrieval of an http get or post +@interface GTMHTTPUploadFetcher : GTMHTTPFetcher { + GTMHTTPFetcher *chunkFetcher_; + + // we'll call through to the delegate's sentData and finished selectors + SEL delegateSentDataSEL_; + SEL delegateFinishedSEL_; + + BOOL needsManualProgress_; + + // the initial fetch's body length and bytes actually sent are + // needed for calculating progress during subsequent chunk uploads + NSUInteger initialBodyLength_; + NSUInteger initialBodySent_; + + NSURL *locationURL_; +#if NS_BLOCKS_AVAILABLE + void (^locationChangeBlock_)(NSURL *); +#elif !__LP64__ + // placeholders: for 32-bit builds, keep the size of the object's ivar section + // the same with and without blocks +#ifndef __clang_analyzer__ + id locationChangePlaceholder_; +#endif +#endif + + // uploadData_ or uploadFileHandle_ may be set, but not both + NSData *uploadData_; + NSFileHandle *uploadFileHandle_; + NSInteger uploadFileHandleLength_; + NSString *uploadMIMEType_; + NSUInteger chunkSize_; + BOOL isPaused_; + BOOL isRestartedUpload_; + + // we keep the latest offset into the upload data just for + // progress reporting + NSUInteger currentOffset_; + + // we store the response headers and status code for the most recent + // chunk fetcher + NSDictionary *responseHeaders_; + NSInteger statusCode_; +} + ++ (GTMHTTPUploadFetcher *)uploadFetcherWithRequest:(NSURLRequest *)request + uploadData:(NSData *)data + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMHTTPFetcherService *)fetcherServiceOrNil; + ++ (GTMHTTPUploadFetcher *)uploadFetcherWithRequest:(NSURLRequest *)request + uploadFileHandle:(NSFileHandle *)fileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMHTTPFetcherService *)fetcherServiceOrNil; + ++ (GTMHTTPUploadFetcher *)uploadFetcherWithLocation:(NSURL *)locationURL + uploadFileHandle:(NSFileHandle *)fileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMHTTPFetcherService *)fetcherServiceOrNil; +- (void)pauseFetching; +- (void)resumeFetching; +- (BOOL)isPaused; + +@property (retain) NSURL *locationURL; +@property (retain) NSData *uploadData; +@property (retain) NSFileHandle *uploadFileHandle; +@property (copy) NSString *uploadMIMEType; +@property (assign) NSUInteger chunkSize; +@property (assign) NSUInteger currentOffset; + +#if NS_BLOCKS_AVAILABLE +// When the upload location changes, the optional locationChangeBlock will be +// called. It will be called with nil once upload succeeds or can no longer +// be attempted. +@property (copy) void (^locationChangeBlock)(NSURL *locationURL); +#endif + +// the fetcher for the current data chunk, if any +@property (retain) GTMHTTPFetcher *chunkFetcher; + +// the active fetcher is the last chunk fetcher, or the upload fetcher itself +// if no chunk fetcher has yet been created +@property (readonly) GTMHTTPFetcher *activeFetcher; + +// the response headers from the most recently-completed fetch +@property (retain) NSDictionary *responseHeaders; + +// the status code from the most recently-completed fetch +@property (assign) NSInteger statusCode; + +@end + +#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPUploadFetcher.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPUploadFetcher.m new file mode 100755 index 0000000..a7cea24 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMHTTPUploadFetcher.m @@ -0,0 +1,947 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMHTTPUploadFetcher.m +// + +#if (!GDATA_REQUIRE_SERVICE_INCLUDES) || GDATA_INCLUDE_DOCS_SERVICE || \ + GDATA_INCLUDE_YOUTUBE_SERVICE || GDATA_INCLUDE_PHOTOS_SERVICE + +#import "GTMHTTPUploadFetcher.h" + +static NSUInteger const kQueryServerForOffset = NSUIntegerMax; + +@interface GTMHTTPFetcher (ProtectedMethods) +@property (readwrite, retain) NSData *downloadedData; +- (void)releaseCallbacks; +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks; +- (void)connectionDidFinishLoading:(NSURLConnection *)connection; +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; +@end + +@interface GTMHTTPUploadFetcher () ++ (GTMHTTPUploadFetcher *)uploadFetcherWithRequest:(NSURLRequest *)request + fetcherService:(GTMHTTPFetcherService *)fetcherService; +- (void)setLocationURL:(NSURL *)location + uploadData:(NSData *)data + uploadFileHandle:(NSFileHandle *)fileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize; + +- (void)uploadNextChunkWithOffset:(NSUInteger)offset; +- (void)uploadNextChunkWithOffset:(NSUInteger)offset + fetcherProperties:(NSMutableDictionary *)props; +- (void)destroyChunkFetcher; + +- (void)handleResumeIncompleteStatusForChunkFetcher:(GTMHTTPFetcher *)chunkFetcher; + +- (void)uploadFetcher:(GTMHTTPFetcher *)fetcher + didSendBytes:(NSInteger)bytesSent + totalBytesSent:(NSInteger)totalBytesSent +totalBytesExpectedToSend:(NSInteger)totalBytesExpected; + +- (void)reportProgressManually; + +- (NSUInteger)fullUploadLength; + +-(BOOL)chunkFetcher:(GTMHTTPFetcher *)chunkFetcher + willRetry:(BOOL)willRetry + forError:(NSError *)error; + +- (void)chunkFetcher:(GTMHTTPFetcher *)chunkFetcher + finishedWithData:(NSData *)data + error:(NSError *)error; +@end + +@interface GTMHTTPUploadFetcher (PrivateMethods) +// private methods of the superclass +- (void)invokeSentDataCallback:(SEL)sel + target:(id)target + didSendBodyData:(NSInteger)bytesWritten + totalBytesWritten:(NSInteger)totalBytesWritten + totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite; + +- (void)invokeFetchCallback:(SEL)sel + target:(id)target + data:(NSData *)data + error:(NSError *)error; + +- (BOOL)invokeRetryCallback:(SEL)sel + target:(id)target + willRetry:(BOOL)willRetry + error:(NSError *)error; +@end + +@implementation GTMHTTPUploadFetcher + ++ (GTMHTTPUploadFetcher *)uploadFetcherWithRequest:(NSURLRequest *)request + uploadData:(NSData *)data + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMHTTPFetcherService *)fetcherService { + GTMHTTPUploadFetcher *fetcher = [self uploadFetcherWithRequest:request + fetcherService:fetcherService]; + [fetcher setLocationURL:nil + uploadData:data + uploadFileHandle:nil + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize]; + return fetcher; +} + ++ (GTMHTTPUploadFetcher *)uploadFetcherWithRequest:(NSURLRequest *)request + uploadFileHandle:(NSFileHandle *)fileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMHTTPFetcherService *)fetcherService { + GTMHTTPUploadFetcher *fetcher = [self uploadFetcherWithRequest:request + fetcherService:fetcherService]; + [fetcher setLocationURL:nil + uploadData:nil + uploadFileHandle:fileHandle + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize]; + return fetcher; +} + ++ (GTMHTTPUploadFetcher *)uploadFetcherWithLocation:(NSURL *)locationURL + uploadFileHandle:(NSFileHandle *)fileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize + fetcherService:(GTMHTTPFetcherService *)fetcherService { + GTMHTTPUploadFetcher *fetcher = [self uploadFetcherWithRequest:nil + fetcherService:fetcherService]; + [fetcher setLocationURL:locationURL + uploadData:nil + uploadFileHandle:fileHandle + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize]; + return fetcher; +} + ++ (GTMHTTPUploadFetcher *)uploadFetcherWithRequest:(NSURLRequest *)request + fetcherService:(GTMHTTPFetcherService *)fetcherService { + // Internal utility method for instantiating fetchers + GTMHTTPUploadFetcher *fetcher; + if (fetcherService) { + fetcher = [fetcherService fetcherWithRequest:request + fetcherClass:self]; + } else { + fetcher = (GTMHTTPUploadFetcher *) [self fetcherWithRequest:request]; + } + return fetcher; +} + +- (void)setLocationURL:(NSURL *)location + uploadData:(NSData *)data + uploadFileHandle:(NSFileHandle *)fileHandle + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(NSUInteger)chunkSize { +#if DEBUG + NSAssert((data == nil) != (fileHandle == nil), + @"upload data and fileHandle are mutually exclusive"); + NSAssert((self.mutableRequest == nil) != (location == nil), + @"request and location are mutually exclusive"); + NSAssert(chunkSize > 0,@"chunk size is zero"); + NSAssert(chunkSize != NSUIntegerMax, @"chunk size is sentinel value"); +#endif + [self setLocationURL:location]; + [self setUploadData:data]; + [self setUploadFileHandle:fileHandle]; + [self setUploadMIMEType:uploadMIMEType]; + [self setChunkSize:chunkSize]; + + // indicate that we've not yet determined the file handle's length + uploadFileHandleLength_ = -1; + + // indicate that we've not yet determined the upload fetcher status + statusCode_ = -1; + + // if this is restarting an upload begun by another fetcher, + // the location is specified but the request is nil + isRestartedUpload_ = (location != nil); + + // add our custom headers to the initial request indicating the data + // type and total size to be delivered later in the chunk requests + NSMutableURLRequest *mutableReq = [self mutableRequest]; + + NSNumber *lengthNum = [NSNumber numberWithUnsignedInteger:[self fullUploadLength]]; + [mutableReq setValue:[lengthNum stringValue] + forHTTPHeaderField:@"X-Upload-Content-Length"]; + + [mutableReq setValue:uploadMIMEType + forHTTPHeaderField:@"X-Upload-Content-Type"]; +} + +- (void)dealloc { + [self releaseCallbacks]; + + [chunkFetcher_ release]; + [locationURL_ release]; +#if NS_BLOCKS_AVAILABLE + [locationChangeBlock_ release]; +#endif + [uploadData_ release]; + [uploadFileHandle_ release]; + [uploadMIMEType_ release]; + [responseHeaders_ release]; + [super dealloc]; +} + +#pragma mark - + +- (NSUInteger)fullUploadLength { + if (uploadData_) { + return [uploadData_ length]; + } else { + if (uploadFileHandleLength_ == -1) { + // first time through, seek to end to determine file length + uploadFileHandleLength_ = (NSInteger) [uploadFileHandle_ seekToEndOfFile]; + } + return (NSUInteger)uploadFileHandleLength_; + } +} + +- (NSData *)uploadSubdataWithOffset:(NSUInteger)offset + length:(NSUInteger)length { + NSData *resultData = nil; + + if (uploadData_) { + NSRange range = NSMakeRange(offset, length); + resultData = [uploadData_ subdataWithRange:range]; + } else { + @try { + [uploadFileHandle_ seekToFileOffset:offset]; + resultData = [uploadFileHandle_ readDataOfLength:length]; + } + @catch (NSException *exception) { + NSLog(@"uploadFileHandle exception: %@", exception); + } + } + + return resultData; +} + +#pragma mark Method overrides affecting the initial fetch only + +- (BOOL)beginFetchWithDelegate:(id)delegate + didFinishSelector:(SEL)finishedSEL { + + GTMAssertSelectorNilOrImplementedWithArgs(delegate, finishedSEL, + @encode(GTMHTTPFetcher *), @encode(NSData *), @encode(NSError *), 0); + + // replace the finishedSEL with our own, since the initial finish callback + // is just the beginning of the upload experience + delegateFinishedSEL_ = finishedSEL; + + // if the client is running early 10.5 or iPhone 2, we may need to manually + // send progress indication since NSURLConnection won't be calling back + // to us during uploads + needsManualProgress_ = ![GTMHTTPFetcher doesSupportSentDataCallback]; + + initialBodyLength_ = [[self postData] length]; + + if (isRestartedUpload_) { + if (![self isPaused]) { + if (delegate) { + [self setDelegate:delegate]; + finishedSel_ = finishedSEL; + } + [self uploadNextChunkWithOffset:kQueryServerForOffset]; + } + return YES; + } + + // we don't need a finish selector since we're overriding + // -connectionDidFinishLoading + return [super beginFetchWithDelegate:delegate + didFinishSelector:NULL]; +} + +#if NS_BLOCKS_AVAILABLE +- (BOOL)beginFetchWithCompletionHandler:(void (^)(NSData *data, NSError *error))handler { + // we don't want to call into the delegate's completion block immediately + // after the finish of the initial connection (the delegate is called only + // when uploading finishes), so we substitute our own completion block to be + // called when the initial connection finishes + void (^holdBlock)(NSData *data, NSError *error) = [[handler copy] autorelease]; + + BOOL flag = [super beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + // callback + if (!isRestartedUpload_) { + if (error == nil) { + // swap in the actual completion block now, as it will be called later + // when the upload chunks have completed + [completionBlock_ autorelease]; + completionBlock_ = [holdBlock copy]; + } else { + // pass the error on to the actual completion block + holdBlock(nil, error); + } + } else { + // If there was no initial request, then this fetch is resuming some + // other uploadFetcher's initial request, and the superclass's connection + // is never used, so at this point we call the user's actual completion + // block. + holdBlock(data, error); + } + }]; + return flag; +} +#endif + +- (void)connection:(NSURLConnection *)connection + didSendBodyData:(NSInteger)bytesWritten + totalBytesWritten:(NSInteger)totalBytesWritten +totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { + + // ignore this callback if we're doing manual progress, mainly so that + // we won't see duplicate progress callbacks when testing with + // doesSupportSentDataCallback turned off + if (needsManualProgress_) return; + + [self uploadFetcher:self + didSendBytes:bytesWritten + totalBytesSent:totalBytesWritten +totalBytesExpectedToSend:totalBytesExpectedToWrite]; +} + +- (BOOL)shouldReleaseCallbacksUponCompletion { + // we don't want the superclass to release the delegate and callback + // blocks once the initial fetch has finished + // + // this is invoked for only successful completion of the connection; + // an error always will invoke and release the callbacks + return NO; +} + +- (void)invokeFinalCallbacksWithData:(NSData *)data + error:(NSError *)error + shouldInvalidateLocation:(BOOL)shouldInvalidateLocation { + // avoid issues due to being released indirectly by a callback + [[self retain] autorelease]; + + if (shouldInvalidateLocation) { + [self setLocationURL:nil]; + } + + if (delegate_ && delegateFinishedSEL_) { + [self invokeFetchCallback:delegateFinishedSEL_ + target:delegate_ + data:data + error:error]; + } + +#if NS_BLOCKS_AVAILABLE + if (completionBlock_) { + completionBlock_(data, error); + } + + [self setLocationChangeBlock:nil]; +#endif + + [self releaseCallbacks]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + // handle failure of the initial fetch as a simple fetcher failure, including + // calling the delegate, and allowing retry to happen if appropriate + SEL prevSel = finishedSel_; // should be null + finishedSel_ = delegateFinishedSEL_; + [super connection:connection didFailWithError:error]; + + // If retry later happens and succeeds, it shouldn't message the delegate + // since we'll continue to chunk uploads. + finishedSel_ = prevSel; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + + // we land here once the initial fetch sending the initial POST body + // has completed + + // let the superclass end its connection + [super connectionDidFinishLoading:connection]; + + NSInteger statusCode = [super statusCode]; + [self setStatusCode:statusCode]; + + NSData *downloadedData = [self downloadedData]; + + // we need to get the upload URL from the location header to continue + NSDictionary *responseHeaders = [self responseHeaders]; + NSString *locationURLStr = [responseHeaders objectForKey:@"Location"]; + + NSError *error = nil; + + if (statusCode >= 300) { + if (retryTimer_) return; + + error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain + code:statusCode + userInfo:nil]; + } else if ([downloadedData length] > 0) { + // The initial response of the resumable upload protocol should have an + // empty body + // + // This problem typically happens because the upload create/edit link URL was + // not supplied with the request, and the server is thus expecting a non- + // resumable request/response. It may also happen if an error JSON error body + // is returned. + // + // We'll consider this status 501 Not Implemented rather than try to parse + // the body to determine the actual error, but will provide the data + // as userInfo for clients to inspect. + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:downloadedData + forKey:kGTMHTTPFetcherStatusDataKey]; + error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain + code:501 + userInfo:userInfo]; + } else { +#if DEBUG + NSAssert([locationURLStr length] > 0, @"need upload location hdr"); +#endif + + if ([locationURLStr length] == 0) { + // we cannot continue since we do not know the location to use + // as our upload destination + // + // we'll consider this status 501 Not Implemented + error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain + code:501 + userInfo:nil]; + } + } + + if (error) { + [self invokeFinalCallbacksWithData:downloadedData + error:error + shouldInvalidateLocation:YES]; + return; + } + + [self setLocationURL:[NSURL URLWithString:locationURLStr]]; + + // we've now sent all of the initial post body data, so we need to include + // its size in future progress indicator callbacks + initialBodySent_ = initialBodyLength_; + + if (needsManualProgress_) { + [self reportProgressManually]; + } + + // just in case the user paused us during the initial fetch... + if (![self isPaused]) { + [self uploadNextChunkWithOffset:0]; + } +} + +- (void)retryFetch { + // Override the fetcher's retryFetch to retry with the saved delegateFinishedSEL_. + [self stopFetchReleasingCallbacks:NO]; + + [self beginFetchWithDelegate:delegate_ + didFinishSelector:delegateFinishedSEL_]; +} + +#pragma mark Chunk fetching methods + +- (void)uploadNextChunkWithOffset:(NSUInteger)offset { + // use the properties in each chunk fetcher + NSMutableDictionary *props = [self properties]; + + [self uploadNextChunkWithOffset:offset + fetcherProperties:props]; +} + +- (void)uploadNextChunkWithOffset:(NSUInteger)offset + fetcherProperties:(NSMutableDictionary *)props { + // upload another chunk + NSUInteger chunkSize = [self chunkSize]; + + NSString *rangeStr, *lengthStr; + NSData *chunkData; + + NSUInteger dataLen = [self fullUploadLength]; + + if (offset == kQueryServerForOffset) { + // resuming, so we'll initially send an empty data block and wait for the + // server to tell us where the current offset really is + chunkData = [NSData data]; + rangeStr = [NSString stringWithFormat:@"bytes */%llu", + (unsigned long long)dataLen]; + lengthStr = @"0"; + offset = 0; + } else { + // uploading the next data chunk + if (dataLen == 0) { +#if DEBUG + NSAssert(offset == 0, @"offset %llu for empty data length", (unsigned long long)offset); +#endif + chunkData = [NSData data]; + rangeStr = @"bytes */0"; + lengthStr = @"0"; + } else { +#if DEBUG + NSAssert(offset < dataLen , @"offset %llu exceeds data length %llu", + (unsigned long long)offset, (unsigned long long)dataLen); +#endif + NSUInteger thisChunkSize = chunkSize; + + // if the chunk size is bigger than the remaining data, or else + // it's close enough in size to the remaining data that we'd rather + // avoid having a whole extra http fetch for the leftover bit, then make + // this chunk size exactly match the remaining data size + BOOL isChunkTooBig = (thisChunkSize + offset > dataLen); + BOOL isChunkAlmostBigEnough = (dataLen - offset < thisChunkSize + 2500); + + if (isChunkTooBig || isChunkAlmostBigEnough) { + thisChunkSize = dataLen - offset; + } + + chunkData = [self uploadSubdataWithOffset:offset + length:thisChunkSize]; + + rangeStr = [NSString stringWithFormat:@"bytes %llu-%llu/%llu", + (unsigned long long)offset, + (unsigned long long)(offset + thisChunkSize - 1), + (unsigned long long)dataLen]; + lengthStr = [NSString stringWithFormat:@"%llu", + (unsigned long long)thisChunkSize]; + } + } + + // track the current offset for progress reporting + [self setCurrentOffset:offset]; + + // + // make the request for fetching + // + + // the chunk upload URL requires no authentication header + NSURL *locURL = [self locationURL]; + NSMutableURLRequest *chunkRequest = [NSMutableURLRequest requestWithURL:locURL]; + + [chunkRequest setHTTPMethod:@"PUT"]; + + // copy the user-agent from the original connection + NSURLRequest *origRequest = [self mutableRequest]; + NSString *userAgent = [origRequest valueForHTTPHeaderField:@"User-Agent"]; + if ([userAgent length] > 0) { + [chunkRequest setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + } + + [chunkRequest setValue:rangeStr forHTTPHeaderField:@"Content-Range"]; + [chunkRequest setValue:lengthStr forHTTPHeaderField:@"Content-Length"]; + + NSString *uploadMIMEType = [self uploadMIMEType]; + [chunkRequest setValue:uploadMIMEType forHTTPHeaderField:@"Content-Type"]; + + // + // make a new fetcher + // + GTMHTTPFetcher *chunkFetcher; + + chunkFetcher = [GTMHTTPFetcher fetcherWithRequest:chunkRequest]; + [chunkFetcher setDelegateQueue:[self delegateQueue]]; + [chunkFetcher setRunLoopModes:[self runLoopModes]]; + [chunkFetcher setAllowedInsecureSchemes:[self allowedInsecureSchemes]]; + [chunkFetcher setAllowLocalhostRequest:[self allowLocalhostRequest]]; + + // if the upload fetcher has a comment, use the same comment for chunks + NSString *baseComment = [self comment]; + if (baseComment) { + [chunkFetcher setCommentWithFormat:@"%@ (%@)", baseComment, rangeStr]; + } + + // give the chunk fetcher the same properties as the previous chunk fetcher + [chunkFetcher setProperties:props]; + + // post the appropriate subset of the full data + [chunkFetcher setPostData:chunkData]; + + // copy other fetcher settings to the new fetcher + [chunkFetcher setRetryEnabled:[self isRetryEnabled]]; + [chunkFetcher setMaxRetryInterval:[self maxRetryInterval]]; + [chunkFetcher setSentDataSelector:[self sentDataSelector]]; + [chunkFetcher setCookieStorageMethod:[self cookieStorageMethod]]; + + if ([self isRetryEnabled]) { + // we interpose our own retry method both so the sender is the upload + // fetcher, and so we can change the request to ask the server to + // tell us where to resume the chunk + [chunkFetcher setRetrySelector:@selector(chunkFetcher:willRetry:forError:)]; + } + + [self setMutableRequest:chunkRequest]; + + // when fetching chunks, a 308 status means "upload more chunks", but + // success (200 or 201 status) and other failures are no different than + // for the regular object fetchers + BOOL didFetch = [chunkFetcher beginFetchWithDelegate:self + didFinishSelector:@selector(chunkFetcher:finishedWithData:error:)]; + if (!didFetch) { + // something went horribly wrong, like the chunk upload URL is invalid + NSError *error = [NSError errorWithDomain:kGTMHTTPFetcherErrorDomain + code:kGTMHTTPFetcherErrorChunkUploadFailed + userInfo:nil]; + + [self invokeFinalCallbacksWithData:nil + error:error + shouldInvalidateLocation:YES]; + [self destroyChunkFetcher]; + } else { + // hang on to the fetcher in case we need to cancel it + [self setChunkFetcher:chunkFetcher]; + } +} + +- (void)reportProgressManually { + // reportProgressManually should be called only when there's no + // NSURLConnection support for sent data callbacks + + // the user wants upload progress, and there's no support in NSURLConnection + // for it, so we'll provide it here after each chunk + // + // the progress will be based on the uploadData and currentOffset, + // so we can pass zeros + [self uploadFetcher:self + didSendBytes:0 + totalBytesSent:0 +totalBytesExpectedToSend:0]; +} + +- (void)chunkFetcher:(GTMHTTPFetcher *)chunkFetcher finishedWithData:(NSData *)data error:(NSError *)error { + [self setStatusCode:[chunkFetcher statusCode]]; + [self setResponseHeaders:[chunkFetcher responseHeaders]]; + + if (error) { + int status = (int)[error code]; + + // status 308 is "resume incomplete", meaning we should get the offset + // from the Range header and upload the next chunk + // + // any other status really is an error + if (status == 308) { + [self handleResumeIncompleteStatusForChunkFetcher:chunkFetcher]; + return; + } else { + // some unexpected status has occurred; handle it as we would a regular + // object fetcher failure + error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain + code:status + userInfo:nil]; + [self invokeFinalCallbacksWithData:data + error:error + shouldInvalidateLocation:NO]; + [self destroyChunkFetcher]; + return; + } + } else { + // the final chunk has uploaded successfully + #if DEBUG && !defined(NS_BLOCK_ASSERTIONS) + NSInteger status = [chunkFetcher statusCode]; + NSAssert1(status == 200 || status == 201, + @"unexpected chunks status %d", (int)status); + #endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) + + // take the chunk fetcher's data as our own + self.downloadedData = data; + + if (needsManualProgress_) { + // do a final upload progress report, indicating all of the chunk data + // has been sent + NSUInteger fullDataLength = [self fullUploadLength] + initialBodyLength_; + [self setCurrentOffset:fullDataLength]; + + [self reportProgressManually]; + } + + // we're done + [self invokeFinalCallbacksWithData:data + error:error + shouldInvalidateLocation:YES]; + + [self destroyChunkFetcher]; + } +} + +- (void)handleResumeIncompleteStatusForChunkFetcher:(GTMHTTPFetcher *)chunkFetcher { + + NSDictionary *responseHeaders = [chunkFetcher responseHeaders]; + + // parse the Range header from the server, since that tells us where we really + // want the next chunk to begin. + // + // lack of a range header means the server has no bytes stored for this upload + NSString *rangeStr = [responseHeaders objectForKey:@"Range"]; + NSUInteger newOffset = 0; + if (rangeStr != nil) { + // parse a content-range, like "bytes=0-999", to find where our new + // offset for uploading from the data really is (at the end of the + // range) + NSScanner *scanner = [NSScanner scannerWithString:rangeStr]; + long long rangeStart = 0, rangeEnd = 0; + if ([scanner scanString:@"bytes=" intoString:nil] + && [scanner scanLongLong:&rangeStart] + && [scanner scanString:@"-" intoString:nil] + && [scanner scanLongLong:&rangeEnd]) { + newOffset = (NSUInteger)rangeEnd + 1; + } + } + + [self setCurrentOffset:newOffset]; + + if (needsManualProgress_) { + [self reportProgressManually]; + } + + // if the response specifies a location, use that for future chunks + NSString *locationURLStr = [responseHeaders objectForKey:@"Location"]; + if ([locationURLStr length] > 0) { + [self setLocationURL:[NSURL URLWithString:locationURLStr]]; + } + + // we want to destroy this chunk fetcher before creating the next one, but + // we want to pass on its properties + NSMutableDictionary *props = [[[chunkFetcher properties] retain] autorelease]; + + // we no longer need to be able to cancel this chunkFetcher + [self destroyChunkFetcher]; + + // We may in the future handle Retry-After and ETag headers per + // http://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal + // but they are not currently sent by the upload server + + [self uploadNextChunkWithOffset:newOffset + fetcherProperties:props]; +} + + +-(BOOL)chunkFetcher:(GTMHTTPFetcher *)chunkFetcher willRetry:(BOOL)willRetry forError:(NSError *)error { + if ([error code] == 308 + && [[error domain] isEqual:kGTMHTTPFetcherStatusDomain]) { + // 308 is a normal chunk fethcher response, not an error + // that needs to be retried + return NO; + } + + if (delegate_ && retrySel_) { + + // call the client with the upload fetcher as the sender (not the chunk + // fetcher) to find out if it wants to retry + willRetry = [self invokeRetryCallback:retrySel_ + target:delegate_ + willRetry:willRetry + error:error]; + } + +#if NS_BLOCKS_AVAILABLE + if (retryBlock_) { + willRetry = retryBlock_(willRetry, error); + } +#endif + + if (willRetry) { + // change the request being retried into a query to the server to + // tell us where to resume + NSMutableURLRequest *chunkRequest = [chunkFetcher mutableRequest]; + + NSUInteger dataLen = [self fullUploadLength]; + NSString *rangeStr = [NSString stringWithFormat:@"bytes */%llu", + (unsigned long long)dataLen]; + + [chunkRequest setValue:rangeStr forHTTPHeaderField:@"Content-Range"]; + [chunkRequest setValue:@"0" forHTTPHeaderField:@"Content-Length"]; + [chunkFetcher setPostData:[NSData data]]; + + // we don't know what our actual offset is anymore, but the server + // will tell us + [self setCurrentOffset:0]; + } + + return willRetry; +} + +- (void)destroyChunkFetcher { + [chunkFetcher_ stopFetching]; + [chunkFetcher_ setProperties:nil]; + [chunkFetcher_ autorelease]; + chunkFetcher_ = nil; +} + +// the chunk fetchers use this as their sentData method +- (void)uploadFetcher:(GTMHTTPFetcher *)chunkFetcher + didSendBytes:(NSInteger)bytesSent + totalBytesSent:(NSInteger)totalBytesSent +totalBytesExpectedToSend:(NSInteger)totalBytesExpected { + // the actual total bytes sent include the initial XML sent, plus the + // offset into the batched data prior to this fetcher + totalBytesSent += initialBodySent_ + currentOffset_; + + // the total bytes expected include the initial XML and the full chunked + // data, independent of how big this fetcher's chunk is + totalBytesExpected = (NSInteger)(initialBodyLength_ + [self fullUploadLength]); + + if (delegate_ && delegateSentDataSEL_) { + // ensure the chunk fetcher survives the callback in case the user pauses + // the upload process + [[chunkFetcher retain] autorelease]; + + [self invokeSentDataCallback:delegateSentDataSEL_ + target:delegate_ + didSendBodyData:bytesSent + totalBytesWritten:totalBytesSent + totalBytesExpectedToWrite:totalBytesExpected]; + } + +#if NS_BLOCKS_AVAILABLE + if (sentDataBlock_) { + sentDataBlock_(bytesSent, totalBytesSent, totalBytesExpected); + } +#endif +} + +#pragma mark - + +- (BOOL)isPaused { + return isPaused_; +} + +- (void)pauseFetching { + isPaused_ = YES; + + // pausing just means stopping the current chunk from uploading; + // when we resume, the magic offset value will force us to send + // a request to the server to figure out what bytes to start sending + // + // we won't try to cancel the initial data upload, but rather will look for + // the magic offset value in -connectionDidFinishLoading before + // creating first initial chunk fetcher, just in case the user + // paused during the initial data upload + [self destroyChunkFetcher]; +} + +- (void)resumeFetching { + if (isPaused_) { + isPaused_ = NO; + + [self uploadNextChunkWithOffset:kQueryServerForOffset]; + } +} + +- (void)stopFetching { + // overrides the superclass + [self destroyChunkFetcher]; + + [super stopFetching]; +} + +#pragma mark - + +@synthesize uploadData = uploadData_, + uploadFileHandle = uploadFileHandle_, + uploadMIMEType = uploadMIMEType_, + chunkSize = chunkSize_, + currentOffset = currentOffset_, + chunkFetcher = chunkFetcher_; + +#if NS_BLOCKS_AVAILABLE +@synthesize locationChangeBlock = locationChangeBlock_; +#endif + +@dynamic activeFetcher; +@dynamic responseHeaders; +@dynamic statusCode; + +- (NSDictionary *)responseHeaders { + // overrides the superclass + + // if asked for the fetcher's response, use the most recent fetcher + if (responseHeaders_) { + return responseHeaders_; + } else { + // no chunk fetcher yet completed, so return whatever we have from the + // initial fetch + return [super responseHeaders]; + } +} + +- (void)setResponseHeaders:(NSDictionary *)dict { + [responseHeaders_ autorelease]; + responseHeaders_ = [dict retain]; +} + +- (NSInteger)statusCode { + if (statusCode_ != -1) { + // overrides the superclass to indicate status appropriate to the initial + // or latest chunk fetch + return statusCode_; + } else { + return [super statusCode]; + } +} + +- (void)setStatusCode:(NSInteger)val { + statusCode_ = val; +} + +- (SEL)sentDataSelector { + // overrides the superclass +#if NS_BLOCKS_AVAILABLE + BOOL hasSentDataBlock = (sentDataBlock_ != NULL); +#else + BOOL hasSentDataBlock = NO; +#endif + if ((delegateSentDataSEL_ || hasSentDataBlock) && !needsManualProgress_) { + return @selector(uploadFetcher:didSendBytes:totalBytesSent:totalBytesExpectedToSend:); + } else { + return NULL; + } +} + +- (void)setSentDataSelector:(SEL)theSelector { + // overrides the superclass + delegateSentDataSEL_ = theSelector; +} + +- (GTMHTTPFetcher *)activeFetcher { + if (chunkFetcher_) { + return chunkFetcher_; + } else { + return self; + } +} + +- (NSURL *)locationURL { + return locationURL_; +} + +- (void)setLocationURL:(NSURL *)url { + if (url != locationURL_) { + [locationURL_ release]; + locationURL_ = [url retain]; + +#if NS_BLOCKS_AVAILABLE + if (locationChangeBlock_) { + locationChangeBlock_(url); + } +#endif + } +} +@end + +#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMMIMEDocument.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMMIMEDocument.h new file mode 100755 index 0000000..62b037b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMMIMEDocument.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// This is a simple class to create a MIME document. To use, allocate +// a new GTMMIMEDocument and start adding parts as necessary. When you are +// done adding parts, call generateInputStream to get an NSInputStream +// containing the contents of your MIME document. +// +// A good reference for MIME is http://en.wikipedia.org/wiki/MIME + +#import + +#if defined(GTL_TARGET_NAMESPACE) + // we're using target namespace macros + #import "GTLDefines.h" +#elif defined(GDATA_TARGET_NAMESPACE) + #import "GDataDefines.h" +#endif + +@interface GTMMIMEDocument : NSObject { + NSMutableArray* parts_; // Contains an ordered set of MimeParts + unsigned long long length_; // Length in bytes of the document. + u_int32_t randomSeed_; // for testing +} + ++ (GTMMIMEDocument *)MIMEDocument; + +// Adds a new part to this mime document with the given headers and body. The +// headers keys and values should be NSStrings +- (void)addPartWithHeaders:(NSDictionary *)headers + body:(NSData *)body; + +// An inputstream that can be used to efficiently read the contents of the +// mime document. +- (void)generateInputStream:(NSInputStream **)outStream + length:(unsigned long long*)outLength + boundary:(NSString **)outBoundary; + +// ------ UNIT TESTING ONLY BELOW ------ + +// For unittesting only, seeds the random number generator +- (void)seedRandomWith:(u_int32_t)seed; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMMIMEDocument.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMMIMEDocument.m new file mode 100755 index 0000000..38b9c25 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMMIMEDocument.m @@ -0,0 +1,281 @@ +/* Copyright (c) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#import "GTMMIMEDocument.h" +#import "GTMGatherInputStream.h" + +// memsrch +// +// Helper routine to search for the existence of a set of bytes (needle) within +// a presumed larger set of bytes (haystack). +// +static BOOL memsrch(const unsigned char* needle, NSUInteger needle_len, + const unsigned char* haystack, NSUInteger haystack_len); + +@interface GTMMIMEPart : NSObject { + NSData* headerData_; // Header content including the ending "\r\n". + NSData* bodyData_; // The body data. +} + ++ (GTMMIMEPart *)partWithHeaders:(NSDictionary *)headers body:(NSData *)body; +- (id)initWithHeaders:(NSDictionary *)headers body:(NSData *)body; +- (BOOL)containsBytes:(const unsigned char *)bytes length:(NSUInteger)length; +- (NSData *)header; +- (NSData *)body; +- (NSUInteger)length; +@end + +@implementation GTMMIMEPart + ++ (GTMMIMEPart *)partWithHeaders:(NSDictionary *)headers body:(NSData *)body { + + return [[[self alloc] initWithHeaders:headers + body:body] autorelease]; +} + +- (id)initWithHeaders:(NSDictionary *)headers + body:(NSData *)body { + + if ((self = [super init]) != nil) { + + bodyData_ = [body retain]; + + // generate the header data by coalescing the dictionary as + // lines of "key: value\r\m" + NSMutableString* headerString = [NSMutableString string]; + + // sort the header keys so we have a deterministic order for + // unit testing + SEL sortSel = @selector(caseInsensitiveCompare:); + NSArray *sortedKeys = [[headers allKeys] sortedArrayUsingSelector:sortSel]; + + for (NSString *key in sortedKeys) { + NSString* value = [headers objectForKey:key]; + +#if DEBUG && !defined(NS_BLOCK_ASSERTIONS) + // look for troublesome characters in the header keys & values + static NSCharacterSet *badChars = nil; + if (!badChars) { + badChars = [[NSCharacterSet characterSetWithCharactersInString:@":\r\n"] retain]; + } + + NSRange badRange = [key rangeOfCharacterFromSet:badChars]; + NSAssert1(badRange.location == NSNotFound, @"invalid key: %@", key); + + badRange = [value rangeOfCharacterFromSet:badChars]; + NSAssert1(badRange.location == NSNotFound, @"invalid value: %@", value); +#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) + + [headerString appendFormat:@"%@: %@\r\n", key, value]; + } + + // headers end with an extra blank line + [headerString appendString:@"\r\n"]; + + headerData_ = [[headerString dataUsingEncoding:NSUTF8StringEncoding] retain]; + } + return self; +} + +- (void) dealloc { + [headerData_ release]; + [bodyData_ release]; + [super dealloc]; +} + +// Returns true if the parts contents contain the given set of bytes. +// +// NOTE: We assume that the 'bytes' we are checking for do not contain "\r\n", +// so we don't need to check the concatenation of the header and body bytes. +- (BOOL)containsBytes:(const unsigned char*)bytes length:(NSUInteger)length { + + // This uses custom memsrch() rather than strcpy because the encoded data may + // contain null values. + return memsrch(bytes, length, [headerData_ bytes], [headerData_ length]) || + memsrch(bytes, length, [bodyData_ bytes], [bodyData_ length]); +} + +- (NSData *)header { + return headerData_; +} + +- (NSData *)body { + return bodyData_; +} + +- (NSUInteger)length { + return [headerData_ length] + [bodyData_ length]; +} +@end + +@implementation GTMMIMEDocument + ++ (GTMMIMEDocument *)MIMEDocument { + return [[[self alloc] init] autorelease]; +} + +- (id)init { + if ((self = [super init]) != nil) { + + parts_ = [[NSMutableArray alloc] init]; + + // Seed the random number generator used to generate mime boundaries + srandomdev(); + } + return self; +} + +- (void)dealloc { + [parts_ release]; + [super dealloc]; +} + +// Adds a new part to this mime document with the given headers and body. +- (void)addPartWithHeaders:(NSDictionary *)headers + body:(NSData *)body { + + GTMMIMEPart* part = [GTMMIMEPart partWithHeaders:headers body:body]; + [parts_ addObject:part]; +} + +// For unit testing only, seeds the random number generator so that we will +// have reproducible boundary strings. +- (void)seedRandomWith:(u_int32_t)seed { + randomSeed_ = seed; +} + +- (u_int32_t)random { + if (randomSeed_) { + // for testing only + return randomSeed_++; + } else { + return arc4random(); + } +} + +// Computes the mime boundary to use. This should only be called +// after all the desired document parts have been added since it must compute +// a boundary that does not exist in the document data. +- (NSString *)uniqueBoundary { + + // use an easily-readable boundary string + NSString *const kBaseBoundary = @"END_OF_PART"; + + NSString *boundary = kBaseBoundary; + + // if the boundary isn't unique, append random numbers, up to 10 attempts; + // if that's still not unique, use a random number sequence instead, + // and call it good + BOOL didCollide = NO; + + const int maxTries = 10; // Arbitrarily chosen maximum attempts. + for (int tries = 0; tries < maxTries; ++tries) { + + NSData *data = [boundary dataUsingEncoding:NSUTF8StringEncoding]; + const void *dataBytes = [data bytes]; + NSUInteger dataLen = [data length]; + + for (GTMMIMEPart *part in parts_) { + didCollide = [part containsBytes:dataBytes length:dataLen]; + if (didCollide) break; + } + + if (!didCollide) break; // we're fine, no more attempts needed + + // try again with a random number appended + boundary = [NSString stringWithFormat:@"%@_%08x", kBaseBoundary, + [self random]]; + } + + if (didCollide) { + // fallback... two random numbers + boundary = [NSString stringWithFormat:@"%08x_tedborg_%08x", + [self random], [self random]]; + } + + return boundary; +} + +- (void)generateInputStream:(NSInputStream **)outStream + length:(unsigned long long*)outLength + boundary:(NSString **)outBoundary { + + // The input stream is of the form: + // --boundary + // [part_1_headers] + // [part_1_data] + // --boundary + // [part_2_headers] + // [part_2_data] + // --boundary-- + + // First we set up our boundary NSData objects. + NSString *boundary = [self uniqueBoundary]; + + NSString *mainBoundary = [NSString stringWithFormat:@"\r\n--%@\r\n", boundary]; + NSString *endBoundary = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary]; + + NSData *mainBoundaryData = [mainBoundary dataUsingEncoding:NSUTF8StringEncoding]; + NSData *endBoundaryData = [endBoundary dataUsingEncoding:NSUTF8StringEncoding]; + + // Now we add them all in proper order to our dataArray. + NSMutableArray* dataArray = [NSMutableArray array]; + unsigned long long length = 0; + + for (GTMMIMEPart* part in parts_) { + [dataArray addObject:mainBoundaryData]; + [dataArray addObject:[part header]]; + [dataArray addObject:[part body]]; + + length += [part length] + [mainBoundaryData length]; + } + + [dataArray addObject:endBoundaryData]; + length += [endBoundaryData length]; + + if (outLength) *outLength = length; + if (outStream) *outStream = [GTMGatherInputStream streamWithArray:dataArray]; + if (outBoundary) *outBoundary = boundary; +} + +@end + + +// memsrch - Return YES if needle is found in haystack, else NO. +static BOOL memsrch(const unsigned char* needle, NSUInteger needleLen, + const unsigned char* haystack, NSUInteger haystackLen) { + + // This is a simple approach. We start off by assuming that both memchr() and + // memcmp are implemented efficiently on the given platform. We search for an + // instance of the first char of our needle in the haystack. If the remaining + // size could fit our needle, then we memcmp to see if it occurs at this point + // in the haystack. If not, we move on to search for the first char again, + // starting from the next character in the haystack. + const unsigned char* ptr = haystack; + NSUInteger remain = haystackLen; + while ((ptr = memchr(ptr, needle[0], remain)) != 0) { + remain = haystackLen - (NSUInteger)(ptr - haystack); + if (remain < needleLen) { + return NO; + } + if (memcmp(ptr, needle, needleLen) == 0) { + return YES; + } + ptr++; + remain--; + } + return NO; +} diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMReadMonitorInputStream.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMReadMonitorInputStream.h new file mode 100755 index 0000000..9e4b3f7 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMReadMonitorInputStream.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + + +// Define only for Mac OS X 10.6+ or iPhone OS 4.0+. +#ifndef GTM_NSSTREAM_DELEGATE + #if (TARGET_OS_MAC && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \ + (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000)) + #define GTM_NSSTREAM_DELEGATE + #else + #define GTM_NSSTREAM_DELEGATE + #endif +#endif // !defined(GTM_NSSTREAM_DELEGATE) + +#ifdef GTM_TARGET_NAMESPACE + // we're using target namespace macros + #import "GTMDefines.h" +#endif + +@interface GTMReadMonitorInputStream : NSInputStream GTM_NSSTREAM_DELEGATE { + @protected + NSInputStream *inputStream_; // encapsulated stream that does the work + + NSThread *thread_; // thread in which this object was created + NSArray *runLoopModes_; // modes for calling callbacks, when necessary + + @private + id readDelegate_; + SEL readSelector_; +} + +// length is passed to the progress callback; it may be zero +// if the progress callback can handle that ++ (id)inputStreamWithStream:(NSInputStream *)input; + +- (id)initWithStream:(NSInputStream *)input; + +// The read monitor selector is called when bytes have been read. It should +// have a signature matching +// +// - (void)inputStream:(GTMReadMonitorInputStream *)stream +// readIntoBuffer:(uint8_t *)buffer +// length:(NSUInteger)length; + +@property (assign) id readDelegate; // WEAK +@property (assign) SEL readSelector; + +// Modes for invoking callbacks, when necessary +@property (retain) NSArray *runLoopModes; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMReadMonitorInputStream.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMReadMonitorInputStream.m new file mode 100755 index 0000000..4a85de5 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-http-fetcher/Source/GTMReadMonitorInputStream.m @@ -0,0 +1,189 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GTMReadMonitorInputStream.h" + +@interface GTMReadMonitorInputStream () +- (void)invokeReadSelectorWithBuffer:(NSData *)data; +@end + +@implementation GTMReadMonitorInputStream + +@synthesize readDelegate = readDelegate_; +@synthesize readSelector = readSelector_; +@synthesize runLoopModes = runLoopModes_; + +// We'll forward all unhandled messages to the NSInputStream class +// or to the encapsulated input stream. This is needed +// for all messages sent to NSInputStream which aren't +// handled by our superclass; that includes various private run +// loop calls. ++ (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + return [NSInputStream methodSignatureForSelector:selector]; +} + ++ (void)forwardInvocation:(NSInvocation*)invocation { + [invocation invokeWithTarget:[NSInputStream class]]; +} + +- (BOOL)respondsToSelector:(SEL)selector { + return [inputStream_ respondsToSelector:selector]; +} + +- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { + return [inputStream_ methodSignatureForSelector:selector]; +} + +- (void)forwardInvocation:(NSInvocation*)invocation { + [invocation invokeWithTarget:inputStream_]; +} + +#pragma mark - + ++ (id)inputStreamWithStream:(NSInputStream *)input { + return [[[self alloc] initWithStream:input] autorelease]; +} + +- (id)initWithStream:(NSInputStream *)input { + self = [super init]; + if (self) { + inputStream_ = [input retain]; + thread_ = [[NSThread currentThread] retain]; + } + return self; +} + +- (id)init { + return [self initWithStream:nil]; +} + +- (void)dealloc { + [inputStream_ release]; + [thread_ release]; + [runLoopModes_ release]; + [super dealloc]; +} + +#pragma mark - + +- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len { + // Read from the encapsulated stream + NSInteger numRead = [inputStream_ read:buffer maxLength:len]; + if (numRead > 0) { + + BOOL isOnOriginalThread = [thread_ isEqual:[NSThread currentThread]]; + + if (readDelegate_ && readSelector_) { + // call the read selector with the buffer and number of bytes actually + // read into it + SEL sel = @selector(invokeReadSelectorWithBuffer:); + + if (isOnOriginalThread) { + // invoke immediately + NSData *data = [NSData dataWithBytesNoCopy:buffer + length:(NSUInteger)numRead + freeWhenDone:NO]; + [self performSelector:sel withObject:data]; + } else { + // copy the buffer into an NSData to be retained by the + // performSelector, and invoke on the proper thread + NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numRead]; + if (runLoopModes_) { + [self performSelector:sel + onThread:thread_ + withObject:data + waitUntilDone:NO + modes:runLoopModes_]; + } else { + [self performSelector:sel + onThread:thread_ + withObject:data + waitUntilDone:NO]; + } + } + } + } + + return numRead; +} + +- (void)invokeReadSelectorWithBuffer:(NSData *)data { + const void *buffer = [data bytes]; + NSUInteger length = [data length]; + + NSMethodSignature *signature = [readDelegate_ methodSignatureForSelector:readSelector_]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:readSelector_]; + [invocation setTarget:readDelegate_]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&buffer atIndex:3]; + [invocation setArgument:&length atIndex:4]; + [invocation invoke]; +} + +- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len { + return [inputStream_ getBuffer:buffer length:len]; +} + +- (BOOL)hasBytesAvailable { + return [inputStream_ hasBytesAvailable]; +} + +#pragma mark Standard messages + +// Pass expected messages to our encapsulated stream. +// +// We want our encapsulated NSInputStream to handle the standard messages; +// we don't want the superclass to handle them. +- (void)open { + [inputStream_ open]; +} + +- (void)close { + [inputStream_ close]; +} + +- (id)delegate { + return [inputStream_ delegate]; +} + +- (void)setDelegate:(id)delegate { + [inputStream_ setDelegate:delegate]; +} + +- (id)propertyForKey:(NSString *)key { + return [inputStream_ propertyForKey:key]; +} +- (BOOL)setProperty:(id)property forKey:(NSString *)key { + return [inputStream_ setProperty:property forKey:key]; +} + +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { + [inputStream_ scheduleInRunLoop:aRunLoop forMode:mode]; +} + +- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { + [inputStream_ removeFromRunLoop:aRunLoop forMode:mode]; +} + +- (NSStreamStatus)streamStatus { + return [inputStream_ streamStatus]; +} + +- (NSError *)streamError { + return [inputStream_ streamError]; +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2Authentication.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2Authentication.h new file mode 100755 index 0000000..02b9ce2 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2Authentication.h @@ -0,0 +1,362 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES + +// This class implements the OAuth 2 protocol for authorizing requests. +// http://tools.ietf.org/html/draft-ietf-oauth-v2 + +#import + +#if GTM_USE_SESSION_FETCHER + #import "GTMSessionFetcher.h" +#else + #import "GTMHTTPFetcher.h" +#endif // GTM_USE_SESSION_FETCHER + +#define GTMOAuth2Fetcher GTMBridgeFetcher +#define GTMOAuth2FetcherService GTMBridgeFetcherService +#define GTMOAuth2FetcherServiceProtocol GTMBridgeFetcherServiceProtocol +#define GTMOAuth2AssertValidSelector GTMBridgeAssertValidSelector +#define GTMOAuth2CookieStorage GTMBridgeCookieStorage +#define kGTMOAuth2FetcherStatusDomain kGTMBridgeFetcherStatusDomain +#define kGTMOAuth2StatusBadRequest kGTMBridgeFetcherStatusBadRequest + + +// Until all OAuth 2 providers are up to the same spec, we'll provide a crude +// way here to override the "Bearer" string in the Authorization header +#ifndef GTM_OAUTH2_BEARER +#define GTM_OAUTH2_BEARER "Bearer" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Service provider name allows stored authorization to be associated with +// the authorizing service +extern NSString *const kGTMOAuth2ServiceProviderGoogle; + +// +// GTMOAuth2SignIn constants, included here for use by clients +// +extern NSString *const kGTMOAuth2ErrorDomain; + +// Error userInfo keys +extern NSString *const kGTMOAuth2ErrorMessageKey; +extern NSString *const kGTMOAuth2ErrorRequestKey; +extern NSString *const kGTMOAuth2ErrorJSONKey; + +enum { + // Error code indicating that the window was prematurely closed + kGTMOAuth2ErrorWindowClosed = -1000, + kGTMOAuth2ErrorAuthorizationFailed = -1001, + kGTMOAuth2ErrorTokenExpired = -1002, + kGTMOAuth2ErrorTokenUnavailable = -1003, + kGTMOAuth2ErrorUnauthorizableRequest = -1004 +}; + + +// Notifications for token fetches +extern NSString *const kGTMOAuth2FetchStarted; +extern NSString *const kGTMOAuth2FetchStopped; + +extern NSString *const kGTMOAuth2FetcherKey; +extern NSString *const kGTMOAuth2FetchTypeKey; +extern NSString *const kGTMOAuth2FetchTypeToken; +extern NSString *const kGTMOAuth2FetchTypeRefresh; +extern NSString *const kGTMOAuth2FetchTypeAssertion; +extern NSString *const kGTMOAuth2FetchTypeUserInfo; + +// Token-issuance errors +extern NSString *const kGTMOAuth2ErrorKey; +extern NSString *const kGTMOAuth2ErrorObjectKey; + +extern NSString *const kGTMOAuth2ErrorInvalidRequest; +extern NSString *const kGTMOAuth2ErrorInvalidClient; +extern NSString *const kGTMOAuth2ErrorInvalidGrant; +extern NSString *const kGTMOAuth2ErrorUnauthorizedClient; +extern NSString *const kGTMOAuth2ErrorUnsupportedGrantType; +extern NSString *const kGTMOAuth2ErrorInvalidScope; + +// Notification that sign-in has completed, and token fetches will begin (useful +// for displaying interstitial messages after the window has closed) +extern NSString *const kGTMOAuth2UserSignedIn; + +// Notification for token changes +extern NSString *const kGTMOAuth2AccessTokenRefreshed; +extern NSString *const kGTMOAuth2RefreshTokenChanged; +extern NSString *const kGTMOAuth2AccessTokenRefreshFailed; + +// Notification for WebView loading +extern NSString *const kGTMOAuth2WebViewStartedLoading; +extern NSString *const kGTMOAuth2WebViewStoppedLoading; +extern NSString *const kGTMOAuth2WebViewKey; +extern NSString *const kGTMOAuth2WebViewStopKindKey; +extern NSString *const kGTMOAuth2WebViewFinished; +extern NSString *const kGTMOAuth2WebViewFailed; +extern NSString *const kGTMOAuth2WebViewCancelled; + +// Notification for network loss during html sign-in display +extern NSString *const kGTMOAuth2NetworkLost; +extern NSString *const kGTMOAuth2NetworkFound; + +#ifdef __cplusplus +} +#endif + +@interface GTMOAuth2Authentication : NSObject { + @private + NSString *clientID_; + NSString *clientSecret_; + NSString *redirectURI_; + NSMutableDictionary *parameters_; + + // authorization parameters + NSURL *tokenURL_; + NSDate *expirationDate_; + + NSString *authorizationTokenKey_; + + NSDictionary *additionalTokenRequestParameters_; + NSDictionary *additionalGrantTypeRequestParameters_; + + // queue of requests for authorization waiting for a valid access token + GTMOAuth2Fetcher *refreshFetcher_; + NSMutableArray *authorizationQueue_; + + id fetcherService_; // WEAK + + Class parserClass_; + + BOOL shouldAuthorizeAllRequests_; + + // arbitrary data retained for the user + id userData_; + NSMutableDictionary *properties_; +} + +// OAuth2 standard protocol parameters +// +// These should be the plain strings; any needed escaping will be provided by +// the library. + +// Request properties +@property (copy) NSString *clientID; +@property (copy) NSString *clientSecret; +@property (copy) NSString *redirectURI; +@property (retain) NSString *scope; +@property (retain) NSString *tokenType; +@property (retain) NSString *assertion; +@property (retain) NSString *refreshScope; + +// Apps may optionally add parameters here to be provided to the token +// endpoint on token requests and refreshes. +@property (retain) NSDictionary *additionalTokenRequestParameters; + +// Apps may optionally add parameters here to be provided to the token +// endpoint on specific token requests and refreshes, keyed by the grant_type. +// For example, if a different "type" parameter is required for obtaining +// the auth code and on refresh, this might be: +// +// viewController.authentication.additionalGrantTypeRequestParameters = @{ +// @"authorization_code" : @{ @"type" : @"code" }, +// @"refresh_token" : @{ @"type" : @"refresh" } +// }; +@property (retain) NSDictionary *additionalGrantTypeRequestParameters; + +// Response properties +@property (retain) NSMutableDictionary *parameters; + +@property (retain) NSString *accessToken; +@property (retain) NSString *refreshToken; +@property (retain) NSNumber *expiresIn; +@property (retain) NSString *code; +@property (retain) NSString *errorString; + +// URL for obtaining access tokens +@property (copy) NSURL *tokenURL; + +// Calculated expiration date (expiresIn seconds added to the +// time the access token was received.) +@property (copy) NSDate *expirationDate; + +// Service identifier, like "Google"; not used for authentication +// +// The provider name is just for allowing stored authorization to be associated +// with the authorizing service. +@property (copy) NSString *serviceProvider; + +// User ID; not used for authentication +@property (retain) NSString *userID; + +// User email and verified status; not used for authentication +// +// The verified string can be checked with -boolValue. If the result is false, +// then the email address is listed with the account on the server, but the +// address has not been confirmed as belonging to the owner of the account. +@property (retain) NSString *userEmail; +@property (retain) NSString *userEmailIsVerified; + +// Property indicating if this auth has a refresh or access token so is suitable +// for authorizing a request. This does not guarantee that the token is valid. +@property (readonly) BOOL canAuthorize; + +// Property indicating if this object will authorize plain http request +// (as well as any non-https requests.) Default is NO, only requests with the +// scheme https are authorized, since security may be compromised if tokens +// are sent over the wire using an unencrypted protocol like http. +@property (assign) BOOL shouldAuthorizeAllRequests; + +// userData is retained for the convenience of the caller +@property (retain) id userData; + +// Stored property values are retained for the convenience of the caller +@property (retain) NSDictionary *properties; + +// Property for the optional fetcher service instance to be used to create +// fetchers +// +// Fetcher service objects retain authorizations, so this is weak to avoid +// circular retains. +@property (assign) id fetcherService; // WEAK + +// Alternative JSON parsing class; this should implement the +// GTMOAuth2ParserClass informal protocol. If this property is +// not set, the class SBJSON must be available in the runtime. +@property (assign) Class parserClass; + +// Key for the response parameter used for the authorization header; by default, +// "access_token" is used, but some servers may expect alternatives, like +// "id_token". +@property (copy) NSString *authorizationTokenKey; + +// Convenience method for creating an authentication object ++ (id)authenticationWithServiceProvider:(NSString *)serviceProvider + tokenURL:(NSURL *)tokenURL + redirectURI:(NSString *)redirectURI + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret; + +// Clear out any authentication values, prepare for a new request fetch +- (void)reset; + +// Main authorization entry points +// +// These will refresh the access token, if necessary, add the access token to +// the request, then invoke the callback. +// +// The request argument may be nil to just force a refresh of the access token, +// if needed. +// +// NOTE: To avoid accidental leaks of bearer tokens, the request must +// be for a URL with the scheme https unless the shouldAuthorizeAllRequests +// property is set. + +// The finish selector should have a signature matching +// - (void)authentication:(GTMOAuth2Authentication *)auth +// request:(NSMutableURLRequest *)request +// finishedWithError:(NSError *)error; + +- (void)authorizeRequest:(NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel; + +#if NS_BLOCKS_AVAILABLE +- (void)authorizeRequest:(NSMutableURLRequest *)request + completionHandler:(void (^)(NSError *error))handler; +#endif + +// Synchronous entry point; authorizing this way cannot refresh an expired +// access token +- (BOOL)authorizeRequest:(NSMutableURLRequest *)request; + +// If the authentication is waiting for a refresh to complete, spin the run +// loop, discarding events, until the fetch has completed +// +// This is only for use in testing or in tools without a user interface. +- (void)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds; + + +////////////////////////////////////////////////////////////////////////////// +// +// Internal properties and methods for use by GTMOAuth2SignIn +// + +// Pending fetcher to get a new access token, if any +@property (retain) GTMOAuth2Fetcher *refreshFetcher; + +// Check if a request is queued up to be authorized +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request; + +// Check if a request appears to be authorized +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request; + +// Stop any pending refresh fetch. This will also cancel the authorization +// for all fetch requests pending authorization. +- (void)stopAuthorization; + +// Prevents authorization callback for a given request. +- (void)stopAuthorizationForRequest:(NSURLRequest *)request; + +// OAuth fetch user-agent header value +- (NSString *)userAgent; + +// Parse and set token and token secret from response data +- (void)setKeysForResponseString:(NSString *)str; +- (void)setKeysForResponseDictionary:(NSDictionary *)dict; + +// Persistent token string for keychain storage +// +// We'll use the format "refresh_token=foo&serviceProvider=bar" so we can +// easily alter what portions of the auth data are stored +// +// Use these methods for serialization +- (NSString *)persistenceResponseString; +- (void)setKeysForPersistenceResponseString:(NSString *)str; + +// method to begin fetching an access token, used by the sign-in object +- (GTMOAuth2Fetcher *)beginTokenFetchWithDelegate:(id)delegate + didFinishSelector:(SEL)finishedSel; + +// Entry point to post a notification about a fetcher currently used for +// obtaining or refreshing a token; the sign-in object will also use this +// to indicate when the user's email address is being fetched. +// +// Fetch type constants are above under "notifications for token fetches" +- (void)notifyFetchIsRunning:(BOOL)isStarting + fetcher:(GTMOAuth2Fetcher *)fetcher + type:(NSString *)fetchType; + +// Arbitrary key-value properties retained for the user +- (void)setProperty:(id)obj forKey:(NSString *)key; +- (id)propertyForKey:(NSString *)key; + +// +// Utilities +// + ++ (NSString *)encodedOAuthValueForString:(NSString *)str; + ++ (NSString *)encodedQueryParametersForDictionary:(NSDictionary *)dict; + ++ (NSDictionary *)dictionaryWithResponseString:(NSString *)responseStr; + ++ (NSDictionary *)dictionaryWithJSONData:(NSData *)data; + ++ (NSString *)scopeWithStrings:(NSString *)firstStr, ... NS_REQUIRES_NIL_TERMINATION; +@end + +#endif // GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2Authentication.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2Authentication.m new file mode 100755 index 0000000..66d2b5a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2Authentication.m @@ -0,0 +1,1315 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES + +#import "GTMOAuth2Authentication.h" + +// Extern strings + +NSString *const kGTMOAuth2ServiceProviderGoogle = @"Google"; + +NSString *const kGTMOAuth2ErrorDomain = @"com.google.GTMOAuth2"; + +NSString *const kGTMOAuth2ErrorMessageKey = @"error"; +NSString *const kGTMOAuth2ErrorRequestKey = @"request"; +NSString *const kGTMOAuth2ErrorJSONKey = @"json"; + +// Notifications +NSString *const kGTMOAuth2FetchStarted = @"kGTMOAuth2FetchStarted"; +NSString *const kGTMOAuth2FetchStopped = @"kGTMOAuth2FetchStopped"; + +NSString *const kGTMOAuth2FetcherKey = @"fetcher"; +NSString *const kGTMOAuth2FetchTypeKey = @"FetchType"; +NSString *const kGTMOAuth2FetchTypeToken = @"token"; +NSString *const kGTMOAuth2FetchTypeRefresh = @"refresh"; +NSString *const kGTMOAuth2FetchTypeAssertion = @"assertion"; +NSString *const kGTMOAuth2FetchTypeUserInfo = @"userInfo"; + +NSString *const kGTMOAuth2ErrorKey = @"error"; +NSString *const kGTMOAuth2ErrorObjectKey = @"kGTMOAuth2ErrorObjectKey"; + +NSString *const kGTMOAuth2ErrorInvalidRequest = @"invalid_request"; +NSString *const kGTMOAuth2ErrorInvalidClient = @"invalid_client"; +NSString *const kGTMOAuth2ErrorInvalidGrant = @"invalid_grant"; +NSString *const kGTMOAuth2ErrorUnauthorizedClient = @"unauthorized_client"; +NSString *const kGTMOAuth2ErrorUnsupportedGrantType = @"unsupported_grant_type"; +NSString *const kGTMOAuth2ErrorInvalidScope = @"invalid_scope"; + +NSString *const kGTMOAuth2UserSignedIn = @"kGTMOAuth2UserSignedIn"; + +NSString *const kGTMOAuth2AccessTokenRefreshed = @"kGTMOAuth2AccessTokenRefreshed"; +NSString *const kGTMOAuth2RefreshTokenChanged = @"kGTMOAuth2RefreshTokenChanged"; +NSString *const kGTMOAuth2AccessTokenRefreshFailed = @"kGTMOAuth2AccessTokenRefreshFailed"; + +NSString *const kGTMOAuth2WebViewStartedLoading = @"kGTMOAuth2WebViewStartedLoading"; +NSString *const kGTMOAuth2WebViewStoppedLoading = @"kGTMOAuth2WebViewStoppedLoading"; +NSString *const kGTMOAuth2WebViewKey = @"kGTMOAuth2WebViewKey"; +NSString *const kGTMOAuth2WebViewStopKindKey = @"kGTMOAuth2WebViewStopKindKey"; +NSString *const kGTMOAuth2WebViewFinished = @"finished"; +NSString *const kGTMOAuth2WebViewFailed = @"failed"; +NSString *const kGTMOAuth2WebViewCancelled = @"cancelled"; + +NSString *const kGTMOAuth2NetworkLost = @"kGTMOAuthNetworkLost"; +NSString *const kGTMOAuth2NetworkFound = @"kGTMOAuthNetworkFound"; + +// standard OAuth keys +static NSString *const kOAuth2AccessTokenKey = @"access_token"; +static NSString *const kOAuth2RefreshTokenKey = @"refresh_token"; +static NSString *const kOAuth2ScopeKey = @"scope"; +static NSString *const kOAuth2ErrorKey = @"error"; +static NSString *const kOAuth2TokenTypeKey = @"token_type"; +static NSString *const kOAuth2ExpiresInKey = @"expires_in"; +static NSString *const kOAuth2CodeKey = @"code"; +static NSString *const kOAuth2AssertionKey = @"assertion"; +static NSString *const kOAuth2RefreshScopeKey = @"refreshScope"; + +// additional persistent keys +static NSString *const kServiceProviderKey = @"serviceProvider"; +static NSString *const kUserIDKey = @"userID"; +static NSString *const kUserEmailKey = @"email"; +static NSString *const kUserEmailIsVerifiedKey = @"isVerified"; + +// fetcher keys +static NSString *const kTokenFetchDelegateKey = @"delegate"; +static NSString *const kTokenFetchSelectorKey = @"sel"; + +// If GTMNSJSONSerialization is available, it is used for formatting JSON +#if (TARGET_OS_MAC && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED < 1070)) || \ + (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED < 50000)) +@interface GTMNSJSONSerialization : NSObject ++ (id)JSONObjectWithData:(NSData *)data options:(NSUInteger)opt error:(NSError **)error; +@end +#endif + +@interface GTMOAuth2ParserClass : NSObject +// just enough of SBJSON to be able to parse +- (id)objectWithString:(NSString*)repr error:(NSError**)error; +@end + +// wrapper class for requests needing authorization and their callbacks +@interface GTMOAuth2AuthorizationArgs : NSObject { + @private + NSMutableURLRequest *request_; + id delegate_; + SEL sel_; + id completionHandler_; + NSThread *thread_; + NSError *error_; +} + +@property (retain) NSMutableURLRequest *request; +@property (retain) id delegate; +@property (assign) SEL selector; +@property (copy) id completionHandler; +@property (retain) NSThread *thread; +@property (retain) NSError *error; + ++ (GTMOAuth2AuthorizationArgs *)argsWithRequest:(NSMutableURLRequest *)req + delegate:(id)delegate + selector:(SEL)sel + completionHandler:(id)completionHandler + thread:(NSThread *)thread; +@end + +@implementation GTMOAuth2AuthorizationArgs + +@synthesize request = request_, + delegate = delegate_, + selector = sel_, + completionHandler = completionHandler_, + thread = thread_, + error = error_; + ++ (GTMOAuth2AuthorizationArgs *)argsWithRequest:(NSMutableURLRequest *)req + delegate:(id)delegate + selector:(SEL)sel + completionHandler:(id)completionHandler + thread:(NSThread *)thread { + GTMOAuth2AuthorizationArgs *obj; + obj = [[[GTMOAuth2AuthorizationArgs alloc] init] autorelease]; + obj.request = req; + obj.delegate = delegate; + obj.selector = sel; + obj.completionHandler = completionHandler; + obj.thread = thread; + return obj; +} + +- (void)dealloc { + [request_ release]; + [delegate_ release]; + [completionHandler_ release]; + [thread_ release]; + [error_ release]; + + [super dealloc]; +} +@end + + +@interface GTMOAuth2Authentication () + +@property (retain) NSMutableArray *authorizationQueue; +@property (readonly) NSString *authorizationToken; + +- (void)setKeysForResponseJSONData:(NSData *)data; + +- (BOOL)authorizeRequestArgs:(GTMOAuth2AuthorizationArgs *)args; + +- (BOOL)authorizeRequestImmediateArgs:(GTMOAuth2AuthorizationArgs *)args; + +- (BOOL)shouldRefreshAccessToken; + +- (void)updateExpirationDate; + +- (void)tokenFetcher:(GTMOAuth2Fetcher *)fetcher + finishedWithData:(NSData *)data + error:(NSError *)error; + +- (void)auth:(GTMOAuth2Authentication *)auth +finishedRefreshWithFetcher:(GTMOAuth2Fetcher *)fetcher + error:(NSError *)error; + +- (void)invokeCallbackArgs:(GTMOAuth2AuthorizationArgs *)args; + ++ (void)invokeDelegate:(id)delegate + selector:(SEL)sel + object:(id)obj1 + object:(id)obj2 + object:(id)obj3; + ++ (NSString *)unencodedOAuthParameterForString:(NSString *)str; ++ (NSString *)encodedQueryParametersForDictionary:(NSDictionary *)dict; + ++ (NSDictionary *)dictionaryWithResponseData:(NSData *)data; + +@end + +@implementation GTMOAuth2Authentication + +@synthesize clientID = clientID_, + clientSecret = clientSecret_, + redirectURI = redirectURI_, + parameters = parameters_, + authorizationTokenKey = authorizationTokenKey_, + tokenURL = tokenURL_, + expirationDate = expirationDate_, + additionalTokenRequestParameters = additionalTokenRequestParameters_, + additionalGrantTypeRequestParameters = additionalGrantTypeRequestParameters_, + refreshFetcher = refreshFetcher_, + fetcherService = fetcherService_, + parserClass = parserClass_, + shouldAuthorizeAllRequests = shouldAuthorizeAllRequests_, + userData = userData_, + properties = properties_, + authorizationQueue = authorizationQueue_; + +// Response parameters +@dynamic accessToken, + refreshToken, + code, + assertion, + refreshScope, + errorString, + tokenType, + scope, + expiresIn, + serviceProvider, + userEmail, + userEmailIsVerified; + +@dynamic canAuthorize; + ++ (id)authenticationWithServiceProvider:(NSString *)serviceProvider + tokenURL:(NSURL *)tokenURL + redirectURI:(NSString *)redirectURI + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret { + GTMOAuth2Authentication *obj = [[[self alloc] init] autorelease]; + obj.serviceProvider = serviceProvider; + obj.tokenURL = tokenURL; + obj.redirectURI = redirectURI; + obj.clientID = clientID; + obj.clientSecret = clientSecret; + return obj; +} + +- (id)init { + self = [super init]; + if (self) { + authorizationQueue_ = [[NSMutableArray alloc] init]; + parameters_ = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (NSString *)description { + NSArray *props = [NSArray arrayWithObjects:@"accessToken", @"refreshToken", + @"code", @"assertion", @"expirationDate", @"errorString", + nil]; + NSMutableString *valuesStr = [NSMutableString string]; + NSString *separator = @""; + for (NSString *prop in props) { + id result = [self valueForKey:prop]; + if (result) { + [valuesStr appendFormat:@"%@%@=\"%@\"", separator, prop, result]; + separator = @", "; + } + } + + return [NSString stringWithFormat:@"%@ %p: {%@}", + [self class], self, valuesStr]; +} + +- (void)dealloc { + [clientID_ release]; + [clientSecret_ release]; + [redirectURI_ release]; + [parameters_ release]; + [authorizationTokenKey_ release]; + [tokenURL_ release]; + [expirationDate_ release]; + [additionalTokenRequestParameters_ release]; + [additionalGrantTypeRequestParameters_ release]; + [refreshFetcher_ release]; + [authorizationQueue_ release]; + [userData_ release]; + [properties_ release]; + + [super dealloc]; +} + +#pragma mark - + +- (void)setKeysForResponseDictionary:(NSDictionary *)dict { + if (dict == nil) return; + + // If a new code or access token is being set, remove the old expiration + NSString *newCode = [dict objectForKey:kOAuth2CodeKey]; + NSString *newAccessToken = [dict objectForKey:kOAuth2AccessTokenKey]; + if (newCode || newAccessToken) { + self.expiresIn = nil; + } + + BOOL didRefreshTokenChange = NO; + NSString *refreshToken = [dict objectForKey:kOAuth2RefreshTokenKey]; + if (refreshToken) { + NSString *priorRefreshToken = self.refreshToken; + + if (priorRefreshToken != refreshToken + && (priorRefreshToken == nil + || ![priorRefreshToken isEqual:refreshToken])) { + didRefreshTokenChange = YES; + } + } + + [self.parameters addEntriesFromDictionary:dict]; + [self updateExpirationDate]; + + if (didRefreshTokenChange) { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMOAuth2RefreshTokenChanged + object:self + userInfo:nil]; + } + // NSLog(@"keys set ----------------------------\n%@", dict); +} + +- (void)setKeysForResponseString:(NSString *)str { + NSDictionary *dict = [[self class] dictionaryWithResponseString:str]; + [self setKeysForResponseDictionary:dict]; +} + +- (void)setKeysForResponseJSONData:(NSData *)data { + NSDictionary *dict = [[self class] dictionaryWithJSONData:data]; + [self setKeysForResponseDictionary:dict]; +} + ++ (NSDictionary *)dictionaryWithJSONData:(NSData *)data { + NSMutableDictionary *obj = nil; + NSError *error = nil; + + Class serializer = NSClassFromString(@"NSJSONSerialization"); + if (serializer) { + const NSUInteger kOpts = (1UL << 0); // NSJSONReadingMutableContainers + obj = [serializer JSONObjectWithData:data + options:kOpts + error:&error]; +#if DEBUG + if (error) { + NSString *str = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + NSLog(@"NSJSONSerialization error %@ parsing %@", + error, str); + } +#endif + return obj; + } else { + // try SBJsonParser or SBJSON + Class jsonParseClass = NSClassFromString(@"SBJsonParser"); + if (!jsonParseClass) { + jsonParseClass = NSClassFromString(@"SBJSON"); + } + if (jsonParseClass) { + GTMOAuth2ParserClass *parser = [[[jsonParseClass alloc] init] autorelease]; + NSString *jsonStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + if (jsonStr) { + obj = [parser objectWithString:jsonStr error:&error]; +#if DEBUG + if (error) { + NSLog(@"%@ error %@ parsing %@", NSStringFromClass(jsonParseClass), + error, jsonStr); + } +#endif + return obj; + } + } else { +#if DEBUG + NSAssert(0, @"GTMOAuth2Authentication: No parser available"); +#endif + } + } + return nil; +} + +#pragma mark Authorizing Requests + +// General entry point for authorizing requests + +#if NS_BLOCKS_AVAILABLE +// Authorizing with a completion block +- (void)authorizeRequest:(NSMutableURLRequest *)request + completionHandler:(void (^)(NSError *error))handler { + + GTMOAuth2AuthorizationArgs *args; + args = [GTMOAuth2AuthorizationArgs argsWithRequest:request + delegate:nil + selector:NULL + completionHandler:handler + thread:[NSThread currentThread]]; + [self authorizeRequestArgs:args]; +} +#endif + +// Authorizing with a callback selector +// +// Selector has the signature +// - (void)authentication:(GTMOAuth2Authentication *)auth +// request:(NSMutableURLRequest *)request +// finishedWithError:(NSError *)error; +- (void)authorizeRequest:(NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel { + GTMOAuth2AssertValidSelector(delegate, sel, + @encode(GTMOAuth2Authentication *), + @encode(NSMutableURLRequest *), + @encode(NSError *), 0); + + GTMOAuth2AuthorizationArgs *args; + args = [GTMOAuth2AuthorizationArgs argsWithRequest:request + delegate:delegate + selector:sel + completionHandler:nil + thread:[NSThread currentThread]]; + [self authorizeRequestArgs:args]; +} + +// Internal routine common to delegate and block invocations +- (BOOL)authorizeRequestArgs:(GTMOAuth2AuthorizationArgs *)args { + BOOL didAttempt = NO; + + @synchronized(authorizationQueue_) { + + BOOL shouldRefresh = [self shouldRefreshAccessToken]; + + if (shouldRefresh) { + // attempt to refresh now; once we have a fresh access token, we will + // authorize the request and call back to the user + didAttempt = YES; + + if (self.refreshFetcher == nil) { + // there's not already a refresh pending + SEL finishedSel = @selector(auth:finishedRefreshWithFetcher:error:); + self.refreshFetcher = [self beginTokenFetchWithDelegate:self + didFinishSelector:finishedSel]; + if (self.refreshFetcher) { + [authorizationQueue_ addObject:args]; + } + } else { + // there's already a refresh pending + [authorizationQueue_ addObject:args]; + } + } + + if (!shouldRefresh || self.refreshFetcher == nil) { + // we're not fetching a new access token, so we can authorize the request + // now + didAttempt = [self authorizeRequestImmediateArgs:args]; + } + } + return didAttempt; +} + +- (void)auth:(GTMOAuth2Authentication *)auth +finishedRefreshWithFetcher:(GTMOAuth2Fetcher *)fetcher + error:(NSError *)error { + @synchronized(authorizationQueue_) { + // If there's an error, we want to try using the old access token anyway, + // in case it's a backend problem preventing refresh, in which case + // access tokens past their expiration date may still work + + self.refreshFetcher = nil; + + // Swap in a new auth queue in case the callbacks try to immediately auth + // another request + NSArray *pendingAuthQueue = [NSArray arrayWithArray:authorizationQueue_]; + [authorizationQueue_ removeAllObjects]; + + BOOL hasAccessToken = ([self.accessToken length] > 0); + + NSString *noteName; + NSDictionary *userInfo = nil; + if (hasAccessToken && error == nil) { + // Successful refresh. + noteName = kGTMOAuth2AccessTokenRefreshed; + userInfo = nil; + } else { + // Google's OAuth 2 implementation returns a 400 with JSON body + // containing error key "invalid_grant" to indicate the refresh token + // is invalid or has been revoked by the user. We'll promote the + // JSON error key's value for easy inspection by the observer. + noteName = kGTMOAuth2AccessTokenRefreshFailed; + NSString *jsonErr = nil; + if ([error code] == kGTMOAuth2StatusBadRequest) { + NSDictionary *json = [[error userInfo] objectForKey:kGTMOAuth2ErrorJSONKey]; + jsonErr = [json objectForKey:kGTMOAuth2ErrorMessageKey]; + } + // error and jsonErr may be nil + userInfo = [NSMutableDictionary dictionary]; + [userInfo setValue:error forKey:kGTMOAuth2ErrorObjectKey]; + [userInfo setValue:jsonErr forKey:kGTMOAuth2ErrorMessageKey]; + } + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:noteName + object:self + userInfo:userInfo]; + + for (GTMOAuth2AuthorizationArgs *args in pendingAuthQueue) { + if (!hasAccessToken && args.error == nil) { + args.error = error; + } + + [self authorizeRequestImmediateArgs:args]; + } + } +} + +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request { + BOOL wasFound = NO; + @synchronized(authorizationQueue_) { + for (GTMOAuth2AuthorizationArgs *args in authorizationQueue_) { + if ([args request] == request) { + wasFound = YES; + break; + } + } + } + return wasFound; +} + +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request { + NSString *authStr = [request valueForHTTPHeaderField:@"Authorization"]; + return ([authStr length] > 0); +} + +- (void)stopAuthorization { + @synchronized(authorizationQueue_) { + [authorizationQueue_ removeAllObjects]; + + [self.refreshFetcher stopFetching]; + self.refreshFetcher = nil; + } +} + +- (void)stopAuthorizationForRequest:(NSURLRequest *)request { + @synchronized(authorizationQueue_) { + NSUInteger argIndex = 0; + BOOL found = NO; + for (GTMOAuth2AuthorizationArgs *args in authorizationQueue_) { + if ([args request] == request) { + found = YES; + break; + } + argIndex++; + } + + if (found) { + [authorizationQueue_ removeObjectAtIndex:argIndex]; + + // If the queue is now empty, go ahead and stop the fetcher. + if ([authorizationQueue_ count] == 0) { + [self stopAuthorization]; + } + } + } +} + +- (BOOL)authorizeRequestImmediateArgs:(GTMOAuth2AuthorizationArgs *)args { + // This authorization entry point never attempts to refresh the access token, + // but does call the completion routine + + NSMutableURLRequest *request = args.request; + + NSURL *requestURL = [request URL]; + NSString *scheme = [requestURL scheme]; + BOOL isAuthorizableRequest = self.shouldAuthorizeAllRequests + || [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame + || [requestURL isFileURL]; + if (!isAuthorizableRequest) { + // Request is not https, so may be insecure + // + // The NSError will be created below +#if DEBUG + NSLog(@"Cannot authorize request with scheme %@ (%@)", scheme, request); +#endif + } + + // Get the access token. + NSString *accessToken = self.authorizationToken; + if (isAuthorizableRequest && [accessToken length] > 0) { + if (request) { + // we have a likely valid access token + NSString *value = [NSString stringWithFormat:@"%s %@", + GTM_OAUTH2_BEARER, accessToken]; + [request setValue:value forHTTPHeaderField:@"Authorization"]; + } + + // We've authorized the request, even if the previous refresh + // failed with an error + args.error = nil; + } else if (args.error == nil) { + NSDictionary *userInfo = nil; + if (request) { + userInfo = [NSDictionary dictionaryWithObject:request + forKey:kGTMOAuth2ErrorRequestKey]; + } + NSInteger code = (isAuthorizableRequest ? + kGTMOAuth2ErrorAuthorizationFailed : + kGTMOAuth2ErrorUnauthorizableRequest); + args.error = [NSError errorWithDomain:kGTMOAuth2ErrorDomain + code:code + userInfo:userInfo]; + } + + // Invoke any callbacks on the proper thread + if (args.delegate || args.completionHandler) { + NSThread *targetThread = args.thread; + BOOL isSameThread = [targetThread isEqual:[NSThread currentThread]]; + + if (isSameThread) { + [self invokeCallbackArgs:args]; + } else { + SEL sel = @selector(invokeCallbackArgs:); + NSOperationQueue *delegateQueue = self.fetcherService.delegateQueue; + if (delegateQueue) { + NSInvocationOperation *op; + op = [[[NSInvocationOperation alloc] initWithTarget:self + selector:sel + object:args] autorelease]; + [delegateQueue addOperation:op]; + } else { + [self performSelector:sel + onThread:targetThread + withObject:args + waitUntilDone:NO]; + } + } + } + + BOOL didAuth = (args.error == nil); + return didAuth; +} + +- (void)invokeCallbackArgs:(GTMOAuth2AuthorizationArgs *)args { + // Invoke the callbacks + NSError *error = args.error; + + id delegate = args.delegate; + SEL sel = args.selector; + if (delegate && sel) { + NSMutableURLRequest *request = args.request; + + NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:delegate]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&request atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + } + +#if NS_BLOCKS_AVAILABLE + id handler = args.completionHandler; + if (handler) { + void (^authCompletionBlock)(NSError *) = handler; + authCompletionBlock(error); + } +#endif +} + +- (BOOL)authorizeRequest:(NSMutableURLRequest *)request { + // Entry point for synchronous authorization mechanisms + GTMOAuth2AuthorizationArgs *args; + args = [GTMOAuth2AuthorizationArgs argsWithRequest:request + delegate:nil + selector:NULL + completionHandler:nil + thread:[NSThread currentThread]]; + return [self authorizeRequestImmediateArgs:args]; +} + +- (BOOL)canAuthorize { + NSString *token = self.refreshToken; + if (token == nil) { + // For services which do not support refresh tokens, we'll just check + // the access token. + token = self.authorizationToken; + } + BOOL canAuth = [token length] > 0; + return canAuth; +} + +- (BOOL)shouldRefreshAccessToken { + // We should refresh the access token when it's missing or nearly expired + // and we have a refresh token + BOOL shouldRefresh = NO; + NSString *accessToken = self.accessToken; + NSString *refreshToken = self.refreshToken; + NSString *assertion = self.assertion; + NSString *code = self.code; + + BOOL hasRefreshToken = ([refreshToken length] > 0); + BOOL hasAccessToken = ([accessToken length] > 0); + BOOL hasAssertion = ([assertion length] > 0); + BOOL hasCode = ([code length] > 0); + + // Determine if we need to refresh the access token + if (hasRefreshToken || hasAssertion || hasCode) { + if (!hasAccessToken) { + shouldRefresh = YES; + } else { + // We'll consider the token expired if it expires 60 seconds from now + // or earlier + NSDate *expirationDate = self.expirationDate; + NSTimeInterval timeToExpire = [expirationDate timeIntervalSinceNow]; + if (expirationDate == nil || timeToExpire < 60.0) { + // access token has expired, or will in a few seconds + shouldRefresh = YES; + } + } + } + return shouldRefresh; +} + +- (void)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds { + // If there is a refresh fetcher pending, wait for it. + // + // This is only intended for unit test or for use in command-line tools. + GTMOAuth2Fetcher *fetcher = self.refreshFetcher; + [fetcher waitForCompletionWithTimeout:timeoutInSeconds]; +} + +#pragma mark Token Fetch + +- (NSString *)userAgent { + NSBundle *bundle = [NSBundle mainBundle]; + NSString *appID = [bundle bundleIdentifier]; + + NSString *version = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + if (version == nil) { + version = [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]; + } + + if (appID && version) { + appID = [appID stringByAppendingFormat:@"/%@", version]; + } + + NSString *userAgent = @"gtm-oauth2"; + if (appID) { + userAgent = [userAgent stringByAppendingFormat:@" %@", appID]; + } + return userAgent; +} + +- (GTMOAuth2Fetcher *)beginTokenFetchWithDelegate:(id)delegate + didFinishSelector:(SEL)finishedSel { + + NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary]; + + NSString *fetchType; + + NSString *refreshToken = self.refreshToken; + NSString *code = self.code; + NSString *assertion = self.assertion; + NSString *grantType = nil; + + if (refreshToken) { + // We have a refresh token + grantType = @"refresh_token"; + [paramsDict setObject:refreshToken forKey:@"refresh_token"]; + + NSString *refreshScope = self.refreshScope; + if ([refreshScope length] > 0) { + [paramsDict setObject:refreshScope forKey:@"scope"]; + } + + fetchType = kGTMOAuth2FetchTypeRefresh; + } else if (code) { + // We have a code string + grantType = @"authorization_code"; + [paramsDict setObject:code forKey:@"code"]; + + NSString *redirectURI = self.redirectURI; + if ([redirectURI length] > 0) { + [paramsDict setObject:redirectURI forKey:@"redirect_uri"]; + } + + NSString *scope = self.scope; + if ([scope length] > 0) { + [paramsDict setObject:scope forKey:@"scope"]; + } + + fetchType = kGTMOAuth2FetchTypeToken; + } else if (assertion) { + // We have an assertion string + grantType = @"http://oauth.net/grant_type/jwt/1.0/bearer"; + [paramsDict setObject:assertion forKey:@"assertion"]; + fetchType = kGTMOAuth2FetchTypeAssertion; + } else { +#if DEBUG + NSAssert(0, @"unexpected lack of code or refresh token for fetching"); +#endif + return nil; + } + [paramsDict setObject:grantType forKey:@"grant_type"]; + + NSString *clientID = self.clientID; + if ([clientID length] > 0) { + [paramsDict setObject:clientID forKey:@"client_id"]; + } + + NSString *clientSecret = self.clientSecret; + if ([clientSecret length] > 0) { + [paramsDict setObject:clientSecret forKey:@"client_secret"]; + } + + NSDictionary *additionalParams = self.additionalTokenRequestParameters; + if (additionalParams) { + [paramsDict addEntriesFromDictionary:additionalParams]; + } + NSDictionary *grantTypeParams = + [self.additionalGrantTypeRequestParameters objectForKey:grantType]; + if (grantTypeParams) { + [paramsDict addEntriesFromDictionary:grantTypeParams]; + } + + NSString *paramStr = [[self class] encodedQueryParametersForDictionary:paramsDict]; + NSData *paramData = [paramStr dataUsingEncoding:NSUTF8StringEncoding]; + + NSURL *tokenURL = self.tokenURL; + + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:tokenURL]; + [request setValue:@"application/x-www-form-urlencoded" + forHTTPHeaderField:@"Content-Type"]; + + NSString *userAgent = [self userAgent]; + [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + + GTMOAuth2Fetcher *fetcher; + id fetcherService = self.fetcherService; + if (fetcherService) { + fetcher = (GTMOAuth2Fetcher *)[fetcherService fetcherWithRequest:request]; + + // Don't use an authorizer for an auth token fetch + fetcher.authorizer = nil; + } else { + fetcher = [GTMOAuth2Fetcher fetcherWithRequest:request]; + } + +#if !STRIP_GTM_FETCH_LOGGING + // The user email address is known at token refresh time, not during the initial code exchange. + NSString *userEmail = [self userEmail]; + NSString *forStr = userEmail ? [NSString stringWithFormat:@"for \"%@\"", userEmail] : @""; + [fetcher setCommentWithFormat:@"GTMOAuth2 %@ fetch to %@ %@", fetchType, [tokenURL host], forStr]; +#endif + + fetcher.bodyData = paramData; + fetcher.retryEnabled = YES; + fetcher.maxRetryInterval = 15.0; + + // Fetcher properties will retain the delegate + [fetcher setProperty:delegate forKey:kTokenFetchDelegateKey]; + if (finishedSel) { + NSString *selStr = NSStringFromSelector(finishedSel); + [fetcher setProperty:selStr forKey:kTokenFetchSelectorKey]; + } + + [fetcher beginFetchWithDelegate:self + didFinishSelector:@selector(tokenFetcher:finishedWithData:error:)]; + + [self notifyFetchIsRunning:YES fetcher:fetcher type:fetchType]; + return fetcher; +} + +- (void)tokenFetcher:(GTMOAuth2Fetcher *)fetcher + finishedWithData:(NSData *)data + error:(NSError *)error { + [self notifyFetchIsRunning:NO fetcher:fetcher type:nil]; + + NSDictionary *responseHeaders = [fetcher responseHeaders]; + NSString *responseType = [responseHeaders valueForKey:@"Content-Type"]; + BOOL isResponseJSON = [responseType hasPrefix:@"application/json"]; + BOOL hasData = ([data length] > 0); + + if (error) { + // Failed. If the error body is JSON, parse it and add it to the error's + // userInfo dictionary. + if (hasData) { + if (isResponseJSON) { + NSDictionary *errorJson = [[self class] dictionaryWithJSONData:data]; + if ([errorJson count] > 0) { +#if DEBUG + NSLog(@"Error %@\nError data:\n%@", error, errorJson); +#endif + // Add the JSON error body to the userInfo of the error + NSMutableDictionary *userInfo; + userInfo = [NSMutableDictionary dictionaryWithObject:errorJson + forKey:kGTMOAuth2ErrorJSONKey]; + NSDictionary *prevUserInfo = [error userInfo]; + if (prevUserInfo) { + [userInfo addEntriesFromDictionary:prevUserInfo]; + } + error = [NSError errorWithDomain:[error domain] + code:[error code] + userInfo:userInfo]; + } + } + } + } else { + // Succeeded; we have the requested token. +#if DEBUG + NSAssert(hasData, @"data missing in token response"); +#endif + + if (hasData) { + if (isResponseJSON) { + [self setKeysForResponseJSONData:data]; + } else { + // Support for legacy token servers that return form-urlencoded data + NSString *dataStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + [self setKeysForResponseString:dataStr]; + } + +#if DEBUG + // Watch for token exchanges that return a non-bearer or unlabeled token + NSString *tokenType = [self tokenType]; + if (tokenType == nil + || [tokenType caseInsensitiveCompare:@"bearer"] != NSOrderedSame) { + NSLog(@"GTMOAuth2: Unexpected token type: %@", tokenType); + } +#endif + } + } + + id delegate = [fetcher propertyForKey:kTokenFetchDelegateKey]; + SEL sel = NULL; + NSString *selStr = [fetcher propertyForKey:kTokenFetchSelectorKey]; + if (selStr) sel = NSSelectorFromString(selStr); + + [[self class] invokeDelegate:delegate + selector:sel + object:self + object:fetcher + object:error]; + + // Prevent a circular reference from retaining the delegate + [fetcher setProperty:nil forKey:kTokenFetchDelegateKey]; +} + +#pragma mark Fetch Notifications + +- (void)notifyFetchIsRunning:(BOOL)isStarting + fetcher:(GTMOAuth2Fetcher *)fetcher + type:(NSString *)fetchType { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + NSString *name = (isStarting ? kGTMOAuth2FetchStarted : kGTMOAuth2FetchStopped); + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + fetcher, kGTMOAuth2FetcherKey, + fetchType, kGTMOAuth2FetchTypeKey, // fetchType may be nil + nil]; + [nc postNotificationName:name + object:self + userInfo:dict]; +} + +#pragma mark Persistent Response Strings + +- (void)setKeysForPersistenceResponseString:(NSString *)str { + // All persistence keys can be set directly as if returned by a server + [self setKeysForResponseString:str]; +} + +// This returns a "response string" that can be passed later to +// setKeysForResponseString: to reuse an old access token in a new auth object +- (NSString *)persistenceResponseString { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:4]; + + NSString *refreshToken = self.refreshToken; + NSString *accessToken = nil; + if (refreshToken == nil) { + // We store the access token only for services that do not support refresh + // tokens; otherwise, we assume the access token is too perishable to + // be worth storing + accessToken = self.accessToken; + } + + // Any nil values will not set a dictionary entry + [dict setValue:refreshToken forKey:kOAuth2RefreshTokenKey]; + [dict setValue:accessToken forKey:kOAuth2AccessTokenKey]; + [dict setValue:self.serviceProvider forKey:kServiceProviderKey]; + [dict setValue:self.userID forKey:kUserIDKey]; + [dict setValue:self.userEmail forKey:kUserEmailKey]; + [dict setValue:self.userEmailIsVerified forKey:kUserEmailIsVerifiedKey]; + [dict setValue:self.scope forKey:kOAuth2ScopeKey]; + + NSString *result = [[self class] encodedQueryParametersForDictionary:dict]; + return result; +} + +- (BOOL)primeForRefresh { + if (self.refreshToken == nil) { + // Cannot refresh without a refresh token + return NO; + } + self.accessToken = nil; + self.expiresIn = nil; + self.expirationDate = nil; + self.errorString = nil; + return YES; +} + +- (void)reset { + // Reset all per-authorization values + self.code = nil; + self.accessToken = nil; + self.refreshToken = nil; + self.assertion = nil; + self.expiresIn = nil; + self.errorString = nil; + self.expirationDate = nil; + self.userEmail = nil; + self.userEmailIsVerified = nil; + self.authorizationTokenKey = nil; +} + +#pragma mark Accessors for Response Parameters + +- (NSString *)authorizationToken { + // The token used for authorization is typically the access token unless + // the user has specified that an alternative parameter be used. + NSString *authorizationToken; + NSString *authTokenKey = self.authorizationTokenKey; + if (authTokenKey != nil) { + authorizationToken = [self.parameters objectForKey:authTokenKey]; + } else { + authorizationToken = self.accessToken; + } + return authorizationToken; +} + +- (NSString *)accessToken { + return [self.parameters objectForKey:kOAuth2AccessTokenKey]; +} + +- (void)setAccessToken:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2AccessTokenKey]; +} + +- (NSString *)refreshToken { + return [self.parameters objectForKey:kOAuth2RefreshTokenKey]; +} + +- (void)setRefreshToken:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2RefreshTokenKey]; +} + +- (NSString *)code { + return [self.parameters objectForKey:kOAuth2CodeKey]; +} + +- (void)setCode:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2CodeKey]; +} + +- (NSString *)assertion { + return [self.parameters objectForKey:kOAuth2AssertionKey]; +} + +- (void)setAssertion:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2AssertionKey]; +} + +- (NSString *)refreshScope { + return [self.parameters objectForKey:kOAuth2RefreshScopeKey]; +} + +- (void)setRefreshScope:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2RefreshScopeKey]; +} + +- (NSString *)errorString { + return [self.parameters objectForKey:kOAuth2ErrorKey]; +} + +- (void)setErrorString:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2ErrorKey]; +} + +- (NSString *)tokenType { + return [self.parameters objectForKey:kOAuth2TokenTypeKey]; +} + +- (void)setTokenType:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2TokenTypeKey]; +} + +- (NSString *)scope { + return [self.parameters objectForKey:kOAuth2ScopeKey]; +} + +- (void)setScope:(NSString *)str { + [self.parameters setValue:str forKey:kOAuth2ScopeKey]; +} + +- (NSNumber *)expiresIn { + id value = [self.parameters objectForKey:kOAuth2ExpiresInKey]; + if ([value isKindOfClass:[NSString class]]) { + value = [NSNumber numberWithInteger:[value integerValue]]; + } + return value; +} + +- (void)setExpiresIn:(NSNumber *)num { + [self.parameters setValue:num forKey:kOAuth2ExpiresInKey]; + [self updateExpirationDate]; +} + +- (void)updateExpirationDate { + // Update our absolute expiration time to something close to when + // the server expects the expiration + NSDate *date = nil; + NSNumber *expiresIn = self.expiresIn; + if (expiresIn) { + unsigned long deltaSeconds = [expiresIn unsignedLongValue]; + if (deltaSeconds > 0) { + date = [NSDate dateWithTimeIntervalSinceNow:deltaSeconds]; + } + } + self.expirationDate = date; +} + +// +// Keys custom to this class, not part of OAuth 2 +// + +- (NSString *)serviceProvider { + return [self.parameters objectForKey:kServiceProviderKey]; +} + +- (void)setServiceProvider:(NSString *)str { + [self.parameters setValue:str forKey:kServiceProviderKey]; +} + +- (NSString *)userID { + return [self.parameters objectForKey:kUserIDKey]; +} + +- (void)setUserID:(NSString *)str { + [self.parameters setValue:str forKey:kUserIDKey]; +} + +- (NSString *)userEmail { + return [self.parameters objectForKey:kUserEmailKey]; +} + +- (void)setUserEmail:(NSString *)str { + [self.parameters setValue:str forKey:kUserEmailKey]; +} + +- (NSString *)userEmailIsVerified { + return [self.parameters objectForKey:kUserEmailIsVerifiedKey]; +} + +- (void)setUserEmailIsVerified:(NSString *)str { + [self.parameters setValue:str forKey:kUserEmailIsVerifiedKey]; +} + +#pragma mark User Properties + +- (void)setProperty:(id)obj forKey:(NSString *)key { + if (obj == nil) { + // User passed in nil, so delete the property + [properties_ removeObjectForKey:key]; + } else { + // Be sure the property dictionary exists + if (properties_ == nil) { + [self setProperties:[NSMutableDictionary dictionary]]; + } + [properties_ setObject:obj forKey:key]; + } +} + +- (id)propertyForKey:(NSString *)key { + id obj = [properties_ objectForKey:key]; + + // Be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[obj retain] autorelease]; +} + +#pragma mark Utility Routines + ++ (NSString *)encodedOAuthValueForString:(NSString *)str { + CFStringRef originalString = (CFStringRef) str; + CFStringRef leaveUnescaped = NULL; + CFStringRef forceEscaped = CFSTR("!*'();:@&=+$,/?%#[]"); + + CFStringRef escapedStr = NULL; + if (str) { + escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, + originalString, + leaveUnescaped, + forceEscaped, + kCFStringEncodingUTF8); + [(id)CFMakeCollectable(escapedStr) autorelease]; + } + + return (NSString *)escapedStr; +} + ++ (NSString *)encodedQueryParametersForDictionary:(NSDictionary *)dict { + // Make a string like "cat=fluffy@dog=spot" + NSMutableString *result = [NSMutableString string]; + NSArray *sortedKeys = [[dict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + NSString *joiner = @""; + for (NSString *key in sortedKeys) { + NSString *value = [dict objectForKey:key]; + NSString *encodedValue = [self encodedOAuthValueForString:value]; + NSString *encodedKey = [self encodedOAuthValueForString:key]; + [result appendFormat:@"%@%@=%@", joiner, encodedKey, encodedValue]; + joiner = @"&"; + } + return result; +} + ++ (void)invokeDelegate:(id)delegate + selector:(SEL)sel + object:(id)obj1 + object:(id)obj2 + object:(id)obj3 { + if (delegate && sel) { + NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:delegate]; + [invocation setArgument:&obj1 atIndex:2]; + [invocation setArgument:&obj2 atIndex:3]; + [invocation setArgument:&obj3 atIndex:4]; + [invocation invoke]; + } +} + ++ (NSString *)unencodedOAuthParameterForString:(NSString *)str { + NSString *plainStr = [str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + return plainStr; +} + ++ (NSDictionary *)dictionaryWithResponseString:(NSString *)responseStr { + // Build a dictionary from a response string of the form + // "cat=fluffy&dog=spot". Missing or empty values are considered + // empty strings; keys and values are percent-decoded. + if (responseStr == nil) return nil; + + NSArray *items = [responseStr componentsSeparatedByString:@"&"]; + + NSMutableDictionary *responseDict = [NSMutableDictionary dictionaryWithCapacity:[items count]]; + + for (NSString *item in items) { + NSString *key = nil; + NSString *value = @""; + + NSRange equalsRange = [item rangeOfString:@"="]; + if (equalsRange.location != NSNotFound) { + // The parameter has at least one '=' + key = [item substringToIndex:equalsRange.location]; + + // There are characters after the '=' + value = [item substringFromIndex:(equalsRange.location + 1)]; + } else { + // The parameter has no '=' + key = item; + } + + NSString *plainKey = [[self class] unencodedOAuthParameterForString:key]; + NSString *plainValue = [[self class] unencodedOAuthParameterForString:value]; + + [responseDict setObject:plainValue forKey:plainKey]; + } + + return responseDict; +} + ++ (NSDictionary *)dictionaryWithResponseData:(NSData *)data { + NSString *responseStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + NSDictionary *dict = [self dictionaryWithResponseString:responseStr]; + return dict; +} + ++ (NSString *)scopeWithStrings:(NSString *)str, ... { + // concatenate the strings, joined by a single space + NSString *result = @""; + NSString *joiner = @""; + if (str) { + va_list argList; + va_start(argList, str); + while (str) { + result = [result stringByAppendingFormat:@"%@%@", joiner, str]; + joiner = @" "; + str = va_arg(argList, id); + } + va_end(argList); + } + return result; +} + +@end + +#endif // GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2SignIn.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2SignIn.h new file mode 100755 index 0000000..f9accbf --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2SignIn.h @@ -0,0 +1,191 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// This sign-in object opens and closes the web view window as needed for +// users to sign in. For signing in to Google, it also obtains +// the authenticated user's email address. +// +// Typically, this will be managed for the application by +// GTMOAuth2ViewControllerTouch or GTMOAuth2WindowController, so this +// class's interface is interesting only if +// you are creating your own window controller for sign-in. +// +// +// Delegate methods implemented by the window controller +// +// The window controller implements two methods for use by the sign-in object, +// the webRequestSelector and the finishedSelector: +// +// webRequestSelector has a signature matching +// - (void)signIn:(GTMOAuth2SignIn *)signIn displayRequest:(NSURLRequest *)request +// +// The web request selector will be invoked with a request to be displayed, or +// nil to close the window when the final callback request has been encountered. +// +// +// finishedSelector has a signature matching +// - (void)signin:(GTMOAuth2SignIn *)signin finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError *)error +// +// The finished selector will be invoked when sign-in has completed, except +// when explicitly canceled by calling cancelSigningIn +// + +#if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES + +#import +#import + +// GTMHTTPFetcher brings in GTLDefines/GDataDefines +#if GTM_USE_SESSION_FETCHER +#import "GTMSessionFetcher.h" +#else +#import "GTMHTTPFetcher.h" +#endif + +#import "GTMOAuth2Authentication.h" + +@interface GTMOAuth2SignIn : NSObject { + @private + GTMOAuth2Authentication *auth_; + + // the endpoint for displaying the sign-in page + NSURL *authorizationURL_; + NSDictionary *additionalAuthorizationParameters_; + + id delegate_; + SEL webRequestSelector_; + SEL finishedSelector_; + + BOOL hasHandledCallback_; + + GTMOAuth2Fetcher *pendingFetcher_; + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + BOOL shouldFetchGoogleUserEmail_; + BOOL shouldFetchGoogleUserProfile_; + NSDictionary *userProfile_; +#endif + + SCNetworkReachabilityRef reachabilityRef_; + NSTimer *networkLossTimer_; + NSTimeInterval networkLossTimeoutInterval_; + BOOL hasNotifiedNetworkLoss_; + + id userData_; +} + +@property (nonatomic, retain) GTMOAuth2Authentication *authentication; + +@property (nonatomic, retain) NSURL *authorizationURL; +@property (nonatomic, retain) NSDictionary *additionalAuthorizationParameters; + +// The delegate is released when signing in finishes or is cancelled +@property (nonatomic, retain) id delegate; +@property (nonatomic, assign) SEL webRequestSelector; +@property (nonatomic, assign) SEL finishedSelector; + +@property (nonatomic, retain) id userData; + +// By default, signing in to Google will fetch the user's email, but will not +// fetch the user's profile. +// +// The email is saved in the auth object. +// The profile is available immediately after sign-in. +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT +@property (nonatomic, assign) BOOL shouldFetchGoogleUserEmail; +@property (nonatomic, assign) BOOL shouldFetchGoogleUserProfile; +@property (nonatomic, retain, readonly) NSDictionary *userProfile; +#endif + +// The default timeout for an unreachable network during display of the +// sign-in page is 30 seconds; set this to 0 to have no timeout +@property (nonatomic, assign) NSTimeInterval networkLossTimeoutInterval; + +// The delegate is retained until sign-in has completed or been canceled +// +// designated initializer +- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + delegate:(id)delegate + webRequestSelector:(SEL)webRequestSelector + finishedSelector:(SEL)finishedSelector; + +// A default authentication object for signing in to Google services +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (GTMOAuth2Authentication *)standardGoogleAuthenticationForScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret; +#endif + +#pragma mark Methods used by the Window Controller + +// Start the sequence of fetches and sign-in window display for sign-in +- (BOOL)startSigningIn; + +// Stop any pending fetches, and close the window (but don't call the +// delegate's finishedSelector) +- (void)cancelSigningIn; + +// Window controllers must tell the sign-in object about any redirect +// requested by the web view, and any changes in the webview window title +// +// If these return YES then the event was handled by the +// sign-in object (typically by closing the window) and should be ignored by +// the window controller's web view + +- (BOOL)requestRedirectedToRequest:(NSURLRequest *)redirectedRequest; +- (BOOL)titleChanged:(NSString *)title; +- (BOOL)cookiesChanged:(NSHTTPCookieStorage *)cookieStorage; +- (BOOL)loadFailedWithError:(NSError *)error; + +// Window controllers must tell the sign-in object if the window was closed +// prematurely by the user (but not by the sign-in object); this calls the +// delegate's finishedSelector +- (void)windowWasClosed; + +// Start the sequences for signing in with an authorization code. The +// authentication must contain an authorization code, otherwise the process +// will fail. +- (void)authCodeObtained; + +#pragma mark - + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT +// Revocation of an authorized token from Google ++ (void)revokeTokenForGoogleAuthentication:(GTMOAuth2Authentication *)auth; + +// Create a fetcher for obtaining the user's Google email address or profile, +// according to the current auth scopes. +// +// The auth object must have been created with appropriate scopes. +// +// The fetcher's response data can be parsed with NSJSONSerialization. ++ (GTMOAuth2Fetcher *)userInfoFetcherWithAuth:(GTMOAuth2Authentication *)auth; +#endif + +#pragma mark - + +// Standard authentication values ++ (NSString *)nativeClientRedirectURI; +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (NSURL *)googleAuthorizationURL; ++ (NSURL *)googleTokenURL; ++ (NSURL *)googleUserInfoURL; +#endif + +@end + +#endif // #if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2SignIn.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2SignIn.m new file mode 100755 index 0000000..472b0b0 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/GTMOAuth2SignIn.m @@ -0,0 +1,971 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES + +#import "GTMOAuth2SignIn.h" + +// we'll default to timing out if the network becomes unreachable for more +// than 30 seconds when the sign-in page is displayed +static const NSTimeInterval kDefaultNetworkLossTimeoutInterval = 30.0; + +// URI indicating an installed app is signing in. This is described at +// +// http://code.google.com/apis/accounts/docs/OAuth2.html#IA +// +NSString *const kOOBString = @"urn:ietf:wg:oauth:2.0:oob"; + + +@interface GTMOAuth2SignIn () +@property (assign) BOOL hasHandledCallback; +@property (retain) GTMOAuth2Fetcher *pendingFetcher; +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT +@property (nonatomic, retain, readwrite) NSDictionary *userProfile; +#endif + +- (void)invokeFinalCallbackWithError:(NSError *)error; + +- (BOOL)startWebRequest; ++ (NSMutableURLRequest *)mutableURLRequestWithURL:(NSURL *)oldURL + paramString:(NSString *)paramStr; +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT +- (void)addScopeForGoogleUserInfo; +- (void)fetchGoogleUserInfo; +#endif +- (void)finishSignInWithError:(NSError *)error; + +- (void)auth:(GTMOAuth2Authentication *)auth +finishedWithFetcher:(GTMOAuth2Fetcher *)fetcher + error:(NSError *)error; + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT +- (void)infoFetcher:(GTMOAuth2Fetcher *)fetcher + finishedWithData:(NSData *)data + error:(NSError *)error; ++ (NSData *)decodeWebSafeBase64:(NSString *)base64Str; +- (void)updateGoogleUserInfoWithData:(NSData *)data; +#endif + +- (void)closeTheWindow; + +- (void)startReachabilityCheck; +- (void)stopReachabilityCheck; +- (void)reachabilityTarget:(SCNetworkReachabilityRef)reachabilityRef + changedFlags:(SCNetworkConnectionFlags)flags; +- (void)reachabilityTimerFired:(NSTimer *)timer; +@end + +@implementation GTMOAuth2SignIn + +@synthesize authentication = auth_; + +@synthesize authorizationURL = authorizationURL_; +@synthesize additionalAuthorizationParameters = additionalAuthorizationParameters_; + +@synthesize delegate = delegate_; +@synthesize webRequestSelector = webRequestSelector_; +@synthesize finishedSelector = finishedSelector_; +@synthesize hasHandledCallback = hasHandledCallback_; +@synthesize pendingFetcher = pendingFetcher_; +@synthesize userData = userData_; + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT +@synthesize shouldFetchGoogleUserEmail = shouldFetchGoogleUserEmail_; +@synthesize shouldFetchGoogleUserProfile = shouldFetchGoogleUserProfile_; +@synthesize userProfile = userProfile_; +#endif + +@synthesize networkLossTimeoutInterval = networkLossTimeoutInterval_; + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (NSURL *)googleAuthorizationURL { + NSString *str = @"https://accounts.google.com/o/oauth2/auth"; + return [NSURL URLWithString:str]; +} + ++ (NSURL *)googleTokenURL { + NSString *str = @"https://accounts.google.com/o/oauth2/token"; + return [NSURL URLWithString:str]; +} + ++ (NSURL *)googleRevocationURL { + NSString *urlStr = @"https://accounts.google.com/o/oauth2/revoke"; + return [NSURL URLWithString:urlStr]; +} + ++ (NSURL *)googleUserInfoURL { +#if GTM_OAUTH2_USES_OPENIDCONNECT + NSString *urlStr = @" https://www.googleapis.com/plus/v1/people/me/openIdConnect"; +#else + NSString *urlStr = @"https://www.googleapis.com/oauth2/v3/userinfo"; +#endif + return [NSURL URLWithString:urlStr]; +} +#endif + ++ (NSString *)nativeClientRedirectURI { + return kOOBString; +} + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (GTMOAuth2Authentication *)standardGoogleAuthenticationForScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret { + NSString *redirectURI = [self nativeClientRedirectURI]; + NSURL *tokenURL = [self googleTokenURL]; + + GTMOAuth2Authentication *auth; + auth = [GTMOAuth2Authentication authenticationWithServiceProvider:kGTMOAuth2ServiceProviderGoogle + tokenURL:tokenURL + redirectURI:redirectURI + clientID:clientID + clientSecret:clientSecret]; + auth.scope = scope; + + return auth; +} + + +- (void)addScopeForGoogleUserInfo { +#if GTM_OAUTH2_USES_OPENIDCONNECT + NSString *const emailScope = @"email"; + NSString *const profileScope = @"profile"; + BOOL (^hasScope)(NSString *, NSString *) = ^(NSString *scopesString, NSString *scope) { + // For one-word scopes, we need an exact match rather than a substring match. + NSArray *words = [scopesString componentsSeparatedByString:@" "]; + return [words containsObject:scope]; + }; +#else + NSString *const emailScope = @"https://www.googleapis.com/auth/userinfo.email"; + NSString *const profileScope = @"https://www.googleapis.com/auth/userinfo.profile"; + BOOL (^hasScope)(NSString *, NSString *) = ^BOOL(NSString *scopesString, NSString *scope) { + return [scopesString rangeOfString:scope].location != NSNotFound; + }; +#endif // GTM_OAUTH2_USES_OPENIDCONNECT + + GTMOAuth2Authentication *auth = self.authentication; + if (self.shouldFetchGoogleUserEmail) { + NSString *scopeStrings = auth.scope; + if (!hasScope(scopeStrings, emailScope)) { + scopeStrings = [GTMOAuth2Authentication scopeWithStrings:scopeStrings, emailScope, nil]; + auth.scope = scopeStrings; + } + } + + if (self.shouldFetchGoogleUserProfile) { + NSString *scopeStrings = auth.scope; + if (!hasScope(scopeStrings, profileScope)) { + scopeStrings = [GTMOAuth2Authentication scopeWithStrings:scopeStrings, profileScope, nil]; + auth.scope = scopeStrings; + } + } +} +#endif + +- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + delegate:(id)delegate + webRequestSelector:(SEL)webRequestSelector + finishedSelector:(SEL)finishedSelector { + // check the selectors on debug builds + GTMOAuth2AssertValidSelector(delegate, webRequestSelector, + @encode(GTMOAuth2SignIn *), @encode(NSURLRequest *), 0); + GTMOAuth2AssertValidSelector(delegate, finishedSelector, + @encode(GTMOAuth2SignIn *), @encode(GTMOAuth2Authentication *), + @encode(NSError *), 0); + + // designated initializer + self = [super init]; + if (self) { + auth_ = [auth retain]; + authorizationURL_ = [authorizationURL retain]; + delegate_ = [delegate retain]; + webRequestSelector_ = webRequestSelector; + finishedSelector_ = finishedSelector; + + // for Google authentication, we want to automatically fetch user info +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + NSString *host = [authorizationURL host]; + if ([host hasSuffix:@".google.com"]) { + shouldFetchGoogleUserEmail_ = YES; + } +#endif + + // default timeout for a lost internet connection while the server + // UI is displayed is 30 seconds + networkLossTimeoutInterval_ = kDefaultNetworkLossTimeoutInterval; + } + return self; +} + +- (void)dealloc { + [self stopReachabilityCheck]; + + [auth_ release]; + [authorizationURL_ release]; + [additionalAuthorizationParameters_ release]; + [delegate_ release]; + [pendingFetcher_ release]; +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + [userProfile_ release]; +#endif + [userData_ release]; + + [super dealloc]; +} + +#pragma mark Sign-in Sequence Methods + +// stop any pending fetches, and close the window (but don't call the +// delegate's finishedSelector) +- (void)cancelSigningIn { + [self.pendingFetcher stopFetching]; + self.pendingFetcher = nil; + + [self.authentication stopAuthorization]; + + [self closeTheWindow]; + + [delegate_ autorelease]; + delegate_ = nil; +} + +// +// This is the entry point to begin the sequence +// - display the authentication web page, and monitor redirects +// - exchange the code for an access token and a refresh token +// - for Google sign-in, fetch the user's email address +// - tell the delegate we're finished +// +- (BOOL)startSigningIn { + // For signing in to Google, append the scope for obtaining the authenticated + // user email and profile, as appropriate +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + [self addScopeForGoogleUserInfo]; +#endif + + // start the authorization + return [self startWebRequest]; +} + +- (NSMutableDictionary *)parametersForWebRequest { + GTMOAuth2Authentication *auth = self.authentication; + NSString *clientID = auth.clientID; + NSString *redirectURI = auth.redirectURI; + + BOOL hasClientID = ([clientID length] > 0); + BOOL hasRedirect = ([redirectURI length] > 0 + || redirectURI == [[self class] nativeClientRedirectURI]); + if (!hasClientID || !hasRedirect) { +#if DEBUG + NSAssert(hasClientID, @"GTMOAuth2SignIn: clientID needed"); + NSAssert(hasRedirect, @"GTMOAuth2SignIn: redirectURI needed"); +#endif + return nil; + } + + // invoke the UI controller's web request selector to display + // the authorization page + + // add params to the authorization URL + NSString *scope = auth.scope; + if ([scope length] == 0) scope = nil; + + NSMutableDictionary *paramsDict = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"code", @"response_type", + clientID, @"client_id", + scope, @"scope", // scope may be nil + nil]; + if (redirectURI) { + [paramsDict setObject:redirectURI forKey:@"redirect_uri"]; + } + return paramsDict; +} + +- (BOOL)startWebRequest { + NSMutableDictionary *paramsDict = [self parametersForWebRequest]; + + NSDictionary *additionalParams = self.additionalAuthorizationParameters; + if (additionalParams) { + [paramsDict addEntriesFromDictionary:additionalParams]; + } + + NSString *paramStr = [GTMOAuth2Authentication encodedQueryParametersForDictionary:paramsDict]; + + NSURL *authorizationURL = self.authorizationURL; + NSMutableURLRequest *request; + request = [[self class] mutableURLRequestWithURL:authorizationURL + paramString:paramStr]; + + [delegate_ performSelector:self.webRequestSelector + withObject:self + withObject:request]; + + // at this point, we're waiting on the server-driven html UI, so + // we want notification if we lose connectivity to the web server + [self startReachabilityCheck]; + return YES; +} + +// utility for making a request from an old URL with some additional parameters ++ (NSMutableURLRequest *)mutableURLRequestWithURL:(NSURL *)oldURL + paramString:(NSString *)paramStr { + if ([paramStr length] == 0) { + return [NSMutableURLRequest requestWithURL:oldURL]; + } + + NSString *query = [oldURL query]; + if ([query length] > 0) { + query = [query stringByAppendingFormat:@"&%@", paramStr]; + } else { + query = paramStr; + } + + NSString *portStr = @""; + NSString *oldPort = [[oldURL port] stringValue]; + if ([oldPort length] > 0) { + portStr = [@":" stringByAppendingString:oldPort]; + } + + NSString *qMark = [query length] > 0 ? @"?" : @""; + NSString *newURLStr = [NSString stringWithFormat:@"%@://%@%@%@%@%@", + [oldURL scheme], [oldURL host], portStr, + [oldURL path], qMark, query]; + NSURL *newURL = [NSURL URLWithString:newURLStr]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:newURL]; + return request; +} + +// entry point for the window controller to tell us that the window +// prematurely closed +- (void)windowWasClosed { + [self stopReachabilityCheck]; + + NSError *error = [NSError errorWithDomain:kGTMOAuth2ErrorDomain + code:kGTMOAuth2ErrorWindowClosed + userInfo:nil]; + [self invokeFinalCallbackWithError:error]; +} + +// internal method to tell the window controller to close the window +- (void)closeTheWindow { + [self stopReachabilityCheck]; + + // a nil request means the window should be closed + [delegate_ performSelector:self.webRequestSelector + withObject:self + withObject:nil]; +} + +// entry point for the window controller to tell us what web page has been +// requested +// +// When the request is for the callback URL, this method invokes +// authCodeObtained and returns YES +- (BOOL)requestRedirectedToRequest:(NSURLRequest *)redirectedRequest { + // for Google's installed app sign-in protocol, we'll look for the + // end-of-sign-in indicator in the titleChanged: method below + NSString *redirectURI = self.authentication.redirectURI; + if (redirectURI == nil) return NO; + + // when we're searching for the window title string, then we can ignore + // redirects + NSString *standardURI = [[self class] nativeClientRedirectURI]; + if (standardURI != nil && [redirectURI isEqual:standardURI]) return NO; + + // compare the redirectURI, which tells us when the web sign-in is done, + // to the actual redirection + NSURL *redirectURL = [NSURL URLWithString:redirectURI]; + NSURL *requestURL = [redirectedRequest URL]; + + // avoid comparing to nil host and path values (such as when redirected to + // "about:blank") + NSString *requestHost = [requestURL host]; + NSString *requestPath = [requestURL path]; + BOOL isCallback; + if (requestHost && requestPath) { + isCallback = [[redirectURL host] isEqual:[requestURL host]] + && [[redirectURL path] isEqual:[requestURL path]]; + } else if (requestURL) { + // handle "about:blank" + isCallback = [redirectURL isEqual:requestURL]; + } else { + isCallback = NO; + } + + if (!isCallback) { + // tell the caller that this request is nothing interesting + return NO; + } + + // we've reached the callback URL + + // try to get the access code + if (!self.hasHandledCallback) { + NSString *responseStr = [[redirectedRequest URL] query]; + [self.authentication setKeysForResponseString:responseStr]; + +#if DEBUG + NSAssert([self.authentication.code length] > 0 + || [self.authentication.errorString length] > 0, + @"response lacks auth code or error"); +#endif + + [self authCodeObtained]; + } + // tell the delegate that we did handle this request + return YES; +} + +// entry point for the window controller to tell us when a new page title has +// been loadded +// +// When the title indicates sign-in has completed, this method invokes +// authCodeObtained and returns YES +- (BOOL)titleChanged:(NSString *)title { + // return YES if the OAuth flow ending title was detected + + // right now we're just looking for a parameter list following the last space + // in the title string, but hopefully we'll eventually get something better + // from the server to search for + NSRange paramsRange = [title rangeOfString:@" " + options:NSBackwardsSearch]; + NSUInteger spaceIndex = paramsRange.location; + if (spaceIndex != NSNotFound) { + NSString *responseStr = [title substringFromIndex:(spaceIndex + 1)]; + + NSDictionary *dict = [GTMOAuth2Authentication dictionaryWithResponseString:responseStr]; + + NSString *code = [dict objectForKey:@"code"]; + NSString *error = [dict objectForKey:@"error"]; + if ([code length] > 0 || [error length] > 0) { + + if (!self.hasHandledCallback) { + [self.authentication setKeysForResponseDictionary:dict]; + + [self authCodeObtained]; + } + return YES; + } + } + return NO; +} + +- (BOOL)cookiesChanged:(NSHTTPCookieStorage *)cookieStorage { + // We're ignoring these. + return NO; +}; + +// entry point for the window controller to tell us when a load has failed +// in the webview +// +// if the initial authorization URL fails, bail out so the user doesn't +// see an empty webview +- (BOOL)loadFailedWithError:(NSError *)error { + NSURL *authorizationURL = self.authorizationURL; + NSURL *failedURL = [[error userInfo] valueForKey:@"NSErrorFailingURLKey"]; // NSURLErrorFailingURLErrorKey defined in 10.6 + + BOOL isAuthURL = [[failedURL host] isEqual:[authorizationURL host]] + && [[failedURL path] isEqual:[authorizationURL path]]; + + if (isAuthURL) { + // We can assume that we have no pending fetchers, since we only + // handle failure to load the initial authorization URL + [self closeTheWindow]; + [self invokeFinalCallbackWithError:error]; + return YES; + } + return NO; +} + +- (void)authCodeObtained { + // the callback page was requested, or the authenticate code was loaded + // into a page's title, so exchange the auth code for access & refresh tokens + // and tell the window to close + + // avoid duplicate signals that the callback point has been reached + self.hasHandledCallback = YES; + + // If the signin was request for exchanging an authentication token to a + // refresh token, there is no window to close. + if (self.webRequestSelector) { + [self closeTheWindow]; + } else { + // For signing in to Google, append the scope for obtaining the + // authenticated user email and profile, as appropriate. This is usually + // done by the startSigningIn method, but this method is not called when + // exchanging an authentication token for a refresh token. +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + [self addScopeForGoogleUserInfo]; +#endif + } + + NSError *error = nil; + + GTMOAuth2Authentication *auth = self.authentication; + NSString *code = auth.code; + if ([code length] > 0) { + // exchange the code for a token + SEL sel = @selector(auth:finishedWithFetcher:error:); + GTMOAuth2Fetcher *fetcher = [auth beginTokenFetchWithDelegate:self + didFinishSelector:sel]; + if (fetcher == nil) { + error = [NSError errorWithDomain:kGTMOAuth2FetcherStatusDomain + code:-1 + userInfo:nil]; + } else { + self.pendingFetcher = fetcher; + } + + // notify the app so it can put up a post-sign in, pre-token exchange UI + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMOAuth2UserSignedIn + object:self + userInfo:nil]; + } else { + // the callback lacked an auth code + NSString *errStr = auth.errorString; + NSDictionary *userInfo = nil; + if ([errStr length] > 0) { + userInfo = [NSDictionary dictionaryWithObject:errStr + forKey:kGTMOAuth2ErrorMessageKey]; + } + + error = [NSError errorWithDomain:kGTMOAuth2ErrorDomain + code:kGTMOAuth2ErrorAuthorizationFailed + userInfo:userInfo]; + } + + if (error) { + [self finishSignInWithError:error]; + } +} + +- (void)auth:(GTMOAuth2Authentication *)auth +finishedWithFetcher:(GTMOAuth2Fetcher *)fetcher + error:(NSError *)error { + self.pendingFetcher = nil; + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + if (error == nil + && (self.shouldFetchGoogleUserEmail || self.shouldFetchGoogleUserProfile) + && [self.authentication.serviceProvider isEqual:kGTMOAuth2ServiceProviderGoogle]) { + // fetch the user's information from the Google server + [self fetchGoogleUserInfo]; + } else { + // we're not authorizing with Google, so we're done + [self finishSignInWithError:error]; + } +#else + [self finishSignInWithError:error]; +#endif +} + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (GTMOAuth2Fetcher *)userInfoFetcherWithAuth:(GTMOAuth2Authentication *)auth { + // create a fetcher for obtaining the user's email or profile + NSURL *infoURL = [[self class] googleUserInfoURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:infoURL]; + + if ([auth respondsToSelector:@selector(userAgent)]) { + NSString *userAgent = [auth userAgent]; + [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + } + [request setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"]; + + GTMOAuth2Fetcher *fetcher; + id fetcherService = nil; + if ([auth respondsToSelector:@selector(fetcherService)]) { + fetcherService = auth.fetcherService; + }; + if (fetcherService) { + fetcher = (GTMOAuth2Fetcher *)[fetcherService fetcherWithRequest:request]; + } else { + fetcher = [GTMOAuth2Fetcher fetcherWithRequest:request]; + } + fetcher.authorizer = auth; + fetcher.retryEnabled = YES; + fetcher.maxRetryInterval = 15.0; +#if !STRIP_GTM_FETCH_LOGGING + // The user email address is known at token refresh time, not during the initial code exchange. + NSString *userEmail = auth.userEmail; + NSString *forStr = userEmail ? [NSString stringWithFormat:@"for \"%@\"", userEmail] : @""; + [fetcher setCommentWithFormat:@"GTMOAuth2 user info %@", forStr]; +#endif + return fetcher; +} + +- (void)fetchGoogleUserInfo { + if (!self.shouldFetchGoogleUserProfile) { + // If we only need email and user ID, not the full profile, and we have an + // id_token, it may have the email and user ID so we won't need to fetch + // them. + GTMOAuth2Authentication *auth = self.authentication; + NSString *idToken = [auth.parameters objectForKey:@"id_token"]; + if ([idToken length] > 0) { + // The id_token has three dot-delimited parts. The second is the + // JSON profile. + // + // http://www.tbray.org/ongoing/When/201x/2013/04/04/ID-Tokens + NSArray *parts = [idToken componentsSeparatedByString:@"."]; + if ([parts count] == 3) { + NSString *part2 = [parts objectAtIndex:1]; + if ([part2 length] > 0) { + NSData *data = [[self class] decodeWebSafeBase64:part2]; + if ([data length] > 0) { + [self updateGoogleUserInfoWithData:data]; + if ([[auth userID] length] > 0 && [[auth userEmail] length] > 0) { + // We obtained user ID and email from the ID token. + [self finishSignInWithError:nil]; + return; + } + } + } + } + } + } + + // Fetch the email and profile from the userinfo endpoint. + GTMOAuth2Authentication *auth = self.authentication; + GTMOAuth2Fetcher *fetcher = [[self class] userInfoFetcherWithAuth:auth]; + [fetcher beginFetchWithDelegate:self + didFinishSelector:@selector(infoFetcher:finishedWithData:error:)]; + + self.pendingFetcher = fetcher; + + [auth notifyFetchIsRunning:YES + fetcher:fetcher + type:kGTMOAuth2FetchTypeUserInfo]; +} + +- (void)infoFetcher:(GTMOAuth2Fetcher *)fetcher + finishedWithData:(NSData *)data + error:(NSError *)error { + GTMOAuth2Authentication *auth = self.authentication; + [auth notifyFetchIsRunning:NO + fetcher:fetcher + type:nil]; + + self.pendingFetcher = nil; + + if (error) { +#if DEBUG + if (data) { + NSString *dataStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + NSLog(@"infoFetcher error: %@\n%@", error, dataStr); + } +#endif + } else { + // We have the authenticated user's info + [self updateGoogleUserInfoWithData:data]; + } + [self finishSignInWithError:error]; +} + +- (void)updateGoogleUserInfoWithData:(NSData *)data { + if (!data) return; + + GTMOAuth2Authentication *auth = self.authentication; + NSDictionary *profileDict = [[auth class] dictionaryWithJSONData:data]; + if (profileDict) { + // Profile dictionary keys mostly conform to + // http://openid.net/specs/openid-connect-messages-1_0.html#StandardClaims + + self.userProfile = profileDict; + + // Save the ID into the auth object + NSString *subjectID = [profileDict objectForKey:@"sub"]; + [auth setUserID:subjectID]; + + // Save the email into the auth object + NSString *email = [profileDict objectForKey:@"email"]; + [auth setUserEmail:email]; + +#if DEBUG + NSAssert([subjectID length] > 0 && [email length] > 0, + @"profile lacks userID or userEmail: %@", profileDict); +#endif + + // The email_verified key is a boolean NSNumber in the userinfo + // endpoint response, but it is a string like "true" in the id_token. + // We want to consistently save it as a string of the boolean value, + // like @"1". + id verified = [profileDict objectForKey:@"email_verified"]; + if ([verified isKindOfClass:[NSString class]]) { + verified = [NSNumber numberWithBool:[verified boolValue]]; + } + + [auth setUserEmailIsVerified:[verified stringValue]]; + } +} + +#endif // !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + +- (void)finishSignInWithError:(NSError *)error { + [self invokeFinalCallbackWithError:error]; +} + +// convenience method for making the final call to our delegate +- (void)invokeFinalCallbackWithError:(NSError *)error { + if (delegate_ && finishedSelector_) { + GTMOAuth2Authentication *auth = self.authentication; + + NSMethodSignature *sig = [delegate_ methodSignatureForSelector:finishedSelector_]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:finishedSelector_]; + [invocation setTarget:delegate_]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&auth atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + } + + // we'll no longer send messages to the delegate + // + // we want to autorelease it rather than assign to the property in case + // the delegate is below us in the call stack + [delegate_ autorelease]; + delegate_ = nil; +} + +#pragma mark Reachability monitoring + +static void ReachabilityCallBack(SCNetworkReachabilityRef target, + SCNetworkConnectionFlags flags, + void *info) { + // pass the flags to the signIn object + GTMOAuth2SignIn *signIn = (GTMOAuth2SignIn *)info; + + [signIn reachabilityTarget:target + changedFlags:flags]; +} + +- (void)startReachabilityCheck { + // the user may set the timeout to 0 to skip the reachability checking + // during display of the sign-in page + if (networkLossTimeoutInterval_ <= 0.0 || reachabilityRef_ != NULL) { + return; + } + + // create a reachability target from the authorization URL, add our callback, + // and schedule it on the run loop so we'll be notified if the network drops + NSURL *url = self.authorizationURL; + const char* host = [[url host] UTF8String]; + reachabilityRef_ = SCNetworkReachabilityCreateWithName(kCFAllocatorSystemDefault, + host); + if (reachabilityRef_) { + BOOL isScheduled = NO; + SCNetworkReachabilityContext ctx = { 0, self, NULL, NULL, NULL }; + + if (SCNetworkReachabilitySetCallback(reachabilityRef_, + ReachabilityCallBack, &ctx)) { + if (SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef_, + CFRunLoopGetCurrent(), + kCFRunLoopDefaultMode)) { + isScheduled = YES; + } + } + + if (!isScheduled) { + CFRelease(reachabilityRef_); + reachabilityRef_ = NULL; + } + } +} + +- (void)destroyUnreachabilityTimer { + [networkLossTimer_ invalidate]; + [networkLossTimer_ autorelease]; + networkLossTimer_ = nil; +} + +- (void)reachabilityTarget:(SCNetworkReachabilityRef)reachabilityRef + changedFlags:(SCNetworkConnectionFlags)flags { + BOOL isConnected = (flags & kSCNetworkFlagsReachable) != 0 + && (flags & kSCNetworkFlagsConnectionRequired) == 0; + + if (isConnected) { + // server is again reachable + [self destroyUnreachabilityTimer]; + + if (hasNotifiedNetworkLoss_) { + // tell the user that the network has been found + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMOAuth2NetworkFound + object:self + userInfo:nil]; + hasNotifiedNetworkLoss_ = NO; + } + } else { + // the server has become unreachable; start the timer, if necessary + if (networkLossTimer_ == nil + && networkLossTimeoutInterval_ > 0 + && !hasNotifiedNetworkLoss_) { + SEL sel = @selector(reachabilityTimerFired:); + networkLossTimer_ = [[NSTimer scheduledTimerWithTimeInterval:networkLossTimeoutInterval_ + target:self + selector:sel + userInfo:nil + repeats:NO] retain]; + } + } +} + +- (void)reachabilityTimerFired:(NSTimer *)timer { + // the user may call [[notification object] cancelSigningIn] to + // dismiss the sign-in + if (!hasNotifiedNetworkLoss_) { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMOAuth2NetworkLost + object:self + userInfo:nil]; + hasNotifiedNetworkLoss_ = YES; + } + + [self destroyUnreachabilityTimer]; +} + +- (void)stopReachabilityCheck { + [self destroyUnreachabilityTimer]; + + if (reachabilityRef_) { + SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef_, + CFRunLoopGetCurrent(), + kCFRunLoopDefaultMode); + SCNetworkReachabilitySetCallback(reachabilityRef_, NULL, NULL); + + CFRelease(reachabilityRef_); + reachabilityRef_ = NULL; + } +} + +#pragma mark Token Revocation + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (void)revokeTokenForGoogleAuthentication:(GTMOAuth2Authentication *)auth { + if (auth.refreshToken != nil + && auth.canAuthorize + && [auth.serviceProvider isEqual:kGTMOAuth2ServiceProviderGoogle]) { + + // create a signed revocation request for this authentication object + NSURL *url = [self googleRevocationURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; + + NSString *token = auth.refreshToken; + NSString *encoded = [GTMOAuth2Authentication encodedOAuthValueForString:token]; + if (encoded != nil) { + NSString *body = [@"token=" stringByAppendingString:encoded]; + + [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; + [request setHTTPMethod:@"POST"]; + + NSString *userAgent = [auth userAgent]; + [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + + // there's nothing to be done if revocation succeeds or fails + GTMOAuth2Fetcher *fetcher; + id fetcherService = auth.fetcherService; + if (fetcherService) { + fetcher = (GTMOAuth2Fetcher *)[fetcherService fetcherWithRequest:request]; + } else { + fetcher = [GTMOAuth2Fetcher fetcherWithRequest:request]; + } + [fetcher setCommentWithFormat:@"GTMOAuth2 revoke token for %@", auth.userEmail]; + + // Use a completion handler fetch for better debugging, but only if we're + // guaranteed that blocks are available in the runtime +#if (!TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)) || \ + (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)) + // Blocks are available + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + #if DEBUG + if (error) { + NSString *errStr = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] autorelease]; + NSLog(@"revoke error: %@", errStr); + } + #endif // DEBUG + }]; +#else + // Blocks may not be available + [fetcher beginFetchWithDelegate:nil didFinishSelector:NULL]; +#endif + } + } + [auth reset]; +} + + +// Based on Cyrus Najmabadi's elegent little encoder and decoder from +// http://www.cocoadev.com/index.pl?BaseSixtyFour and on GTLBase64 + ++ (NSData *)decodeWebSafeBase64:(NSString *)base64Str { + static char decodingTable[128]; + static BOOL hasInited = NO; + + if (!hasInited) { + char webSafeEncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + memset(decodingTable, 0, 128); + for (unsigned int i = 0; i < sizeof(webSafeEncodingTable); i++) { + decodingTable[(unsigned int) webSafeEncodingTable[i]] = (char)i; + } + hasInited = YES; + } + + // The input string should be plain ASCII. + const char *cString = [base64Str cStringUsingEncoding:NSASCIIStringEncoding]; + if (cString == nil) return nil; + + NSInteger inputLength = (NSInteger)strlen(cString); + // Input length is not being restricted to multiples of 4. + if (inputLength == 0) return [NSData data]; + + while (inputLength > 0 && cString[inputLength - 1] == '=') { + inputLength--; + } + + NSInteger outputLength = inputLength * 3 / 4; + NSMutableData* data = [NSMutableData dataWithLength:(NSUInteger)outputLength]; + uint8_t *output = [data mutableBytes]; + + NSInteger inputPoint = 0; + NSInteger outputPoint = 0; + char *table = decodingTable; + + while (inputPoint < inputLength - 1) { + int i0 = cString[inputPoint++]; + int i1 = cString[inputPoint++]; + int i2 = inputPoint < inputLength ? cString[inputPoint++] : 'A'; // 'A' will decode to \0 + int i3 = inputPoint < inputLength ? cString[inputPoint++] : 'A'; + + output[outputPoint++] = (uint8_t)((table[i0] << 2) | (table[i1] >> 4)); + if (outputPoint < outputLength) { + output[outputPoint++] = (uint8_t)(((table[i1] & 0xF) << 4) | (table[i2] >> 2)); + } + if (outputPoint < outputLength) { + output[outputPoint++] = (uint8_t)(((table[i2] & 0x3) << 6) | table[i3]); + } + } + + return data; +} + +#endif // !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + +@end + +#endif // #if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewControllerTouch.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewControllerTouch.h new file mode 100755 index 0000000..8670b03 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewControllerTouch.h @@ -0,0 +1,398 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMOAuth2ViewControllerTouch.h +// +// This view controller for iPhone handles sign-in via OAuth to Google or +// other services. +// +// This controller is not reusable; create a new instance of this controller +// every time the user will sign in. +// + +#if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES + +#import + +#if TARGET_OS_IPHONE + +#import + +#import "GTMOAuth2Authentication.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern NSString *const kGTMOAuth2KeychainErrorDomain; + +// Notifications that the view controller is swapping out and back in cookies. +// Apps may use this to avoid relying on the cookie store while view controller +// has them swapped out. +extern NSString *const kGTMOAuth2CookiesWillSwapOut; +extern NSString *const kGTMOAuth2CookiesDidSwapIn; + +#ifdef __cplusplus +} +#endif + +@class GTMOAuth2SignIn; +@class GTMOAuth2ViewControllerTouch; + +typedef void (^GTMOAuth2ViewControllerCompletionHandler)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error); + +@interface GTMOAuth2ViewControllerTouch : UIViewController { + @private + UIButton *backButton_; + UIButton *forwardButton_; + UIActivityIndicatorView *initialActivityIndicator_; + UIView *navButtonsView_; + UIBarButtonItem *rightBarButtonItem_; + UIWebView *webView_; + + // The object responsible for the sign-in networking sequence; it holds + // onto the authentication object as well. + GTMOAuth2SignIn *signIn_; + + // the page request to load when awakeFromNib occurs + NSURLRequest *request_; + + // The user we're calling back + // + // The delegate is retained only until the callback is invoked + // or the sign-in is canceled + id delegate_; + SEL finishedSelector_; + +#if NS_BLOCKS_AVAILABLE + GTMOAuth2ViewControllerCompletionHandler completionBlock_; + + void (^popViewBlock_)(void); +#endif + + NSString *keychainItemName_; + CFTypeRef keychainItemAccessibility_; + + // if non-nil, the html string to be displayed immediately upon opening + // of the web view + NSString *initialHTMLString_; + + // set to 1 or -1 if the user sets the showsInitialActivityIndicator + // property + int mustShowActivityIndicator_; + + // if non-nil, the URL for which cookies will be deleted when the + // browser view is dismissed + NSURL *browserCookiesURL_; + + id userData_; + NSMutableDictionary *properties_; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + // We delegate the decision to our owning NavigationController (if any). + // But, the NavigationController will call us back, and ask us. + // BOOL keeps us from infinite looping. + BOOL isInsideShouldAutorotateToInterfaceOrientation_; +#endif + + // YES, when view first shown in this signIn session. + BOOL isViewShown_; + + // YES, after the view has fully transitioned in. + BOOL didViewAppear_; + + // YES between sends of start and stop notifications + BOOL hasNotifiedWebViewStartedLoading_; + + // To prevent us from calling our delegate's selector more than once. + BOOL hasCalledFinished_; + + // Set in a webView callback. + BOOL hasDoneFinalRedirect_; + + // Set during the pop initiated by the sign-in object; otherwise, + // viewWillDisappear indicates that some external change of the view + // has stopped the sign-in. + BOOL didDismissSelf_; + + // Work around default cookie policy bug in iOS 7; see comments in viewWillAppear. + NSHTTPCookieAcceptPolicy savedCookiePolicy_; +} + +// the application and service name to use for saving the auth tokens +// to the keychain +@property (nonatomic, copy) NSString *keychainItemName; + +// the keychain item accessibility is a system constant for use +// with kSecAttrAccessible. +// +// Since it's a system constant, we do not need to retain it. +@property (nonatomic, assign) CFTypeRef keychainItemAccessibility; + +// optional html string displayed immediately upon opening the web view +// +// This string is visible just until the sign-in web page loads, and +// may be used for a "Loading..." type of message or to set the +// initial view color +@property (nonatomic, copy) NSString *initialHTMLString; + +// an activity indicator shows during initial webview load when no initial HTML +// string is specified, but the activity indicator can be forced to be shown +// with this property +@property (nonatomic, assign) BOOL showsInitialActivityIndicator; + +// the underlying object to hold authentication tokens and authorize http +// requests +@property (nonatomic, retain, readonly) GTMOAuth2Authentication *authentication; + +// the underlying object which performs the sign-in networking sequence +@property (nonatomic, retain, readonly) GTMOAuth2SignIn *signIn; + +// user interface elements +@property (nonatomic, retain) IBOutlet UIButton *backButton; +@property (nonatomic, retain) IBOutlet UIButton *forwardButton; +@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *initialActivityIndicator; +@property (nonatomic, retain) IBOutlet UIView *navButtonsView; +@property (nonatomic, retain) IBOutlet UIBarButtonItem *rightBarButtonItem; +@property (nonatomic, retain) IBOutlet UIWebView *webView; + +#if NS_BLOCKS_AVAILABLE +// An optional block to be called when the view should be popped. If not set, +// the view controller will use its navigation controller to pop the view. +@property (nonatomic, copy) void (^popViewBlock)(void); +#endif + +// the default timeout for an unreachable network during display of the +// sign-in page is 30 seconds; set this to 0 to have no timeout +@property (nonatomic, assign) NSTimeInterval networkLossTimeoutInterval; + +// if set, cookies are deleted for this URL when the view is hidden +// +// This is now vestigial and ignored; all cookies are temporarily removed +// from cookie storage when sign-in begins. +@property (nonatomic, retain) NSURL *browserCookiesURL; + +// userData is retained for the convenience of the caller +@property (nonatomic, retain) id userData; + +// Stored property values are retained for the convenience of the caller +- (void)setProperty:(id)obj forKey:(NSString *)key; +- (id)propertyForKey:(NSString *)key; + +@property (nonatomic, retain) NSDictionary *properties; + +// Method for creating a controller to authenticate to Google services +// +// scope is the requested scope of authorization +// (like "http://www.google.com/m8/feeds") +// +// keychain item name is used for storing the token on the keychain, +// keychainItemName should be like "My Application: Google Latitude" +// (or set to nil if no persistent keychain storage is desired) +// +// the delegate is retained only until the finished selector is invoked +// or the sign-in is canceled +// +// If you don't like the default nibName and bundle, you can change them +// using the UIViewController properties once you've made one of these. +// +// finishedSelector is called after authentication completes. It should follow +// this signature. +// +// - (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController +// finishedWithAuth:(GTMOAuth2Authentication *)auth +// error:(NSError *)error; +// +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (id)controllerWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector; + +- (id)initWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector; + +#if NS_BLOCKS_AVAILABLE ++ (id)controllerWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler; + +- (id)initWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler; +#endif +#endif + +// Create a controller for authenticating to non-Google services, taking +// explicit endpoint URLs and an authentication object ++ (id)controllerWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName // may be nil + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector; + +// This is the designated initializer +- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector; + +#if NS_BLOCKS_AVAILABLE ++ (id)controllerWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName // may be nil + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler; + +- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler; +#endif + +// subclasses may override authNibName to specify a custom name ++ (NSString *)authNibName; + +// subclasses may override authNibBundle to specify a custom bundle ++ (NSBundle *)authNibBundle; + +// subclasses may override setUpNavigation to provide their own navigation +// controls +- (void)setUpNavigation; + +// Swaps out the system cookies. The default implementation saves the system +// cookies and then switches to the cookies used for sign-in, initally empty. +// +// subclasses may override swapOutCookies to implement their own cookie +// management scheme. +- (void)swapOutCookies; + +// Swaps in the system cookies that were swapped out. The default implementation +// saves the cookies used for sign-in and then restores the system cookies +// that were saved in |swapOutCookies|. +// +// subclasses may override swapInCookies to implement their own cookie +// management scheme. +- (void)swapInCookies; + +// apps may replace the sign-in class with their own subclass of it ++ (Class)signInClass; ++ (void)setSignInClass:(Class)theClass; + +- (void)cancelSigningIn; + +// revocation of an authorized token from Google +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (void)revokeTokenForGoogleAuthentication:(GTMOAuth2Authentication *)auth; +#endif + +// +// Keychain +// + +// create an authentication object for Google services from the access +// token and secret stored in the keychain; if no token is available, return +// an unauthorized auth object. OK to pass NULL for the error parameter. +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (GTMOAuth2Authentication *)authForGoogleFromKeychainForName:(NSString *)keychainItemName + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + error:(NSError **)error; +// Equivalent to calling the method above with a NULL error parameter. ++ (GTMOAuth2Authentication *)authForGoogleFromKeychainForName:(NSString *)keychainItemName + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret; +#endif + +// add tokens from the keychain, if available, to the authentication object +// +// returns YES if the authentication object was authorized from the keychain ++ (BOOL)authorizeFromKeychainForName:(NSString *)keychainItemName + authentication:(GTMOAuth2Authentication *)auth + error:(NSError **)error; + +// method for deleting the stored access token and secret, useful for "signing +// out" ++ (BOOL)removeAuthFromKeychainForName:(NSString *)keychainItemName; + +// method for saving the stored access token and secret +// +// returns YES if the save was successful. OK to pass NULL for the error +// parameter. ++ (BOOL)saveParamsToKeychainForName:(NSString *)keychainItemName + accessibility:(CFTypeRef)accessibility + authentication:(GTMOAuth2Authentication *)auth + error:(NSError **)error; + +// older version, defaults to kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly ++ (BOOL)saveParamsToKeychainForName:(NSString *)keychainItemName + authentication:(GTMOAuth2Authentication *)auth; + +@end + +// To function, GTMOAuth2ViewControllerTouch needs a certain amount of access +// to the iPhone's keychain. To keep things simple, its keychain access is +// broken out into a helper class. We declare it here in case you'd like to use +// it too, to store passwords. + +enum { + kGTMOAuth2KeychainErrorBadArguments = -1301, + kGTMOAuth2KeychainErrorNoPassword = -1302 +}; + + +@interface GTMOAuth2Keychain : NSObject + ++ (GTMOAuth2Keychain *)defaultKeychain; + +// OK to pass nil for the error parameter. +- (NSString *)passwordForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error; + +// OK to pass nil for the error parameter. +- (BOOL)removePasswordForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error; + +// OK to pass nil for the error parameter. +// +// accessibility should be one of the constants for kSecAttrAccessible +// such as kSecAttrAccessibleWhenUnlocked +- (BOOL)setPassword:(NSString *)password + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + error:(NSError **)error; + +// For unit tests: allow setting a mock object ++ (void)setDefaultKeychain:(GTMOAuth2Keychain *)keychain; + +@end + +#endif // TARGET_OS_IPHONE + +#endif // #if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewControllerTouch.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewControllerTouch.m new file mode 100755 index 0000000..976e6cf --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewControllerTouch.m @@ -0,0 +1,1104 @@ +/* Copyright (c) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// GTMOAuth2ViewControllerTouch.m +// + +#import +#import + +#if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES + +#if TARGET_OS_IPHONE + +#import "GTMOAuth2ViewControllerTouch.h" + +#import "GTMOAuth2SignIn.h" +#import "GTMOAuth2Authentication.h" + +NSString *const kGTMOAuth2KeychainErrorDomain = @"com.google.GTMOAuthKeychain"; + +NSString *const kGTMOAuth2CookiesWillSwapOut = @"kGTMOAuth2CookiesWillSwapOut"; +NSString *const kGTMOAuth2CookiesDidSwapIn = @"kGTMOAuth2CookiesDidSwapIn"; + +static NSString * const kGTMOAuth2AccountName = @"OAuth"; +static GTMOAuth2Keychain* gGTMOAuth2DefaultKeychain = nil; + +@interface GTMOAuth2ViewControllerTouch() +@property (nonatomic, copy) NSURLRequest *request; +@property (nonatomic, copy) NSArray *systemCookies; +@property (nonatomic, copy) NSArray *signInCookies; +@end + +@implementation GTMOAuth2ViewControllerTouch + +// IBOutlets +@synthesize request = request_, + systemCookies = systemCookies_, + signInCookies = signInCookies_, + backButton = backButton_, + forwardButton = forwardButton_, + navButtonsView = navButtonsView_, + rightBarButtonItem = rightBarButtonItem_, + webView = webView_, + initialActivityIndicator = initialActivityIndicator_; + +@synthesize keychainItemName = keychainItemName_, + keychainItemAccessibility = keychainItemAccessibility_, + initialHTMLString = initialHTMLString_, + browserCookiesURL = browserCookiesURL_, + signIn = signIn_, + userData = userData_, + properties = properties_; + +#if NS_BLOCKS_AVAILABLE +@synthesize popViewBlock = popViewBlock_; +#endif + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (id)controllerWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector { + return [[[self alloc] initWithScope:scope + clientID:clientID + clientSecret:clientSecret + keychainItemName:keychainItemName + delegate:delegate + finishedSelector:finishedSelector] autorelease]; +} + +- (id)initWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector { + // convenient entry point for Google authentication + + Class signInClass = [[self class] signInClass]; + + GTMOAuth2Authentication *auth; + auth = [signInClass standardGoogleAuthenticationForScope:scope + clientID:clientID + clientSecret:clientSecret]; + NSURL *authorizationURL = [signInClass googleAuthorizationURL]; + return [self initWithAuthentication:auth + authorizationURL:authorizationURL + keychainItemName:keychainItemName + delegate:delegate + finishedSelector:finishedSelector]; +} + +#if NS_BLOCKS_AVAILABLE + ++ (id)controllerWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler { + return [[[self alloc] initWithScope:scope + clientID:clientID + clientSecret:clientSecret + keychainItemName:keychainItemName + completionHandler:handler] autorelease]; +} + +- (id)initWithScope:(NSString *)scope + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + keychainItemName:(NSString *)keychainItemName + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler { + // convenient entry point for Google authentication + + Class signInClass = [[self class] signInClass]; + + GTMOAuth2Authentication *auth; + auth = [signInClass standardGoogleAuthenticationForScope:scope + clientID:clientID + clientSecret:clientSecret]; + NSURL *authorizationURL = [signInClass googleAuthorizationURL]; + self = [self initWithAuthentication:auth + authorizationURL:authorizationURL + keychainItemName:keychainItemName + delegate:nil + finishedSelector:NULL]; + if (self) { + completionBlock_ = [handler copy]; + } + return self; +} + +#endif // NS_BLOCKS_AVAILABLE +#endif // !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + ++ (id)controllerWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector { + return [[[self alloc] initWithAuthentication:auth + authorizationURL:authorizationURL + keychainItemName:keychainItemName + delegate:delegate + finishedSelector:finishedSelector] autorelease]; +} + +- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName + delegate:(id)delegate + finishedSelector:(SEL)finishedSelector { + + NSString *nibName = [[self class] authNibName]; + NSBundle *nibBundle = [[self class] authNibBundle]; + + self = [super initWithNibName:nibName bundle:nibBundle]; + if (self != nil) { + delegate_ = [delegate retain]; + finishedSelector_ = finishedSelector; + + Class signInClass = [[self class] signInClass]; + + // use the supplied auth and OAuth endpoint URLs + signIn_ = [[signInClass alloc] initWithAuthentication:auth + authorizationURL:authorizationURL + delegate:self + webRequestSelector:@selector(signIn:displayRequest:) + finishedSelector:@selector(signIn:finishedWithAuth:error:)]; + + [self setKeychainItemName:keychainItemName]; + + savedCookiePolicy_ = (NSHTTPCookieAcceptPolicy)NSUIntegerMax; + } + return self; +} + +#if NS_BLOCKS_AVAILABLE ++ (id)controllerWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler { + return [[[self alloc] initWithAuthentication:auth + authorizationURL:authorizationURL + keychainItemName:keychainItemName + completionHandler:handler] autorelease]; +} + +- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth + authorizationURL:(NSURL *)authorizationURL + keychainItemName:(NSString *)keychainItemName + completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler { + // fall back to the non-blocks init + self = [self initWithAuthentication:auth + authorizationURL:authorizationURL + keychainItemName:keychainItemName + delegate:nil + finishedSelector:NULL]; + if (self) { + completionBlock_ = [handler copy]; + } + return self; +} +#endif + +- (void)dealloc { + [webView_ setDelegate:nil]; + + [backButton_ release]; + [forwardButton_ release]; + [initialActivityIndicator_ release]; + [navButtonsView_ release]; + [rightBarButtonItem_ release]; + [webView_ stopLoading]; + [webView_ release]; + [signIn_ release]; + [request_ release]; + [systemCookies_ release]; + [signInCookies_ release]; + [delegate_ release]; +#if NS_BLOCKS_AVAILABLE + [completionBlock_ release]; + [popViewBlock_ release]; +#endif + [keychainItemName_ release]; + [initialHTMLString_ release]; + [browserCookiesURL_ release]; + [userData_ release]; + [properties_ release]; + + [super dealloc]; +} + ++ (NSString *)authNibName { + // subclasses may override this to specify a custom nib name + return @"GTMOAuth2ViewTouch"; +} + ++ (NSBundle *)authNibBundle { + // subclasses may override this to specify a custom nib bundle + return nil; +} + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (GTMOAuth2Authentication *)authForGoogleFromKeychainForName:(NSString *)keychainItemName + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret { + return [self authForGoogleFromKeychainForName:keychainItemName + clientID:clientID + clientSecret:clientSecret + error:NULL]; +} + ++ (GTMOAuth2Authentication *)authForGoogleFromKeychainForName:(NSString *)keychainItemName + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret + error:(NSError **)error { + Class signInClass = [self signInClass]; + NSURL *tokenURL = [signInClass googleTokenURL]; + NSString *redirectURI = [signInClass nativeClientRedirectURI]; + + GTMOAuth2Authentication *auth; + auth = [GTMOAuth2Authentication authenticationWithServiceProvider:kGTMOAuth2ServiceProviderGoogle + tokenURL:tokenURL + redirectURI:redirectURI + clientID:clientID + clientSecret:clientSecret]; + [[self class] authorizeFromKeychainForName:keychainItemName + authentication:auth + error:error]; + return auth; +} + +#endif + ++ (BOOL)authorizeFromKeychainForName:(NSString *)keychainItemName + authentication:(GTMOAuth2Authentication *)newAuth + error:(NSError **)error { + newAuth.accessToken = nil; + + BOOL didGetTokens = NO; + GTMOAuth2Keychain *keychain = [GTMOAuth2Keychain defaultKeychain]; + NSString *password = [keychain passwordForService:keychainItemName + account:kGTMOAuth2AccountName + error:error]; + if (password != nil) { + [newAuth setKeysForResponseString:password]; + didGetTokens = YES; + } + return didGetTokens; +} + ++ (BOOL)removeAuthFromKeychainForName:(NSString *)keychainItemName { + GTMOAuth2Keychain *keychain = [GTMOAuth2Keychain defaultKeychain]; + return [keychain removePasswordForService:keychainItemName + account:kGTMOAuth2AccountName + error:nil]; +} + ++ (BOOL)saveParamsToKeychainForName:(NSString *)keychainItemName + authentication:(GTMOAuth2Authentication *)auth { + return [self saveParamsToKeychainForName:keychainItemName + accessibility:NULL + authentication:auth + error:NULL]; +} + ++ (BOOL)saveParamsToKeychainForName:(NSString *)keychainItemName + accessibility:(CFTypeRef)accessibility + authentication:(GTMOAuth2Authentication *)auth + error:(NSError **)error { + [self removeAuthFromKeychainForName:keychainItemName]; + // don't save unless we have a token that can really authorize requests + if (![auth canAuthorize]) { + if (error) { + *error = [NSError errorWithDomain:kGTMOAuth2ErrorDomain + code:kGTMOAuth2ErrorTokenUnavailable + userInfo:nil]; + } + return NO; + } + + if (accessibility == NULL + && &kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly != NULL) { + accessibility = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + } + + // make a response string containing the values we want to save + NSString *password = [auth persistenceResponseString]; + GTMOAuth2Keychain *keychain = [GTMOAuth2Keychain defaultKeychain]; + return [keychain setPassword:password + forService:keychainItemName + accessibility:accessibility + account:kGTMOAuth2AccountName + error:error]; +} + +- (void)loadView { + NSString *nibPath = nil; + NSBundle *nibBundle = [self nibBundle]; + if (nibBundle == nil) { + nibBundle = [NSBundle mainBundle]; + } + NSString *nibName = self.nibName; + if (nibName != nil) { + nibPath = [nibBundle pathForResource:nibName ofType:@"nib"]; + } + if (nibPath != nil && [[NSFileManager defaultManager] fileExistsAtPath:nibPath]) { + [super loadView]; + } else { + // One of the requirements of loadView is that a valid view object is set to + // self.view upon completion. Otherwise, subclasses that attempt to + // access self.view after calling [super loadView] will enter an infinite + // loop due to the fact that UIViewController's -view accessor calls + // loadView when self.view is nil. + self.view = [[[UIView alloc] init] autorelease]; + +#if DEBUG + NSLog(@"missing %@.nib", nibName); +#endif + } +} + + +- (void)viewDidLoad { + [super viewDidLoad]; + [self setUpNavigation]; +} + +- (void)setUpNavigation { + rightBarButtonItem_.customView = navButtonsView_; + self.navigationItem.rightBarButtonItem = rightBarButtonItem_; +} + +- (void)popView { +#if NS_BLOCKS_AVAILABLE + void (^popViewBlock)() = self.popViewBlock; +#else + id popViewBlock = nil; +#endif + + if (popViewBlock || self.navigationController.topViewController == self) { + if (!self.view.hidden) { + // Set the flag to our viewWillDisappear method so it knows + // this is a disappearance initiated by the sign-in object, + // not the user cancelling via the navigation controller + didDismissSelf_ = YES; + + if (popViewBlock) { +#if NS_BLOCKS_AVAILABLE + popViewBlock(); + self.popViewBlock = nil; +#endif + } else { + [self.navigationController popViewControllerAnimated:YES]; + } + self.view.hidden = YES; + } + } +} + +- (void)notifyWithName:(NSString *)name + webView:(UIWebView *)webView + kind:(NSString *)kind { + BOOL isStarting = [name isEqual:kGTMOAuth2WebViewStartedLoading]; + if (hasNotifiedWebViewStartedLoading_ == isStarting) { + // Duplicate notification + // + // UIWebView's delegate methods are so unbalanced that there's little + // point trying to keep a count, as it could easily end up stuck greater + // than zero. + // + // We don't really have a way to track the starts and stops of + // subframe loads, too, as the webView in the notification is always + // for the topmost request. + return; + } + hasNotifiedWebViewStartedLoading_ = isStarting; + + // Notification for webview load starting and stopping + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: + webView, kGTMOAuth2WebViewKey, + kind, kGTMOAuth2WebViewStopKindKey, // kind may be nil + nil]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:name + object:self + userInfo:dict]; +} + +- (void)cancelSigningIn { + // The application has explicitly asked us to cancel signing in + // (so no further callback is required) + hasCalledFinished_ = YES; + + [delegate_ autorelease]; + delegate_ = nil; + +#if NS_BLOCKS_AVAILABLE + [completionBlock_ autorelease]; + completionBlock_ = nil; +#endif + + // The sign-in object's cancel method will close the window + [signIn_ cancelSigningIn]; + hasDoneFinalRedirect_ = YES; +} + +static Class gSignInClass = Nil; + ++ (Class)signInClass { + if (gSignInClass == Nil) { + gSignInClass = [GTMOAuth2SignIn class]; + } + return gSignInClass; +} + ++ (void)setSignInClass:(Class)theClass { + gSignInClass = theClass; +} + +#pragma mark Token Revocation + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT ++ (void)revokeTokenForGoogleAuthentication:(GTMOAuth2Authentication *)auth { + [[self signInClass] revokeTokenForGoogleAuthentication:auth]; +} +#endif + +#pragma mark Browser Cookies + +- (GTMOAuth2Authentication *)authentication { + return self.signIn.authentication; +} + +- (void)swapOutCookies { + // Switch to the cookie set used for sign-in, initially empty. + self.systemCookies = [self swapBrowserCookies:self.signInCookies]; +} + +- (void)swapInCookies { + // Switch back to the saved system cookies. + self.signInCookies = [self swapBrowserCookies:self.systemCookies]; +} + +- (NSArray *)swapBrowserCookies:(NSArray *)newCookies { + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + + NSHTTPCookieAcceptPolicy savedPolicy = [cookieStorage cookieAcceptPolicy]; + [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; + + NSArray *priorCookies = [[[cookieStorage cookies] copy] autorelease]; + for (NSHTTPCookie *cookie in priorCookies) { + [cookieStorage deleteCookie:cookie]; + } + for (NSHTTPCookie *cookie in newCookies) { + [cookieStorage setCookie:cookie]; + } + + [cookieStorage setCookieAcceptPolicy:savedPolicy]; + + return priorCookies; +} + +#pragma mark Accessors + +- (void)setNetworkLossTimeoutInterval:(NSTimeInterval)val { + signIn_.networkLossTimeoutInterval = val; +} + +- (NSTimeInterval)networkLossTimeoutInterval { + return signIn_.networkLossTimeoutInterval; +} + +- (BOOL)shouldUseKeychain { + NSString *name = self.keychainItemName; + return ([name length] > 0); +} + +- (BOOL)showsInitialActivityIndicator { + return (mustShowActivityIndicator_ == 1 || initialHTMLString_ == nil); +} + +- (void)setShowsInitialActivityIndicator:(BOOL)flag { + mustShowActivityIndicator_ = (flag ? 1 : -1); +} + +#pragma mark User Properties + +- (void)setProperty:(id)obj forKey:(NSString *)key { + if (obj == nil) { + // User passed in nil, so delete the property + [properties_ removeObjectForKey:key]; + } else { + // Be sure the property dictionary exists + if (properties_ == nil) { + [self setProperties:[NSMutableDictionary dictionary]]; + } + [properties_ setObject:obj forKey:key]; + } +} + +- (id)propertyForKey:(NSString *)key { + id obj = [properties_ objectForKey:key]; + + // Be sure the returned pointer has the life of the autorelease pool, + // in case self is released immediately + return [[obj retain] autorelease]; +} + +#pragma mark SignIn callbacks + +- (void)signIn:(GTMOAuth2SignIn *)signIn displayRequest:(NSURLRequest *)request { + // This is the signIn object's webRequest method, telling the controller + // to either display the request in the webview, or if the request is nil, + // to close the window. + // + // All web requests and all window closing goes through this routine + +#if DEBUG + if (self.navigationController) { + if (self.navigationController.topViewController != self && request != nil) { + NSLog(@"Unexpected: Request to show, when already on top. request %@", [request URL]); + } else if(self.navigationController.topViewController != self && request == nil) { + NSLog(@"Unexpected: Request to pop, when not on top. request nil"); + } + } +#endif + + if (request != nil) { + const NSTimeInterval kJanuary2011 = 1293840000; + BOOL isDateValid = ([[NSDate date] timeIntervalSince1970] > kJanuary2011); + if (isDateValid) { + // Display the request. + self.request = request; + // The app may prefer some html other than blank white to be displayed + // before the sign-in web page loads. + // The first fetch might be slow, so the client programmer may want + // to show a local "loading" message. + // On iOS 5+, UIWebView will ignore loadHTMLString: if it's followed by + // a loadRequest: call, so if there is a "loading" message we defer + // the loadRequest: until after after we've drawn the "loading" message. + // + // If there is no initial html string, we show the activity indicator + // unless the user set showsInitialActivityIndicator to NO; if there + // is an initial html string, we hide the indicator unless the user set + // showsInitialActivityIndicator to YES. + NSString *html = self.initialHTMLString; + if ([html length] > 0) { + [initialActivityIndicator_ setHidden:(mustShowActivityIndicator_ < 1)]; + [self.webView loadHTMLString:html baseURL:nil]; + } else { + [initialActivityIndicator_ setHidden:(mustShowActivityIndicator_ < 0)]; + [self.webView loadRequest:request]; + } + } else { + // clock date is invalid, so signing in would fail with an unhelpful error + // from the server. Warn the user in an html string showing a watch icon, + // question mark, and the system date and time. Hopefully this will clue + // in brighter users, or at least give them a clue when they report the + // problem to developers. + // + // Even better is for apps to check the system clock and show some more + // helpful, localized instructions for users; this is really a fallback. + NSString *const html = @"

" + @"⌚ ?
System Clock Incorrect
%@" + @"
"; + NSString *errHTML = [NSString stringWithFormat:html, [NSDate date]]; + + [[self webView] loadHTMLString:errHTML baseURL:nil]; + } + } else { + // request was nil. + [self popView]; + } +} + +- (void)signIn:(GTMOAuth2SignIn *)signIn + finishedWithAuth:(GTMOAuth2Authentication *)auth + error:(NSError *)error { + if (!hasCalledFinished_) { + hasCalledFinished_ = YES; + + if (error == nil) { + if (self.shouldUseKeychain) { + NSString *keychainItemName = self.keychainItemName; + if (auth.canAuthorize) { + // save the auth params in the keychain + CFTypeRef accessibility = self.keychainItemAccessibility; + [[self class] saveParamsToKeychainForName:keychainItemName + accessibility:accessibility + authentication:auth + error:NULL]; + } else { + // remove the auth params from the keychain + [[self class] removeAuthFromKeychainForName:keychainItemName]; + } + } + } + + if (delegate_ && finishedSelector_) { + SEL sel = finishedSelector_; + NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:delegate_]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&auth atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + } + + [delegate_ autorelease]; + delegate_ = nil; + +#if NS_BLOCKS_AVAILABLE + if (completionBlock_) { + completionBlock_(self, auth, error); + + // release the block here to avoid a retain loop on the controller + [completionBlock_ autorelease]; + completionBlock_ = nil; + } +#endif + } +} + +- (void)moveWebViewFromUnderNavigationBar { + CGRect dontCare; + CGRect webFrame = self.view.bounds; + UINavigationBar *navigationBar = self.navigationController.navigationBar; + CGRectDivide(webFrame, &dontCare, &webFrame, + navigationBar.frame.size.height, CGRectMinYEdge); + [self.webView setFrame:webFrame]; +} + +// isTranslucent is defined in iPhoneOS 3.0 on. +- (BOOL)isNavigationBarTranslucent { + UINavigationBar *navigationBar = [[self navigationController] navigationBar]; + BOOL isTranslucent = + ([navigationBar respondsToSelector:@selector(isTranslucent)] && + [navigationBar isTranslucent]); + return isTranslucent; +} + +#pragma mark - +#pragma mark Protocol implementations + +- (void)viewWillAppear:(BOOL)animated { + // See the comment on clearBrowserCookies in viewWillDisappear. + [[NSNotificationCenter defaultCenter] postNotificationName:kGTMOAuth2CookiesWillSwapOut + object:self + userInfo:nil]; + [self swapOutCookies]; + + if (!isViewShown_) { + isViewShown_ = YES; + if ([self isNavigationBarTranslucent]) { + [self moveWebViewFromUnderNavigationBar]; + } + if (![signIn_ startSigningIn]) { + // Can't start signing in. We must pop our view. + // UIWebview needs time to stabilize. Animations need time to complete. + // We remove ourself from the view stack after that. + [self performSelector:@selector(popView) + withObject:nil + afterDelay:0.5 + inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; + } + + // Work around iOS 7.0 bug described in https://devforums.apple.com/thread/207323 by temporarily + // setting our cookie storage policy to be permissive enough to keep the sign-in server + // satisfied, just in case the app inherited from Safari a policy that blocks all cookies. + NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + NSHTTPCookieAcceptPolicy policy = [storage cookieAcceptPolicy]; + if (policy == NSHTTPCookieAcceptPolicyNever) { + savedCookiePolicy_ = policy; + [storage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain]; + } + } + + [super viewWillAppear:animated]; +} + +- (void)viewDidAppear:(BOOL)animated { + didViewAppear_ = YES; + [super viewDidAppear:animated]; +} + +- (void)viewWillDisappear:(BOOL)animated { + if (![self isBeingObscured:self]) { + if (!didDismissSelf_) { + // We won't receive further webview delegate messages, so be sure the + // started loading notification is balanced, if necessary + [self notifyWithName:kGTMOAuth2WebViewStoppedLoading + webView:self.webView + kind:kGTMOAuth2WebViewCancelled]; + + // We are not popping ourselves, so presumably we are being popped by the + // navigation controller; tell the sign-in object to close up shop + // + // this will indirectly call our signIn:finishedWithAuth:error: method + // for us + [signIn_ windowWasClosed]; + +#if NS_BLOCKS_AVAILABLE + self.popViewBlock = nil; +#endif + } + + if (savedCookiePolicy_ != (NSHTTPCookieAcceptPolicy)NSUIntegerMax) { + NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + [storage setCookieAcceptPolicy:savedCookiePolicy_]; + savedCookiePolicy_ = (NSHTTPCookieAcceptPolicy)NSUIntegerMax; + } + } + + [self swapInCookies]; + [[NSNotificationCenter defaultCenter] postNotificationName:kGTMOAuth2CookiesDidSwapIn + object:self + userInfo:nil]; + [super viewWillDisappear:animated]; +} + +- (BOOL)isBeingObscured:(UIViewController *)vc { + // Check if this view controller, or an ancestor, is being disappearing because + // of being obscured by another view. + if ([vc isBeingDismissed] || [vc isMovingFromParentViewController]) { + return NO; + } + UIViewController *parentVC = vc.parentViewController; + if (parentVC) { + return [self isBeingObscured:parentVC]; + } + return YES; +} + +- (void)viewDidLayoutSubviews { + // We don't call super's version of this method because + // -[UIViewController viewDidLayoutSubviews] is documented as a no-op, that + // didn't exist before iOS 5. + [initialActivityIndicator_ setCenter:[webView_ center]]; +} + +- (BOOL)webView:(UIWebView *)webView + shouldStartLoadWithRequest:(NSURLRequest *)request + navigationType:(UIWebViewNavigationType)navigationType { + + if (!hasDoneFinalRedirect_) { + hasDoneFinalRedirect_ = [signIn_ requestRedirectedToRequest:request]; + if (hasDoneFinalRedirect_) { + // signIn has told the view to close + return NO; + } + } + return YES; +} + +- (void)updateUI { + [backButton_ setEnabled:[[self webView] canGoBack]]; + [forwardButton_ setEnabled:[[self webView] canGoForward]]; +} + +- (void)webViewDidStartLoad:(UIWebView *)webView { + [self notifyWithName:kGTMOAuth2WebViewStartedLoading + webView:webView + kind:nil]; + [self updateUI]; +} + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + [self notifyWithName:kGTMOAuth2WebViewStoppedLoading + webView:webView + kind:kGTMOAuth2WebViewFinished]; + + NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"]; + if ([title length] > 0) { + [signIn_ titleChanged:title]; + } else { +#if DEBUG && !defined(NS_BLOCK_ASSERTIONS) + // Verify that Javascript is enabled + NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"1+1"]; + NSAssert([result integerValue] == 2, @"GTMOAuth2: Javascript is required"); +#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) + } + + if (self.request && [self.initialHTMLString length] > 0) { + // The request was pending. + [self setInitialHTMLString:nil]; + [self.webView loadRequest:self.request]; + } else { + [initialActivityIndicator_ setHidden:YES]; + [signIn_ cookiesChanged:[NSHTTPCookieStorage sharedHTTPCookieStorage]]; + + [self updateUI]; + } +} + +- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { + [self notifyWithName:kGTMOAuth2WebViewStoppedLoading + webView:webView + kind:kGTMOAuth2WebViewFailed]; + + // Tell the sign-in object that a load failed; if it was the authorization + // URL, it will pop the view and return an error to the delegate. + if (didViewAppear_) { + BOOL isUserInterruption = ([error code] == NSURLErrorCancelled + && [[error domain] isEqual:NSURLErrorDomain]); + if (isUserInterruption) { + // Ignore this error: + // Users report that this error occurs when clicking too quickly on the + // accept button, before the page has completely loaded. Ignoring + // this error seems to provide a better experience than does immediately + // cancelling sign-in. + // + // This error also occurs whenever UIWebView is sent the stopLoading + // message, so if we ever send that message intentionally, we need to + // revisit this bypass. + return; + } + + [signIn_ loadFailedWithError:error]; + } else { + // UIWebview needs time to stabilize. Animations need time to complete. + [signIn_ performSelector:@selector(loadFailedWithError:) + withObject:error + afterDelay:0.5 + inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; + } +} + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 +// When running on a device with an OS version < 6, this gets called. +// +// Since it is never called in iOS 6 or greater, if your min deployment +// target is iOS6 or greater, then you don't need to have this method compiled +// into your app. +// +// When running on a device with an OS version 6 or greater, this code is +// not called. - (NSUInteger)supportedInterfaceOrientations; would be called, +// if it existed. Since it is absent, +// Allow the default orientations: All for iPad, all but upside down for iPhone. +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + BOOL value = YES; + if (!isInsideShouldAutorotateToInterfaceOrientation_) { + isInsideShouldAutorotateToInterfaceOrientation_ = YES; + UIViewController *navigationController = [self navigationController]; + if (navigationController != nil) { + value = [navigationController shouldAutorotateToInterfaceOrientation:interfaceOrientation]; + } else { + value = [super shouldAutorotateToInterfaceOrientation:interfaceOrientation]; + } + isInsideShouldAutorotateToInterfaceOrientation_ = NO; + } + return value; +} +#endif + + +@end + + +#pragma mark Common Code + +@implementation GTMOAuth2Keychain + ++ (GTMOAuth2Keychain *)defaultKeychain { + if (gGTMOAuth2DefaultKeychain == nil) { + gGTMOAuth2DefaultKeychain = [[self alloc] init]; + } + return gGTMOAuth2DefaultKeychain; +} + + +// For unit tests: allow setting a mock object ++ (void)setDefaultKeychain:(GTMOAuth2Keychain *)keychain { + if (gGTMOAuth2DefaultKeychain != keychain) { + [gGTMOAuth2DefaultKeychain release]; + gGTMOAuth2DefaultKeychain = [keychain retain]; + } +} + +- (NSString *)keyForService:(NSString *)service account:(NSString *)account { + return [NSString stringWithFormat:@"com.google.GTMOAuth.%@%@", service, account]; +} + +// The Keychain API isn't available on the iPhone simulator in SDKs before 3.0, +// so, on early simulators we use a fake API, that just writes, unencrypted, to +// NSUserDefaults. +#if TARGET_IPHONE_SIMULATOR && __IPHONE_OS_VERSION_MAX_ALLOWED < 30000 +#pragma mark Simulator + +// Simulator - just simulated, not secure. +- (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { + NSString *result = nil; + if (0 < [service length] && 0 < [account length]) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSString *key = [self keyForService:service account:account]; + result = [defaults stringForKey:key]; + if (result == nil && error != NULL) { + *error = [NSError errorWithDomain:kGTMOAuth2KeychainErrorDomain + code:kGTMOAuth2KeychainErrorNoPassword + userInfo:nil]; + } + } else if (error != NULL) { + *error = [NSError errorWithDomain:kGTMOAuth2KeychainErrorDomain + code:kGTMOAuth2KeychainErrorBadArguments + userInfo:nil]; + } + return result; + +} + + +// Simulator - just simulated, not secure. +- (BOOL)removePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { + BOOL didSucceed = NO; + if (0 < [service length] && 0 < [account length]) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSString *key = [self keyForService:service account:account]; + [defaults removeObjectForKey:key]; + [defaults synchronize]; + } else if (error != NULL) { + *error = [NSError errorWithDomain:kGTMOAuth2KeychainErrorDomain + code:kGTMOAuth2KeychainErrorBadArguments + userInfo:nil]; + } + return didSucceed; +} + +// Simulator - just simulated, not secure. +- (BOOL)setPassword:(NSString *)password + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + error:(NSError **)error { + BOOL didSucceed = NO; + if (0 < [password length] && 0 < [service length] && 0 < [account length]) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSString *key = [self keyForService:service account:account]; + [defaults setObject:password forKey:key]; + [defaults synchronize]; + didSucceed = YES; + } else if (error != NULL) { + *error = [NSError errorWithDomain:kGTMOAuth2KeychainErrorDomain + code:kGTMOAuth2KeychainErrorBadArguments + userInfo:nil]; + } + return didSucceed; +} + +#else // ! TARGET_IPHONE_SIMULATOR +#pragma mark Device + ++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys: + (id)kSecClassGenericPassword, (id)kSecClass, + @"OAuth", (id)kSecAttrGeneric, + account, (id)kSecAttrAccount, + service, (id)kSecAttrService, + nil]; + return query; +} + +- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + return [[self class] keychainQueryForService:service account:account]; +} + + + +// iPhone +- (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { + OSStatus status = kGTMOAuth2KeychainErrorBadArguments; + NSString *result = nil; + if (0 < [service length] && 0 < [account length]) { + CFDataRef passwordData = NULL; + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; + [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; + + status = SecItemCopyMatching((CFDictionaryRef)keychainQuery, + (CFTypeRef *)&passwordData); + if (status == noErr && 0 < [(NSData *)passwordData length]) { + result = [[[NSString alloc] initWithData:(NSData *)passwordData + encoding:NSUTF8StringEncoding] autorelease]; + } + if (passwordData != NULL) { + CFRelease(passwordData); + } + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kGTMOAuth2KeychainErrorDomain + code:status + userInfo:nil]; + } + return result; +} + + +// iPhone +- (BOOL)removePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { + OSStatus status = kGTMOAuth2KeychainErrorBadArguments; + if (0 < [service length] && 0 < [account length]) { + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + status = SecItemDelete((CFDictionaryRef)keychainQuery); + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kGTMOAuth2KeychainErrorDomain + code:status + userInfo:nil]; + } + return status == noErr; +} + +// iPhone +- (BOOL)setPassword:(NSString *)password + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + error:(NSError **)error { + OSStatus status = kGTMOAuth2KeychainErrorBadArguments; + if (0 < [service length] && 0 < [account length]) { + [self removePasswordForService:service account:account error:nil]; + if (0 < [password length]) { + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + [keychainQuery setObject:passwordData forKey:(id)kSecValueData]; + + if (accessibility != NULL && &kSecAttrAccessible != NULL) { + [keychainQuery setObject:(id)accessibility + forKey:(id)kSecAttrAccessible]; + } + status = SecItemAdd((CFDictionaryRef)keychainQuery, NULL); + } + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kGTMOAuth2KeychainErrorDomain + code:status + userInfo:nil]; + } + return status == noErr; +} + +#endif // ! TARGET_IPHONE_SIMULATOR + +@end + +#endif // TARGET_OS_IPHONE + +#endif // #if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewTouch.xib b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewTouch.xib new file mode 100755 index 0000000..4f91fa4 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/Pods/gtm-oauth2/Source/Touch/GTMOAuth2ViewTouch.xib @@ -0,0 +1,494 @@ + + + + 1024 + 12C60 + 2840 + 1187.34 + 625.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 1926 + + + YES + IBProxyObject + IBUIActivityIndicatorView + IBUIBarButtonItem + IBUIButton + IBUINavigationItem + IBUIView + IBUIWebView + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + OAuth + IBCocoaTouchFramework + + + IBCocoaTouchFramework + 1 + + + + 292 + + YES + + + 292 + {30, 30} + + + + NO + NO + IBCocoaTouchFramework + 0 + 0 + {0, -2} + + + 3 + MQA + + + 2 + MC41OTYwNzg0NiAwLjY4NjI3NDUzIDAuOTUyOTQxMjQgMC42MDAwMDAwMgA + + + + 3 + MC41AA + + + Helvetica-Bold + Helvetica + 2 + 24 + + + Helvetica-Bold + 24 + 16 + + + + + 292 + {{30, 0}, {30, 30}} + + + + NO + NO + IBCocoaTouchFramework + 0 + 0 + {0, -2} + + + + 2 + MC41ODQzMTM3NSAwLjY3NDUwOTgyIDAuOTUyOTQxMjQgMC42MDAwMDAwMgA + + + + + + + + {60, 30} + + + + + 3 + MSAwAA + + NO + NO + + 3 + 3 + + IBCocoaTouchFramework + + + + 274 + + YES + + + 274 + {320, 460} + + + + + 1 + MSAxIDEAA + + YES + YES + IBCocoaTouchFramework + 1 + YES + + + + 301 + {{150, 115}, {20, 20}} + + + + _NS:9 + NO + IBCocoaTouchFramework + NO + YES + 2 + + + {320, 460} + + + + + 3 + MQA + + 2 + + + IBCocoaTouchFramework + + + + + YES + + + rightBarButtonItem + + + + 20 + + + + navButtonsView + + + + 22 + + + + backButton + + + + 25 + + + + forwardButton + + + + 26 + + + + view + + + + 28 + + + + webView + + + + 29 + + + + initialActivityIndicator + + + + 33 + + + + delegate + + + + 9 + + + + rightBarButtonItem + + + + 14 + + + + goBack + + + 7 + + 18 + + + + goForward + + + 7 + + 19 + + + + + YES + + 0 + + YES + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + YES + + + + + 10 + + + + + 15 + + + YES + + + + + + + 16 + + + + + 17 + + + + + 27 + + + YES + + + + + + + 4 + + + + + 31 + + + + + + + YES + + YES + -1.CustomClassName + -1.IBPluginDependency + -2.CustomClassName + -2.IBPluginDependency + 10.IBPluginDependency + 15.IBPluginDependency + 16.IBPluginDependency + 17.IBPluginDependency + 27.IBPluginDependency + 31.IBPluginDependency + 4.IBPluginDependency + 6.IBPluginDependency + + + YES + GTMOAuth2ViewControllerTouch + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + + + + YES + + + + + 33 + + + + YES + + GTMOAuth2ViewControllerTouch + UIViewController + + YES + + YES + backButton + forwardButton + initialActivityIndicator + navButtonsView + rightBarButtonItem + webView + + + YES + UIButton + UIButton + UIActivityIndicatorView + UIView + UIBarButtonItem + UIWebView + + + + YES + + YES + backButton + forwardButton + initialActivityIndicator + navButtonsView + rightBarButtonItem + webView + + + YES + + backButton + UIButton + + + forwardButton + UIButton + + + initialActivityIndicator + UIActivityIndicatorView + + + navButtonsView + UIView + + + rightBarButtonItem + UIBarButtonItem + + + webView + UIWebView + + + + + IBProjectSource + ./Classes/GTMOAuth2ViewControllerTouch.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 1926 + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcodeproj/project.pbxproj b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcodeproj/project.pbxproj new file mode 100755 index 0000000..4f0b09f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcodeproj/project.pbxproj @@ -0,0 +1,1321 @@ + + + + + archiveVersion + 1 + classes + + objectVersion + 46 + objects + + 2130D19A745D333E0BAB22D7 + + buildActionMask + 2147483647 + files + + inputPaths + + isa + PBXShellScriptBuildPhase + name + Check Pods Manifest.lock + outputPaths + + runOnlyForDeploymentPostprocessing + 0 + shellPath + /bin/sh + shellScript + diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null +if [[ $? != 0 ]] ; then + cat << EOM +error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. +EOM + exit 1 +fi + + showEnvVarsInLog + 0 + + 29BD41CB1AA7E14D00D19857 + + isa + PBXFileReference + lastKnownFileType + folder.assetcatalog + path + Media.xcassets + sourceTree + <group> + + 29BD41CC1AA7E14D00D19857 + + fileRef + 29BD41CB1AA7E14D00D19857 + isa + PBXBuildFile + + 29BD41CD1AA7E14D00D19857 + + fileRef + 29BD41CB1AA7E14D00D19857 + isa + PBXBuildFile + + 29F5A1F51AA7BBD700783492 + + children + + 29F5A2071AA7BBD700783492 + 29F5A2201AA7BBD700783492 + 29F5A2001AA7BBD700783492 + 29F5A1FF1AA7BBD700783492 + E484FB5E6EAE6DF562E4DE8C + + isa + PBXGroup + sourceTree + <group> + + 29F5A1F61AA7BBD700783492 + + attributes + + CLASSPREFIX + QE + LastUpgradeCheck + 0510 + ORGANIZATIONNAME + Google Developers + TargetAttributes + + 29F5A2181AA7BBD700783492 + + TestTargetID + 29F5A1FD1AA7BBD700783492 + + + + buildConfigurationList + 29F5A1F91AA7BBD700783492 + compatibilityVersion + Xcode 3.2 + developmentRegion + English + hasScannedForEncodings + 0 + isa + PBXProject + knownRegions + + en + + mainGroup + 29F5A1F51AA7BBD700783492 + productRefGroup + 29F5A1FF1AA7BBD700783492 + projectDirPath + + projectReferences + + projectRoot + + targets + + 29F5A1FD1AA7BBD700783492 + 29F5A2181AA7BBD700783492 + + + 29F5A1F91AA7BBD700783492 + + buildConfigurations + + 29F5A2281AA7BBD700783492 + 29F5A2291AA7BBD700783492 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + 29F5A1FA1AA7BBD700783492 + + buildActionMask + 2147483647 + files + + 29F5A2361AA7C36F00783492 + 29F5A2121AA7BBD700783492 + 29F5A23B1AA7C49700783492 + 29F5A2321AA7C2B500783492 + 29F5A20E1AA7BBD700783492 + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 29F5A1FB1AA7BBD700783492 + + buildActionMask + 2147483647 + files + + 29F5A2041AA7BBD700783492 + 29F5A2061AA7BBD700783492 + 29F5A2021AA7BBD700783492 + 91395690E091120F59FDE3B7 + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 29F5A1FC1AA7BBD700783492 + + buildActionMask + 2147483647 + files + + 29F5A23E1AA7C82B00783492 + 29F5A20C1AA7BBD700783492 + 29BD41CC1AA7E14D00D19857 + 29F5A2141AA7BBD700783492 + + isa + PBXResourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 29F5A1FD1AA7BBD700783492 + + buildConfigurationList + 29F5A22A1AA7BBD700783492 + buildPhases + + 698465DF8F9136D38816A4BB + 29F5A1FA1AA7BBD700783492 + 29F5A1FB1AA7BBD700783492 + 29F5A1FC1AA7BBD700783492 + BECB89CF7073B3284B0FA3AA + + buildRules + + dependencies + + isa + PBXNativeTarget + name + ios-quickeditor + productName + ios-quickeditor + productReference + 29F5A1FE1AA7BBD700783492 + productType + com.apple.product-type.application + + 29F5A1FE1AA7BBD700783492 + + explicitFileType + wrapper.application + includeInIndex + 0 + isa + PBXFileReference + path + ios-quickeditor.app + sourceTree + BUILT_PRODUCTS_DIR + + 29F5A1FF1AA7BBD700783492 + + children + + 29F5A1FE1AA7BBD700783492 + 29F5A2191AA7BBD700783492 + + isa + PBXGroup + name + Products + sourceTree + <group> + + 29F5A2001AA7BBD700783492 + + children + + 29F5A2011AA7BBD700783492 + 29F5A2031AA7BBD700783492 + 29F5A2051AA7BBD700783492 + 29F5A21A1AA7BBD700783492 + 2EA1417AA2B38AB75FF12D54 + + isa + PBXGroup + name + Frameworks + sourceTree + <group> + + 29F5A2011AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + Foundation.framework + path + System/Library/Frameworks/Foundation.framework + sourceTree + SDKROOT + + 29F5A2021AA7BBD700783492 + + fileRef + 29F5A2011AA7BBD700783492 + isa + PBXBuildFile + + 29F5A2031AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreGraphics.framework + path + System/Library/Frameworks/CoreGraphics.framework + sourceTree + SDKROOT + + 29F5A2041AA7BBD700783492 + + fileRef + 29F5A2031AA7BBD700783492 + isa + PBXBuildFile + + 29F5A2051AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + UIKit.framework + path + System/Library/Frameworks/UIKit.framework + sourceTree + SDKROOT + + 29F5A2061AA7BBD700783492 + + fileRef + 29F5A2051AA7BBD700783492 + isa + PBXBuildFile + + 29F5A2071AA7BBD700783492 + + children + + 29F5A2101AA7BBD700783492 + 29F5A2111AA7BBD700783492 + 29F5A2131AA7BBD700783492 + 29F5A2081AA7BBD700783492 + 29F5A2301AA7C2B500783492 + 29F5A2311AA7C2B500783492 + 29F5A2341AA7C36F00783492 + 29F5A2351AA7C36F00783492 + 29F5A2381AA7C44500783492 + 29F5A2391AA7C49700783492 + 29F5A23A1AA7C49700783492 + 29F5A23D1AA7C82B00783492 + 29BD41CB1AA7E14D00D19857 + + isa + PBXGroup + path + ios-quickeditor + sourceTree + <group> + + 29F5A2081AA7BBD700783492 + + children + + 29F5A2091AA7BBD700783492 + 29F5A20A1AA7BBD700783492 + 29F5A20D1AA7BBD700783492 + 29F5A20F1AA7BBD700783492 + + isa + PBXGroup + name + Supporting Files + sourceTree + <group> + + 29F5A2091AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + text.plist.xml + path + ios-quickeditor-Info.plist + sourceTree + <group> + + 29F5A20A1AA7BBD700783492 + + children + + 29F5A20B1AA7BBD700783492 + + isa + PBXVariantGroup + name + InfoPlist.strings + sourceTree + <group> + + 29F5A20B1AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + text.plist.strings + name + en + path + en.lproj/InfoPlist.strings + sourceTree + <group> + + 29F5A20C1AA7BBD700783492 + + fileRef + 29F5A20A1AA7BBD700783492 + isa + PBXBuildFile + + 29F5A20D1AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + main.m + sourceTree + <group> + + 29F5A20E1AA7BBD700783492 + + fileRef + 29F5A20D1AA7BBD700783492 + isa + PBXBuildFile + + 29F5A20F1AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + ios-quickeditor-Prefix.pch + sourceTree + <group> + + 29F5A2101AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + QEAppDelegate.h + sourceTree + <group> + + 29F5A2111AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + QEAppDelegate.m + sourceTree + <group> + + 29F5A2121AA7BBD700783492 + + fileRef + 29F5A2111AA7BBD700783492 + isa + PBXBuildFile + + 29F5A2131AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + folder.assetcatalog + path + Images.xcassets + sourceTree + <group> + + 29F5A2141AA7BBD700783492 + + fileRef + 29F5A2131AA7BBD700783492 + isa + PBXBuildFile + + 29F5A2151AA7BBD700783492 + + buildActionMask + 2147483647 + files + + 29F5A2331AA7C2B500783492 + 29F5A2271AA7BBD700783492 + 29F5A23C1AA7C49700783492 + 29F5A2371AA7C36F00783492 + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 29F5A2161AA7BBD700783492 + + buildActionMask + 2147483647 + files + + 29F5A21B1AA7BBD700783492 + 29F5A21D1AA7BBD700783492 + 29F5A21C1AA7BBD700783492 + 8B820E3B59DE7C30EC85EEAC + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 29F5A2171AA7BBD700783492 + + buildActionMask + 2147483647 + files + + 29F5A23F1AA7C82B00783492 + 29BD41CD1AA7E14D00D19857 + 29F5A2251AA7BBD700783492 + + isa + PBXResourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + 29F5A2181AA7BBD700783492 + + buildConfigurationList + 29F5A22D1AA7BBD700783492 + buildPhases + + 2130D19A745D333E0BAB22D7 + 29F5A2151AA7BBD700783492 + 29F5A2161AA7BBD700783492 + 29F5A2171AA7BBD700783492 + 6736D994DC2A3B0DD1C7A707 + + buildRules + + dependencies + + 29F5A21F1AA7BBD700783492 + + isa + PBXNativeTarget + name + ios-quickeditorTests + productName + ios-quickeditorTests + productReference + 29F5A2191AA7BBD700783492 + productType + com.apple.product-type.bundle.unit-test + + 29F5A2191AA7BBD700783492 + + explicitFileType + wrapper.cfbundle + includeInIndex + 0 + isa + PBXFileReference + path + ios-quickeditorTests.xctest + sourceTree + BUILT_PRODUCTS_DIR + + 29F5A21A1AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + XCTest.framework + path + Library/Frameworks/XCTest.framework + sourceTree + DEVELOPER_DIR + + 29F5A21B1AA7BBD700783492 + + fileRef + 29F5A21A1AA7BBD700783492 + isa + PBXBuildFile + + 29F5A21C1AA7BBD700783492 + + fileRef + 29F5A2011AA7BBD700783492 + isa + PBXBuildFile + + 29F5A21D1AA7BBD700783492 + + fileRef + 29F5A2051AA7BBD700783492 + isa + PBXBuildFile + + 29F5A21E1AA7BBD700783492 + + containerPortal + 29F5A1F61AA7BBD700783492 + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + 29F5A1FD1AA7BBD700783492 + remoteInfo + ios-quickeditor + + 29F5A21F1AA7BBD700783492 + + isa + PBXTargetDependency + target + 29F5A1FD1AA7BBD700783492 + targetProxy + 29F5A21E1AA7BBD700783492 + + 29F5A2201AA7BBD700783492 + + children + + 29F5A2261AA7BBD700783492 + 29F5A2211AA7BBD700783492 + + isa + PBXGroup + path + ios-quickeditorTests + sourceTree + <group> + + 29F5A2211AA7BBD700783492 + + children + + 29F5A2221AA7BBD700783492 + 29F5A2231AA7BBD700783492 + + isa + PBXGroup + name + Supporting Files + sourceTree + <group> + + 29F5A2221AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + text.plist.xml + path + ios-quickeditorTests-Info.plist + sourceTree + <group> + + 29F5A2231AA7BBD700783492 + + children + + 29F5A2241AA7BBD700783492 + + isa + PBXVariantGroup + name + InfoPlist.strings + sourceTree + <group> + + 29F5A2241AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + text.plist.strings + name + en + path + en.lproj/InfoPlist.strings + sourceTree + <group> + + 29F5A2251AA7BBD700783492 + + fileRef + 29F5A2231AA7BBD700783492 + isa + PBXBuildFile + + 29F5A2261AA7BBD700783492 + + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + ios_quickeditorTests.m + sourceTree + <group> + + 29F5A2271AA7BBD700783492 + + fileRef + 29F5A2261AA7BBD700783492 + isa + PBXBuildFile + + 29F5A2281AA7BBD700783492 + + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + CLANG_CXX_LANGUAGE_STANDARD + gnu++0x + CLANG_CXX_LIBRARY + libc++ + CLANG_ENABLE_MODULES + YES + CLANG_ENABLE_OBJC_ARC + YES + CLANG_WARN_BOOL_CONVERSION + YES + CLANG_WARN_CONSTANT_CONVERSION + YES + CLANG_WARN_DIRECT_OBJC_ISA_USAGE + YES_ERROR + CLANG_WARN_EMPTY_BODY + YES + CLANG_WARN_ENUM_CONVERSION + YES + CLANG_WARN_INT_CONVERSION + YES + CLANG_WARN_OBJC_ROOT_CLASS + YES_ERROR + CLANG_WARN__DUPLICATE_METHOD_MATCH + YES + CODE_SIGN_IDENTITY[sdk=iphoneos*] + iPhone Developer + COPY_PHASE_STRIP + NO + GCC_C_LANGUAGE_STANDARD + gnu99 + GCC_DYNAMIC_NO_PIC + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_PREPROCESSOR_DEFINITIONS + + DEBUG=1 + $(inherited) + + GCC_SYMBOLS_PRIVATE_EXTERN + NO + GCC_WARN_64_TO_32_BIT_CONVERSION + YES + GCC_WARN_ABOUT_RETURN_TYPE + YES_ERROR + GCC_WARN_UNDECLARED_SELECTOR + YES + GCC_WARN_UNINITIALIZED_AUTOS + YES_AGGRESSIVE + GCC_WARN_UNUSED_FUNCTION + YES + GCC_WARN_UNUSED_VARIABLE + YES + IPHONEOS_DEPLOYMENT_TARGET + 7.1 + ONLY_ACTIVE_ARCH + YES + SDKROOT + iphoneos + TARGETED_DEVICE_FAMILY + 1,2 + + isa + XCBuildConfiguration + name + Debug + + 29F5A2291AA7BBD700783492 + + buildSettings + + ALWAYS_SEARCH_USER_PATHS + NO + CLANG_CXX_LANGUAGE_STANDARD + gnu++0x + CLANG_CXX_LIBRARY + libc++ + CLANG_ENABLE_MODULES + YES + CLANG_ENABLE_OBJC_ARC + YES + CLANG_WARN_BOOL_CONVERSION + YES + CLANG_WARN_CONSTANT_CONVERSION + YES + CLANG_WARN_DIRECT_OBJC_ISA_USAGE + YES_ERROR + CLANG_WARN_EMPTY_BODY + YES + CLANG_WARN_ENUM_CONVERSION + YES + CLANG_WARN_INT_CONVERSION + YES + CLANG_WARN_OBJC_ROOT_CLASS + YES_ERROR + CLANG_WARN__DUPLICATE_METHOD_MATCH + YES + CODE_SIGN_IDENTITY[sdk=iphoneos*] + iPhone Developer + COPY_PHASE_STRIP + YES + ENABLE_NS_ASSERTIONS + NO + GCC_C_LANGUAGE_STANDARD + gnu99 + GCC_WARN_64_TO_32_BIT_CONVERSION + YES + GCC_WARN_ABOUT_RETURN_TYPE + YES_ERROR + GCC_WARN_UNDECLARED_SELECTOR + YES + GCC_WARN_UNINITIALIZED_AUTOS + YES_AGGRESSIVE + GCC_WARN_UNUSED_FUNCTION + YES + GCC_WARN_UNUSED_VARIABLE + YES + IPHONEOS_DEPLOYMENT_TARGET + 7.1 + SDKROOT + iphoneos + TARGETED_DEVICE_FAMILY + 1,2 + VALIDATE_PRODUCT + YES + + isa + XCBuildConfiguration + name + Release + + 29F5A22A1AA7BBD700783492 + + buildConfigurations + + 29F5A22B1AA7BBD700783492 + 29F5A22C1AA7BBD700783492 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + 29F5A22B1AA7BBD700783492 + + baseConfigurationReference + 9B542E2340F3F3B63F0576C9 + buildSettings + + ASSETCATALOG_COMPILER_APPICON_NAME + AppIcon + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME + LaunchImage + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + ios-quickeditor/ios-quickeditor-Prefix.pch + INFOPLIST_FILE + ios-quickeditor/ios-quickeditor-Info.plist + PRODUCT_NAME + $(TARGET_NAME) + WRAPPER_EXTENSION + app + + isa + XCBuildConfiguration + name + Debug + + 29F5A22C1AA7BBD700783492 + + baseConfigurationReference + CC2F7BE63867536DA09EF5E2 + buildSettings + + ASSETCATALOG_COMPILER_APPICON_NAME + AppIcon + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME + LaunchImage + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + ios-quickeditor/ios-quickeditor-Prefix.pch + INFOPLIST_FILE + ios-quickeditor/ios-quickeditor-Info.plist + PRODUCT_NAME + $(TARGET_NAME) + WRAPPER_EXTENSION + app + + isa + XCBuildConfiguration + name + Release + + 29F5A22D1AA7BBD700783492 + + buildConfigurations + + 29F5A22E1AA7BBD700783492 + 29F5A22F1AA7BBD700783492 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + 29F5A22E1AA7BBD700783492 + + baseConfigurationReference + 9B542E2340F3F3B63F0576C9 + buildSettings + + BUNDLE_LOADER + $(BUILT_PRODUCTS_DIR)/ios-quickeditor.app/ios-quickeditor + FRAMEWORK_SEARCH_PATHS + + $(SDKROOT)/Developer/Library/Frameworks + $(inherited) + $(DEVELOPER_FRAMEWORKS_DIR) + + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + ios-quickeditor/ios-quickeditor-Prefix.pch + GCC_PREPROCESSOR_DEFINITIONS + + DEBUG=1 + $(inherited) + + INFOPLIST_FILE + ios-quickeditorTests/ios-quickeditorTests-Info.plist + PRODUCT_NAME + $(TARGET_NAME) + TEST_HOST + $(BUNDLE_LOADER) + WRAPPER_EXTENSION + xctest + + isa + XCBuildConfiguration + name + Debug + + 29F5A22F1AA7BBD700783492 + + baseConfigurationReference + CC2F7BE63867536DA09EF5E2 + buildSettings + + BUNDLE_LOADER + $(BUILT_PRODUCTS_DIR)/ios-quickeditor.app/ios-quickeditor + FRAMEWORK_SEARCH_PATHS + + $(SDKROOT)/Developer/Library/Frameworks + $(inherited) + $(DEVELOPER_FRAMEWORKS_DIR) + + GCC_PRECOMPILE_PREFIX_HEADER + YES + GCC_PREFIX_HEADER + ios-quickeditor/ios-quickeditor-Prefix.pch + INFOPLIST_FILE + ios-quickeditorTests/ios-quickeditorTests-Info.plist + PRODUCT_NAME + $(TARGET_NAME) + TEST_HOST + $(BUNDLE_LOADER) + WRAPPER_EXTENSION + xctest + + isa + XCBuildConfiguration + name + Release + + 29F5A2301AA7C2B500783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + QEUtilities.h + sourceTree + <group> + + 29F5A2311AA7C2B500783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + QEUtilities.m + sourceTree + <group> + + 29F5A2321AA7C2B500783492 + + fileRef + 29F5A2311AA7C2B500783492 + isa + PBXBuildFile + + 29F5A2331AA7C2B500783492 + + fileRef + 29F5A2311AA7C2B500783492 + isa + PBXBuildFile + + 29F5A2341AA7C36F00783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + QEFileEditViewController.h + sourceTree + <group> + + 29F5A2351AA7C36F00783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + QEFileEditViewController.m + sourceTree + <group> + + 29F5A2361AA7C36F00783492 + + fileRef + 29F5A2351AA7C36F00783492 + isa + PBXBuildFile + + 29F5A2371AA7C36F00783492 + + fileRef + 29F5A2351AA7C36F00783492 + isa + PBXBuildFile + + 29F5A2381AA7C44500783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + QEFileEditDelegate.h + sourceTree + <group> + + 29F5A2391AA7C49700783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + path + QEFilesListViewController.h + sourceTree + <group> + + 29F5A23A1AA7C49700783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.objc + path + QEFilesListViewController.m + sourceTree + <group> + + 29F5A23B1AA7C49700783492 + + fileRef + 29F5A23A1AA7C49700783492 + isa + PBXBuildFile + + 29F5A23C1AA7C49700783492 + + fileRef + 29F5A23A1AA7C49700783492 + isa + PBXBuildFile + + 29F5A23D1AA7C82B00783492 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + file.storyboard + path + MainStoryboard.storyboard + sourceTree + <group> + + 29F5A23E1AA7C82B00783492 + + fileRef + 29F5A23D1AA7C82B00783492 + isa + PBXBuildFile + + 29F5A23F1AA7C82B00783492 + + fileRef + 29F5A23D1AA7C82B00783492 + isa + PBXBuildFile + + 2EA1417AA2B38AB75FF12D54 + + explicitFileType + archive.ar + includeInIndex + 0 + isa + PBXFileReference + path + libPods.a + sourceTree + BUILT_PRODUCTS_DIR + + 6736D994DC2A3B0DD1C7A707 + + buildActionMask + 2147483647 + files + + inputPaths + + isa + PBXShellScriptBuildPhase + name + Copy Pods Resources + outputPaths + + runOnlyForDeploymentPostprocessing + 0 + shellPath + /bin/sh + shellScript + "${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh" + + showEnvVarsInLog + 0 + + 698465DF8F9136D38816A4BB + + buildActionMask + 2147483647 + files + + inputPaths + + isa + PBXShellScriptBuildPhase + name + Check Pods Manifest.lock + outputPaths + + runOnlyForDeploymentPostprocessing + 0 + shellPath + /bin/sh + shellScript + diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null +if [[ $? != 0 ]] ; then + cat << EOM +error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. +EOM + exit 1 +fi + + showEnvVarsInLog + 0 + + 8B820E3B59DE7C30EC85EEAC + + fileRef + 2EA1417AA2B38AB75FF12D54 + isa + PBXBuildFile + + 91395690E091120F59FDE3B7 + + fileRef + 2EA1417AA2B38AB75FF12D54 + isa + PBXBuildFile + + 9B542E2340F3F3B63F0576C9 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + name + Pods.debug.xcconfig + path + Pods/Target Support Files/Pods/Pods.debug.xcconfig + sourceTree + <group> + + BECB89CF7073B3284B0FA3AA + + buildActionMask + 2147483647 + files + + inputPaths + + isa + PBXShellScriptBuildPhase + name + Copy Pods Resources + outputPaths + + runOnlyForDeploymentPostprocessing + 0 + shellPath + /bin/sh + shellScript + "${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh" + + showEnvVarsInLog + 0 + + CC2F7BE63867536DA09EF5E2 + + includeInIndex + 1 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + name + Pods.release.xcconfig + path + Pods/Target Support Files/Pods/Pods.release.xcconfig + sourceTree + <group> + + E484FB5E6EAE6DF562E4DE8C + + children + + 9B542E2340F3F3B63F0576C9 + CC2F7BE63867536DA09EF5E2 + + isa + PBXGroup + name + Pods + sourceTree + <group> + + + rootObject + 29F5A1F61AA7BBD700783492 + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..216977a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcworkspace/contents.xcworkspacedata b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..50df987 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Images.xcassets/AppIcon.appiconset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..b7f3352 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Images.xcassets/LaunchImage.launchimage/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100755 index 0000000..6f870a4 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,51 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "subtype" : "retina4", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/MainStoryboard.storyboard b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/MainStoryboard.storyboard new file mode 100755 index 0000000..531fd8c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/MainStoryboard.storyboard @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/Contents.json new file mode 100755 index 0000000..28a8bf4 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_add_black_24dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_add_black_24dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_add_black_24dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp-1.png new file mode 100755 index 0000000..1ea8dd9 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp-2.png new file mode 100755 index 0000000..a633259 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp.png new file mode 100755 index 0000000..a48d400 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_24dp.imageset/ic_add_black_24dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/Contents.json new file mode 100755 index 0000000..ad581cb --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_add_black_48dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_add_black_48dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_add_black_48dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp-1.png new file mode 100755 index 0000000..43bc427 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp-2.png new file mode 100755 index 0000000..b94d1c9 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp.png new file mode 100755 index 0000000..1ea8dd9 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_add_black_48dp.imageset/ic_add_black_48dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/Contents.json new file mode 100755 index 0000000..aa90065 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_delete_black_24dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_delete_black_24dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_delete_black_24dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp-1.png new file mode 100755 index 0000000..e677071 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp-2.png new file mode 100755 index 0000000..8d86e58 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp.png new file mode 100755 index 0000000..213fe67 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_24dp.imageset/ic_delete_black_24dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/Contents.json new file mode 100755 index 0000000..677bce9 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_delete_black_48dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_delete_black_48dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_delete_black_48dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp-1.png new file mode 100755 index 0000000..e74f379 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp-2.png new file mode 100755 index 0000000..780d5ad Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp.png new file mode 100755 index 0000000..e677071 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_delete_black_48dp.imageset/ic_delete_black_48dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/Contents.json new file mode 100755 index 0000000..66d22e3 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_mode_edit_black_24dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_mode_edit_black_24dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_mode_edit_black_24dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp-1.png new file mode 100755 index 0000000..aa7748a Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp-2.png new file mode 100755 index 0000000..827b684 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp.png new file mode 100755 index 0000000..0350968 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_24dp.imageset/ic_mode_edit_black_24dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/Contents.json new file mode 100755 index 0000000..9ecd462 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_mode_edit_black_48dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_mode_edit_black_48dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_mode_edit_black_48dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp-1.png new file mode 100755 index 0000000..d3c4cce Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp-2.png new file mode 100755 index 0000000..74f0c79 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp.png new file mode 100755 index 0000000..aa7748a Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_mode_edit_black_48dp.imageset/ic_mode_edit_black_48dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/Contents.json new file mode 100755 index 0000000..26ef049 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_refresh_black_24dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_refresh_black_24dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_refresh_black_24dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp-1.png new file mode 100755 index 0000000..b532f62 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp-2.png new file mode 100755 index 0000000..8c54dad Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp.png new file mode 100755 index 0000000..aee4fea Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_24dp.imageset/ic_refresh_black_24dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/Contents.json new file mode 100755 index 0000000..a124ef3 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_refresh_black_48dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_refresh_black_48dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_refresh_black_48dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp-1.png new file mode 100755 index 0000000..b6e1124 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp-2.png new file mode 100755 index 0000000..f613e28 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp.png new file mode 100755 index 0000000..b532f62 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_refresh_black_48dp.imageset/ic_refresh_black_48dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/Contents.json new file mode 100755 index 0000000..d1965a8 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_save_black_24dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_save_black_24dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_save_black_24dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp-1.png new file mode 100755 index 0000000..fb9c14b Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp-2.png new file mode 100755 index 0000000..c7ce7a4 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp.png new file mode 100755 index 0000000..d6c10ed Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_24dp.imageset/ic_save_black_24dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/Contents.json b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/Contents.json new file mode 100755 index 0000000..376fb4c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "ic_save_black_48dp.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "ic_save_black_48dp-1.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "ic_save_black_48dp-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp-1.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp-1.png new file mode 100755 index 0000000..d5306e1 Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp-1.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp-2.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp-2.png new file mode 100755 index 0000000..52647ff Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp-2.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp.png b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp.png new file mode 100755 index 0000000..fb9c14b Binary files /dev/null and b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/Media.xcassets/ic_save_black_48dp.imageset/ic_save_black_48dp.png differ diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEAppDelegate.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEAppDelegate.h new file mode 100755 index 0000000..1334207 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEAppDelegate.h @@ -0,0 +1,22 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +@interface QEAppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEAppDelegate.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEAppDelegate.m new file mode 100755 index 0000000..4848e95 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEAppDelegate.m @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "QEAppDelegate.h" + +@implementation QEAppDelegate + +@synthesize window = _window; + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // 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. + // 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. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // 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. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // 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. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // 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. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditDelegate.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditDelegate.h new file mode 100755 index 0000000..6cf9bdb --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditDelegate.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "GTLDrive.h" + +@protocol QEFileEditDelegate +- (NSInteger)didUpdateFileWithIndex:(NSInteger)index + driveFile:(GTLDriveFile *)driveFile; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditViewController.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditViewController.h new file mode 100755 index 0000000..e59451e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditViewController.h @@ -0,0 +1,43 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "GTLDrive.h" +#import "QEFileEditDelegate.h" +#import + +@interface QEFileEditViewController : UIViewController + +@property GTLServiceDrive *driveService; +@property GTLDriveFile *driveFile; +@property id delegate; +@property NSInteger fileIndex; + +@property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton; +@property (weak, nonatomic) IBOutlet UITextView *textView; + +@property (strong) NSString *originalContent; +@property (strong) NSString *fileTitle; + +- (IBAction)saveButtonClicked:(id)sender; +- (IBAction)deleteButtonClicked:(id)sender; +- (IBAction)renameButtonClicked:(id)sender; + +- (void)loadFileContent; +- (void)saveFile; +- (void)deleteFile; +- (void)toggleSaveButton; + + +@end \ No newline at end of file diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditViewController.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditViewController.m new file mode 100755 index 0000000..717c58e --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFileEditViewController.m @@ -0,0 +1,208 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "QEFileEditViewController.h" +#import "QEUtilities.h" + +@implementation QEFileEditViewController +@synthesize driveService = _driveService; +@synthesize driveFile = _driveFile; +@synthesize delegate = _delegate; +@synthesize saveButton = _saveButton; +@synthesize textView = _textView; +@synthesize originalContent = _originalContent; +@synthesize fileTitle = _fileTitle; +@synthesize fileIndex = _fileIndex; + +#pragma mark - Managing the detail item +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. + self.textView.delegate = self; + + if (self.fileIndex == -1) { + self.fileTitle = @"New file"; + } else { + self.fileTitle = self.driveFile.title; + } + + self.title = self.fileTitle; + + // In case of new file, show the title dialog. + if (self.fileIndex == -1) { + [self renameButtonClicked:nil]; + } else { + [self loadFileContent]; + } +} + +- (void)viewDidUnload +{ + [self setSaveButton:nil]; + [self setTextView:nil]; + [super viewDidUnload]; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); +} + +- (void)textViewDidBeginEditing:(UITextView *)textView { + UIBarButtonItem *doneButton = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(doneEditing:)]; + self.navigationItem.leftBarButtonItem = doneButton; +} + +- (void)textViewDidChange:(UITextView *)textView { + [self toggleSaveButton]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { + if (buttonIndex == 1) { + self.fileTitle = [[[alertView textFieldAtIndex:0] text] copy]; + self.title = self.fileTitle; + } + [self toggleSaveButton]; +} + +- (IBAction)doneEditing:(id)sender { + [self.view endEditing:YES]; + self.navigationItem.leftBarButtonItem = nil; +} + +- (IBAction)saveButtonClicked:(id)sender { + [self saveFile]; +} + +- (IBAction)deleteButtonClicked:(id)sender { + [self deleteFile]; +} + +- (IBAction)renameButtonClicked:(id)sender { + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Edit title" + message:@"" + delegate:self + cancelButtonTitle:@"Cancel" + otherButtonTitles:@"Ok", nil]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + UITextField * alertTextField = [alert textFieldAtIndex:0]; + alertTextField.placeholder = @"File's title"; + alertTextField.text = self.fileTitle; + [alert show]; +} + +- (void)loadFileContent { + UIAlertView *alert = [QEUtilities showLoadingMessageWithTitle:@"Loading file content" + delegate:self]; + GTMHTTPFetcher *fetcher = + [self.driveService.fetcherService fetcherWithURLString:self.driveFile.downloadUrl]; + + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + [alert dismissWithClickedButtonIndex:0 animated:YES]; + if (error == nil) { + NSString* fileContent = [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding]; + self.textView.text = fileContent; + self.originalContent = [fileContent copy]; + } else { + NSLog(@"An error occurred: %@", error); + [QEUtilities showErrorMessageWithTitle:@"Unable to load file" + message:[error description] + delegate:self]; + } + }]; +} + +- (void)saveFile { + GTLUploadParameters *uploadParameters = nil; + + // Only update the file content if different. + if (![self.originalContent isEqualToString:self.textView.text]) { + NSData *fileContent = + [self.textView.text dataUsingEncoding:NSUTF8StringEncoding]; + uploadParameters = + [GTLUploadParameters uploadParametersWithData:fileContent MIMEType:@"text/plain"]; + } + + self.driveFile.title = self.fileTitle; + GTLQueryDrive *query = nil; + if (self.driveFile.identifier == nil || self.driveFile.identifier.length == 0) { + // This is a new file, instantiate an insert query. + query = [GTLQueryDrive queryForFilesInsertWithObject:self.driveFile + uploadParameters:uploadParameters]; + } else { + // This file already exists, instantiate an update query. + query = [GTLQueryDrive queryForFilesUpdateWithObject:self.driveFile + fileId:self.driveFile.identifier + uploadParameters:uploadParameters]; + } + UIAlertView *alert = [QEUtilities showLoadingMessageWithTitle:@"Saving file" + delegate:self]; + + [self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket, + GTLDriveFile *updatedFile, + NSError *error) { + [alert dismissWithClickedButtonIndex:0 animated:YES]; + if (error == nil) { + self.driveFile = updatedFile; + self.originalContent = [self.textView.text copy]; + self.fileTitle = [updatedFile.title copy]; + [self toggleSaveButton]; + [self.delegate didUpdateFileWithIndex:self.fileIndex + driveFile:self.driveFile]; + [self doneEditing:nil]; + } else { + NSLog(@"An error occurred: %@", error); + [QEUtilities showErrorMessageWithTitle:@"Unable to save file" + message:[error description] + delegate:self]; + } + }]; +} + +- (void)deleteFile { + GTLQueryDrive *deleteQuery = + [GTLQueryDrive queryForFilesDeleteWithFileId:self.driveFile.identifier]; + UIAlertView *alert = [QEUtilities showLoadingMessageWithTitle:@"Deleting file" + delegate:self]; + + [self.driveService executeQuery:deleteQuery completionHandler:^(GTLServiceTicket *ticket, + id object, + NSError *error) { + [alert dismissWithClickedButtonIndex:0 animated:YES]; + if (error == nil) { + self.fileIndex = [self.delegate didUpdateFileWithIndex:self.fileIndex + driveFile:nil]; + [self.navigationController popViewControllerAnimated:YES]; + } else { + NSLog(@"An error occurred: %@", error); + [QEUtilities showErrorMessageWithTitle:@"Unable to delete file" + message:[error description] + delegate:self]; + } + }]; +} + +- (void)toggleSaveButton { + self.saveButton.enabled = + self.textView.text.length > 0 && + (![self.originalContent isEqualToString:self.textView.text] || + ![self.fileTitle isEqualToString:self.driveFile.title]); +} +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFilesListViewController.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFilesListViewController.h new file mode 100755 index 0000000..679548b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFilesListViewController.h @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import +#import "QEFileEditDelegate.h" +#import "GTMOAuth2ViewControllerTouch.h" + +@interface QEFilesListViewController : UITableViewController +@property (weak, nonatomic) IBOutlet UIBarButtonItem *addButton; +@property (weak, nonatomic) IBOutlet UIBarButtonItem *authButton; +@property (weak, nonatomic) IBOutlet UIBarButtonItem *refreshButton; + +@property (weak, readonly) GTLServiceDrive *driveService; +@property (retain) NSMutableArray *driveFiles; +@property BOOL isAuthorized; + +- (IBAction)signoutButtonClicked:(id)sender; +- (IBAction)refreshButtonClicked:(id)sender; + +- (void)toggleActionButtons:(BOOL)enabled; +- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController + finishedWithAuth:(GTMOAuth2Authentication *)auth + error:(NSError *)error; +- (void)isAuthorizedWithAuthentication:(GTMOAuth2Authentication *)auth; +- (void)loadDriveFiles; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFilesListViewController.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFilesListViewController.m new file mode 100755 index 0000000..be89d49 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEFilesListViewController.m @@ -0,0 +1,239 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "QEFilesListViewController.h" + +#import "GTLDrive.h" +#import "GTMOAuth2ViewControllerTouch.h" + +#import "QEFileEditViewController.h" +#import "QEUtilities.h" + +// Constants used for OAuth 2.0 authorization. +static NSString *const kKeychainItemName = @"iOSDriveSample: Google Drive"; +static NSString *const kClientId = @"709207149709-ji3gmrdvavd93r268ni6p3vg0r19m7q8.apps.googleusercontent.com"; +static NSString *const kClientSecret = @"3khRO33vwYeWN2ASShpxgovN"; + +@implementation QEFilesListViewController +@synthesize addButton = _addButton; +@synthesize authButton = _authButton; +@synthesize refreshButton = _refreshButton; +@synthesize driveFiles = _driveFiles; +@synthesize isAuthorized = _isAuthorized; + + +- (void)awakeFromNib +{ + [super awakeFromNib]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Check for authorization. + GTMOAuth2Authentication *auth = + [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName + clientID:kClientId + clientSecret:kClientSecret]; + if ([auth canAuthorize]) { + [self isAuthorizedWithAuthentication:auth]; + } +} + +- (void)viewDidUnload +{ + [self setAddButton:nil]; + [self setRefreshButton:nil]; + [self setAuthButton:nil]; + [super viewDidUnload]; + // Release any retained subviews of the main view. +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + if (!self.isAuthorized) { + [self showSignIn]; + } else { + // Sort Drive Files by modified date (descending order). + [self.driveFiles sortUsingComparator:^NSComparisonResult(GTLDriveFile *lhs, + GTLDriveFile *rhs) { + return [rhs.modifiedDate.date compare:lhs.modifiedDate.date]; + }]; + [self.tableView reloadData]; + } +} + +- (void)showSignIn { + // Sign in. + SEL finishedSelector = @selector(viewController:finishedWithAuth:error:); + GTMOAuth2ViewControllerTouch *authViewController = + [[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDriveFile + clientID:kClientId + clientSecret:kClientSecret + keychainItemName:kKeychainItemName + delegate:self + finishedSelector:finishedSelector]; + [self presentViewController:authViewController + animated:YES + completion:nil]; + +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); +} + +#pragma mark - Table View + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return self.driveFiles.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; + + GTLDriveFile *file = [self.driveFiles objectAtIndex:indexPath.row]; + cell.textLabel.text = file.title; + return cell; +} + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + QEFileEditViewController *viewController = [segue destinationViewController]; + NSString *segueIdentifier = segue.identifier; + viewController.driveService = [self driveService]; + viewController.delegate = self; + + if ([segueIdentifier isEqualToString:@"editFile"]) { + NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; + GTLDriveFile *file = [self.driveFiles objectAtIndex:indexPath.row]; + viewController.driveFile = file; + viewController.fileIndex = indexPath.row; + } else if ([segueIdentifier isEqualToString:@"addFile"]) { + viewController.driveFile = [GTLDriveFile object]; + viewController.fileIndex = -1; + } +} + +- (NSInteger)didUpdateFileWithIndex:(NSInteger)index + driveFile:(GTLDriveFile *)driveFile { + if (index == -1) { + if (driveFile != nil) { + // New file inserted. + [self.driveFiles insertObject:driveFile atIndex:0]; + index = 0; + } + } else { + if (driveFile != nil) { + // File has been updated. + [self.driveFiles replaceObjectAtIndex:index withObject:driveFile]; + } else { + // File has been deleted. + [self.driveFiles removeObjectAtIndex:index]; + index = -1; + } + } + return index; +} + +- (GTLServiceDrive *)driveService { + static GTLServiceDrive *service = nil; + + if (!service) { + service = [[GTLServiceDrive alloc] init]; + + // Have the service object set tickets to fetch consecutive pages + // of the feed so we do not need to manually fetch them. + service.shouldFetchNextPages = YES; + + // Have the service object set tickets to retry temporary error conditions + // automatically. + service.retryEnabled = YES; + } + return service; +} + +- (IBAction)signoutButtonClicked:(id)sender { + // Sign out + [GTMOAuth2ViewControllerTouch removeAuthFromKeychainForName:kKeychainItemName]; + [[self driveService] setAuthorizer:nil]; + self.isAuthorized = NO; + [self toggleActionButtons:NO]; + [self.driveFiles removeAllObjects]; + [self.tableView reloadData]; + [self showSignIn]; +} + +- (IBAction)refreshButtonClicked:(id)sender { + [self loadDriveFiles]; +} + +- (void)toggleActionButtons:(BOOL)enabled { + self.addButton.enabled = enabled; + self.refreshButton.enabled = enabled; +} + +- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController + finishedWithAuth:(GTMOAuth2Authentication *)auth + error:(NSError *)error { + [self dismissViewControllerAnimated:YES completion:nil]; + if (error == nil) { + [self isAuthorizedWithAuthentication:auth]; + } +} + +- (void)isAuthorizedWithAuthentication:(GTMOAuth2Authentication *)auth { + [[self driveService] setAuthorizer:auth]; + self.authButton.title = @"Sign out"; + self.isAuthorized = YES; + [self toggleActionButtons:YES]; + [self loadDriveFiles]; +} + +- (void)loadDriveFiles { + GTLQueryDrive *query = [GTLQueryDrive queryForFilesList]; + query.q = @"mimeType = 'text/plain'"; + + UIAlertView *alert = [QEUtilities showLoadingMessageWithTitle:@"Loading files" + delegate:self]; + [self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket, + GTLDriveFileList *files, + NSError *error) { + [alert dismissWithClickedButtonIndex:0 animated:YES]; + if (error == nil) { + if (self.driveFiles == nil) { + self.driveFiles = [[NSMutableArray alloc] init]; + } + [self.driveFiles removeAllObjects]; + [self.driveFiles addObjectsFromArray:files.items]; + [self.tableView reloadData]; + } else { + NSLog(@"An error occurred: %@", error); + [QEUtilities showErrorMessageWithTitle:@"Unable to load files" + message:[error description] + delegate:self]; + } + }]; +} +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEUtilities.h b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEUtilities.h new file mode 100755 index 0000000..c54859b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEUtilities.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +@interface QEUtilities : NSObject ++ (UIAlertView *)showLoadingMessageWithTitle:(NSString *)title + delegate:(id)delegate; ++ (void)showErrorMessageWithTitle:(NSString *)title + message:(NSString *)message + delegate:(id)delegate; +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEUtilities.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEUtilities.m new file mode 100755 index 0000000..951c61b --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/QEUtilities.m @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "QEUtilities.h" + +@implementation QEUtilities ++ (UIAlertView *)showLoadingMessageWithTitle:(NSString *)title + delegate:(id)delegate { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title + message:@"" + delegate:self + cancelButtonTitle:nil + otherButtonTitles:nil]; + UIActivityIndicatorView *progress= + [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125, 50, 30, 30)]; + progress.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge; + [alert addSubview:progress]; + [progress startAnimating]; + [alert show]; + return alert; +} + ++ (void)showErrorMessageWithTitle:(NSString *)title + message:(NSString*)message + delegate:(id)delegate { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title + message:message + delegate:self + cancelButtonTitle:@"Dismiss" + otherButtonTitles:nil]; + [alert show]; +} +@end diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/en.lproj/InfoPlist.strings b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/en.lproj/InfoPlist.strings new file mode 100755 index 0000000..477b28f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/ios-quickeditor-Info.plist b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/ios-quickeditor-Info.plist new file mode 100755 index 0000000..a8b5310 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/ios-quickeditor-Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.drive.samples.ios-quick-editor.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIMainStoryboardFile + MainStoryboard + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/ios-quickeditor-Prefix.pch b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/ios-quickeditor-Prefix.pch new file mode 100755 index 0000000..743435c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/ios-quickeditor-Prefix.pch @@ -0,0 +1,16 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iOS SDK 3.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/main.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/main.m new file mode 100755 index 0000000..583530a --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditor/main.m @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "QEAppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([QEAppDelegate class])); + } +} diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/en.lproj/InfoPlist.strings b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/en.lproj/InfoPlist.strings new file mode 100755 index 0000000..477b28f --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/ios-quickeditorTests-Info.plist b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/ios-quickeditorTests-Info.plist new file mode 100755 index 0000000..05fdb7c --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/ios-quickeditorTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.drive.samples.ios-quick-editor.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/ios_quickeditorTests.m b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/ios_quickeditorTests.m new file mode 100755 index 0000000..fb987c8 --- /dev/null +++ b/Students/Benny/GoogleDriveTest/GoogleDriveProject/ios-quickeditor/ios-quickeditorTests/ios_quickeditorTests.m @@ -0,0 +1,34 @@ +// +// ios_quickeditorTests.m +// ios-quickeditorTests +// +// Created by Steven Bazyl on 3/4/15. +// Copyright (c) 2015 Google Developers. All rights reserved. +// + +#import + +@interface ios_quickeditorTests : XCTestCase + +@end + +@implementation ios_quickeditorTests + +- (void)setUp +{ + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample +{ + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Objective-C.xcodeproj/project.pbxproj b/Students/Benny/Les 1 OCMock/Objective-C.xcodeproj/project.pbxproj new file mode 100644 index 0000000..90e237f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C.xcodeproj/project.pbxproj @@ -0,0 +1,662 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 3E6A68F2875FFD7000CFBD3B /* Pods_Objective_C.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 448F0579C3D01F05FB92C71B /* Pods_Objective_C.framework */; }; + 46929BEF2E048A1113335625 /* Pods_Objective_CTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73A6D6506AF1FB6921C8A7D3 /* Pods_Objective_CTests.framework */; }; + B56B82241E841DD100ECBEC0 /* PostDetailViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B56B82231E841DD100ECBEC0 /* PostDetailViewModel.m */; }; + B5B3315C1E83CC2C00A9E7EB /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B3315B1E83CC2C00A9E7EB /* Post.swift */; }; + B5B3315E1E83CC5500A9E7EB /* BridgeFaroService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B3315D1E83CC5500A9E7EB /* BridgeFaroService.swift */; }; + B5B331601E83CC6D00A9E7EB /* BridgeCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B3315F1E83CC6D00A9E7EB /* BridgeCall.swift */; }; + B5B331621E83CC7F00A9E7EB /* PostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B331611E83CC7F00A9E7EB /* PostService.swift */; }; + C0DA0AB51E81335E00A6E9F8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DA0AB41E81335E00A6E9F8 /* main.m */; }; + C0DA0AB81E81335E00A6E9F8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DA0AB71E81335E00A6E9F8 /* AppDelegate.m */; }; + C0DA0ABB1E81335E00A6E9F8 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DA0ABA1E81335E00A6E9F8 /* ViewController.m */; }; + C0DA0ABE1E81335E00A6E9F8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0DA0ABC1E81335E00A6E9F8 /* Main.storyboard */; }; + C0DA0AC01E81335E00A6E9F8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C0DA0ABF1E81335E00A6E9F8 /* Assets.xcassets */; }; + C0DA0AC31E81335E00A6E9F8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0DA0AC11E81335E00A6E9F8 /* LaunchScreen.storyboard */; }; + C0DA0ACE1E81335E00A6E9F8 /* Objective_CTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DA0ACD1E81335E00A6E9F8 /* Objective_CTests.m */; }; + C0DA0ADA1E8139C100A6E9F8 /* ViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DA0AD91E8139C100A6E9F8 /* ViewModel.m */; }; + C0F314911E82B58A0094B4E5 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0F314901E82B58A0094B4E5 /* Example.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + C0DA0ACA1E81335E00A6E9F8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C0DA0AA81E81335E00A6E9F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0DA0AAF1E81335E00A6E9F8; + remoteInfo = "Objective-C"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0F2641C64B4878BD58008B7D /* Pods-Objective-C.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Objective-C.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.debug.xcconfig"; sourceTree = ""; }; + 448F0579C3D01F05FB92C71B /* Pods_Objective_C.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Objective_C.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5AE52596F4B3A514C00551C0 /* Pods-Objective-CTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Objective-CTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.debug.xcconfig"; sourceTree = ""; }; + 6803A380D282E648E2D64DC3 /* Pods-Objective-CTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Objective-CTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.release.xcconfig"; sourceTree = ""; }; + 73A6D6506AF1FB6921C8A7D3 /* Pods_Objective_CTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Objective_CTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B1A5D9CC53353FDF8E54BCC6 /* Pods-Objective-C.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Objective-C.release.xcconfig"; path = "Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.release.xcconfig"; sourceTree = ""; }; + B56B82221E841DD100ECBEC0 /* PostDetailViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PostDetailViewModel.h; sourceTree = ""; }; + B56B82231E841DD100ECBEC0 /* PostDetailViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PostDetailViewModel.m; sourceTree = ""; }; + B5B3315B1E83CC2C00A9E7EB /* Post.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; + B5B3315D1E83CC5500A9E7EB /* BridgeFaroService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BridgeFaroService.swift; sourceTree = ""; }; + B5B3315F1E83CC6D00A9E7EB /* BridgeCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BridgeCall.swift; sourceTree = ""; }; + B5B331611E83CC7F00A9E7EB /* PostService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostService.swift; sourceTree = ""; }; + C0DA0AB01E81335E00A6E9F8 /* Objective-C.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Objective-C.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + C0DA0AB41E81335E00A6E9F8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + C0DA0AB61E81335E00A6E9F8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + C0DA0AB71E81335E00A6E9F8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + C0DA0AB91E81335E00A6E9F8 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + C0DA0ABA1E81335E00A6E9F8 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + C0DA0ABD1E81335E00A6E9F8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + C0DA0ABF1E81335E00A6E9F8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + C0DA0AC21E81335E00A6E9F8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + C0DA0AC41E81335E00A6E9F8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C0DA0AC91E81335E00A6E9F8 /* Objective-CTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Objective-CTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + C0DA0ACD1E81335E00A6E9F8 /* Objective_CTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Objective_CTests.m; sourceTree = ""; }; + C0DA0ACF1E81335E00A6E9F8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C0DA0AD81E8139C100A6E9F8 /* ViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewModel.h; sourceTree = ""; }; + C0DA0AD91E8139C100A6E9F8 /* ViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewModel.m; sourceTree = ""; }; + C0F3148F1E82B58A0094B4E5 /* Objective-C-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Objective-C-Bridging-Header.h"; sourceTree = ""; }; + C0F314901E82B58A0094B4E5 /* Example.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Example.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + C0DA0AAD1E81335E00A6E9F8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E6A68F2875FFD7000CFBD3B /* Pods_Objective_C.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C0DA0AC61E81335E00A6E9F8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 46929BEF2E048A1113335625 /* Pods_Objective_CTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 11979AAFAFF920DABBDA0A68 /* Pods */ = { + isa = PBXGroup; + children = ( + 0F2641C64B4878BD58008B7D /* Pods-Objective-C.debug.xcconfig */, + B1A5D9CC53353FDF8E54BCC6 /* Pods-Objective-C.release.xcconfig */, + 5AE52596F4B3A514C00551C0 /* Pods-Objective-CTests.debug.xcconfig */, + 6803A380D282E648E2D64DC3 /* Pods-Objective-CTests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 14EC93B90F090CE403316D4D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 448F0579C3D01F05FB92C71B /* Pods_Objective_C.framework */, + 73A6D6506AF1FB6921C8A7D3 /* Pods_Objective_CTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + B5B331571E83CBD300A9E7EB /* Models */ = { + isa = PBXGroup; + children = ( + B5B3315B1E83CC2C00A9E7EB /* Post.swift */, + ); + name = Models; + sourceTree = ""; + }; + B5B331581E83CBDD00A9E7EB /* Faro */ = { + isa = PBXGroup; + children = ( + B5B3315D1E83CC5500A9E7EB /* BridgeFaroService.swift */, + B5B3315F1E83CC6D00A9E7EB /* BridgeCall.swift */, + B5B331611E83CC7F00A9E7EB /* PostService.swift */, + ); + name = Faro; + sourceTree = ""; + }; + B5D6B0D01E83BD75006564CC /* Modules */ = { + isa = PBXGroup; + children = ( + B5D6B0D11E83BD88006564CC /* Main */, + B5D6B0D21E83BD9A006564CC /* TableView */, + ); + name = Modules; + sourceTree = ""; + }; + B5D6B0D11E83BD88006564CC /* Main */ = { + isa = PBXGroup; + children = ( + C0DA0AB61E81335E00A6E9F8 /* AppDelegate.h */, + C0DA0AB71E81335E00A6E9F8 /* AppDelegate.m */, + C0DA0ABC1E81335E00A6E9F8 /* Main.storyboard */, + ); + name = Main; + sourceTree = ""; + }; + B5D6B0D21E83BD9A006564CC /* TableView */ = { + isa = PBXGroup; + children = ( + C0F314901E82B58A0094B4E5 /* Example.swift */, + C0DA0AB91E81335E00A6E9F8 /* ViewController.h */, + C0DA0ABA1E81335E00A6E9F8 /* ViewController.m */, + C0DA0AD81E8139C100A6E9F8 /* ViewModel.h */, + C0DA0AD91E8139C100A6E9F8 /* ViewModel.m */, + B56B82221E841DD100ECBEC0 /* PostDetailViewModel.h */, + B56B82231E841DD100ECBEC0 /* PostDetailViewModel.m */, + ); + name = TableView; + sourceTree = ""; + }; + B5D6B0D31E83BDB8006564CC /* UI */ = { + isa = PBXGroup; + children = ( + C0DA0ABF1E81335E00A6E9F8 /* Assets.xcassets */, + C0DA0AC11E81335E00A6E9F8 /* LaunchScreen.storyboard */, + ); + name = UI; + sourceTree = ""; + }; + C0DA0AA71E81335E00A6E9F8 = { + isa = PBXGroup; + children = ( + C0DA0AB21E81335E00A6E9F8 /* Objective-C */, + C0DA0ACC1E81335E00A6E9F8 /* Objective-CTests */, + C0DA0AB11E81335E00A6E9F8 /* Products */, + 11979AAFAFF920DABBDA0A68 /* Pods */, + 14EC93B90F090CE403316D4D /* Frameworks */, + ); + sourceTree = ""; + }; + C0DA0AB11E81335E00A6E9F8 /* Products */ = { + isa = PBXGroup; + children = ( + C0DA0AB01E81335E00A6E9F8 /* Objective-C.app */, + C0DA0AC91E81335E00A6E9F8 /* Objective-CTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + C0DA0AB21E81335E00A6E9F8 /* Objective-C */ = { + isa = PBXGroup; + children = ( + B5B331581E83CBDD00A9E7EB /* Faro */, + B5B331571E83CBD300A9E7EB /* Models */, + B5D6B0D01E83BD75006564CC /* Modules */, + C0F3148F1E82B58A0094B4E5 /* Objective-C-Bridging-Header.h */, + C0DA0AB31E81335E00A6E9F8 /* Supporting Files */, + B5D6B0D31E83BDB8006564CC /* UI */, + ); + path = "Objective-C"; + sourceTree = ""; + }; + C0DA0AB31E81335E00A6E9F8 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + C0DA0AC41E81335E00A6E9F8 /* Info.plist */, + C0DA0AB41E81335E00A6E9F8 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + C0DA0ACC1E81335E00A6E9F8 /* Objective-CTests */ = { + isa = PBXGroup; + children = ( + C0DA0ACD1E81335E00A6E9F8 /* Objective_CTests.m */, + C0DA0ACF1E81335E00A6E9F8 /* Info.plist */, + ); + path = "Objective-CTests"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + C0DA0AAF1E81335E00A6E9F8 /* Objective-C */ = { + isa = PBXNativeTarget; + buildConfigurationList = C0DA0AD21E81335E00A6E9F8 /* Build configuration list for PBXNativeTarget "Objective-C" */; + buildPhases = ( + F69B13B06696FBE6E426BF22 /* [CP] Check Pods Manifest.lock */, + C0DA0AAC1E81335E00A6E9F8 /* Sources */, + C0DA0AAD1E81335E00A6E9F8 /* Frameworks */, + C0DA0AAE1E81335E00A6E9F8 /* Resources */, + A6DA640E9D9E8F518ED8D229 /* [CP] Embed Pods Frameworks */, + ED30FD0A8BED92788E9C7B4B /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Objective-C"; + productName = "Objective-C"; + productReference = C0DA0AB01E81335E00A6E9F8 /* Objective-C.app */; + productType = "com.apple.product-type.application"; + }; + C0DA0AC81E81335E00A6E9F8 /* Objective-CTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = C0DA0AD51E81335E00A6E9F8 /* Build configuration list for PBXNativeTarget "Objective-CTests" */; + buildPhases = ( + 312DA70D376FA070CADD150F /* [CP] Check Pods Manifest.lock */, + C0DA0AC51E81335E00A6E9F8 /* Sources */, + C0DA0AC61E81335E00A6E9F8 /* Frameworks */, + C0DA0AC71E81335E00A6E9F8 /* Resources */, + D3583D88EAA00196EF961665 /* [CP] Embed Pods Frameworks */, + FE803A571BBC57D0FF9C0660 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + C0DA0ACB1E81335E00A6E9F8 /* PBXTargetDependency */, + ); + name = "Objective-CTests"; + productName = "Objective-CTests"; + productReference = C0DA0AC91E81335E00A6E9F8 /* Objective-CTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C0DA0AA81E81335E00A6E9F8 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = icapps; + TargetAttributes = { + C0DA0AAF1E81335E00A6E9F8 = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = SCZPF223NC; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + }; + C0DA0AC81E81335E00A6E9F8 = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = SCZPF223NC; + ProvisioningStyle = Automatic; + TestTargetID = C0DA0AAF1E81335E00A6E9F8; + }; + }; + }; + buildConfigurationList = C0DA0AAB1E81335E00A6E9F8 /* Build configuration list for PBXProject "Objective-C" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = C0DA0AA71E81335E00A6E9F8; + productRefGroup = C0DA0AB11E81335E00A6E9F8 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + C0DA0AAF1E81335E00A6E9F8 /* Objective-C */, + C0DA0AC81E81335E00A6E9F8 /* Objective-CTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + C0DA0AAE1E81335E00A6E9F8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C0DA0AC31E81335E00A6E9F8 /* LaunchScreen.storyboard in Resources */, + C0DA0AC01E81335E00A6E9F8 /* Assets.xcassets in Resources */, + C0DA0ABE1E81335E00A6E9F8 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C0DA0AC71E81335E00A6E9F8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 312DA70D376FA070CADD150F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + A6DA640E9D9E8F518ED8D229 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D3583D88EAA00196EF961665 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + ED30FD0A8BED92788E9C7B4B /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + F69B13B06696FBE6E426BF22 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + FE803A571BBC57D0FF9C0660 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + C0DA0AAC1E81335E00A6E9F8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C0DA0ABB1E81335E00A6E9F8 /* ViewController.m in Sources */, + B5B3315E1E83CC5500A9E7EB /* BridgeFaroService.swift in Sources */, + C0DA0AB81E81335E00A6E9F8 /* AppDelegate.m in Sources */, + C0DA0ADA1E8139C100A6E9F8 /* ViewModel.m in Sources */, + B5B331601E83CC6D00A9E7EB /* BridgeCall.swift in Sources */, + B56B82241E841DD100ECBEC0 /* PostDetailViewModel.m in Sources */, + B5B3315C1E83CC2C00A9E7EB /* Post.swift in Sources */, + C0DA0AB51E81335E00A6E9F8 /* main.m in Sources */, + B5B331621E83CC7F00A9E7EB /* PostService.swift in Sources */, + C0F314911E82B58A0094B4E5 /* Example.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C0DA0AC51E81335E00A6E9F8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C0DA0ACE1E81335E00A6E9F8 /* Objective_CTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + C0DA0ACB1E81335E00A6E9F8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C0DA0AAF1E81335E00A6E9F8 /* Objective-C */; + targetProxy = C0DA0ACA1E81335E00A6E9F8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + C0DA0ABC1E81335E00A6E9F8 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + C0DA0ABD1E81335E00A6E9F8 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + C0DA0AC11E81335E00A6E9F8 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + C0DA0AC21E81335E00A6E9F8 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + C0DA0AD01E81335E00A6E9F8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C0DA0AD11E81335E00A6E9F8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C0DA0AD31E81335E00A6E9F8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0F2641C64B4878BD58008B7D /* Pods-Objective-C.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = SCZPF223NC; + INFOPLIST_FILE = "Objective-C/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "be.icapps.Objective-C"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Objective-C/Objective-C-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + C0DA0AD41E81335E00A6E9F8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B1A5D9CC53353FDF8E54BCC6 /* Pods-Objective-C.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = SCZPF223NC; + INFOPLIST_FILE = "Objective-C/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "be.icapps.Objective-C"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Objective-C/Objective-C-Bridging-Header.h"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; + C0DA0AD61E81335E00A6E9F8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5AE52596F4B3A514C00551C0 /* Pods-Objective-CTests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = SCZPF223NC; + INFOPLIST_FILE = "Objective-CTests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "be.icapps.Objective-CTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Objective-C.app/Objective-C"; + }; + name = Debug; + }; + C0DA0AD71E81335E00A6E9F8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6803A380D282E648E2D64DC3 /* Pods-Objective-CTests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = SCZPF223NC; + INFOPLIST_FILE = "Objective-CTests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "be.icapps.Objective-CTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Objective-C.app/Objective-C"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C0DA0AAB1E81335E00A6E9F8 /* Build configuration list for PBXProject "Objective-C" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C0DA0AD01E81335E00A6E9F8 /* Debug */, + C0DA0AD11E81335E00A6E9F8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C0DA0AD21E81335E00A6E9F8 /* Build configuration list for PBXNativeTarget "Objective-C" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C0DA0AD31E81335E00A6E9F8 /* Debug */, + C0DA0AD41E81335E00A6E9F8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C0DA0AD51E81335E00A6E9F8 /* Build configuration list for PBXNativeTarget "Objective-CTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C0DA0AD61E81335E00A6E9F8 /* Debug */, + C0DA0AD71E81335E00A6E9F8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = C0DA0AA81E81335E00A6E9F8 /* Project object */; +} diff --git a/Students/Benny/Les 1 OCMock/Objective-C.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Students/Benny/Les 1 OCMock/Objective-C.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..b07da77 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Students/Benny/Les 1 OCMock/Objective-C.xcworkspace/contents.xcworkspacedata b/Students/Benny/Les 1 OCMock/Objective-C.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..f8eb338 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Students/Benny/Les 1 OCMock/Objective-C/AppDelegate.h b/Students/Benny/Les 1 OCMock/Objective-C/AppDelegate.h new file mode 100644 index 0000000..241b044 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// Objective-C +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; +@property int foo; + +@end + diff --git a/Students/Benny/Les 1 OCMock/Objective-C/AppDelegate.m b/Students/Benny/Les 1 OCMock/Objective-C/AppDelegate.m new file mode 100644 index 0000000..28e30b6 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/AppDelegate.m @@ -0,0 +1,54 @@ +// +// AppDelegate.m +// Objective-C +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import "AppDelegate.h" +#import "Objective_C-Swift.h" +#import "ViewModel.h" + +@interface AppDelegate () + + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + // 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. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // 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. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // 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. +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Objective-C/Assets.xcassets/AppIcon.appiconset/Contents.json b/Students/Benny/Les 1 OCMock/Objective-C/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..1d060ed --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Students/Benny/Les 1 OCMock/Objective-C/Base.lproj/LaunchScreen.storyboard b/Students/Benny/Les 1 OCMock/Objective-C/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..fdf3f97 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Students/Benny/Les 1 OCMock/Objective-C/Base.lproj/Main.storyboard b/Students/Benny/Les 1 OCMock/Objective-C/Base.lproj/Main.storyboard new file mode 100644 index 0000000..58ca2fe --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/Base.lproj/Main.storyboard @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Students/Benny/Les 1 OCMock/Objective-C/BridgeCall.swift b/Students/Benny/Les 1 OCMock/Objective-C/BridgeCall.swift new file mode 100644 index 0000000..d50dce4 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/BridgeCall.swift @@ -0,0 +1,19 @@ +// +// BridgeCall.swift +// Objective-C +// +// Created by Ben Algoet on 23/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +import Faro + +class BridgeCall: NSObject { + let call: Call + + init(_ path: String) { + call = Call(path: path) + return + } + +} diff --git a/Students/Benny/Les 1 OCMock/Objective-C/BridgeFaroService.swift b/Students/Benny/Les 1 OCMock/Objective-C/BridgeFaroService.swift new file mode 100644 index 0000000..d2d9d99 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/BridgeFaroService.swift @@ -0,0 +1,18 @@ +// +// BridgeFaroService.swift +// Objective-C +// +// Created by Ben Algoet on 23/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +import Faro + +class BridgeFaroService: NSObject { + public let service: Service + + override init() { + service = Service(configuration: Configuration(baseURL: "http://jsonplaceholder.typicode.com")) + } + +} diff --git a/Students/Benny/Les 1 OCMock/Objective-C/Example.swift b/Students/Benny/Les 1 OCMock/Objective-C/Example.swift new file mode 100644 index 0000000..aca272f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/Example.swift @@ -0,0 +1,20 @@ +// +// Example.swift +// Objective-C +// +// Created by Stijn Willems on 22/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +import Foundation + +class App { + + var foo: Int { + get { + return _foo + } + } + + private var _foo: Int = 0 +} diff --git a/Students/Benny/Les 1 OCMock/Objective-C/Info.plist b/Students/Benny/Les 1 OCMock/Objective-C/Info.plist new file mode 100644 index 0000000..2a6bbfd --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/Info.plist @@ -0,0 +1,54 @@ + + + + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + CFBundlePackageType + APPL + CFBundleDevelopmentRegion + en + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Students/Benny/Les 1 OCMock/Objective-C/Objective-C-Bridging-Header.h b/Students/Benny/Les 1 OCMock/Objective-C/Objective-C-Bridging-Header.h new file mode 100644 index 0000000..1b2cb5d --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/Objective-C-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/Students/Benny/Les 1 OCMock/Objective-C/Post.swift b/Students/Benny/Les 1 OCMock/Objective-C/Post.swift new file mode 100644 index 0000000..75d5782 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/Post.swift @@ -0,0 +1,29 @@ +// +// Post.swift +// Objective-C +// +// Created by Ben Algoet on 23/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +import Faro + +class Post: NSObject, Deserializable { + + var userId: NSNumber? + var id: NSNumber? + var title: String? + var body: String? + + required init?(from raw: Any) { + guard let json = raw as? [String: Any] else { + return + } + + userId = json["userId"] as? NSNumber + id = json["id"] as? NSNumber + title <-> json["title"] + body <-> json["body"] + } + +} diff --git a/Students/Benny/Les 1 OCMock/Objective-C/PostDetailViewModel.h b/Students/Benny/Les 1 OCMock/Objective-C/PostDetailViewModel.h new file mode 100644 index 0000000..c11a7c2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/PostDetailViewModel.h @@ -0,0 +1,19 @@ +// +// PostDetailViewModel.h +// Objective-C +// +// Created by Ben Algoet on 23/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import +#import "Objective_C-Swift.h" + +@interface PostDetailViewModel : NSObject + +@property (nonatomic, strong) Post * post; +-(NSString *) title; + +- (id) initWithPost: (Post *) post; + +@end diff --git a/Students/Benny/Les 1 OCMock/Objective-C/PostDetailViewModel.m b/Students/Benny/Les 1 OCMock/Objective-C/PostDetailViewModel.m new file mode 100644 index 0000000..41634cc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/PostDetailViewModel.m @@ -0,0 +1,35 @@ +// +// PostDetailViewModel.m +// Objective-C +// +// Created by Ben Algoet on 23/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import "PostDetailViewModel.h" + +@interface PostDetailViewModel() + +@end + +@implementation PostDetailViewModel + +- (id) initWithPost:(Post *)post { + self = [super init]; + if(self) { + self.post = post; + } + return self; +} + + +#pragma MARK: - Variables +-(NSNumber *) postId { + return self.post.id; +} + +-(NSString *) title { + return self.post.title; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Objective-C/PostService.swift b/Students/Benny/Les 1 OCMock/Objective-C/PostService.swift new file mode 100644 index 0000000..907bb99 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/PostService.swift @@ -0,0 +1,34 @@ +// +// PostService.swift +// Objective-C +// +// Created by Ben Algoet on 23/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +import Faro + +class PostService: BridgeFaroService { + + func post(posts: @escaping ([Post]) -> Void, fail: @escaping (String) -> Void) { + let _ = fetchPost(BridgeCall("posts"), posts: posts, fail: fail) + } + + func fetchPost(_ call: BridgeCall, posts: @escaping ([Post]) -> Void, fail: @escaping (String) -> Void) -> URLSessionDataTask? { + return service.perform(call.call) { (result: Result) in + switch result { + case .models(let models): + guard let models = models else { + fail("Fail") + return + } + posts(models) + case .failure(let error): + fail("\(error)") + default: + fail("Fail") + } + } + } + +} diff --git a/Students/Benny/Les 1 OCMock/Objective-C/ViewController.h b/Students/Benny/Les 1 OCMock/Objective-C/ViewController.h new file mode 100644 index 0000000..401eed2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// Objective-C +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/Students/Benny/Les 1 OCMock/Objective-C/ViewController.m b/Students/Benny/Les 1 OCMock/Objective-C/ViewController.m new file mode 100644 index 0000000..24df1ae --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/ViewController.m @@ -0,0 +1,48 @@ +// +// ViewController.m +// Objective-C +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import "ViewController.h" +#import "ViewModel.h" + +@interface ViewController () + +@property (weak, nonatomic) IBOutlet UITableView *tableView; + +@property ViewModel *viewModel; +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + if (self) { + _viewModel = [[ViewModel alloc] init]; + [self.viewModel load:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + [self.tableView reloadData]; + }); + }]; + } +} + +#pragma MARK: - UITableViewDataSource + +- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.viewModel.posts.count; +} + +- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"tableViewCell"]; + + cell.textLabel.text = [self.viewModel postDetailViewModelAtIndexPath: indexPath].title; + + return cell; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Objective-C/ViewModel.h b/Students/Benny/Les 1 OCMock/Objective-C/ViewModel.h new file mode 100644 index 0000000..f7a747c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/ViewModel.h @@ -0,0 +1,21 @@ +// +// ViewModel.h +// Objective-C +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import +#import +#import "Objective_C-Swift.h" +#import "PostDetailViewModel.h" + +@interface ViewModel : NSObject + +@property (nonatomic, strong) NSArray *posts; +@property (nonatomic, strong) PostService * service; + +- (void) load: (void (^)(void))done; +- (PostDetailViewModel *) postDetailViewModelAtIndexPath: (NSIndexPath *) indexPath; +@end diff --git a/Students/Benny/Les 1 OCMock/Objective-C/ViewModel.m b/Students/Benny/Les 1 OCMock/Objective-C/ViewModel.m new file mode 100644 index 0000000..e8aaa6a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/ViewModel.m @@ -0,0 +1,49 @@ +// +// ViewModel.m +// Objective-C +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import "ViewModel.h" +#import "Objective_C-Swift.h" + + +@interface ViewModel() + +@property (nonatomic, strong) NSArray * models; + +@end + +@implementation ViewModel + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.service = [[PostService alloc] init]; + } + return self; +} +#pragma MARK: - Service + +- (void) load:(void (^)(void))done { + __weak ViewModel *weakSelf = self; + [self.service postWithPosts:^(NSArray * _Nonnull posts) { + weakSelf.posts = posts; + done(); + } fail:^(NSString * _Nonnull fail) { + NSLog(@"%@", fail); + }]; +} + +- (PostDetailViewModel *) postDetailViewModelAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.row < _posts.count) { + return [[PostDetailViewModel alloc] initWithPost: self.posts[indexPath.row]]; + } else { + return nil; + } +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Objective-C/main.m b/Students/Benny/Les 1 OCMock/Objective-C/main.m new file mode 100644 index 0000000..5d7da9a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-C/main.m @@ -0,0 +1,16 @@ +// +// main.m +// Objective-C +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/Students/Benny/Les 1 OCMock/Objective-CTests/Info.plist b/Students/Benny/Les 1 OCMock/Objective-CTests/Info.plist new file mode 100644 index 0000000..6c6c23c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-CTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Students/Benny/Les 1 OCMock/Objective-CTests/Objective_CTests.m b/Students/Benny/Les 1 OCMock/Objective-CTests/Objective_CTests.m new file mode 100644 index 0000000..f6a4697 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Objective-CTests/Objective_CTests.m @@ -0,0 +1,41 @@ +// +// Objective_CTests.m +// Objective-CTests +// +// Created by Stijn Willems on 21/03/2017. +// Copyright © 2017 icapps. All rights reserved. +// + +#import +#import +#import "ViewModel.h" + +@import Nimble; +@import Quick; + + +@interface Objective_CTests : QuickSpec + +@end + +@implementation Objective_CTests + +-(void)spec { + + describe(@"ViewModel List helpers", ^{ + + it(@"instantiates from models", ^ { + + id mockArray = OCMClassMock([NSArray class]); + [OCMStub([mockArray count]) andReturnValue: OCMOCK_VALUE(30)]; + + ViewModel* viewModel = [[ViewModel alloc] initWithModels:mockArray]; + + expect([viewModel numberOfModels]).to(equal(@30)); + }); + }); + +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Podfile b/Students/Benny/Les 1 OCMock/Podfile new file mode 100644 index 0000000..05707d6 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Podfile @@ -0,0 +1,21 @@ +# Uncomment the next line to define a global platform for your project +platform :ios, '10.0' + +use_frameworks! + +target 'Objective-C' do + # Uncomment the next line if you're using Swift or would like to use dynamic frameworks + # use_frameworks! + + # Pods for Objective-C + + pod 'Faro' + + target 'Objective-CTests' do + inherit! :search_paths + pod 'OCMock', '~> 3.4' + pod 'Quick' + pod 'Nimble' + end + +end diff --git a/Students/Benny/Les 1 OCMock/Podfile.lock b/Students/Benny/Les 1 OCMock/Podfile.lock new file mode 100644 index 0000000..d43d771 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Podfile.lock @@ -0,0 +1,21 @@ +PODS: + - Faro (1.0.9) + - Nimble (6.0.1) + - OCMock (3.4) + - Quick (1.1.0) + +DEPENDENCIES: + - Faro + - Nimble + - OCMock (~> 3.4) + - Quick + +SPEC CHECKSUMS: + Faro: 62a1fedc46cee416e4eb9dddaff7fd4ed071834a + Nimble: 1527fd1bd2b4cf0636251a36bc8ab37e81da8347 + OCMock: 35ae71d6a8fcc1b59434d561d1520b9dd4f15765 + Quick: dafc587e21eed9f4cab3249b9f9015b0b7a7f71d + +PODFILE CHECKSUM: b4f1f9fd02145326c8d1075e90b75b997c1e70a4 + +COCOAPODS: 1.2.0 diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/LICENSE b/Students/Benny/Les 1 OCMock/Pods/Faro/LICENSE new file mode 100644 index 0000000..07615f1 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 iCapps + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/README.md b/Students/Benny/Les 1 OCMock/Pods/Faro/README.md new file mode 100644 index 0000000..ea52f22 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/README.md @@ -0,0 +1,159 @@ +![](./Images/FaroShield.jpg) + +[![BuddyBuild](https://dashboard.buddybuild.com/api/statusImage?appID=57ea1d04856a610100f8208a&branch=develop&build=latest)](https://dashboard.buddybuild.com/apps/57ea1d04856a610100f8208a/build/latest) + [![Version](https://img.shields.io/cocoapods/v/Faro.svg?style=flat)](http://cocoapods.org/pods/Faro) [![License](https://img.shields.io/cocoapods/l/Faro.svg?style=flat)](http://cocoapods.org/pods/Faro) [![Platform](https://img.shields.io/cocoapods/p/Faro.svg?style=flat)](http://cocoapods.org/pods/Faro) +[![Language Swift 3.0](https://img.shields.io/badge/Language-Swift%203.0-orange.svg?style=flat)](https://swift.org) + +====== + +For a quick start follow the instructions below. For more in depth information on why and how we build Faro, the [wiki](https://github.com/icapps/ios-faro/wiki) page. + +## Concept +We build a service request by using a `Service` class as the point where you fire your `Call` and get a `Result`. + +### Features + +*Service* +* Service written to use Swift without using the Objective-C runtime +* Service cleanly encapsulates all the parameters to handle a network request in `Call`. +* Easily write a 'MockService' to load JSON from a local drive + +*Automagically Parse* +* Use our Deserialization and Serialization operators to parse relations and properties + +*Protocols* +* Because we use Protocols you can use any type including CoreData's `NSManagedObject` 💪🏼 + +*Mocking* +* Use `FaroService` singleton if you want to switch between data from the server or a file. +* Handy for unit tests 💪🏼 +* Handy if API is not yet available 🤓 + +## Define a Call + +You can write your example service so that a call becomes a oneliner. +```Swift +let call = Call(path: "posts", method: HTTPMethod.GET, rootNode: "rootNode") +// the rootNode is used to query the json in the response in `rootNode(from json:)` +``` +## Perform a Call + +Take a look at the `ServiceSpec`, in short: +```swift + let service = Service(configuration: Configuration(baseURL: "http://jsonplaceholder.typicode.com") + let call = Call(path: "posts") + + service.perform(call) { (result: Result) in + DispatchQueue.main.async { + switch result { + case .models(let models): + print("🎉 \(models)") + default: + print("💣 fail") + } + } + }) +``` +## Serialize / Deserialize + +Deserialization and Serialization can happen automagically. For a more detailed example you can take a look at the ParseableSpec tests. + +### Deserializable + +```swift +class Zoo: Deserializable { + var uuid: String? + var color: String? + var animal: Animal? + var date: Date? + var animalArray: [Animal]? + + required init?(from raw: Any) { + guard let json = raw as? [String: Any?] else { + return nil + } + self.uuid <-> json["uuid"] + self.color <-> json["color"] + self.animal <-> json["animal"] + self.animalArray <-> json["animalArray"] + self.date <-> (json["date"], "yyyy-MM-dd") + } +} + +``` +### Serializable + +```swift +extension Zoo: Serializable { + + var json: [String : Any?] { + get { + var json = [String: Any]() + json["uuid"] <-> self.uuid + json["color"] <-> self.color + json["animal"] <-> self.animal + json["animalArray"] <-> self.animalArray + json["date"] <-> self.date + return json + } + } +} +``` + +### Type with required property + +Because swift requires all properties to be set before we can call `map(from:)` on `self` you will have to do required properties manually. + +````swift +class Gail: Deserializable { + var cellNumber: String + var foodTicket: String? + + required init?(from raw: Any) { + guard let json = raw as? [String: String] else { + return nil + } + + do { + cellNumber = try parse("cellNumber", from: json) + } catch { + return nil + } + self.foodTicket <-> json["foodTicket"] + } + +} + +``` + + +## Requirements + +- iOS 8 or higher +- Because we use generics you can only use this pod in Swift only files. You can mix and Match with Objective-C but not with generic classes. Types [More info](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-ID53) + +## Installation + +Faro is available through [CocoaPods](http://cocoapods.org) and the [Swift Package Manager](https://swift.org/package-manager/). + +To install it with CocoaPods, add the following line to your Podfile: + +```ruby +pod "Faro" +``` + +## Contribution + +> Don't think too hard, try hard! + +More info on the [contribution guidelines](https://github.com/icapps/ios-faro/wiki/Contribution) wiki page. + +### Coding Guidelines + +We follow the [iCapps Coding guidelines](https://github.com/icapps/coding-guidelines/tree/master/iOS/Swift). + +We use Swiftlint to keep everything neat. + +## License + +Faro is available under the MIT license. See the LICENSE file for more info. diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Adaptor/Adaptable.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Adaptor/Adaptable.swift new file mode 100644 index 0000000..cf5cd6a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Adaptor/Adaptable.swift @@ -0,0 +1,5 @@ +import Foundation + +public protocol Adaptable: class { + func serialize(from data: Data, result: (Result ) -> ()) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Adaptor/JSONAdaptor.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Adaptor/JSONAdaptor.swift new file mode 100644 index 0000000..86cc91e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Adaptor/JSONAdaptor.swift @@ -0,0 +1,24 @@ +import Foundation + +open class JSONAdaptor: Adaptable { + + public init() { + + } + + open func serialize(from data: Data, result: (Result ) -> ()) { + do { + let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) + result(.json(json)) + } catch { + guard let faroError = error as? FaroError else { + print("💣 Unknown error \(error)") + result(.failure(FaroError.general)) + return + } + + result(.failure(faroError)) + } + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Call.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Call.swift new file mode 100644 index 0000000..d7cad92 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Call.swift @@ -0,0 +1,114 @@ +public enum HTTPMethod: String { + case GET, POST, PUT, DELETE, PATCH +} + +open class Call { + open let path: String + open let httpMethod: HTTPMethod + open var rootNode: String? + open var parameter: Parameter? + + public convenience init (path: String, method: HTTPMethod = .POST, rootNode: String? = nil, serializableModel: T) { + self.init(path: path, method: method, rootNode: rootNode, parameter: .jsonNode(serializableModel.json)) + } + /// Initializes Call to retreive object(s) from the server. + /// parameter rootNode: used to extract JSON in method `rootNode(from:)`. + public init(path: String, method: HTTPMethod = .GET, rootNode: String? = nil, parameter: Parameter? = nil) { + self.path = path + self.httpMethod = method + self.rootNode = rootNode + self.parameter = parameter + } + + open func request(withConfiguration configuration: Configuration) -> URLRequest? { + var request = URLRequest(url: URL(string: "\(configuration.baseURL)/\(path)")!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData) // uses default timeout + request.httpMethod = httpMethod.rawValue + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request = insertParameter(request: request) + return request + } + + /// Use to begin paring at the correct `rootnode`. + /// Override if you want different behaviour then: + /// `{"rootNode": }` ` is returned when `rootNode` is set. + open func rootNode(from json: Any) -> JsonNode { + let json = extractNodeIfNeeded(from: json) + + if let jsonArray = json as? [Any] { + return .nodeArray(jsonArray) + }else if let json = json as? [String: Any] { + return .nodeObject(json) + }else { + return .nodeNotFound(json: json ?? "") + } + } + + private func extractNodeIfNeeded(from json: Any?) -> Any? { + guard let rootNode = rootNode, let rootedJson = json as? [String: Any] else { + return json + } + + return rootedJson[rootNode] + } + + private func insertParameter(request: URLRequest) -> URLRequest { + guard let parameter = parameter else { + return request + } + + do { + switch parameter { + case .httpHeader(let headers): + return insertInHeaders(with: headers, request: request) + case .urlComponents(let components): + return insertInUrl(with: components, request: request) + case .jsonNode(let json): + return try insertInBody(with: json, request: request) + case .jsonArray(let jsonArray): + return try insertInBody(with: jsonArray, request: request) + } + } catch { + printFaroError(error) + return request + } + } + + private func insertInHeaders(with headers: [String: String], request: URLRequest) -> URLRequest { + var newRequest = request + for (key, value) in headers { + newRequest.addValue(value, forHTTPHeaderField: key) + } + return newRequest + } + + private func insertInUrl(with componentsDict: [String: String], request: URLRequest) -> URLRequest { + guard componentsDict.values.count > 0 else { + return request + } + + var newRequest: URLRequest! = request + var components = URLComponents(url: newRequest.url!, resolvingAgainstBaseURL: false) + if (components?.queryItems == nil) { + components?.queryItems = [URLQueryItem]() + } + let sortedComponents = componentsDict.sorted(by: { $0.0 < $1.0 }) + for (key, value) in sortedComponents { + components?.queryItems?.append(URLQueryItem(name: key, value: value)) + } + newRequest.url = components?.url + return newRequest + } + + private func insertInBody(with json: Any, request: URLRequest) throws -> URLRequest { + if request.httpMethod == HTTPMethod.GET.rawValue { + throw FaroError.malformed(info: "HTTP " + request.httpMethod! + " request can't have a body") + } + var newRequest = request + newRequest.httpBody = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) + + return newRequest + } + +} + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Configuration.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Configuration.swift new file mode 100644 index 0000000..16361f8 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Configuration.swift @@ -0,0 +1,20 @@ +import Foundation + +/// Use for different configurations for the specific environment you want to use for *Bar.* +open class Configuration { + open let baseURL: String + + /// For now we only support JSON. Can be Changed in the future + open let adaptor: Adaptable + open var url: URL? { + get { + return URL(string: baseURL) + } + } + + public init(baseURL: String, adaptor: Adaptable = JSONAdaptor()) { + self.baseURL = baseURL + self.adaptor = adaptor + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/DateParser.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/DateParser.swift new file mode 100644 index 0000000..6a0ef5c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/DateParser.swift @@ -0,0 +1,15 @@ +import Foundation + +class DateParser { + internal static let shared = DateParser() + internal let dateFormatter = DateFormatter() + internal var dateFormat: String { + get { + return dateFormatter.dateFormat + } set { + if dateFormatter.dateFormat != newValue { + dateFormatter.dateFormat = newValue + } + } + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/Deserializable.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/Deserializable.swift new file mode 100644 index 0000000..3b771ed --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/Deserializable.swift @@ -0,0 +1,14 @@ +import Foundation + +/// Sets data on a class `Type`. +public protocol Deserializable { + + init?(from raw: Any) + +} + +public protocol Updatable { + + func update(from raw: Any) throws + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/DeserializeFunctions.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/DeserializeFunctions.swift new file mode 100644 index 0000000..6a2d246 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/DeserializeFunctions.swift @@ -0,0 +1,77 @@ +import Foundation + +// MARK: - RawRepresentable Types + +// MARK: - String + +public func parse (_ named: String, from: [String: Any]) throws -> T! where T.RawValue == String { + if !named.isEmpty { + guard let raw = from[named] as? T.RawValue, let value = T(rawValue:raw) else { + throw FaroError.emptyValue(key: named) + } + return value + } else { + throw FaroError.emptyKey + } +} + +// MARK: - Int + +public func parse (_ named: String, from: [String: Any]) throws -> T! where T.RawValue == Int { + if !named.isEmpty { + guard let raw = from[named] as? T.RawValue, let value = T(rawValue:raw) else { + throw FaroError.emptyValue(key: named) + } + return value + } else { + throw FaroError.emptyKey + } +} + +// MARK: - Any Type + +public func parse (_ named: String, from: [String: Any]) throws -> T! { + if !named.isEmpty { + guard let value = from[named] as? T else { + throw FaroError.emptyValue(key: named) + } + return value + } else { + throw FaroError.emptyKey + } +} + +public func parse(_ named: String, from: [String: Any], format: String? = nil) throws -> Date! { + if let format = format { + DateParser.shared.dateFormat = format + } + if !named.isEmpty { + if let value = from[named] as? TimeInterval { + return Date(timeIntervalSince1970: value) + } else if from[named] is String && DateParser.shared.dateFormat.characters.count > 0 { + return DateParser.shared.dateFormatter.date(from: from[named] as! String) + } + throw FaroError.emptyValue(key: named) + } else { + throw FaroError.emptyKey + } +} + +public func parse(_ named: String, from: [String: Any]) throws -> T { + guard let json = from[named] as? [String: Any] else { + throw FaroError.emptyCollection(key: named, json: from) + } + guard let model = T(from: json) else { + throw FaroError.emptyCollection(key: named, json: from) + } + return model +} + +public func parse(_ named: String, from: [String: Any]) throws -> [T] { + if let json = from[named] as? [[String: Any]] { + return json.flatMap { T(from: $0) } + } else { + throw FaroError.emptyCollection(key: named, json: from) + } +} + diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/DeserializeOperators.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/DeserializeOperators.swift new file mode 100644 index 0000000..9912ca8 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Deserialize/DeserializeOperators.swift @@ -0,0 +1,105 @@ +import Foundation + +/// The operator we define assings a value. Therefore its Precendencegroup is AssignmentPrecedence. +/// Used for optional properties +infix operator <->: AssignmentPrecedence + + +public func <->

(lhs: inout P?, rhs: Any?) where P: Deserializable { + guard let dict = rhs as? [String: Any] else { + lhs = nil + return + } + lhs = P(from: dict) +} + +public func <->

(lhs: inout [P]?, rhs: Any?) where P: Deserializable { + guard let rawObjects = rhs as? [[String: Any]] else { + lhs = nil + return + } + lhs = rawObjects.flatMap { P(from: $0) } +} + +// MARK: - Deserialize operators + +// MARK: - Primitive Types - Single +public func <-> (lhs: inout Int?, rhs: Any?) { + lhs = rhs as? Int +} + +public func <-> (lhs: inout Double?, rhs: Any?) { + lhs = rhs as? Double +} + +public func <-> (lhs: inout Bool?, rhs: Any?) { + lhs = rhs as? Bool +} + +public func <-> (lhs: inout String?, rhs: Any?) { + lhs = rhs as? String +} + +public func <-> (lhs: inout Date?, rhs: TimeInterval?) { + guard let timeInterval = rhs else { + return + } + + lhs = Date(timeIntervalSince1970: timeInterval) +} + +public func <-> (lhs: inout Date?, rhs: (Any?, String)) { + guard let date = rhs.0 as? String else { + return + } + + DateParser.shared.dateFormat = rhs.1 + lhs = DateParser.shared.dateFormatter.date(from: date) +} + + +// MARK: - Primitive Types - Array +public func <-> (lhs: inout [Int]?, rhs: Any?) { + lhs = rhs as? [Int] +} + +public func <-> (lhs: inout [Double]?, rhs: Any?) { + lhs = rhs as? [Double] +} + +public func <-> (lhs: inout [Bool]?, rhs: Any?) { + lhs = rhs as? [Bool] +} + +public func <-> (lhs: inout [String]?, rhs: Any?) { + lhs = rhs as? [String] +} + +public func <-> (lhs: inout [Date]?, rhs: [TimeInterval]?) { + guard let rhs = rhs else { + lhs = nil + return + } + lhs = [Date]() + rhs.forEach { timeInterval in + lhs?.append(Date(timeIntervalSince1970: timeInterval)) + } + +} + +public func <-> (lhs: inout [Date]?, rhs: [(Any?, String)]?) { + guard let rhs = rhs else { + lhs = nil + return + } + + lhs = [Date]() + + rhs.forEach { dateTuple in + DateParser.shared.dateFormat = dateTuple.1 + if let dateString = dateTuple.0 as? String, let date = DateParser.shared.dateFormatter.date(from: dateString) { + lhs?.append(date) + } + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Error/ErrorPrinting.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Error/ErrorPrinting.swift new file mode 100644 index 0000000..743a020 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Error/ErrorPrinting.swift @@ -0,0 +1,48 @@ +import Foundation + +public func printFaroError(_ error: Error) { + var faroError = error + if !(error is FaroError) { + faroError = FaroError.nonFaroError(error) + } + switch faroError as! FaroError { + case .general: + print("💣 General service error") + case .invalidUrl(let url): + print("💣invalid url: \(url)") + case .invalidResponseData(_): + print("💣 Invalid response data") + case .invalidAuthentication: + print("💣 Invalid authentication") + case .shouldOverride: + print("💣 You should override this method") + case .nonFaroError(let nonFaroError): + print("💣 Error from service: \(nonFaroError)") + case .rootNodeNotFound(json: let json): + print("💣 Could not find root node in json: \(json)") + case .networkError(let networkError, let data): + if let data = data { + //TODO: FARO-29 Print this from the content type returned. + let string = String(data: data, encoding: .utf8) + print("💣 HTTP error: \(networkError) message: \(string)") + } else { + print("💣 HTTP error: \(networkError)") + } + case .emptyCollection: + print("💣 empty collection") + case .emptyKey: + print("💣 missing key") + case .emptyValue(let key): + print("❓no value for key " + key) + case .malformed(let info): + print("💣 \(info)") + case .serializationError: + print("💣serialization error") + case .updateNotPossible(json: let json, model: let model): + print("❓ update not possilbe with \(json) on model \(model)") + case .invalidSession(message: let message): + print("💀 you tried to perform a request on a session that is invalid") + print("💀 message: \(message)") + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Error/FaroError.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Error/FaroError.swift new file mode 100644 index 0000000..5a8b52e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Error/FaroError.swift @@ -0,0 +1,38 @@ +public enum FaroError: Error, Equatable { + public init(_ error: FaroError) { + self = error + } + + case general + case invalidUrl(String) + case invalidResponseData(Data?) + case invalidAuthentication + case shouldOverride + case nonFaroError(Error) + case rootNodeNotFound(json: Any) + case networkError(Int, data: Data?) + case emptyKey + case emptyValue(key: String) + case emptyCollection(key: String, json: [String: Any]) + case malformed(info: String) + case serializationError + case updateNotPossible(json: Any, model: Any) + case invalidSession(message: String) +} + +public func == (lhs: FaroError, rhs: FaroError) -> Bool { + switch (lhs, rhs) { + case (.general, .general): + return true + case (.invalidAuthentication, .invalidAuthentication): + return true + case (.invalidUrl(let url_lhs), .invalidUrl(let url_rhs)): // tailor:disable + return url_lhs == url_rhs + case (.invalidResponseData (_), .invalidResponseData (_)): + return true + case (.networkError(let lStatusCode, _ ), .networkError(let rStatusCode, _ )): + return lStatusCode == rStatusCode + default: + return false + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/FaroService.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/FaroService.swift new file mode 100644 index 0000000..852ca04 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/FaroService.swift @@ -0,0 +1,26 @@ +/// You can use this as a singleton that switches between using real data or data from a file. +/// To switch we use `MockSwitch` +open class FaroService: Service { + /// Set this to a service. You can chose the `MockService` if the server is not yet available + public static var sharedService: Service? + + public static func setup(with baseURL: String , session: FaroSessionable = FaroSession()) { + FaroService.sharedService = Service(configuration: Configuration(baseURL: baseURL), faroSession: session) + } + + /// Returns real or mocked service. Run `setup(with:session:)` before calling this function. + /// If you don't we default to returning the MockService + public static var shared: Service { + guard let sharedService = FaroService.sharedService else { + var message = " You should run FaroService.setup(with:) in the AppDelegate after startup to have a service pointing to a server." + printFaroError(FaroError.malformed(info: message)) + message = "🍞 Falling back on using the MockService." + printFaroError(FaroError.malformed(info: message)) + FaroService.sharedService = MockService() + return FaroService.sharedService! + } + + return sharedService + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/FaroSession.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/FaroSession.swift new file mode 100644 index 0000000..ca4a27f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/FaroSession.swift @@ -0,0 +1,84 @@ +// MARK: - Protocols + +public protocol FaroSessionable { + var session: URLSession {get} + + func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask + + func resume(_ task: URLSessionDataTask) +} + +public protocol FaroQueueSessionable: FaroSessionable { +} + +// MARK: - Classes + +/// `URLSession` is wrapped in this class to control datatasks creation. +open class FaroSession: FaroSessionable { + public let session: URLSession + + /// Is instanitated with a default `URLSession.shared` singleton or anything you provide. + public init(_ session : URLSession = URLSession.shared) { + self.session = session + } + + open func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask { + return session.dataTask(with: request, completionHandler: completionHandler) + } + + open func resume(_ task: URLSessionDataTask) { + task.resume() + } + +} + +// MARK: - Invalidate session + +/// All functions are forwarded to `URLSession` +public extension FaroSessionable { + + public func finishTasksAndInvalidate() { + session.finishTasksAndInvalidate() + } + + public func flush(completionHandler: @escaping () -> Void) { + session.flush(completionHandler: completionHandler) + } + + public func getTasksWithCompletionHandler(_ completionHandler: @escaping ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask]) -> Void) { + session.getTasksWithCompletionHandler(completionHandler) + } + + public func invalidateAndCancel() { + session.invalidateAndCancel() + } + + public func reset(completionHandler: @escaping () -> Void) { + session.reset(completionHandler: completionHandler) + } + +} +/// `URLSession` is wrapped in this class to control datatasks. +/// This class does not use a singled `URLSession.shared`. This means once you cancel the session this class becomes invalid, +/// any following task will fail. +open class FaroQueueSession: FaroQueueSessionable { + public let session: URLSession + + /// Instantiates with a default `URLSessionConfiguration` + /// # Warning + /// > You can cancell this request but then the session will become invalid + /// > If you provide the `URLSession.shared` singleton cancel will not work! + public init(_ session : URLSession = URLSession(configuration: URLSessionConfiguration.default)) { + self.session = session + } + + // Returns an upload data tasks that can continue when in the background + open func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask { + return session.dataTask(with: request, completionHandler: completionHandler) + } + + open func resume(_ task: URLSessionDataTask) { + task.resume() + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/JSONReader.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/JSONReader.swift new file mode 100644 index 0000000..56b87a0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/JSONReader.swift @@ -0,0 +1,62 @@ +class JSONReader: NSObject { + static func parseFile(named: String!, for bundle: Bundle) -> Any? { + var named = named.replacingOccurrences(of: "/", with: "_") + let start = named.startIndex + let end = named.index(named.startIndex, offsetBy: 1) + + let range = start..(_ call: Call, autoStart: Bool = true, jsonResult: @escaping (Result) -> ()) -> URLSessionDataTask? { + if let mockDictionary = mockDictionary { + jsonResult(.json(mockDictionary)) + return MockURLSessionTask() + } + + guard let url = url(from: call) else { + let faroError = FaroError.malformed(info: "No valid url") + printFaroError(faroError) + jsonResult(.failure(faroError)) + return MockURLSessionTask() + } + + guard let mockJSON = JSONReader.parseFile(named: url, for: bundle!) else { + let faroError = FaroError.malformed(info: "Could not find dummy file at \(url)") + printFaroError(faroError) + jsonResult(.failure(faroError)) + return MockURLSessionTask() + } + + jsonResult(.json(mockJSON)) + return MockURLSessionTask() + } + + /// You can override this for custom behaviour + /// by default returns the url from the call + open func url(from call: Call) -> String? { + let request = call.request(withConfiguration: configuration) + return request?.url?.absoluteString + } + +} + diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/MockSession.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/MockSession.swift new file mode 100644 index 0000000..7626315 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/MockSession.swift @@ -0,0 +1,110 @@ +import Foundation + +open class MockURLSession: URLSession { + + open override func invalidateAndCancel() { + // Do nothing + } + + open override func finishTasksAndInvalidate() { + // Do nothing + } + +} +open class MockSession: FaroQueueSessionable { + + public let session: URLSession + public var data: Data? + public var urlResponse: URLResponse? + public var error: Error? + + var completionHandlers = [Int : ((Data?, URLResponse?, Error?) -> ())]() + + public init(data: Data? = nil, urlResponse: URLResponse? = nil, error: Error? = nil) { + self.data = data + self.urlResponse = urlResponse + self.error = error + self.session = MockURLSession() + } + + open func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> ()) -> URLSessionDataTask { + let task = MockURLSessionTask() + completionHandlers[task.taskIdentifier] = completionHandler + return task + } + + open func resume(_ task: URLSessionDataTask) { + let completionHandler = completionHandlers[task.taskIdentifier] + completionHandler?(data, urlResponse, error) + } + +} + +open class MockAsyncSession: MockSession { + + private let delay: DispatchTimeInterval + + var tasksToFail: Set? + var mockFailedResponse = HTTPURLResponse(url: URL(string: "http://www.google.com")!, statusCode: 401, httpVersion:nil, headerFields: nil) + + public init(data: Data? = nil, urlResponse: URLResponse? = nil, error: Error? = nil, delay: DispatchTimeInterval = .nanoseconds(1)) { + self.delay = delay + super.init(data: data, urlResponse: urlResponse, error: error) + } + + open override func resume(_ task: URLSessionDataTask) { + let delayTime = DispatchTime.now() + delay + let completionHandler = completionHandlers[task.taskIdentifier] + DispatchQueue.main.asyncAfter(deadline: delayTime) { + (task as! MockURLSessionTask).mockedState = .completed + + if let tasksToFail = self.tasksToFail { + if tasksToFail.contains(task as! MockURLSessionTask) { + completionHandler?(self.data, self.mockFailedResponse, self.error) + } else { + completionHandler?(self.data, self.urlResponse, self.error) + } + } else { + completionHandler?(self.data, self.urlResponse, self.error) + } + } + } + +} + +open class MockURLSessionTask : URLSessionDataTask{ + + private let uuid: UUID + public override init() { + uuid = UUID() + super.init() + } + + override open var taskIdentifier: Int { + get { + return uuid.hashValue + } + } + + var mockedState: URLSessionTask.State = .suspended + + override open var state: URLSessionTask.State { + get { + return mockedState + } + } + + override open func cancel() { + mockedState = .canceling + } + + + override open func suspend() { + mockedState = .suspended + } + + override open func resume() { + mockedState = .running + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ParameterEnum.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ParameterEnum.swift new file mode 100644 index 0000000..32b9b1d --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ParameterEnum.swift @@ -0,0 +1,6 @@ +public enum Parameter { + case httpHeader([String: String]) + case jsonArray([[String: Any]]) + case jsonNode([String: Any]) + case urlComponents([String: String]) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Result.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Result.swift new file mode 100644 index 0000000..1d34365 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Result.swift @@ -0,0 +1,23 @@ +/// `Result` is used to deliver results mapped in the `Bar`. +public enum Result { + case model(M?) + case models([M]?) + /// The server returned a valid JSON response. + case json(Any) + case data(Foundation.Data) + /// Server returned with statuscode 200...201 but no response data. For Example Post + case ok + case failure(FaroError) +} + +public enum WriteResult { + case ok + case failure(FaroError) +} + +public enum JsonNode { + case nodeObject([String: Any]) + case nodeArray([Any]) + case nodeNotFound(json: Any) + case nodeNotSerialized +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Serialize/Serializable.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Serialize/Serializable.swift new file mode 100644 index 0000000..ebacf0f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Serialize/Serializable.swift @@ -0,0 +1,8 @@ +import Foundation + +/// Serializes any `Type` into json. +public protocol Serializable { + + var json: [String: Any] {get} + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Serialize/SerializeOperators.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Serialize/SerializeOperators.swift new file mode 100644 index 0000000..d477dcc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Serialize/SerializeOperators.swift @@ -0,0 +1,76 @@ +import Foundation + +/// MARK: - Serizalise operators + +/// Will put a 'Type' into 'Any?' Type that can receive it. +public func <->

(lhs: inout Any?, rhs: [P]?) where P: Serializable { + guard let rhs = rhs else { + return + } + var array = [[String: Any]]() + for serializable in rhs { + array.append(serializable.json) + } + lhs = array +} + +public func <->

(lhs: inout Any?, rhs: P?) where P: Serializable { + lhs = rhs?.json +} + +/// Handy operators + +public func <-> (lhs: inout Any?, rhs: String?) { + guard let rhs = rhs else { + return + } + lhs = rhs +} + +public func <-> (lhs: inout Any?, rhs: Int?) { + guard let rhs = rhs else { + return + } + lhs = rhs +} + +public func <-> (lhs: inout Any?, rhs: Bool?) { + guard let rhs = rhs else { + return + } + lhs = rhs +} + +public func <-> (lhs: inout Any?, rhs: Double?) { + guard let rhs = rhs else { + return + } + lhs = rhs +} + +public func <-> (lhs: inout Any?, rhs: Date?) { + guard let rhs = rhs else { + return + } + lhs = rhs.timeIntervalSince1970 +} + +/// Arrays + +public func <-> (lhs: inout Any?, rhs: [String]?) { + guard let rhs = rhs else { + return + } + lhs = rhs +} + +/// Serialize a date to the requested format as the string in the tupple +public func <-> (lhs: inout Any?, rhs: (Date?, String)) { + guard let date = rhs.0 else { + return + } + DateParser.shared.dateFormat = rhs.1 + lhs = DateParser.shared.dateFormatter.string(from: date) +} + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Service.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Service.swift new file mode 100644 index 0000000..7556847 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/Service.swift @@ -0,0 +1,309 @@ +// MARK: Class implementation + +/// Default implementation of a service. +/// Serves your `Call` to a server and parses the respons. +/// Response is delivered to you as a `Result` that you can use in a switch. You get the most detailed results with the functions below. +/// If you want you can use the convenience functions in the extension. They call these functions and print the errors by default. +/// If you need more control over the errors you can use these functions directly. +/// _Remark_: If you need to cancel, know when everything is done, service request to continue in the background use `ServiceQueue`. +/// _Warning_: The session holds a strong reference to it's delegates. You should invalidate or we do in at `deinit` +open class Service { + open let configuration: Configuration + + let faroSession: FaroSessionable + + public init(configuration: Configuration, faroSession: FaroSessionable = FaroSession()) { + self.configuration = configuration + self.faroSession = faroSession + } + + // MARK: - Results transformed to Model(s) + + // MARK: - Update + + /// The other `perform` methods create the model. This function updates the model. + /// - parameter call: gives the details to find the entity on the server + /// - parameter autostart: by default this is true. This means that `resume()` is called immeditatly on the `URLSessionDataTask` created by this function. + /// - parameter updateModel: JSON will be given to this model to update + /// - parameter modelResult: `Result` closure should be called with `case Model(M)` other cases are a failure. + /// - returns: URLSessionDataTask if the task could not be created that probably means the `URLSession` is invalid. + @discardableResult + open func perform(_ call: Call, on updateModel: M?, autoStart: Bool = true, modelResult: @escaping (Result) -> ()) -> URLSessionDataTask? { + + return performJsonResult(call, autoStart: autoStart) { (jsonResult: Result) in + switch jsonResult { + case .json(let json): + modelResult(self.handle(json: json, on: updateModel, call: call)) + default: + modelResult(jsonResult) + break + } + } + } + + // MARK: - Create + + /// On success create a model and updates it with the received JSON data. + /// - parameter call: gives the details to find the entity on the server + /// - parameter autostart: by default this is true. This means that `resume()` is called immeditatly on the `URLSessionDataTask` created by this function. + /// - parameter modelResult : `Result` closure should be called with `case Model(M)` other cases are a failure. + /// - returns: URLSessionDataTask if the task could not be created that probably means the `URLSession` is invalid. + @discardableResult + open func perform(_ call: Call, autoStart: Bool = true, modelResult: @escaping (Result) -> ()) -> URLSessionDataTask? { + + return performJsonResult(call, autoStart: autoStart) { (jsonResult: Result) in + switch jsonResult { + case .json(let json): + modelResult(self.handle(json: json, call: call)) + default: + modelResult(jsonResult) + break + } + } + } + + // MARK: - With Paging information + + /// On success create a model and updates it with the received JSON data. The JSON is also passed to `page` closure and can be inspected for paging information. + /// - parameter call: gives the details to find the entity on the server + /// - parameter autostart: by default this is true. This means that `resume()` is called immeditatly on the `URLSessionDataTask` created by this function. + /// - parameter modelResult : `Result` closure should be called with `case Model(M)` other cases are a failure. + /// - returns: URLSessionDataTask if the task could not be created that probably means the `URLSession` is invalid. + @discardableResult + open func perform(_ call: Call, page: @escaping(P?)->(), autoStart: Bool = true, modelResult: @escaping (Result) -> ()) -> URLSessionDataTask? { + + return performJsonResult(call, autoStart: autoStart) { (jsonResult: Result) in + switch jsonResult { + case .json(let json): + modelResult(self.handle(json: json, call: call)) + page(P(from: json)) + default: + modelResult(jsonResult) + break + } + } + } + + // MARK: - JSON results + + /// Handles incomming data and tries to parse the data as JSON. + /// - parameter call: gives the details to find the entity on the server + /// - parameter autostart: by default this is true. This means that `resume()` is called immeditatly on the `URLSessionDataTask` created by this function. + /// - parameter jsonResult: closure is called when valid or invalid json data is received. + /// - returns: URLSessionDataTask if the task could not be created that probably means the `URLSession` is invalid. + @discardableResult + open func performJsonResult(_ call: Call, autoStart: Bool = true, jsonResult: @escaping (Result) -> ()) -> URLSessionDataTask? { + + guard let request = call.request(withConfiguration: configuration) else { + jsonResult(.failure(FaroError.invalidUrl("\(configuration.baseURL)/\(call.path)"))) + return nil + } + + let task = faroSession.dataTask(with: request, completionHandler: { (data, response, error) in + let dataResult = self.handle(data: data, urlResponse: response, error: error) as Result + switch dataResult { + case .data(let data): + self.configuration.adaptor.serialize(from: data) { (serializedResult: Result) in + switch serializedResult { + case .json(json: let json): + jsonResult(.json(json)) + default: + jsonResult(serializedResult) + } + } + default: + jsonResult(dataResult) + } + + }) + + guard autoStart else { + return task + } + + faroSession.resume(task) + return task + } + + // MARK: - WRITE calls (like .POST, .PUT, ...) + /// Use this to write to the server when you do not need a data result, just ok. + /// If you expect a data result use `perform(call:result:)` + /// - parameter call: should be of a type that does not expect data in the result. + /// - parameter writeResult: `WriteResult` closure should be called with `.ok` other cases are a failure. + /// - returns: URLSessionDataTask if the task could not be created that probably means the `URLSession` is invalid. + @discardableResult + open func performWrite(_ writeCall: Call, autoStart: Bool = true, writeResult: @escaping (WriteResult) -> ()) -> URLSessionDataTask? { + + guard let request = writeCall.request(withConfiguration: configuration) else { + writeResult(.failure(FaroError.invalidUrl("\(configuration.baseURL)/\(writeCall.path)"))) + return nil + } + + let task = faroSession.dataTask(with: request, completionHandler: { (data, response, error) in + writeResult(self.handleWrite(data: data, urlResponse: response, error: error)) + }) + + guard autoStart else { + return task + } + + faroSession.resume(task) + return task + } + + // MARK: - Handles + + open func handleWrite(data: Data?, urlResponse: URLResponse?, error: Error?) -> WriteResult { + if let faroError = raisesFaroError(data: data, urlResponse: urlResponse, error: error) { + return .failure(faroError) + } + + return .ok + } + + open func handle(data: Data?, urlResponse: URLResponse?, error: Error?) -> Result { + + if let faroError = raisesFaroError(data: data, urlResponse: urlResponse, error: error) { + return .failure(faroError) + } + + if let data = data { + return .data(data) + } else { + return .ok + } + } + + open func handle(json: Any, on updateModel: M? = nil, call: Call) -> Result { + + let rootNode = call.rootNode(from: json) + switch rootNode { + case .nodeObject(let node): + return handleNode(node, on: updateModel, call: call) + case .nodeArray(let nodes): + return handleNodeArray(nodes, on: updateModel, call: call) + case .nodeNotFound(let json): + return Result.failure(.rootNodeNotFound(json: json)) + case .nodeNotSerialized: + return Result.failure(.serializationError) + } + } + + // MARK: - Internal + + func print(_ error: FaroError, and fail: (FaroError)->()) { + printFaroError(error) + fail(error) + } + + func handle(_ result: Result, and fail: (FaroError)->()) { + switch result { + case .failure(let faroError): + print(faroError, and: fail) + default: + let faroError = FaroError.general + printFaroError(faroError) + fail(faroError) + } + } + + // MARK: - Invalidate session + /// All functions are forwarded to `FaroSession` + + open func finishTasksAndInvalidate() { + faroSession.finishTasksAndInvalidate() + } + + open func flush(completionHandler: @escaping () -> Void) { + faroSession.flush(completionHandler: completionHandler) + } + + open func getTasksWithCompletionHandler(_ completionHandler: @escaping ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask]) -> Void) { + faroSession.getTasksWithCompletionHandler(completionHandler) + } + + open func invalidateAndCancel() { + faroSession.invalidateAndCancel() + } + + open func reset(completionHandler: @escaping () -> Void) { + faroSession.reset(completionHandler: completionHandler) + } + + deinit { + faroSession.finishTasksAndInvalidate() + } + +} + +// MARK: - Privates + +extension Service { + + fileprivate func raisesFaroError(data: Data?, urlResponse: URLResponse?, error: Error?)-> FaroError? { + guard error == nil else { + let returnError = FaroError.nonFaroError(error!) + printFaroError(returnError) + return returnError + } + + guard let httpResponse = urlResponse as? HTTPURLResponse else { + let returnError = FaroError.networkError(0, data: data) + printFaroError(returnError) + return returnError + } + + let statusCode = httpResponse.statusCode + guard statusCode < 400 else { + let returnError = FaroError.networkError(statusCode, data: data) + printFaroError(returnError) + return returnError + } + + guard 200...204 ~= statusCode else { + let returnError = FaroError.networkError(statusCode, data: data) + printFaroError(returnError) + return returnError + } + + return nil + } + + fileprivate func handleNodeArray(_ nodes: [Any], on updateModel: M? = nil, call: Call) -> Result { + if let _ = updateModel { + let faroError = FaroError.malformed(info: "Could not parse \(nodes) for type \(M.self) into updateModel \(updateModel). We currently only support updating of single objects. An arry of objects was returned") + printFaroError(faroError) + return Result.failure(faroError) + } + var models = [M]() + for node in nodes { + if let model = M(from: node) { + models.append(model) + } else { + let faroError = FaroError.malformed(info: "Could not parse \(nodes) for type \(M.self)") + printFaroError(faroError) + return Result.failure(faroError) + } + } + return Result.models(models) + } + + fileprivate func handleNode(_ node: [String: Any], on updateModel: M? = nil, call: Call) -> Result { + if let updateModel = updateModel as? Updatable { + do { + try updateModel.update(from: node) + }catch { + return Result.failure(.nonFaroError(error)) + } + return Result.model(updateModel as? M) + } else { + if let _ = updateModel { + let faroError = FaroError.malformed(info: "An updateModel \(updateModel) was provided. But does not conform to protocol \(Updatable.self)") + printFaroError(faroError) + } + return Result.model(M(from: node)) + } + } + + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ServiceConvenienceExtension.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ServiceConvenienceExtension.swift new file mode 100644 index 0000000..6baa1dc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ServiceConvenienceExtension.swift @@ -0,0 +1,123 @@ +import Foundation + +/// The perform methods are preferred but these methods are for convenience. +/// They do some default error handling. +/// These functions are deprecated!!! +extension Service { + + // MARK: - Results transformed to Model(s) + + // MARK: - Update + + /// Performs the call to the server. Provide a model + /// - parameter call: where can the server be found? + /// - parameter fail: if we cannot initialize the model this call will fail and print the failure. + /// - parameter ok: returns initialized model + @available(*, deprecated: 1.1, obsoleted: 2.0, message: "You should use the `perform` functions in `Service` with result enum.") + open func performUpdate(_ call: Call, on updateModel: ModelType, autoStart: Bool = true, fail: @escaping (FaroError)->(), ok:@escaping (ModelType)->()) { + perform(call, on: updateModel, autoStart: autoStart) { (result) in + switch result { + case .model(let model): + guard let model = model else { + let faroError = FaroError.malformed(info: "UpdateModel \(updateModel) could not be updated. Maybe you did not implement update correctly failed?") + self.print(faroError, and: fail) + return + } + ok(model) + case .models( _ ): + let faroError = FaroError.malformed(info: "Requested a single response be received a collection.") + self.print(faroError, and: fail) + default: + self.handle(result, and: fail) + } + } + } + + // MARK: - Create + + // MARK: - Single model response + + /// Performs the call to the server. Provide a model + /// - parameter call: where can the server be found? + /// - parameter fail: if we cannot initialize the model this call will fail and print the failure. + /// - parameter ok: returns initialized model + @available(*, deprecated: 1.1, obsoleted: 2.0, message: "You should use the `perform` functions in `Service` with result enum.") + open func performSingle(_ call: Call, autoStart: Bool = true, fail: @escaping (FaroError)->(), ok:@escaping (ModelType)->()) { + perform(call, autoStart: autoStart) { (result: Result) in + switch result { + case .model(let model): + guard let model = model else { + let faroError = FaroError.malformed(info: "Model could not be initialized. Maybe your init(from raw:) failed?") + self.print(faroError, and: fail) + return + } + ok(model) + case .models( _ ): + let faroError = FaroError.malformed(info: "Requested a single response be received a collection.") + self.print(faroError, and: fail) + default: + self.handle(result, and: fail) + } + } + } + + // MARK: - Collection model response + + /// Performs the call to the server. Provide a model + /// - parameter call: where can the server be found? + /// - parameter fail: if we cannot initialize the model this call will fail and print the failure. + /// - parameter ok: returns initialized array of models + @available(*, deprecated: 1.1, obsoleted: 2.0, message: "You should use the `perform` functions in `Service` with result enum.") + open func performCollection(_ call: Call, autoStart: Bool = true, fail: @escaping (FaroError)->(), ok:@escaping ([ModelType])->()) { + perform(call, autoStart: autoStart) { (result: Result) in + switch result { + case .models(let models): + guard let models = models else { + let faroError = FaroError.malformed(info: "Model could not be initialized. Maybe your init(from raw:) failed?") + self.print(faroError, and: fail) + return + } + ok(models) + default: + self.handle(result, and: fail) + } + } + } + + // MARK: - With Paging information + + @available(*, deprecated: 1.1, obsoleted: 2.0, message: "You should use the `perform` functions in `Service` with result enum.") + open func performSingle(_ call: Call, autoStart: Bool = true, page: @escaping(PagingType?)->(), fail: @escaping (FaroError)->(), ok:@escaping (ModelType)->()) { + perform(call, page: page, autoStart: autoStart) { (result: Result) in + switch result { + case .model(let model): + guard let model = model else { + let faroError = FaroError.malformed(info: "Model could not be initialized. Maybe your init(from raw:) failed?") + self.print(faroError, and: fail) + return + } + ok(model) + default: + self.handle(result, and: fail) + } + } + } + + @available(*, deprecated: 1.1, obsoleted: 2.0, message: "You should use the `perform` functions in `Service` with result enum.") + open func performCollection(_ call: Call, page: @escaping(PagingType?)->(), fail: @escaping (FaroError)->(), ok:@escaping ([ModelType])->()) { + perform(call, page: page) { (result: Result) in + switch result { + case .models(let models): + guard let models = models else { + let faroError = FaroError.malformed(info: "Models could not be initialized. Maybe your init(from raw:) failed?") + self.print(faroError, and: fail) + return + } + ok(models) + default: + self.handle(result, and: fail) + } + } + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ServiceQueue.swift b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ServiceQueue.swift new file mode 100644 index 0000000..3966120 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Faro/Sources/ServiceQueue.swift @@ -0,0 +1,130 @@ +import Foundation + +/// Tasks can be autostarted or started manualy. The taks are still handled bij an URLSession like in `Service`, but +/// we store the TaskIdentifiers. When a task completes it is removed from the queue and `final()`. +/// It has its own `URLSession` which it invalidates once the queue is finished. You need to create another instance of `ServiceQueue` to be able to +/// perform new request after you fired the first queue. +open class ServiceQueue: Service { + + var taskQueue: Set + var failedTasks: Set? + + private let final: (_ failedTasks: Set?)->() + + /// Creates a queue that lasts until final is called. When all request in the queue are finished the session becomes invalid. + /// For future queued request you have to create a new ServiceQueue instance. + /// - parameter configuration: Faro service configuration + /// - parameter faroSession: You can provide a custom `URLSession` via `FaroQueueSession`. + /// - parameter final: closure is callen when all requests are performed. + public init(configuration: Configuration, faroSession: FaroQueueSessionable = FaroQueueSession(), final: @escaping(_ failedTasks: Set?)->()) { + self.final = final + taskQueue = Set() + super.init(configuration: configuration, faroSession: faroSession) + } + + open override func performJsonResult(_ call: Call, autoStart: Bool = false, jsonResult: @escaping (Result) -> ()) -> URLSessionDataTask? { + var task: URLSessionDataTask? + task = super.performJsonResult(call, autoStart: autoStart) { [weak self] (stage1JsonResult: Result) in + guard let strongSelf = self else { + jsonResult(stage1JsonResult) + return + } + /// Store ID of failed tasks to report + switch stage1JsonResult { + case .json(_), .ok: + strongSelf.cleanupQueue(for: task) + case .failure(_): + strongSelf.cleanupQueue(for: task, didFail: true) + default: + strongSelf.cleanupQueue(for: task) + } + + + jsonResult(stage1JsonResult) + strongSelf.shouldCallFinal() + } + + add(task) + return task + } + + open override func performWrite(_ writeCall: Call, autoStart: Bool, writeResult: @escaping (WriteResult) -> ()) -> URLSessionDataTask? { + var task: URLSessionDataTask? + task = super.performWrite(writeCall, autoStart: autoStart) { [weak self] (result) in + guard let strongSelf = self else { + writeResult(result) + return + } + + switch result { + case .ok: + strongSelf.cleanupQueue(for: task) + default: + strongSelf.cleanupQueue(for: task, didFail: true) + } + + writeResult(result) + strongSelf.shouldCallFinal() + } + add(task) + return task + } + + private func add(_ task: URLSessionDataTask?) { + guard let createdTask = task else { + printFaroError(FaroError.invalidSession(message: "\(self) tried to ")) + return + } + taskQueue.insert(createdTask) + } + + private func cleanupQueue(for task: URLSessionDataTask?, didFail: Bool = false) { + if let task = task { + let _ = taskQueue.remove(task) + if(didFail) { + if failedTasks == nil { + failedTasks = Set() + } + failedTasks?.insert(task) + } + } + } + + private func shouldCallFinal() { + if !hasOustandingTasks { + final(failedTasks) + finishTasksAndInvalidate() + } + } + + // MARK: - Interact with tasks + + open var hasOustandingTasks: Bool { + get { + return taskQueue.count > 0 + } + } + + open func resume(_ task: URLSessionDataTask) { + faroSession.resume(task) + } + + open func resumeAll() { + let notStartedTasks = taskQueue.filter { $0.state != .running || $0.state != .completed} + notStartedTasks.forEach { (task) in + faroSession.resume(task) + } + } + + // MARK: - Invalidate session overrides + + override open func invalidateAndCancel() { + taskQueue.removeAll() + failedTasks?.removeAll() + faroSession.invalidateAndCancel() + } + + deinit { + faroSession.finishTasksAndInvalidate() + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Manifest.lock b/Students/Benny/Les 1 OCMock/Pods/Manifest.lock new file mode 100644 index 0000000..d43d771 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Manifest.lock @@ -0,0 +1,21 @@ +PODS: + - Faro (1.0.9) + - Nimble (6.0.1) + - OCMock (3.4) + - Quick (1.1.0) + +DEPENDENCIES: + - Faro + - Nimble + - OCMock (~> 3.4) + - Quick + +SPEC CHECKSUMS: + Faro: 62a1fedc46cee416e4eb9dddaff7fd4ed071834a + Nimble: 1527fd1bd2b4cf0636251a36bc8ab37e81da8347 + OCMock: 35ae71d6a8fcc1b59434d561d1520b9dd4f15765 + Quick: dafc587e21eed9f4cab3249b9f9015b0b7a7f71d + +PODFILE CHECKSUM: b4f1f9fd02145326c8d1075e90b75b997c1e70a4 + +COCOAPODS: 1.2.0 diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/LICENSE b/Students/Benny/Les 1 OCMock/Pods/Nimble/LICENSE new file mode 100644 index 0000000..82b84bf --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/README.md b/Students/Benny/Les 1 OCMock/Pods/Nimble/README.md new file mode 100644 index 0000000..ecf9501 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/README.md @@ -0,0 +1,1443 @@ +# Nimble + +Use Nimble to express the expected outcomes of Swift +or Objective-C expressions. Inspired by +[Cedar](https://github.com/pivotal/cedar). + +```swift +// Swift +expect(1 + 1).to(equal(2)) +expect(1.2).to(beCloseTo(1.1, within: 0.1)) +expect(3) > 2 +expect("seahorse").to(contain("sea")) +expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi")) +expect(ocean.isClean).toEventually(beTruthy()) +``` + +# How to Use Nimble + + + +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [Some Background: Expressing Outcomes Using Assertions in XCTest](#some-background-expressing-outcomes-using-assertions-in-xctest) +- [Nimble: Expectations Using `expect(...).to`](#nimble-expectations-using-expectto) + - [Custom Failure Messages](#custom-failure-messages) + - [Type Safety](#type-safety) + - [Operator Overloads](#operator-overloads) + - [Lazily Computed Values](#lazily-computed-values) + - [C Primitives](#c-primitives) + - [Asynchronous Expectations](#asynchronous-expectations) + - [Objective-C Support](#objective-c-support) + - [Disabling Objective-C Shorthand](#disabling-objective-c-shorthand) +- [Built-in Matcher Functions](#built-in-matcher-functions) + - [Type Checking](#type-checking) + - [Equivalence](#equivalence) + - [Identity](#identity) + - [Comparisons](#comparisons) + - [Types/Classes](#typesclasses) + - [Truthiness](#truthiness) + - [Swift Assertions](#swift-assertions) + - [Swift Error Handling](#swift-error-handling) + - [Exceptions](#exceptions) + - [Collection Membership](#collection-membership) + - [Strings](#strings) + - [Checking if all elements of a collection pass a condition](#checking-if-all-elements-of-a-collection-pass-a-condition) + - [Verify collection count](#verify-collection-count) + - [Verify a notification was posted](#verifying-a-notification-was-posted) + - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers) +- [Writing Your Own Matchers](#writing-your-own-matchers) + - [Lazy Evaluation](#lazy-evaluation) + - [Type Checking via Swift Generics](#type-checking-via-swift-generics) + - [Customizing Failure Messages](#customizing-failure-messages) + - [Supporting Objective-C](#supporting-objective-c) + - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers) +- [Installing Nimble](#installing-nimble) + - [Installing Nimble as a Submodule](#installing-nimble-as-a-submodule) + - [Installing Nimble via CocoaPods](#installing-nimble-via-cocoapods) + - [Using Nimble without XCTest](#using-nimble-without-xctest) + + + +# Some Background: Expressing Outcomes Using Assertions in XCTest + +Apple's Xcode includes the XCTest framework, which provides +assertion macros to test whether code behaves properly. +For example, to assert that `1 + 1 = 2`, XCTest has you write: + +```swift +// Swift + +XCTAssertEqual(1 + 1, 2, "expected one plus one to equal two") +``` + +Or, in Objective-C: + +```objc +// Objective-C + +XCTAssertEqual(1 + 1, 2, @"expected one plus one to equal two"); +``` + +XCTest assertions have a couple of drawbacks: + +1. **Not enough macros.** There's no easy way to assert that a string + contains a particular substring, or that a number is less than or + equal to another. +2. **It's hard to write asynchronous tests.** XCTest forces you to write + a lot of boilerplate code. + +Nimble addresses these concerns. + +# Nimble: Expectations Using `expect(...).to` + +Nimble allows you to express expectations using a natural, +easily understood language: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).to(equal("Squee!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).to(equal(@"Squee!")); +``` + +> The `expect` function autocompletes to include `file:` and `line:`, + but these parameters are optional. Use the default values to have + Xcode highlight the correct line when an expectation is not met. + +To perform the opposite expectation--to assert something is *not* +equal--use `toNot` or `notTo`: + +```swift +// Swift + +import Nimble + +expect(seagull.squawk).toNot(equal("Oh, hello there!")) +expect(seagull.squawk).notTo(equal("Oh, hello there!")) +``` + +```objc +// Objective-C + +@import Nimble; + +expect(seagull.squawk).toNot(equal(@"Oh, hello there!")); +expect(seagull.squawk).notTo(equal(@"Oh, hello there!")); +``` + +## Custom Failure Messages + +Would you like to add more information to the test's failure messages? Use the `description` optional argument to add your own text: + +```swift +// Swift + +expect(1 + 1).to(equal(3)) +// failed - expected to equal <3>, got <2> + +expect(1 + 1).to(equal(3), description: "Make sure libKindergartenMath is loaded") +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3>, got <2> +``` + +Or the *WithDescription version in Objective-C: + +```objc +// Objective-C + +@import Nimble; + +expect(@(1+1)).to(equal(@3)); +// failed - expected to equal <3.0000>, got <2.0000> + +expect(@(1+1)).toWithDescription(equal(@3), @"Make sure libKindergartenMath is loaded"); +// failed - Make sure libKindergartenMath is loaded +// expected to equal <3.0000>, got <2.0000> +``` + +## Type Safety + +Nimble makes sure you don't compare two types that don't match: + +```swift +// Swift + +// Does not compile: +expect(1 + 1).to(equal("Squee!")) +``` + +> Nimble uses generics--only available in Swift--to ensure + type correctness. That means type checking is + not available when using Nimble in Objective-C. :sob: + +## Operator Overloads + +Tired of so much typing? With Nimble, you can use overloaded operators +like `==` for equivalence, or `>` for comparisons: + +```swift +// Swift + +// Passes if squawk does not equal "Hi!": +expect(seagull.squawk) != "Hi!" + +// Passes if 10 is greater than 2: +expect(10) > 2 +``` + +> Operator overloads are only available in Swift, so you won't be able + to use this syntax in Objective-C. :broken_heart: + +## Lazily Computed Values + +The `expect` function doesn't evaluate the value it's given until it's +time to match. So Nimble can test whether an expression raises an +exception once evaluated: + +```swift +// Swift + +// Note: Swift currently doesn't have exceptions. +// Only Objective-C code can raise exceptions +// that Nimble will catch. +// (see https://github.com/Quick/Nimble/issues/220#issuecomment-172667064) +let exception = NSException( + name: NSInternalInconsistencyException, + reason: "Not enough fish in the sea.", + userInfo: ["something": "is fishy"]) +expect { exception.raise() }.to(raiseException()) + +// Also, you can customize raiseException to be more specific +expect { exception.raise() }.to(raiseException(named: NSInternalInconsistencyException)) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea")) +expect { exception.raise() }.to(raiseException( + named: NSInternalInconsistencyException, + reason: "Not enough fish in the sea", + userInfo: ["something": "is fishy"])) +``` + +Objective-C works the same way, but you must use the `expectAction` +macro when making an expectation on an expression that has no return +value: + +```objc +// Objective-C + +NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"Not enough fish in the sea." + userInfo:nil]; +expectAction(^{ [exception raise]; }).to(raiseException()); + +// Use the property-block syntax to be more specific. +expectAction(^{ [exception raise]; }).to(raiseException().named(NSInternalInconsistencyException)); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea")); +expectAction(^{ [exception raise]; }).to(raiseException(). + named(NSInternalInconsistencyException). + reason("Not enough fish in the sea"). + userInfo(@{@"something": @"is fishy"})); + +// You can also pass a block for custom matching of the raised exception +expectAction(exception.raise()).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(NSInternalInconsistencyException)); +})); +``` + +## C Primitives + +Some testing frameworks make it hard to test primitive C values. +In Nimble, it just works: + +```swift +// Swift + +let actual: CInt = 1 +let expectedValue: CInt = 1 +expect(actual).to(equal(expectedValue)) +``` + +In fact, Nimble uses type inference, so you can write the above +without explicitly specifying both types: + +```swift +// Swift + +expect(1 as CInt).to(equal(1)) +``` + +> In Objective-C, Nimble only supports Objective-C objects. To + make expectations on primitive C values, wrap then in an object + literal: + + ```objc + expect(@(1 + 1)).to(equal(@2)); + ``` + +## Asynchronous Expectations + +In Nimble, it's easy to make expectations on values that are updated +asynchronously. Just use `toEventually` or `toEventuallyNot`: + +```swift +// Swift + +dispatch_async(dispatch_get_main_queue()) { + ocean.add("dolphins") + ocean.add("whales") +} +expect(ocean).toEventually(contain("dolphins", "whales")) +``` + + +```objc +// Objective-C +dispatch_async(dispatch_get_main_queue(), ^{ + [ocean add:@"dolphins"]; + [ocean add:@"whales"]; +}); +expect(ocean).toEventually(contain(@"dolphins", @"whales")); +``` + +Note: toEventually triggers its polls on the main thread. Blocking the main +thread will cause Nimble to stop the run loop. This can cause test pollution +for whatever incomplete code that was running on the main thread. Blocking the +main thread can be caused by blocking IO, calls to sleep(), deadlocks, and +synchronous IPC. + +In the above example, `ocean` is constantly re-evaluated. If it ever +contains dolphins and whales, the expectation passes. If `ocean` still +doesn't contain them, even after being continuously re-evaluated for one +whole second, the expectation fails. + +Sometimes it takes more than a second for a value to update. In those +cases, use the `timeout` parameter: + +```swift +// Swift + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).toEventually(contain("starfish"), timeout: 3) + +// Evaluate someValue every 0.2 seconds repeatedly until it equals 100, or fails if it timeouts after 5.5 seconds. +expect(someValue).toEventually(equal(100), timeout: 5.5, pollInterval: 0.2) +``` + +```objc +// Objective-C + +// Waits three seconds for ocean to contain "starfish": +expect(ocean).withTimeout(3).toEventually(contain(@"starfish")); +``` + +You can also provide a callback by using the `waitUntil` function: + +```swift +// Swift + +waitUntil { done in + // do some stuff that takes a while... + NSThread.sleepForTimeInterval(0.5) + done() +} +``` + +```objc +// Objective-C + +waitUntil(^(void (^done)(void)){ + // do some stuff that takes a while... + [NSThread sleepForTimeInterval:0.5]; + done(); +}); +``` + +`waitUntil` also optionally takes a timeout parameter: + +```swift +// Swift + +waitUntil(timeout: 10) { done in + // do some stuff that takes a while... + NSThread.sleepForTimeInterval(1) + done() +} +``` + +```objc +// Objective-C + +waitUntilTimeout(10, ^(void (^done)(void)){ + // do some stuff that takes a while... + [NSThread sleepForTimeInterval:1]; + done(); +}); +``` + +Note: waitUntil triggers its timeout code on the main thread. Blocking the main +thread will cause Nimble to stop the run loop to continue. This can cause test +pollution for whatever incomplete code that was running on the main thread. +Blocking the main thread can be caused by blocking IO, calls to sleep(), +deadlocks, and synchronous IPC. + +In some cases (e.g. when running on slower machines) it can be useful to modify +the default timeout and poll interval values. This can be done as follows: + +```swift +// Swift + +// Increase the global timeout to 5 seconds: +Nimble.AsyncDefaults.Timeout = 5 + +// Slow the polling interval to 0.1 seconds: +Nimble.AsyncDefaults.PollInterval = 0.1 +``` + +## Objective-C Support + +Nimble has full support for Objective-C. However, there are two things +to keep in mind when using Nimble in Objective-C: + +1. All parameters passed to the `expect` function, as well as matcher + functions like `equal`, must be Objective-C objects or can be converted into + an `NSObject` equivalent: + + ```objc + // Objective-C + + @import Nimble; + + expect(@(1 + 1)).to(equal(@2)); + expect(@"Hello world").to(contain(@"world")); + + // Boxed as NSNumber * + expect(2).to(equal(2)); + expect(1.2).to(beLessThan(2.0)); + expect(true).to(beTruthy()); + + // Boxed as NSString * + expect("Hello world").to(equal("Hello world")); + + // Boxed as NSRange + expect(NSMakeRange(1, 10)).to(equal(NSMakeRange(1, 10))); + ``` + +2. To make an expectation on an expression that does not return a value, + such as `-[NSException raise]`, use `expectAction` instead of + `expect`: + + ```objc + // Objective-C + + expectAction(^{ [exception raise]; }).to(raiseException()); + ``` + +The following types are currently converted to an `NSObject` type: + + - **C Numeric types** are converted to `NSNumber *` + - `NSRange` is converted to `NSValue *` + - `char *` is converted to `NSString *` + +For the following matchers: + +- `equal` +- `beGreaterThan` +- `beGreaterThanOrEqual` +- `beLessThan` +- `beLessThanOrEqual` +- `beCloseTo` +- `beTrue` +- `beFalse` +- `beTruthy` +- `beFalsy` +- `haveCount` + +If you would like to see more, [file an issue](https://github.com/Quick/Nimble/issues). + +## Disabling Objective-C Shorthand + +Nimble provides a shorthand for expressing expectations using the +`expect` function. To disable this shorthand in Objective-C, define the +`NIMBLE_DISABLE_SHORT_SYNTAX` macro somewhere in your code before +importing Nimble: + +```objc +#define NIMBLE_DISABLE_SHORT_SYNTAX 1 + +@import Nimble; + +NMB_expect(^{ return seagull.squawk; }, __FILE__, __LINE__).to(NMB_equal(@"Squee!")); +``` + +> Disabling the shorthand is useful if you're testing functions with + names that conflict with Nimble functions, such as `expect` or + `equal`. If that's not the case, there's no point in disabling the + shorthand. + +# Built-in Matcher Functions + +Nimble includes a wide variety of matcher functions. + +## Type Checking + +Nimble supports checking the type membership of any kind of object, whether +Objective-C conformant or not: + +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// The following tests pass +expect(1).to(beKindOf(Int.self)) +expect("turtle").to(beKindOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).to(beKindOf(SomeProtocol.self)) +expect(classObject).to(beKindOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beKindOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).to(beKindOf(SomeProtocol.self)) +expect(structObject).to(beKindOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beKindOf(SomeClassConformingToProtocol.self)) +``` + +```objc +// Objective-C + +// The following tests pass +NSMutableArray *array = [NSMutableArray array]; +expect(array).to(beAKindOf([NSArray class])); +expect(@1).toNot(beAKindOf([NSNull class])); +``` + +Objects can be tested for their exact types using the `beAnInstanceOf` matcher: +```swift +// Swift + +protocol SomeProtocol{} +class SomeClassConformingToProtocol: SomeProtocol{} +struct SomeStructConformingToProtocol: SomeProtocol{} + +// Unlike the 'beKindOf' matcher, the 'beAnInstanceOf' matcher only +// passes if the object is the EXACT type requested. The following +// tests pass -- note its behavior when working in an inheritance hierarchy. +expect(1).to(beAnInstanceOf(Int.self)) +expect("turtle").to(beAnInstanceOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(classObject).to(beAnInstanceOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beAnInstanceOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).toNot(beAnInstanceOf(SomeProtocol.self)) +expect(structObject).to(beAnInstanceOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beAnInstanceOf(SomeClassConformingToProtocol.self)) +```` + +## Equivalence + +```swift +// Swift + +// Passes if actual is equivalent to expected: +expect(actual).to(equal(expected)) +expect(actual) == expected + +// Passes if actual is not equivalent to expected: +expect(actual).toNot(equal(expected)) +expect(actual) != expected +``` + +```objc +// Objective-C + +// Passes if actual is equivalent to expected: +expect(actual).to(equal(expected)) + +// Passes if actual is not equivalent to expected: +expect(actual).toNot(equal(expected)) +``` + +Values must be `Equatable`, `Comparable`, or subclasses of `NSObject`. +`equal` will always fail when used to compare one or more `nil` values. + +## Identity + +```swift +// Swift + +// Passes if actual has the same pointer address as expected: +expect(actual).to(beIdenticalTo(expected)) +expect(actual) === expected + +// Passes if actual does not have the same pointer address as expected: +expect(actual).toNot(beIdenticalTo(expected)) +expect(actual) !== expected +``` + +Its important to remember that `beIdenticalTo` only makes sense when comparing types with reference semantics, which have a notion of identity. In Swift, that means a `class`. This matcher will not work with types with value semantics such as `struct` or `enum`. If you need to compare two value types, you can either compare individual properties or if it makes sense to do so, make your type implement `Equatable` and use Nimble's equivalence matchers instead. + + +```objc +// Objective-C + +// Passes if actual has the same pointer address as expected: +expect(actual).to(beIdenticalTo(expected)); + +// Passes if actual does not have the same pointer address as expected: +expect(actual).toNot(beIdenticalTo(expected)); +``` + +## Comparisons + +```swift +// Swift + +expect(actual).to(beLessThan(expected)) +expect(actual) < expected + +expect(actual).to(beLessThanOrEqualTo(expected)) +expect(actual) <= expected + +expect(actual).to(beGreaterThan(expected)) +expect(actual) > expected + +expect(actual).to(beGreaterThanOrEqualTo(expected)) +expect(actual) >= expected +``` + +```objc +// Objective-C + +expect(actual).to(beLessThan(expected)); +expect(actual).to(beLessThanOrEqualTo(expected)); +expect(actual).to(beGreaterThan(expected)); +expect(actual).to(beGreaterThanOrEqualTo(expected)); +``` + +> Values given to the comparison matchers above must implement + `Comparable`. + +Because of how computers represent floating point numbers, assertions +that two floating point numbers be equal will sometimes fail. To express +that two numbers should be close to one another within a certain margin +of error, use `beCloseTo`: + +```swift +// Swift + +expect(actual).to(beCloseTo(expected, within: delta)) +``` + +```objc +// Objective-C + +expect(actual).to(beCloseTo(expected).within(delta)); +``` + +For example, to assert that `10.01` is close to `10`, you can write: + +```swift +// Swift + +expect(10.01).to(beCloseTo(10, within: 0.1)) +``` + +```objc +// Objective-C + +expect(@(10.01)).to(beCloseTo(@10).within(0.1)); +``` + +There is also an operator shortcut available in Swift: + +```swift +// Swift + +expect(actual) ≈ expected +expect(actual) ≈ (expected, delta) + +``` +(Type Option-x to get ≈ on a U.S. keyboard) + +The former version uses the default delta of 0.0001. Here is yet another way to do this: + +```swift +// Swift + +expect(actual) ≈ expected ± delta +expect(actual) == expected ± delta + +``` +(Type Option-Shift-= to get ± on a U.S. keyboard) + +If you are comparing arrays of floating point numbers, you'll find the following useful: + +```swift +// Swift + +expect([0.0, 2.0]) ≈ [0.0001, 2.0001] +expect([0.0, 2.0]).to(beCloseTo([0.1, 2.1], within: 0.1)) + +``` + +> Values given to the `beCloseTo` matcher must be coercable into a + `Double`. + +## Types/Classes + +```swift +// Swift + +// Passes if instance is an instance of aClass: +expect(instance).to(beAnInstanceOf(aClass)) + +// Passes if instance is an instance of aClass or any of its subclasses: +expect(instance).to(beAKindOf(aClass)) +``` + +```objc +// Objective-C + +// Passes if instance is an instance of aClass: +expect(instance).to(beAnInstanceOf(aClass)); + +// Passes if instance is an instance of aClass or any of its subclasses: +expect(instance).to(beAKindOf(aClass)); +``` + +> Instances must be Objective-C objects: subclasses of `NSObject`, + or Swift objects bridged to Objective-C with the `@objc` prefix. + +For example, to assert that `dolphin` is a kind of `Mammal`: + +```swift +// Swift + +expect(dolphin).to(beAKindOf(Mammal)) +``` + +```objc +// Objective-C + +expect(dolphin).to(beAKindOf([Mammal class])); +``` + +> `beAnInstanceOf` uses the `-[NSObject isMemberOfClass:]` method to + test membership. `beAKindOf` uses `-[NSObject isKindOfClass:]`. + +## Truthiness + +```swift +// Passes if actual is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()) + +// Passes if actual is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()) + +// Passes if actual is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()) + +// Passes if actual is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()) + +// Passes if actual is nil: +expect(actual).to(beNil()) +``` + +```objc +// Objective-C + +// Passes if actual is not nil, true, or an object with a boolean value of true: +expect(actual).to(beTruthy()); + +// Passes if actual is only true (not nil or an object conforming to Boolean true): +expect(actual).to(beTrue()); + +// Passes if actual is nil, false, or an object with a boolean value of false: +expect(actual).to(beFalsy()); + +// Passes if actual is only false (not nil or an object conforming to Boolean false): +expect(actual).to(beFalse()); + +// Passes if actual is nil: +expect(actual).to(beNil()); +``` + +## Swift Assertions + +If you're using Swift, you can use the `throwAssertion` matcher to check if an assertion is thrown (e.g. `fatalError()`). This is made possible by [@mattgallagher](https://github.com/mattgallagher)'s [CwlPreconditionTesting](https://github.com/mattgallagher/CwlPreconditionTesting) library. + +```swift +// Swift + +// Passes if somethingThatThrows() throws an assertion, such as calling fatalError() or precondition fails: +expect { () -> Void in fatalError() }.to(throwAssertion()) +expect { precondition(false) }.to(throwAssertion()) + +// Passes if throwing a NSError is not equal to throwing an assertion: +expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + +// Passes if the post assertion code is not run: +var reachedPoint1 = false +var reachedPoint2 = false +expect { + reachedPoint1 = true + precondition(false, "condition message") + reachedPoint2 = true +}.to(throwAssertion()) + +expect(reachedPoint1) == true +expect(reachedPoint2) == false +``` + +Notes: + +* This feature is only available in Swift. +* It is only supported for `x86_64` binaries, meaning _you cannot run this matcher on iOS devices, only simulators_. +* The tvOS simulator is supported, but using a different mechanism, requiring you to turn off the `Debug executable` scheme setting for your tvOS scheme's Test configuration. + +## Swift Error Handling + +If you're using Swift 2.0+, you can use the `throwError` matcher to check if an error is thrown. + +```swift +// Swift + +// Passes if somethingThatThrows() throws an ErrorProtocol: +expect{ try somethingThatThrows() }.to(throwError()) + +// Passes if somethingThatThrows() throws an error with a given domain: +expect{ try somethingThatThrows() }.to(throwError { (error: ErrorProtocol) in + expect(error._domain).to(equal(NSCocoaErrorDomain)) +}) + +// Passes if somethingThatThrows() throws an error with a given case: +expect{ try somethingThatThrows() }.to(throwError(NSCocoaError.PropertyListReadCorruptError)) + +// Passes if somethingThatThrows() throws an error with a given type: +expect{ try somethingThatThrows() }.to(throwError(errorType: NimbleError.self)) +``` + +If you are working directly with `ErrorProtocol` values, as is sometimes the case when using `Result` or `Promise` types, you can use the `matchError` matcher to check if the error is the same error is is supposed to be, without requiring explicit casting. + +```swift +// Swift + +let actual: ErrorProtocol = … + +// Passes if actual contains any error value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum)) + +// Passes if actual contains the Timeout value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.Timeout)) + +// Passes if actual contains an NSError equal to the given one: +expect(actual).to(matchError(NSError(domain: "err", code: 123, userInfo: nil))) +``` + +Note: This feature is only available in Swift. + +## Exceptions + +```swift +// Swift + +// Passes if actual, when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if actual raises an exception with the given name: +expect(actual).to(raiseException(named: name)) + +// Passes if actual raises an exception with the given name and reason: +expect(actual).to(raiseException(named: name, reason: reason)) + +// Passes if actual raises an exception and it passes expectations in the block +// (in this case, if name begins with 'a r') +expect { exception.raise() }.to(raiseException { (exception: NSException) in + expect(exception.name).to(beginWith("a r")) +}) +``` + +```objc +// Objective-C + +// Passes if actual, when evaluated, raises an exception: +expect(actual).to(raiseException()) + +// Passes if actual raises an exception with the given name +expect(actual).to(raiseException().named(name)) + +// Passes if actual raises an exception with the given name and reason: +expect(actual).to(raiseException().named(name).reason(reason)) + +// Passes if actual raises an exception and it passes expectations in the block +// (in this case, if name begins with 'a r') +expect(actual).to(raiseException().satisfyingBlock(^(NSException *exception) { + expect(exception.name).to(beginWith(@"a r")); +})); +``` + +Note: Swift currently doesn't have exceptions (see [#220](https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)). Only Objective-C code can raise +exceptions that Nimble will catch. + +## Collection Membership + +```swift +// Swift + +// Passes if all of the expected values are members of actual: +expect(actual).to(contain(expected...)) + +// Passes if actual is an empty collection (it contains no elements): +expect(actual).to(beEmpty()) +``` + +```objc +// Objective-C + +// Passes if expected is a member of actual: +expect(actual).to(contain(expected)); + +// Passes if actual is an empty collection (it contains no elements): +expect(actual).to(beEmpty()); +``` + +> In Swift `contain` takes any number of arguments. The expectation + passes if all of them are members of the collection. In Objective-C, + `contain` only takes one argument [for now](https://github.com/Quick/Nimble/issues/27). + +For example, to assert that a list of sea creature names contains +"dolphin" and "starfish": + +```swift +// Swift + +expect(["whale", "dolphin", "starfish"]).to(contain("dolphin", "starfish")) +``` + +```objc +// Objective-C + +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"dolphin")); +expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"starfish")); +``` + +> `contain` and `beEmpty` expect collections to be instances of + `NSArray`, `NSSet`, or a Swift collection composed of `Equatable` elements. + +To test whether a set of elements is present at the beginning or end of +an ordered collection, use `beginWith` and `endWith`: + +```swift +// Swift + +// Passes if the elements in expected appear at the beginning of actual: +expect(actual).to(beginWith(expected...)) + +// Passes if the the elements in expected come at the end of actual: +expect(actual).to(endWith(expected...)) +``` + +```objc +// Objective-C + +// Passes if the elements in expected appear at the beginning of actual: +expect(actual).to(beginWith(expected)); + +// Passes if the the elements in expected come at the end of actual: +expect(actual).to(endWith(expected)); +``` + +> `beginWith` and `endWith` expect collections to be instances of + `NSArray`, or ordered Swift collections composed of `Equatable` + elements. + + Like `contain`, in Objective-C `beginWith` and `endWith` only support + a single argument [for now](https://github.com/Quick/Nimble/issues/27). + +For code that returns collections of complex objects without a strict +ordering, there is the `containElementSatisfying` matcher: + +```swift +struct Turtle { + var color: String! +} + +var turtles = functionThatReturnsSomeTurtlesInAnyOrder() + +// This set of matchers passes whether the array is [{color: "blue"}, {color: "green"}] +// or [{color: "green"}, {color: "blue"}] +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "green" +})) +expect(turtles).to(containElementSatisfying({ turtle in + return turtle.color == "blue" +}, "that is a turtle with color 'blue'")) + +// The second matcher will incorporate the provided string in the error message +// should it fail +``` + +```objc +@interface Turtle: NSObject +@property(nonatomic) NSString *color; +@end +@implementation Turtle @end + +NSArray *turtles = functionThatReturnsSomeTurtlesInAnyOrder(); + +// This set of matchers passes whether the array is [{color: "blue"}, {color: "green"}] +// or [{color: "green"}, {color: "blue"}] +expect(turtles).to(containElementSatisfying(^BOOL(id object) { + return [turtle.color isEqualToString:@"green"]; +})); +expect(turtles).to(containElementSatisfying(^BOOL(id object) { + return [turtle.color isEqualToString:@"blue"]; +})); +``` + +## Strings + +```swift +// Swift + +// Passes if actual contains substring expected: +expect(actual).to(contain(expected)) + +// Passes if actual begins with substring: +expect(actual).to(beginWith(expected)) + +// Passes if actual ends with substring: +expect(actual).to(endWith(expected)) + +// Passes if actual is an empty string, "": +expect(actual).to(beEmpty()) + +// Passes if actual matches the regular expression defined in expected: +expect(actual).to(match(expected)) +``` + +```objc +// Objective-C + +// Passes if actual contains substring expected: +expect(actual).to(contain(expected)); + +// Passes if actual begins with substring: +expect(actual).to(beginWith(expected)); + +// Passes if actual ends with substring: +expect(actual).to(endWith(expected)); + +// Passes if actual is an empty string, "": +expect(actual).to(beEmpty()); + +// Passes if actual matches the regular expression defined in expected: +expect(actual).to(match(expected)) +``` + +## Checking if all elements of a collection pass a condition + +```swift +// Swift + +// with a custom function: +expect([1,2,3,4]).to(allPass({$0 < 5})) + +// with another matcher: +expect([1,2,3,4]).to(allPass(beLessThan(5))) +``` + +```objc +// Objective-C + +expect(@[@1, @2, @3,@4]).to(allPass(beLessThan(@5))); +``` + +For Swift the actual value has to be a Sequence, e.g. an array, a set or a custom seqence type. + +For Objective-C the actual value has to be a NSFastEnumeration, e.g. NSArray and NSSet, of NSObjects and only the variant which +uses another matcher is available here. + +## Verify collection count + +```swift +// Swift + +// passes if actual collection's count is equal to expected +expect(actual).to(haveCount(expected)) + +// passes if actual collection's count is not equal to expected +expect(actual).notTo(haveCount(expected)) +``` + +```objc +// Objective-C + +// passes if actual collection's count is equal to expected +expect(actual).to(haveCount(expected)) + +// passes if actual collection's count is not equal to expected +expect(actual).notTo(haveCount(expected)) +``` + +For Swift the actual value must be a `Collection` such as array, dictionary or set. + +For Objective-C the actual value has to be one of the following classes `NSArray`, `NSDictionary`, `NSSet`, `NSHashTable` or one of their subclasses. + +## Foundation + +### Verifying a Notification was posted + +```swift +// Swift +let testNotification = Notification(name: "Foo", object: nil) + +// passes if the closure in expect { ... } posts a notification to the default +// notification center. +expect { + NotificationCenter.default.postNotification(testNotification) +}.to(postNotifications(equal([testNotification])) + +// passes if the closure in expect { ... } posts a notification to a given +// notification center +let notificationCenter = NotificationCenter() +expect { + notificationCenter.postNotification(testNotification) +}.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter)) +``` + +> This matcher is only available in Swift. + +## Matching a value to any of a group of matchers + +```swift +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(10), beGreaterThan(20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equal(7))) + +// in Swift you also have the option to use the || operator to achieve a similar function +expect(82).to(beLessThan(50) || beGreaterThan(80)) +``` + +```objc +// passes if actual is either less than 10 or greater than 20 +expect(actual).to(satisfyAnyOf(beLessThan(@10), beGreaterThan(@20))) + +// can include any number of matchers -- the following will pass +// **be careful** -- too many matchers can be the sign of an unfocused test +expect(@6).to(satisfyAnyOf(equal(@2), equal(@3), equal(@4), equal(@5), equal(@6), equal(@7))) +``` + +Note: This matcher allows you to chain any number of matchers together. This provides flexibility, + but if you find yourself chaining many matchers together in one test, consider whether you + could instead refactor that single test into multiple, more precisely focused tests for + better coverage. + +# Writing Your Own Matchers + +In Nimble, matchers are Swift functions that take an expected +value and return a `MatcherFunc` closure. Take `equal`, for example: + +```swift +// Swift + +public func equal(expectedValue: T?) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(expectedValue)>" + if let actualValue = try actualExpression.evaluate() { + return actualValue == expectedValue + } else { + return false + } + } +} +``` + +The return value of a `MatcherFunc` closure is a `Bool` that indicates +whether the actual value matches the expectation: `true` if it does, or +`false` if it doesn't. + +> The actual `equal` matcher function does not match when either + `actual` or `expected` are nil; the example above has been edited for + brevity. + +Since matchers are just Swift functions, you can define them anywhere: +at the top of your test file, in a file shared by all of your tests, or +in an Xcode project you distribute to others. + +> If you write a matcher you think everyone can use, consider adding it + to Nimble's built-in set of matchers by sending a pull request! Or + distribute it yourself via GitHub. + +For examples of how to write your own matchers, just check out the +[`Matchers` directory](https://github.com/Quick/Nimble/tree/master/Sources/Nimble/Matchers) +to see how Nimble's built-in set of matchers are implemented. You can +also check out the tips below. + +## Lazy Evaluation + +`actualExpression` is a lazy, memoized closure around the value provided to the +`expect` function. The expression can either be a closure or a value directly +passed to `expect(...)`. In order to determine whether that value matches, +custom matchers should call `actualExpression.evaluate()`: + +```swift +// Swift + +public func beNil() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be nil" + return actualExpression.evaluate() == nil + } +} +``` + +In the above example, `actualExpression` is not `nil`--it is a closure +that returns a value. The value it returns, which is accessed via the +`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil` +matcher function returns `true`, indicating that the expectation passed. + +Use `expression.isClosure` to determine if the expression will be invoking +a closure to produce its value. + +## Type Checking via Swift Generics + +Using Swift's generics, matchers can constrain the type of the actual value +passed to the `expect` function by modifying the return type. + +For example, the following matcher, `haveDescription`, only accepts actual +values that implement the `Printable` protocol. It checks their `description` +against the one provided to the matcher function, and passes if they are the same: + +```swift +// Swift + +public func haveDescription(description: String) -> MatcherFunc { + return MatcherFunc { actual, failureMessage in + return actual.evaluate().description == description + } +} +``` + +## Customizing Failure Messages + +By default, Nimble outputs the following failure message when an +expectation fails: + +``` +expected to match, got <\(actual)> +``` + +You can customize this message by modifying the `failureMessage` struct +from within your `MatcherFunc` closure. To change the verb "match" to +something else, update the `postfixMessage` property: + +```swift +// Swift + +// Outputs: expected to be under the sea, got <\(actual)> +failureMessage.postfixMessage = "be under the sea" +``` + +You can change how the `actual` value is displayed by updating +`failureMessage.actualValue`. Or, to remove it altogether, set it to +`nil`: + +```swift +// Swift + +// Outputs: expected to be under the sea +failureMessage.actualValue = nil +failureMessage.postfixMessage = "be under the sea" +``` + +## Supporting Objective-C + +To use a custom matcher written in Swift from Objective-C, you'll have +to extend the `NMBObjCMatcher` class, adding a new class method for your +custom matcher. The example below defines the class method +`+[NMBObjCMatcher beNilMatcher]`: + +```swift +// Swift + +extension NMBObjCMatcher { + public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualBlock, failureMessage, location in + let block = ({ actualBlock() as NSObject? }) + let expr = Expression(expression: block, location: location) + return beNil().matches(expr, failureMessage: failureMessage) + } + } +} +``` + +The above allows you to use the matcher from Objective-C: + +```objc +// Objective-C + +expect(actual).to([NMBObjCMatcher beNilMatcher]()); +``` + +To make the syntax easier to use, define a C function that calls the +class method: + +```objc +// Objective-C + +FOUNDATION_EXPORT id beNil() { + return [NMBObjCMatcher beNilMatcher]; +} +``` + +### Properly Handling `nil` in Objective-C Matchers + +When supporting Objective-C, make sure you handle `nil` appropriately. +Like [Cedar](https://github.com/pivotal/cedar/issues/100), +**most matchers do not match with nil**. This is to bring prevent test +writers from being surprised by `nil` values where they did not expect +them. + +Nimble provides the `beNil` matcher function for test writer that want +to make expectations on `nil` objects: + +```objc +// Objective-C + +expect(nil).to(equal(nil)); // fails +expect(nil).to(beNil()); // passes +``` + +If your matcher does not want to match with nil, you use `NonNilMatcherFunc` +and the `canMatchNil` constructor on `NMBObjCMatcher`. Using both types will +automatically generate expected value failure messages when they're nil. + +```swift + +public func beginWith(startingElement: T) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + if let actualValue = actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + return actualGenerator.next() == startingElement + } + return false + } +} + +extension NMBObjCMatcher { + public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.evaluate() + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } +} +``` + +# Installing Nimble + +> Nimble can be used on its own, or in conjunction with its sister + project, [Quick](https://github.com/Quick/Quick). To install both + Quick and Nimble, follow [the installation instructions in the Quick + Documentation](https://github.com/Quick/Quick/blob/master/Documentation/en-us/InstallingQuick.md). + +Nimble can currently be installed in one of two ways: using CocoaPods, or with +git submodules. + +## Installing Nimble as a Submodule + +To use Nimble as a submodule to test your macOS, iOS or tvOS applications, follow +these 4 easy steps: + +1. Clone the Nimble repository +2. Add Nimble.xcodeproj to the Xcode workspace for your project +3. Link Nimble.framework to your test target +4. Start writing expectations! + +For more detailed instructions on each of these steps, +read [How to Install Quick](https://github.com/Quick/Quick#how-to-install-quick). +Ignore the steps involving adding Quick to your project in order to +install just Nimble. + +## Installing Nimble via CocoaPods + +To use Nimble in CocoaPods to test your macOS, iOS or tvOS applications, add +Nimble to your podfile and add the ```use_frameworks!``` line to enable Swift +support for CocoaPods. + +```ruby +platform :ios, '8.0' + +source 'https://github.com/CocoaPods/Specs.git' + +# Whatever pods you need for your app go here + +target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do + use_frameworks! + pod 'Nimble', '~> 5.0.0' +end +``` + +Finally run `pod install`. + +## Using Nimble without XCTest + +Nimble is integrated with XCTest to allow it work well when used in Xcode test +bundles, however it can also be used in a standalone app. After installing +Nimble using one of the above methods, there are two additional steps required +to make this work. + +1. Create a custom assertion handler and assign an instance of it to the + global `NimbleAssertionHandler` variable. For example: + +```swift +class MyAssertionHandler : AssertionHandler { + func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) { + if (!assertion) { + print("Expectation failed: \(message.stringValue)") + } + } +} +``` +```swift +// Somewhere before you use any assertions +NimbleAssertionHandler = MyAssertionHandler() +``` + +2. Add a post-build action to fix an issue with the Swift XCTest support + library being unnecessarily copied into your app + * Edit your scheme in Xcode, and navigate to Build -> Post-actions + * Click the "+" icon and select "New Run Script Action" + * Open the "Provide build settings from" dropdown and select your target + * Enter the following script contents: +``` +rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib" +``` + +You can now use Nimble assertions in your code and handle failures as you see +fit. diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h new file mode 100644 index 0000000..6ec6a29 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h @@ -0,0 +1,30 @@ +// +// CwlCatchException.h +// CwlCatchException +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +//! Project version number for CwlCatchException. +FOUNDATION_EXPORT double CwlCatchExceptionVersionNumber; + +//! Project version string for CwlCatchException. +FOUNDATION_EXPORT const unsigned char CwlCatchExceptionVersionString[]; + +__attribute__((visibility("hidden"))) +NSException* __nullable catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)()); diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m new file mode 100644 index 0000000..4f9772c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m @@ -0,0 +1,35 @@ +// +// CwlCatchException.m +// CwlAssertionTesting +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "CwlCatchException.h" + +__attribute__((visibility("hidden"))) +NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)()) { + @try { + inBlock(); + } @catch (NSException *exception) { + if ([exception isKindOfClass:type]) { + return exception; + } else { + @throw; + } + } + return nil; +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift new file mode 100644 index 0000000..b44a232 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift @@ -0,0 +1,32 @@ +// +// CwlCatchException.swift +// CwlAssertionTesting +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +import Foundation + +// We can't simply cast to Self? in the catchInBlock method so we need this generic function wrapper to do the conversion for us. Mildly annoying. +private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? { + return catchExceptionOfKind(type, block) as? T +} + +extension NSException { + public static func catchException(in block: () -> Void) -> Self? { + return catchReturnTypeConverter(self, block: block) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift new file mode 100644 index 0000000..5bf2794 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift @@ -0,0 +1,76 @@ +// +// CwlBadInstructionException.swift +// CwlPreconditionTesting +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +import Foundation + +private func raiseBadInstructionException() { + BadInstructionException().raise() +} + +/// A simple NSException subclass. It's not required to subclass NSException (since the exception type is represented in the name) but this helps for identifying the exception through runtime type. +@objc public class BadInstructionException: NSException { + static var name: String = "com.cocoawithlove.BadInstruction" + + init() { + super.init(name: NSExceptionName(rawValue: BadInstructionException.name), reason: nil, userInfo: nil) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + /// An Objective-C callable function, invoked from the `mach_exc_server` callback function `catch_mach_exception_raise_state` to push the `raiseBadInstructionException` function onto the stack. + public class func catch_mach_exception_raise_state(_ exception_port: mach_port_t, exception: exception_type_t, code: UnsafePointer, codeCnt: mach_msg_type_number_t, flavor: UnsafeMutablePointer, old_state: UnsafePointer, old_stateCnt: mach_msg_type_number_t, new_state: thread_state_t, new_stateCnt: UnsafeMutablePointer) -> kern_return_t { + + #if arch(x86_64) + // Make sure we've been given enough memory + if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT { + return KERN_INVALID_ARGUMENT + } + + // Read the old thread state + var state = old_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { return $0.pointee } + + // 1. Decrement the stack pointer + state.__rsp -= __uint64_t(MemoryLayout.size) + + // 2. Save the old Instruction Pointer to the stack. + if let pointer = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(state.__rsp)) { + pointer.pointee = state.__rip + } else { + return KERN_INVALID_ARGUMENT + } + + // 3. Set the Instruction Pointer to the new function's address + var f: @convention(c) () -> Void = raiseBadInstructionException + withUnsafePointer(to: &f) { + state.__rip = $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { return $0.pointee } + } + + // Write the new thread state + new_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { $0.pointee = state } + new_stateCnt.pointee = x86_THREAD_STATE64_COUNT + + return KERN_SUCCESS + #else + fatalError("Unavailable for this CPU architecture") + #endif + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h new file mode 100644 index 0000000..0333ed2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h @@ -0,0 +1,61 @@ +// +// CwlCatchBadInstruction.h +// CwlPreconditionTesting +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#if defined(__x86_64__) + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +// The request_mach_exception_raise_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; +} request_mach_exception_raise_t; + +// The reply_mach_exception_raise_state_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift. +typedef struct +{ + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; +} reply_mach_exception_raise_state_t; + +extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +NS_ASSUME_NONNULL_END + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m new file mode 100644 index 0000000..22c1377 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m @@ -0,0 +1,50 @@ +// +// CwlCatchBadInstruction.m +// CwlPreconditionTesting +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#if defined(__x86_64__) + +#import "CwlCatchBadInstruction.h" + +// Assuming the "PRODUCT_NAME" macro is defined, this will create the name of the Swift generated header file +#define STRINGIZE_NO_EXPANSION(A) #A +#define STRINGIZE_WITH_EXPANSION(A) STRINGIZE_NO_EXPANSION(A) +#define SWIFT_INCLUDE STRINGIZE_WITH_EXPANSION(PRODUCT_NAME-Swift.h) + +// Include the Swift generated header file +#import SWIFT_INCLUDE + +/// A basic function that receives callbacks from mach_exc_server and relays them to the Swift implemented BadInstructionException.catch_mach_exception_raise_state. +kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { + return [BadInstructionException catch_mach_exception_raise_state:exception_port exception:exception code:code codeCnt:codeCnt flavor:flavor old_state:old_state old_stateCnt:old_stateCnt new_state:new_state new_stateCnt:new_stateCnt]; +} + +// The mach port should be configured so that this function is never used. +kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) { + assert(false); + return KERN_FAILURE; +} + +// The mach port should be configured so that this function is never used. +kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { + assert(false); + return KERN_FAILURE; +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift new file mode 100644 index 0000000..4d82f7a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -0,0 +1,193 @@ +// +// CwlCatchBadInstruction.swift +// CwlPreconditionTesting +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +import Foundation + +#if arch(x86_64) + + private enum PthreadError: Error { case code(Int32) } + private enum MachExcServer: Error { case code(kern_return_t) } + + /// A quick function for converting Mach error results into Swift errors + private func kernCheck(_ f: () -> Int32) throws { + let r = f() + guard r == KERN_SUCCESS else { + throw NSError(domain: NSMachErrorDomain, code: Int(r), userInfo: nil) + } + } + + extension execTypesCountTuple { + mutating func pointer(in block: (UnsafeMutablePointer) -> R) -> R { + return withUnsafeMutablePointer(to: &self) { p -> R in + return p.withMemoryRebound(to: T.self, capacity: EXC_TYPES_COUNT) { ptr -> R in + return block(ptr) + } + } + } + } + + extension request_mach_exception_raise_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R { + return withUnsafeMutablePointer(to: &self) { p -> R in + return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in + return block(ptr) + } + } + } + } + + extension reply_mach_exception_raise_state_t { + mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R { + return withUnsafeMutablePointer(to: &self) { p -> R in + return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in + return block(ptr) + } + } + } + } + + /// A structure used to store context associated with the Mach message port + private struct MachContext { + var masks = execTypesCountTuple() + var count: mach_msg_type_number_t = 0 + var ports = execTypesCountTuple() + var behaviors = execTypesCountTuple() + var flavors = execTypesCountTuple() + var currentExceptionPort: mach_port_t = 0 + var handlerThread: pthread_t? = nil + + mutating func withUnsafeMutablePointers(in block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R { + return masks.pointer { masksPtr in + return ports.pointer { portsPtr in + return behaviors.pointer { behaviorsPtr in + return flavors.pointer { flavorsPtr in + return block(masksPtr, portsPtr, behaviorsPtr, flavorsPtr) + } + } + } + } + } + } + + /// A function for receiving mach messages and parsing the first with mach_exc_server (and if any others are received, throwing them away). + private func machMessageHandler(_ arg: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? { + let context = arg.assumingMemoryBound(to: MachContext.self).pointee + var request = request_mach_exception_raise_t() + var reply = reply_mach_exception_raise_state_t() + + var handledfirstException = false + repeat { do { + // Request the next mach message from the port + request.Head.msgh_local_port = context.currentExceptionPort + request.Head.msgh_size = UInt32(MemoryLayout.size) + try kernCheck { request.withMsgHeaderPointer { requestPtr in + mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, request.Head.msgh_size, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL)) + } } + + // Prepare the reply structure + reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.Head.msgh_bits), 0) + reply.Head.msgh_local_port = UInt32(MACH_PORT_NULL) + reply.Head.msgh_remote_port = request.Head.msgh_remote_port + reply.Head.msgh_size = UInt32(MemoryLayout.size) + reply.NDR = NDR_record + + if !handledfirstException { + // Use the MiG generated server to invoke our handler for the request and fill in the rest of the reply structure + guard request.withMsgHeaderPointer(in: { requestPtr in reply.withMsgHeaderPointer { replyPtr in + mach_exc_server(requestPtr, replyPtr) + } }) != 0 else { throw MachExcServer.code(reply.RetCode) } + + handledfirstException = true + } else { + // If multiple fatal errors occur, don't handle subsquent errors (let the program crash) + reply.RetCode = KERN_FAILURE + } + + // Send the reply + try kernCheck { reply.withMsgHeaderPointer { replyPtr in + mach_msg(replyPtr, MACH_SEND_MSG, reply.Head.msgh_size, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL)) + } } + } catch let error as NSError where (error.domain == NSMachErrorDomain && (error.code == Int(MACH_RCV_PORT_CHANGED) || error.code == Int(MACH_RCV_INVALID_NAME))) { + // Port was already closed before we started or closed while we were listening. + // This means the controlling thread shut down. + return nil + } catch { + // Should never be reached but this is testing code, don't try to recover, just abort + fatalError("Mach message error: \(error)") + } } while true + } + + /// Run the provided block. If a mach "BAD_INSTRUCTION" exception is raised, catch it and return a BadInstructionException (which captures stack information about the throw site, if desired). Otherwise return nil. + /// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a "BAD_INSTRUCTION" exception is raised, the block will be exited before completion via Objective-C exception. The risks associated with an Objective-C exception apply here: most Swift/Objective-C functions are *not* exception-safe. Memory may be leaked and the program will not necessarily be left in a safe state. + /// - parameter block: a function without parameters that will be run + /// - returns: if an EXC_BAD_INSTRUCTION is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`. + public func catchBadInstruction(in block: () -> Void) -> BadInstructionException? { + var context = MachContext() + var result: BadInstructionException? = nil + do { + var handlerThread: pthread_t? = nil + defer { + // 8. Wait for the thread to terminate *if* we actually made it to the creation point + // The mach port should be destroyed *before* calling pthread_join to avoid a deadlock. + if handlerThread != nil { + pthread_join(handlerThread!, nil) + } + } + + try kernCheck { + // 1. Create the mach port + mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &context.currentExceptionPort) + } + defer { + // 7. Cleanup the mach port + mach_port_destroy(mach_task_self_, context.currentExceptionPort) + } + + try kernCheck { + // 2. Configure the mach port + mach_port_insert_right(mach_task_self_, context.currentExceptionPort, context.currentExceptionPort, MACH_MSG_TYPE_MAKE_SEND) + } + + try kernCheck { context.withUnsafeMutablePointers { masksPtr, portsPtr, behaviorsPtr, flavorsPtr in + // 3. Apply the mach port as the handler for this thread + thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, context.currentExceptionPort, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, &context.count, portsPtr, behaviorsPtr, flavorsPtr) + } } + + defer { context.withUnsafeMutablePointers { masksPtr, portsPtr, behaviorsPtr, flavorsPtr in + // 6. Unapply the mach port + _ = thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, 0, EXCEPTION_DEFAULT, THREAD_STATE_NONE, masksPtr, &context.count, portsPtr, behaviorsPtr, flavorsPtr) + } } + + try withUnsafeMutablePointer(to: &context) { c throws in + // 4. Create the thread + let e = pthread_create(&handlerThread, nil, machMessageHandler, c) + guard e == 0 else { throw PthreadError.code(e) } + + // 5. Run the block + result = BadInstructionException.catchException(in: block) + } + } catch { + // Should never be reached but this is testing code, don't try to recover, just abort + fatalError("Mach port error: \(error)") + } + return result + } + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift new file mode 100644 index 0000000..35e1ad5 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift @@ -0,0 +1,63 @@ +// +// CwlDarwinDefinitions.swift +// CwlPreconditionTesting +// +// Created by Matt Gallagher on 2016/01/10. +// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +import Darwin + +#if arch(x86_64) + +// From /usr/include/mach/port.h +// #define MACH_PORT_RIGHT_RECEIVE ((mach_port_right_t) 1) +let MACH_PORT_RIGHT_RECEIVE: mach_port_right_t = 1 + +// From /usr/include/mach/message.h +// #define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */ +// #define MACH_MSGH_BITS_REMOTE(bits) \ +// ((bits) & MACH_MSGH_BITS_REMOTE_MASK) +// #define MACH_MSGH_BITS(remote, local) /* legacy */ \ +// ((remote) | ((local) << 8)) +let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20 +func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) } +func MACH_MSGH_BITS(_ remote: UInt32, _ local: UInt32) -> UInt32 { return ((remote) | ((local) << 8)) } + +// From /usr/include/mach/exception_types.h +// #define EXC_BAD_INSTRUCTION 2 /* Instruction failed */ +// #define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION) +// #define EXCEPTION_DEFAULT 1 +let EXC_BAD_INSTRUCTION: UInt32 = 2 +let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION +let EXCEPTION_DEFAULT: Int32 = 1 + +// From /usr/include/mach/i386/thread_status.h +// #define THREAD_STATE_NONE 13 +// #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \ +// ( sizeof (x86_thread_state64_t) / sizeof (int) )) +let THREAD_STATE_NONE: Int32 = 13 +let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout.size / MemoryLayout.size) + +let EXC_TYPES_COUNT = 14 +struct execTypesCountTuple { + // From /usr/include/mach/i386/exception.h + // #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */ + var value: (T, T, T, T, T, T, T, T, T, T, T, T, T, T) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + init() { + } +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c new file mode 100644 index 0000000..2334538 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c @@ -0,0 +1,537 @@ +/* + * IDENTIFICATION: + * stub generated Mon Jan 11 00:24:26 2016 + * with a MiG generated by bootstrap_cmds-93 + * OPTIONS: + */ + +/* Module mach_exc */ + +#if defined(__x86_64__) + +#define __MIG_check__Request__mach_exc_subsystem__ 1 + +#include "mach_excServer.h" + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __DeclareRcvRpc +#define __DeclareRcvRpc(_NUM_, _NAME_) +#endif /* __DeclareRcvRpc */ + +#ifndef __BeforeRcvRpc +#define __BeforeRcvRpc(_NUM_, _NAME_) +#endif /* __BeforeRcvRpc */ + +#ifndef __AfterRcvRpc +#define __AfterRcvRpc(_NUM_, _NAME_) +#endif /* __AfterRcvRpc */ + +#ifndef __DeclareRcvSimple +#define __DeclareRcvSimple(_NUM_, _NAME_) +#endif /* __DeclareRcvSimple */ + +#ifndef __BeforeRcvSimple +#define __BeforeRcvSimple(_NUM_, _NAME_) +#endif /* __BeforeRcvSimple */ + +#ifndef __AfterRcvSimple +#define __AfterRcvSimple(_NUM_, _NAME_) +#endif /* __AfterRcvSimple */ + +#define novalue void + +#define msgh_request_port msgh_local_port +#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) +#define msgh_reply_port msgh_remote_port +#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) + +#define MIG_RETURN_ERROR(X, code) {\ + ((mig_reply_error_t *)X)->RetCode = code;\ + ((mig_reply_error_t *)X)->NDR = NDR_record;\ + return;\ + } + +/* Forward Declarations */ + + +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_t__defined) +#define __MIG_check__Request__mach_exception_raise_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P) +{ + + typedef __Request__mach_exception_raise_t __Request; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise */ +mig_internal novalue _Xmach_exception_raise + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_t __Request; + typedef __Reply__mach_exception_raise_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_t__defined */ + + __DeclareRcvRpc(2405, "mach_exception_raise") + __BeforeRcvRpc(2405, "mach_exception_raise") + +#if defined(__MIG_check__Request__mach_exception_raise_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */ + + OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); + + OutP->NDR = NDR_record; + + + __AfterRcvRpc(2405, "mach_exception_raise") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state */ +mig_internal novalue _Xmach_exception_raise_state + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_t __Request; + typedef __Reply__mach_exception_raise_state_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */ + + __DeclareRcvRpc(2406, "mach_exception_raise_state") + __BeforeRcvRpc(2406, "mach_exception_raise_state") + +#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2406, "mach_exception_raise_state") +} + +#if ( __MigTypeCheck ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_identity_t __Request; + __Request *In1P; +#if __MigTypeCheck + unsigned int msgh_size; +#endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + +#if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; +#endif /* __MigTypeCheck */ + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); +#if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; +#endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + +#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ +#if __MigTypeCheck + if ( In1P->old_stateCnt > 224 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; +#endif /* __MigTypeCheck */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck ) */ + + +/* Routine mach_exception_raise_state_identity */ +mig_internal novalue _Xmach_exception_raise_state_identity + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + mach_msg_trailer_t trailer; + } Request __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + typedef __Request__mach_exception_raise_state_identity_t __Request; + typedef __Reply__mach_exception_raise_state_identity_t Reply __attribute__((unused)); + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; +#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; +#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */ + + __DeclareRcvRpc(2407, "mach_exception_raise_state_identity") + __BeforeRcvRpc(2407, "mach_exception_raise_state_identity") + +#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } +#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ + + OutP->new_stateCnt = 224; + + OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2407, "mach_exception_raise_state_identity") +} + + + +/* Description of this subsystem, for use in direct RPC */ +const struct catch_mach_exc_subsystem catch_mach_exc_subsystem = { + mach_exc_server_routine, + 2405, + 2408, + (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem), + (vm_address_t)0, + { + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)}, + } +}; + +mig_external boolean_t mach_exc_server + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + register mig_routine_t routine; + + OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + + if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) || + ((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + (*routine) (InHeadP, OutHeadP); + return TRUE; +} + +mig_external mig_routine_t mach_exc_server_routine + (mach_msg_header_t *InHeadP) +{ + register int msgh_id; + + msgh_id = InHeadP->msgh_id - 2405; + + if ((msgh_id > 2) || (msgh_id < 0)) + return 0; + + return catch_mach_exc_subsystem.routine[msgh_id].stub_routine; +} + +#endif + diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h new file mode 100644 index 0000000..766ba11 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h @@ -0,0 +1,298 @@ +#ifndef _mach_exc_server_ +#define _mach_exc_server_ + +/* Module mach_exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#ifndef USING_VOUCHERS +#define USING_VOUCHERS +#endif +#ifndef __VOUCHER_FORWARD_TYPE_DECLS__ +#define __VOUCHER_FORWARD_TYPE_DECLS__ +#ifdef __cplusplus +extern "C" { +#endif + extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import)); +#ifdef __cplusplus +} +#endif +#endif // __VOUCHER_FORWARD_TYPE_DECLS__ +#endif // __has_include() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_exc_MSG_COUNT +#define mach_exc_MSG_COUNT 3 +#endif /* mach_exc_MSG_COUNT */ + +#include +#include +#include +#include + +#ifdef __BeforeMigServerHeader +__BeforeMigServerHeader +#endif /* __BeforeMigServerHeader */ + + +/* Routine mach_exception_raise */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t catch_mach_exception_raise +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine mach_exception_raise_state */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t catch_mach_exception_raise_state +( + mach_port_t exception_port, + exception_type_t exception, + const mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine mach_exception_raise_state_identity */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t catch_mach_exception_raise_state_identity +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t mach_exc_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +mig_routine_t mach_exc_server_routine( + mach_msg_header_t *InHeadP); + + +/* Description of this subsystem, for use in direct RPC */ +extern const struct catch_mach_exc_subsystem { + mig_server_routine_t server; /* Server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + unsigned int maxsize; /* Max msg size */ + vm_address_t reserved; /* Reserved */ + struct routine_descriptor /*Array of routine descriptors */ + routine[3]; +} catch_mach_exc_subsystem; + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[224]; + } __Request__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + + +/* union of all requests */ + +#ifndef __RequestUnion__catch_mach_exc_subsystem__defined +#define __RequestUnion__catch_mach_exc_subsystem__defined +union __RequestUnion__catch_mach_exc_subsystem { + __Request__mach_exception_raise_t Request_mach_exception_raise; + __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; + __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[224]; + } __Reply__mach_exception_raise_state_identity_t __attribute__((unused)); +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + + +/* union of all replies */ + +#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined +#define __ReplyUnion__catch_mach_exc_subsystem__defined +union __ReplyUnion__catch_mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_exc +#define subsystem_to_name_map_mach_exc \ + { "mach_exception_raise", 2405 },\ + { "mach_exception_raise_state", 2406 },\ + { "mach_exception_raise_state_identity", 2407 } +#endif + +#ifdef __AfterMigServerHeader +__AfterMigServerHeader +#endif /* __AfterMigServerHeader */ + +#endif /* _mach_exc_server_ */ diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift new file mode 100644 index 0000000..2e58fdf --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift @@ -0,0 +1,17 @@ +import Foundation + +/// Protocol for the assertion handler that Nimble uses for all expectations. +public protocol AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) +} + +/// Global backing interface for assertions that Nimble creates. +/// Defaults to a private test handler that passes through to XCTest. +/// +/// If XCTest is not available, you must assign your own assertion handler +/// before using any matchers, otherwise Nimble will abort the program. +/// +/// @see AssertionHandler +public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in + return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler() +}() diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift new file mode 100644 index 0000000..94a9030 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift @@ -0,0 +1,19 @@ +/// AssertionDispatcher allows multiple AssertionHandlers to receive +/// assertion messages. +/// +/// @warning Does not fully dispatch if one of the handlers raises an exception. +/// This is possible with XCTest-based assertion handlers. +/// +public class AssertionDispatcher: AssertionHandler { + let handlers: [AssertionHandler] + + public init(handlers: [AssertionHandler]) { + self.handlers = handlers + } + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + for handler in handlers { + handler.assert(assertion, message: message, location: location) + } + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift new file mode 100644 index 0000000..740c392 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift @@ -0,0 +1,100 @@ +import Foundation + +/// A data structure that stores information about an assertion when +/// AssertionRecorder is set as the Nimble assertion handler. +/// +/// @see AssertionRecorder +/// @see AssertionHandler +public struct AssertionRecord: CustomStringConvertible { + /// Whether the assertion succeeded or failed + public let success: Bool + /// The failure message the assertion would display on failure. + public let message: FailureMessage + /// The source location the expectation occurred on. + public let location: SourceLocation + + public var description: String { + return "AssertionRecord { success=\(success), message='\(message.stringValue)', location=\(location) }" + } +} + +/// An AssertionHandler that silently records assertions that Nimble makes. +/// This is useful for testing failure messages for matchers. +/// +/// @see AssertionHandler +public class AssertionRecorder: AssertionHandler { + /// All the assertions that were captured by this recorder + public var assertions = [AssertionRecord]() + + public init() {} + + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + assertions.append( + AssertionRecord( + success: assertion, + message: message, + location: location)) + } +} + +/// Allows you to temporarily replace the current Nimble assertion handler with +/// the one provided for the scope of the closure. +/// +/// Once the closure finishes, then the original Nimble assertion handler is restored. +/// +/// @see AssertionHandler +public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, closure: () throws -> Void) { + let environment = NimbleEnvironment.activeInstance + let oldRecorder = environment.assertionHandler + let capturer = NMBExceptionCapture(handler: nil, finally: ({ + environment.assertionHandler = oldRecorder + })) + environment.assertionHandler = tempAssertionHandler + capturer.tryBlock { + try! closure() + } +} + +/// Captures expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about expectations +/// that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherFailingExpectations +public func gatherExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler + let recorder = AssertionRecorder() + let handlers: [AssertionHandler] + + if silently { + handlers = [recorder] + } else { + handlers = [recorder, previousRecorder] + } + + let dispatcher = AssertionDispatcher(handlers: handlers) + withAssertionHandler(dispatcher, closure: closure) + return recorder.assertions +} + +/// Captures failed expectations that occur in the given closure. Note that all +/// expectations will still go through to the default Nimble handler. +/// +/// This can be useful if you want to gather information about failed +/// expectations that occur within a closure. +/// +/// @param silently expectations are no longer send to the default Nimble +/// assertion handler when this is true. Defaults to false. +/// +/// @see gatherExpectations +/// @see raiseException source for an example use case. +public func gatherFailingExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] { + let assertions = gatherExpectations(silently: silently, closure: closure) + return assertions.filter { assertion in + !assertion.success + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift new file mode 100644 index 0000000..1c51cd7 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift @@ -0,0 +1,131 @@ +import Foundation + +#if _runtime(_ObjC) + +internal struct ObjCMatcherWrapper: Matcher { + let matcher: NMBMatcher + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.matches( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + return matcher.doesNotMatch( + ({ try! actualExpression.evaluate() }), + failureMessage: failureMessage, + location: actualExpression.location) + } +} + +// Equivalent to Expectation, but for Nimble's Objective-C interface +public class NMBExpectation: NSObject { + internal let _actualBlock: () -> NSObject! + internal var _negative: Bool + internal let _file: FileString + internal let _line: UInt + internal var _timeout: TimeInterval = 1.0 + + public init(actualBlock: @escaping () -> NSObject!, negative: Bool, file: FileString, line: UInt) { + self._actualBlock = actualBlock + self._negative = negative + self._file = file + self._line = line + } + + private var expectValue: Expectation { + return expect(_file, line: _line) { + self._actualBlock() as NSObject? + } + } + + public var withTimeout: (TimeInterval) -> NMBExpectation { + return ({ timeout in self._timeout = timeout + return self + }) + } + + public var to: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher)) + }) + } + + public var toWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher), description: description) + }) + } + + public var toNot: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.toNot( + ObjCMatcherWrapper(matcher: matcher) + ) + }) + } + + public var toNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.toNot( + ObjCMatcherWrapper(matcher: matcher), description: description + ) + }) + } + + public var notTo: (NMBMatcher) -> Void { return toNot } + + public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription } + + public var toEventually: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + }) + } + + public var toEventuallyWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + }) + } + + public var toEventuallyNot: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + }) + } + + public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + }) + } + + public var toNotEventually: (NMBMatcher) -> Void { return toEventuallyNot } + + public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { return toEventuallyNotWithDescription } + + public class func failWithMessage(_ message: String, file: FileString, line: UInt) { + fail(message, location: SourceLocation(file: file, line: line)) + } +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift new file mode 100644 index 0000000..19a4567 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift @@ -0,0 +1,81 @@ +import Foundation + +#if _runtime(_ObjC) + +public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) -> Bool +public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) -> Bool + +public class NMBObjCMatcher: NSObject, NMBMatcher { + let _match: MatcherBlock + let _doesNotMatch: MatcherBlock + let canMatchNil: Bool + + public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) { + self.canMatchNil = canMatchNil + self._match = matcher + self._doesNotMatch = notMatcher + } + + public convenience init(matcher: @escaping MatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in + return !matcher(actualExpression, failureMessage) + })) + } + + public convenience init(matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: true, matcher: matcher) + } + + public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) { + self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, false) + }), notMatcher: ({ actualExpression, failureMessage in + return matcher(actualExpression, failureMessage, true) + })) + } + + private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + do { + if !canMatchNil { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return false + } + } + } catch let error { + failureMessage.actualValue = "an unexpected error thrown: \(error)" + return false + } + return true + } + + public func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _match( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let expr = Expression(expression: actualBlock, location: location) + let result = _doesNotMatch( + expr, + failureMessage) + if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { + return result + } else { + return false + } + } +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift new file mode 100644 index 0000000..a55cb27 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift @@ -0,0 +1,45 @@ +import Dispatch +import Foundation + +/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this +/// class' existance +internal class NimbleEnvironment { + static var activeInstance: NimbleEnvironment { + get { + let env = Thread.current.threadDictionary["NimbleEnvironment"] + if let env = env as? NimbleEnvironment { + return env + } else { + let newEnv = NimbleEnvironment() + self.activeInstance = newEnv + return newEnv + } + } + set { + Thread.current.threadDictionary["NimbleEnvironment"] = newValue + } + } + + // TODO: eventually migrate the global to this environment value + var assertionHandler: AssertionHandler { + get { return NimbleAssertionHandler } + set { NimbleAssertionHandler = newValue } + } + + var suppressTVOSAssertionWarning: Bool = false + var awaiter: Awaiter + + init() { + let timeoutQueue: DispatchQueue + if #available(OSX 10.10, *) { + timeoutQueue = DispatchQueue.global(qos: .userInitiated) + } else { + timeoutQueue = DispatchQueue.global(priority: .high) + } + + awaiter = Awaiter( + waitLock: AssertionWaitLock(), + asyncQueue: .main, + timeoutQueue: timeoutQueue) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift new file mode 100644 index 0000000..78e6dd9 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -0,0 +1,76 @@ +import Foundation +import XCTest + +/// Default handler for Nimble. This assertion handler passes failures along to +/// XCTest. +public class NimbleXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + recordFailure("\(message.stringValue)\n", location: location) + } + } +} + +/// Alternative handler for Nimble. This assertion handler passes failures along +/// to XCTest by attempting to reduce the failure message size. +public class NimbleShortXCTestHandler: AssertionHandler { + public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + if !assertion { + let msg: String + if let actual = message.actualValue { + msg = "got: \(actual) \(message.postfixActual)" + } else { + msg = "expected \(message.to) \(message.postfixMessage)" + } + recordFailure("\(msg)\n", location: location) + } + } +} + +/// Fallback handler in case XCTest is unavailable. This assertion handler will abort +/// the program if it is invoked. +class NimbleXCTestUnavailableHandler: AssertionHandler { + func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { + fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.") + } +} + +#if !SWIFT_PACKAGE +/// Helper class providing access to the currently executing XCTestCase instance, if any +@objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation { + @objc static let sharedInstance = CurrentTestCaseTracker() + + private(set) var currentTestCase: XCTestCase? + + @objc func testCaseWillStart(_ testCase: XCTestCase) { + currentTestCase = testCase + } + + @objc func testCaseDidFinish(_ testCase: XCTestCase) { + currentTestCase = nil + } +} +#endif + +func isXCTestAvailable() -> Bool { +#if _runtime(_ObjC) + // XCTest is weakly linked and so may not be present + return NSClassFromString("XCTestCase") != nil +#else + return true +#endif +} + +private func recordFailure(_ message: String, location: SourceLocation) { +#if SWIFT_PACKAGE + XCTFail("\(message)", file: location.file, line: location.line) +#else + if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase { + testCase.recordFailure(withDescription: message, inFile: location.file, atLine: location.line, expected: true) + } else { + let msg = "Attempted to report a test failure to XCTest while no test case was running. " + + "The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)" + NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() + } +#endif +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/DSL+Wait.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/DSL+Wait.swift new file mode 100644 index 0000000..f7f373f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/DSL+Wait.swift @@ -0,0 +1,98 @@ +import Dispatch +import Foundation + +private enum ErrorResult { + case exception(NSException) + case error(Error) + case none +} + +/// Only classes, protocols, methods, properties, and subscript declarations can be +/// bridges to Objective-C via the @objc keyword. This class encapsulates callback-style +/// asynchronous waiting logic so that it may be called from Objective-C and Swift. +internal class NMBWait: NSObject { + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) -> Void { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } + + // Using a throwable closure makes this method not objc compatible. + internal class func throwableUntil( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) throws -> Void) -> Void { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let leeway = timeout / 2.0 + let result = awaiter.performBlock { (done: @escaping (ErrorResult) -> Void) throws -> Void in + DispatchQueue.main.async { + let capture = NMBExceptionCapture( + handler: ({ exception in + done(.exception(exception)) + }), + finally: ({ }) + ) + capture.tryBlock { + do { + try action { + done(.none) + } + } catch let e { + done(.error(e)) + } + } + } + }.timeout(timeout, forcefullyAbortTimeout: leeway).wait("waitUntil(...)", file: file, line: line) + + switch result { + case .incomplete: internalError("Reached .incomplete state for waitUntil(...).") + case .blockedRunLoop: + fail(blockedRunLoopErrorMessageFor("-waitUntil()", leeway: leeway), + file: file, line: line) + case .timedOut: + let pluralize = (timeout == 1 ? "" : "s") + fail("Waited more than \(timeout) second\(pluralize)", file: file, line: line) + case let .raisedException(exception): + fail("Unexpected exception raised: \(exception)") + case let .errorThrown(error): + fail("Unexpected error thrown: \(error)") + case .completed(.exception(let exception)): + fail("Unexpected exception raised: \(exception)") + case .completed(.error(let error)): + fail("Unexpected error thrown: \(error)") + case .completed(.none): // success + break + } + } + + #if SWIFT_PACKAGE + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) -> Void { + until(timeout: 1, file: file, line: line, action: action) + } + #else + @objc(untilFile:line:action:) + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) -> Void { + until(timeout: 1, file: file, line: line, action: action) + } + #endif +} + +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> String { + return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive (\(leeway) seconds is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run." +} + +/// Wait asynchronously until the done closure is called or the timeout has been reached. +/// +/// @discussion +/// Call the done() closure to indicate the waiting has completed. +/// +/// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function +/// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. +public func waitUntil(timeout: TimeInterval = 1, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) -> Void { + NMBWait.until(timeout: timeout, file: file, line: line, action: action) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/DSL.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 0000000..7ebd684 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/DSL.swift @@ -0,0 +1,64 @@ +import Foundation + +/// Make an expectation on a given actual value. The value given is lazily evaluated. +public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation { + return Expectation( + expression: Expression( + expression: expression, + location: SourceLocation(file: file, line: line), + isClosure: true)) +} + +/// Make an expectation on a given actual value. The closure is lazily invoked. +public func expect(_ file: FileString = #file, line: UInt = #line, expression: @escaping () throws -> T?) -> Expectation { + return Expectation( + expression: Expression( + expression: expression, + location: SourceLocation(file: file, line: line), + isClosure: true)) +} + +/// Always fails the test with a message and a specified location. +public func fail(_ message: String, location: SourceLocation) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(false, message: FailureMessage(stringValue: message), location: location) +} + +/// Always fails the test with a message. +public func fail(_ message: String, file: FileString = #file, line: UInt = #line) { + fail(message, location: SourceLocation(file: file, line: line)) +} + +/// Always fails the test. +public func fail(_ file: FileString = #file, line: UInt = #line) { + fail("fail() always fails", file: file, line: line) +} + +/// Like Swift's precondition(), but raises NSExceptions instead of sigaborts +internal func nimblePrecondition( + _ expr: @autoclosure() -> Bool, + _ name: @autoclosure() -> String, + _ message: @autoclosure() -> String, + file: StaticString = #file, + line: UInt = #line) { + let result = expr() + if !result { +#if _runtime(_ObjC) + let e = NSException( + name: NSExceptionName(name()), + reason: message(), + userInfo: nil) + e.raise() +#else + preconditionFailure("\(name()) - \(message())", file: file, line: line) +#endif + } +} + +internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never { + fatalError( + "Nimble Bug Found: \(msg) at \(file):\(line).\n" + + "Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the " + + "code snippet that caused this error." + ) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Expectation.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Expectation.swift new file mode 100644 index 0000000..c5978f4 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Expectation.swift @@ -0,0 +1,71 @@ +import Foundation + +internal func expressionMatches(_ expression: Expression, matcher: U, to: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = to + do { + let pass = try matcher.matches(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.actualValue = "an unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +internal func expressionDoesNotMatch(_ expression: Expression, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage) + where U: Matcher, U.ValueType == T { + let msg = FailureMessage() + msg.userDescription = description + msg.to = toNot + do { + let pass = try matcher.doesNotMatch(expression, failureMessage: msg) + if msg.actualValue == "" { + msg.actualValue = "<\(stringify(try expression.evaluate()))>" + } + return (pass, msg) + } catch let error { + msg.actualValue = "an unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +public struct Expectation { + + public let expression: Expression + + public func verify(_ pass: Bool, _ message: FailureMessage) { + let handler = NimbleEnvironment.activeInstance.assertionHandler + handler.assert(pass, message: message, location: expression.location) + } + + /// Tests the actual value using a matcher to match. + public func to(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + let (pass, msg) = expressionMatches(expression, matcher: matcher, to: "to", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + public func toNot(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + let (pass, msg) = expressionDoesNotMatch(expression, matcher: matcher, toNot: "to not", description: description) + verify(pass, msg) + } + + /// Tests the actual value using a matcher to not match. + /// + /// Alias to toNot(). + public func notTo(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + toNot(matcher, description: description) + } + + // see: + // - AsyncMatcherWrapper for extension + // - NMBExpectation for Objective-C interface +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Expression.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Expression.swift new file mode 100644 index 0000000..f7afffe --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Expression.swift @@ -0,0 +1,90 @@ +import Foundation + +// Memoizes the given closure, only calling the passed +// closure once; even if repeat calls to the returned closure +internal func memoizedClosure(_ closure: @escaping () throws -> T) -> (Bool) throws -> T { + var cache: T? + return ({ withoutCaching in + if withoutCaching || cache == nil { + cache = try closure() + } + return cache! + }) +} + +/// Expression represents the closure of the value inside expect(...). +/// Expressions are memoized by default. This makes them safe to call +/// evaluate() multiple times without causing a re-evaluation of the underlying +/// closure. +/// +/// @warning Since the closure can be any code, Objective-C code may choose +/// to raise an exception. Currently, Expression does not memoize +/// exception raising. +/// +/// This provides a common consumable API for matchers to utilize to allow +/// Nimble to change internals to how the captured closure is managed. +public struct Expression { + internal let _expression: (Bool) throws -> T? + internal let _withoutCaching: Bool + public let location: SourceLocation + public let isClosure: Bool + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. The expression is memoized. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(expression: @escaping () throws -> T?, location: SourceLocation, isClosure: Bool = true) { + self._expression = memoizedClosure(expression) + self.location = location + self._withoutCaching = false + self.isClosure = isClosure + } + + /// Creates a new expression struct. Normally, expect(...) will manage this + /// creation process. + /// + /// @param expression The closure that produces a given value. + /// @param location The source location that this closure originates from. + /// @param withoutCaching Indicates if the struct should memoize the given + /// closure's result. Subsequent evaluate() calls will + /// not call the given closure if this is true. + /// @param isClosure A bool indicating if the captured expression is a + /// closure or internally produced closure. Some matchers + /// may require closures. For example, toEventually() + /// requires an explicit closure. This gives Nimble + /// flexibility if @autoclosure behavior changes between + /// Swift versions. Nimble internals always sets this true. + public init(memoizedExpression: @escaping (Bool) throws -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = true) { + self._expression = memoizedExpression + self.location = location + self._withoutCaching = withoutCaching + self.isClosure = isClosure + } + + /// Returns a new Expression from the given expression. Identical to a map() + /// on this type. This should be used only to typecast the Expression's + /// closure value. + /// + /// The returned expression will preserve location and isClosure. + /// + /// @param block The block that can cast the current Expression value to a + /// new type. + public func cast(_ block: @escaping (T?) throws -> U?) -> Expression { + return Expression(expression: ({ try block(self.evaluate()) }), location: self.location, isClosure: self.isClosure) + } + + public func evaluate() throws -> T? { + return try self._expression(_withoutCaching) + } + + public func withoutCaching() -> Expression { + return Expression(memoizedExpression: self._expression, location: location, withoutCaching: true, isClosure: isClosure) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/FailureMessage.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/FailureMessage.swift new file mode 100644 index 0000000..24b6c8f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/FailureMessage.swift @@ -0,0 +1,65 @@ +import Foundation + +/// Encapsulates the failure message that matchers can report to the end user. +/// +/// This is shared state between Nimble and matchers that mutate this value. +public class FailureMessage: NSObject { + public var expected: String = "expected" + public var actualValue: String? = "" // empty string -> use default; nil -> exclude + public var to: String = "to" + public var postfixMessage: String = "match" + public var postfixActual: String = "" + /// An optional message that will be appended as a new line and provides additional details + /// about the failure. This message will only be visible in the issue navigator / in logs but + /// not directly in the source editor since only a single line is presented there. + public var extendedMessage: String? = nil + public var userDescription: String? = nil + + public var stringValue: String { + get { + if let value = _stringValueOverride { + return value + } else { + return computeStringValue() + } + } + set { + _stringValueOverride = newValue + } + } + + internal var _stringValueOverride: String? + + public override init() { + } + + public init(stringValue: String) { + _stringValueOverride = stringValue + } + + internal func stripNewlines(_ str: String) -> String { + let whitespaces = CharacterSet.whitespacesAndNewlines + return str + .components(separatedBy: "\n") + .map { line in line.trimmingCharacters(in: whitespaces) } + .joined(separator: "") + } + + internal func computeStringValue() -> String { + var value = "\(expected) \(to) \(postfixMessage)" + if let actualValue = actualValue { + value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)" + } + value = stripNewlines(value) + + if let extendedMessage = extendedMessage { + value += "\n\(stripNewlines(extendedMessage))" + } + + if let userDescription = userDescription { + return "\(userDescription)\n\(value)" + } + + return value + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/AllPass.swift new file mode 100644 index 0000000..73e79d3 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/AllPass.swift @@ -0,0 +1,94 @@ +import Foundation + +public func allPass + (_ passFunc: @escaping (T?) -> Bool) -> NonNilMatcherFunc + where U: Sequence, U.Iterator.Element == T { + return allPass("pass a condition", passFunc) +} + +public func allPass + (_ passName: String, _ passFunc: @escaping (T?) -> Bool) -> NonNilMatcherFunc + where U: Sequence, U.Iterator.Element == T { + return createAllPassMatcher { expression, failureMessage in + failureMessage.postfixMessage = passName + return passFunc(try expression.evaluate()) + } +} + +public func allPass + (_ matcher: V) -> NonNilMatcherFunc + where U: Sequence, V: Matcher, U.Iterator.Element == V.ValueType { + return createAllPassMatcher { + try matcher.matches($0, failureMessage: $1) + } +} + +private func createAllPassMatcher + (_ elementEvaluator: @escaping (Expression, FailureMessage) throws -> Bool) -> NonNilMatcherFunc + where U: Sequence, U.Iterator.Element == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.actualValue = nil + if let actualValue = try actualExpression.evaluate() { + for currentElement in actualValue { + let exp = Expression( + expression: {currentElement}, location: actualExpression.location) + if try !elementEvaluator(exp, failureMessage) { + failureMessage.postfixMessage = + "all \(failureMessage.postfixMessage)," + + " but failed first at element <\(stringify(currentElement))>" + + " in <\(stringify(actualValue))>" + return false + } + } + failureMessage.postfixMessage = "all \(failureMessage.postfixMessage)" + } else { + failureMessage.postfixMessage = "all pass (use beNil() to match nils)" + return false + } + + return true + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func allPassMatcher(_ matcher: NMBObjCMatcher) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + var nsObjects = [NSObject]() + + var collectionIsUsable = true + if let value = actualValue as? NSFastEnumeration { + let generator = NSFastEnumerationIterator(value) + while let obj = generator.next() { + if let nsObject = obj as? NSObject { + nsObjects.append(nsObject) + } else { + collectionIsUsable = false + break + } + } + } else { + collectionIsUsable = false + } + + if !collectionIsUsable { + failureMessage.postfixMessage = + "allPass only works with NSFastEnumeration (NSArray, NSSet, ...) of NSObjects" + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + let expr = Expression(expression: ({ nsObjects }), location: location) + let elementEvaluator: (Expression, FailureMessage) -> Bool = { + expression, failureMessage in + return matcher.matches({try! expression.evaluate()}, failureMessage: failureMessage, location: expr.location) + } + return try! createAllPassMatcher(elementEvaluator).matches( + expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift new file mode 100644 index 0000000..b971ccc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift @@ -0,0 +1,141 @@ +import Foundation + +/// If you are running on a slower machine, it could be useful to increase the default timeout value +/// or slow down poll interval. Default timeout interval is 1, and poll interval is 0.01. +public struct AsyncDefaults { + public static var Timeout: TimeInterval = 1 + public static var PollInterval: TimeInterval = 0.01 +} + +internal struct AsyncMatcherWrapper: Matcher + where U: Matcher, U.ValueType == T { + let fullMatcher: U + let timeoutInterval: TimeInterval + let pollInterval: TimeInterval + + init(fullMatcher: U, timeoutInterval: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval) { + self.fullMatcher = fullMatcher + self.timeoutInterval = timeoutInterval + self.pollInterval = pollInterval + } + + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let fnName = "expect(...).toEventually(...)" + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: fnName) { + try self.fullMatcher.matches(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.actualValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.actualValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventually(...).") + } + } + + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { + let uncachedExpression = actualExpression.withoutCaching() + let result = pollBlock( + pollInterval: pollInterval, + timeoutInterval: timeoutInterval, + file: actualExpression.location.file, + line: actualExpression.location.line, + fnName: "expect(...).toEventuallyNot(...)") { + try self.fullMatcher.doesNotMatch(uncachedExpression, failureMessage: failureMessage) + } + switch result { + case let .completed(isSuccessful): return isSuccessful + case .timedOut: return false + case let .errorThrown(error): + failureMessage.actualValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.actualValue = "an unexpected exception thrown: <\(exception)>" + return false + case .blockedRunLoop: + failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)." + return false + case .incomplete: + internalError("Reached .incomplete state for toEventuallyNot(...).") + } + } +} + +private let toEventuallyRequiresClosureError = FailureMessage(stringValue: "expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )\nSwift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function") + +extension Expectation { + /// Tests the actual value using a matcher to match by checking continuously + /// at each pollInterval until the timeout is reached. + /// + /// @discussion + /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function + /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. + public func toEventually(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionMatches( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + to: "to eventually", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// @discussion + /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function + /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. + public func toEventuallyNot(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + if expression.isClosure { + let (pass, msg) = expressionDoesNotMatch( + expression, + matcher: AsyncMatcherWrapper( + fullMatcher: matcher, + timeoutInterval: timeout, + pollInterval: pollInterval), + toNot: "to eventually not", + description: description + ) + verify(pass, msg) + } else { + verify(false, toEventuallyRequiresClosureError) + } + } + + /// Tests the actual value using a matcher to not match by checking + /// continuously at each pollInterval until the timeout is reached. + /// + /// Alias of toEventuallyNot() + /// + /// @discussion + /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function + /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. + public func toNotEventually(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + where U: Matcher, U.ValueType == T { + return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift new file mode 100644 index 0000000..f636a72 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift @@ -0,0 +1,48 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +public func beAKindOf(_ expectedType: T.Type) -> NonNilMatcherFunc { + return NonNilMatcherFunc {actualExpression, failureMessage in + failureMessage.postfixMessage = "be a kind of \(String(describing: expectedType))" + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + failureMessage.actualValue = "" + return false + } + + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + + guard validInstance is T else { + return false + } + + return true + } +} + +#if _runtime(_ObjC) + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +/// @see beAnInstanceOf if you want to match against the exact class +public func beAKindOf(_ expectedClass: AnyClass) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let instance = try actualExpression.evaluate() + if let validInstance = instance { + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + } else { + failureMessage.actualValue = "" + } + failureMessage.postfixMessage = "be a kind of \(String(describing: expectedClass))" + return instance != nil && instance!.isKind(of: expectedClass) + } +} + +extension NMBObjCMatcher { + public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! beAKindOf(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift new file mode 100644 index 0000000..07ce3d3 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift @@ -0,0 +1,50 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class. +public func beAnInstanceOf(_ expectedType: T.Type) -> NonNilMatcherFunc { + return NonNilMatcherFunc {actualExpression, failureMessage in + failureMessage.postfixMessage = "be an instance of \(String(describing: expectedType))" + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + failureMessage.actualValue = "" + return false + } + + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + + if type(of: validInstance) == expectedType { + return true + } + + return false + } +} + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +/// @see beAKindOf if you want to match against subclasses +public func beAnInstanceOf(_ expectedClass: AnyClass) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let instance = try actualExpression.evaluate() + if let validInstance = instance { + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + } else { + failureMessage.actualValue = "" + } + failureMessage.postfixMessage = "be an instance of \(String(describing: expectedClass))" +#if _runtime(_ObjC) + return instance != nil && instance!.isMember(of: expectedClass) +#else + return instance != nil && type(of: instance!) == expectedClass +#endif + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! beAnInstanceOf(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift new file mode 100644 index 0000000..95c52cf --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift @@ -0,0 +1,122 @@ +import Foundation + +internal let DefaultDelta = 0.0001 + +internal func isCloseTo(_ actualValue: NMBDoubleConvertible?, expectedValue: NMBDoubleConvertible, delta: Double, failureMessage: FailureMessage) -> Bool { + failureMessage.postfixMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" + failureMessage.actualValue = "<\(stringify(actualValue))>" + return actualValue != nil && abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta +} + +/// A Nimble matcher that succeeds when a value is close to another. This is used for floating +/// point values which can have imprecise results when doing arithmetic on them. +/// +/// @see equal +public func beCloseTo(_ expectedValue: Double, within delta: Double = DefaultDelta) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta, failureMessage: failureMessage) + } +} + +/// A Nimble matcher that succeeds when a value is close to another. This is used for floating +/// point values which can have imprecise results when doing arithmetic on them. +/// +/// @see equal +public func beCloseTo(_ expectedValue: NMBDoubleConvertible, within delta: Double = DefaultDelta) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta, failureMessage: failureMessage) + } +} + +#if _runtime(_ObjC) +public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher { + var _expected: NSNumber + var _delta: CDouble + init(expected: NSNumber, within: CDouble) { + _expected = expected + _delta = within + } + + public func matches(_ actualExpression: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let actualBlock: () -> NMBDoubleConvertible? = ({ + return actualExpression() as? NMBDoubleConvertible + }) + let expr = Expression(expression: actualBlock, location: location) + let matcher = beCloseTo(self._expected, within: self._delta) + return try! matcher.matches(expr, failureMessage: failureMessage) + } + + public func doesNotMatch(_ actualExpression: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let actualBlock: () -> NMBDoubleConvertible? = ({ + return actualExpression() as? NMBDoubleConvertible + }) + let expr = Expression(expression: actualBlock, location: location) + let matcher = beCloseTo(self._expected, within: self._delta) + return try! matcher.doesNotMatch(expr, failureMessage: failureMessage) + } + + public var within: (CDouble) -> NMBObjCBeCloseToMatcher { + return ({ delta in + return NMBObjCBeCloseToMatcher(expected: self._expected, within: delta) + }) + } +} + +extension NMBObjCMatcher { + public class func beCloseToMatcher(_ expected: NSNumber, within: CDouble) -> NMBObjCBeCloseToMatcher { + return NMBObjCBeCloseToMatcher(expected: expected, within: within) + } +} +#endif + +public func beCloseTo(_ expectedValues: [Double], within delta: Double = DefaultDelta) -> NonNilMatcherFunc <[Double]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))" + if let actual = try actualExpression.evaluate() { + failureMessage.actualValue = "<\(stringify(actual))>" + + if actual.count != expectedValues.count { + return false + } else { + for (index, actualItem) in actual.enumerated() { + if fabs(actualItem - expectedValues[index]) > delta { + return false + } + } + return true + } + } + return false + } +} + +// MARK: - Operators + +infix operator ≈ : ComparisonPrecedence + +public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: NMBDoubleConvertible) { + lhs.to(beCloseTo(rhs)) +} + +public func ≈(lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) { + lhs.to(beCloseTo(rhs.expected, within: rhs.delta)) +} + +public func == (lhs: Expectation, rhs: (expected: NMBDoubleConvertible, delta: Double)) { + lhs.to(beCloseTo(rhs.expected, within: rhs.delta)) +} + +// make this higher precedence than exponents so the Doubles either end aren't pulled in +// unexpectantly +precedencegroup PlusMinusOperatorPrecedence { + higherThan: BitwiseShiftPrecedence +} + +infix operator ± : PlusMinusOperatorPrecedence +public func ±(lhs: NMBDoubleConvertible, rhs: Double) -> (expected: NMBDoubleConvertible, delta: Double) { + return (expected: lhs, delta: rhs) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeEmpty.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeEmpty.swift new file mode 100644 index 0000000..2ea2cdb --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeEmpty.swift @@ -0,0 +1,91 @@ +import Foundation + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For strings, it is an empty string. +public func beEmpty() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualSeq = try actualExpression.evaluate() + if actualSeq == nil { + return true + } + var generator = actualSeq!.makeIterator() + return generator.next() == nil + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For strings, it is an empty string. +public func beEmpty() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualString = try actualExpression.evaluate() + return actualString == nil || NSString(string: actualString!).length == 0 + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For NSString instances, it is an empty string. +public func beEmpty() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualString = try actualExpression.evaluate() + return actualString == nil || actualString!.length == 0 + } +} + +// Without specific overrides, beEmpty() is ambiguous for NSDictionary, NSArray, +// etc, since they conform to Sequence as well as NMBCollection. + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For strings, it is an empty string. +public func beEmpty() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualDictionary = try actualExpression.evaluate() + return actualDictionary == nil || actualDictionary!.count == 0 + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For strings, it is an empty string. +public func beEmpty() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualArray = try actualExpression.evaluate() + return actualArray == nil || actualArray!.count == 0 + } +} + +/// A Nimble matcher that succeeds when a value is "empty". For collections, this +/// means the are no items in that collection. For strings, it is an empty string. +public func beEmpty() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actual = try actualExpression.evaluate() + return actual == nil || actual!.count == 0 + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beEmptyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + failureMessage.postfixMessage = "be empty" + if let value = actualValue as? NMBCollection { + let expr = Expression(expression: ({ value as NMBCollection }), location: location) + return try! beEmpty().matches(expr, failureMessage: failureMessage) + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! beEmpty().matches(expr, failureMessage: failureMessage) + } else if let actualValue = actualValue { + failureMessage.postfixMessage = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" + failureMessage.actualValue = "\(String(describing: type(of: actualValue))) type" + } + return false + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift new file mode 100644 index 0000000..c7eb84c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual > expected + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: NMBComparable?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending + return matches + } +} + +public func >(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThan(rhs)) +} + +public func > (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beGreaterThan(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift new file mode 100644 index 0000000..2949fce --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift @@ -0,0 +1,44 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if let actual = actualValue, let expected = expectedValue { + return actual >= expected + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending + return matches + } +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift new file mode 100644 index 0000000..8df7e5f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift @@ -0,0 +1,46 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is the same instance +/// as the expected instance. +public func beIdenticalTo(_ expected: Any?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + #if os(Linux) + let actual = try actualExpression.evaluate() as? AnyObject + #else + let actual = try actualExpression.evaluate() as AnyObject? + #endif + failureMessage.actualValue = "\(identityAsString(actual))" + failureMessage.postfixMessage = "be identical to \(identityAsString(expected))" + #if os(Linux) + return actual === (expected as? AnyObject) && actual !== nil + #else + return actual === (expected as AnyObject?) && actual !== nil + #endif + } +} + +public func === (lhs: Expectation, rhs: Any?) { + lhs.to(beIdenticalTo(rhs)) +} +public func !== (lhs: Expectation, rhs: Any?) { + lhs.toNot(beIdenticalTo(rhs)) +} + +/// A Nimble matcher that succeeds when the actual value is the same instance +/// as the expected instance. +/// +/// Alias for "beIdenticalTo". +public func be(_ expected: Any?) -> NonNilMatcherFunc { + return beIdenticalTo(expected) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let aExpr = actualExpression.cast { $0 as Any? } + return try! beIdenticalTo(expected).matches(aExpr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLessThan.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLessThan.swift new file mode 100644 index 0000000..5bbbf36 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLessThan.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual < expected + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: NMBComparable?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending + return matches + } +} + +public func <(lhs: Expectation, rhs: T) { + lhs.to(beLessThan(rhs)) +} + +public func < (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beLessThan(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThan(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift new file mode 100644 index 0000000..a0cd2f0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift @@ -0,0 +1,42 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual <= expected + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + return actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedDescending + } +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil:false) { actualExpression, failureMessage in + let expr = actualExpression.cast { $0 as? NMBComparable } + return try! beLessThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLogical.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLogical.swift new file mode 100644 index 0000000..49272a3 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeLogical.swift @@ -0,0 +1,173 @@ +import Foundation + +extension Int8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int8Value + } +} + +extension UInt8: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint8Value + } +} + +extension Int16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int16Value + } +} + +extension UInt16: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint16Value + } +} + +extension Int32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int32Value + } +} + +extension UInt32: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint32Value + } +} + +extension Int64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).int64Value + } +} + +extension UInt64: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uint64Value + } +} + +extension Float: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).floatValue + } +} + +extension Double: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).doubleValue + } +} + +extension Int: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).intValue + } +} + +extension UInt: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = NSNumber(value: value).uintValue + } +} + +internal func matcherWithFailureMessage(_ matcher: NonNilMatcherFunc, postprocessor: @escaping (FailureMessage) -> Void) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + defer { postprocessor(failureMessage) } + return try matcher.matcher(actualExpression, failureMessage) + } +} + +// MARK: beTrue() / beFalse() + +/// A Nimble matcher that succeeds when the actual value is exactly true. +/// This matcher will not match against nils. +public func beTrue() -> NonNilMatcherFunc { + return matcherWithFailureMessage(equal(true)) { failureMessage in + failureMessage.postfixMessage = "be true" + } +} + +/// A Nimble matcher that succeeds when the actual value is exactly false. +/// This matcher will not match against nils. +public func beFalse() -> NonNilMatcherFunc { + return matcherWithFailureMessage(equal(false)) { failureMessage in + failureMessage.postfixMessage = "be false" + } +} + +// MARK: beTruthy() / beFalsy() + +/// A Nimble matcher that succeeds when the actual value is not logically false. +public func beTruthy() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be truthy" + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return number.boolValue == true + } + + return actualValue == (true as T) + } + return actualValue != nil + } +} + +/// A Nimble matcher that succeeds when the actual value is logically false. +/// This matcher will match against nils. +public func beFalsy() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be falsy" + let actualValue = try actualExpression.evaluate() + if let actualValue = actualValue { + // FIXME: This is a workaround to SR-2290. + // See: + // - https://bugs.swift.org/browse/SR-2290 + // - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873 + if let number = actualValue as? NSNumber { + return number.boolValue == false + } + + return actualValue == (false as T) + } + return actualValue == nil + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beTruthyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTruthy().matches(expr, failureMessage: failureMessage) + } + } + + public class func beFalsyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalsy().matches(expr, failureMessage: failureMessage) + } + } + + public class func beTrueMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beTrue().matches(expr, failureMessage: failureMessage) + } + } + + public class func beFalseMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } + return try! beFalse().matches(expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeNil.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeNil.swift new file mode 100644 index 0000000..a6fb31f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeNil.swift @@ -0,0 +1,20 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is nil. +public func beNil() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be nil" + let actualValue = try actualExpression.evaluate() + return actualValue == nil + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + return try! beNil().matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeVoid.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeVoid.swift new file mode 100644 index 0000000..92a8d43 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeVoid.swift @@ -0,0 +1,18 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is Void. +public func beVoid() -> MatcherFunc<()> { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be void" + let actualValue: ()? = try actualExpression.evaluate() + return actualValue != nil + } +} + +public func == (lhs: Expectation<()>, rhs: ()) { + lhs.to(beVoid()) +} + +public func != (lhs: Expectation<()>, rhs: ()) { + lhs.toNot(beVoid()) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeginWith.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeginWith.swift new file mode 100644 index 0000000..31cbe5d --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/BeginWith.swift @@ -0,0 +1,63 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's first element +/// is equal to the expected value. +public func beginWith(_ startingElement: T) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + if let actualValue = try actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + return actualGenerator.next() == startingElement + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual collection's first element +/// is equal to the expected object. +public func beginWith(_ startingElement: Any) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + guard let collection = try actualExpression.evaluate() else { return false } + guard collection.count > 0 else { return false } + #if os(Linux) + guard let collectionValue = collection.object(at: 0) as? NSObject else { + return false + } + #else + let collectionValue = collection.object(at: 0) as AnyObject + #endif + return collectionValue.isEqual(startingElement) + } +} + +/// A Nimble matcher that succeeds when the actual string contains expected substring +/// where the expected substring's location is zero. +public func beginWith(_ startingSubstring: String) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingSubstring)>" + if let actual = try actualExpression.evaluate() { + let range = actual.range(of: startingSubstring) + return range != nil && range!.lowerBound == actual.startIndex + } + return false + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beginWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if let _ = actual as? String { + let expr = actualExpression.cast { $0 as? String } + return try! beginWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! beginWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Contain.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Contain.swift new file mode 100644 index 0000000..5053642 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Contain.swift @@ -0,0 +1,94 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence contains the expected value. +public func contain(_ items: T...) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return contain(items) +} + +public func contain(_ items: [T]) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + if let actual = try actualExpression.evaluate() { + return items.all { + return actual.contains($0) + } + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: String...) -> NonNilMatcherFunc { + return contain(substrings) +} + +public func contain(_ substrings: [String]) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { + let range = actual.range(of: $0) + return range != nil && !range!.isEmpty + } + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: NSString...) -> NonNilMatcherFunc { + return contain(substrings) +} + +public func contain(_ substrings: [NSString]) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>" + if let actual = try actualExpression.evaluate() { + return substrings.all { actual.range(of: $0.description).length != 0 } + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual collection contains the expected object. +public func contain(_ items: Any?...) -> NonNilMatcherFunc { + return contain(items) +} + +public func contain(_ items: [Any?]) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + guard let actual = try actualExpression.evaluate() else { return false } + return items.all { item in + return item != nil && actual.contains(item!) + } + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func containMatcher(_ expected: [NSObject]) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + if let value = actualValue as? NMBContainer { + let expr = Expression(expression: ({ value as NMBContainer }), location: location) + + // A straightforward cast on the array causes this to crash, so we have to cast the individual items + let expectedOptionals: [Any?] = expected.map({ $0 as Any? }) + return try! contain(expectedOptionals).matches(expr, failureMessage: failureMessage) + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! contain(expected as! [String]).matches(expr, failureMessage: failureMessage) + } else if actualValue != nil { + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)" + } else { + failureMessage.postfixMessage = "contain <\(arrayAsString(expected))>" + } + return false + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift new file mode 100644 index 0000000..ae8cca2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -0,0 +1,59 @@ +import Foundation + +public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> NonNilMatcherFunc where S.Iterator.Element == T { + + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.actualValue = nil + + if predicateDescription == "" { + failureMessage.postfixMessage = "find object in collection that satisfies predicate" + } else { + failureMessage.postfixMessage = "find object in collection \(predicateDescription)" + } + + if let sequence = try actualExpression.evaluate() { + for object in sequence { + if predicate(object) { + return true + } + } + + return false + } + + return false + } +} + +#if _runtime(_ObjC) + extension NMBObjCMatcher { + public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let value = try! actualExpression.evaluate() + guard let enumeration = value as? NSFastEnumeration else { + failureMessage.postfixMessage = "containElementSatisfying must be provided an NSFastEnumeration object" + failureMessage.actualValue = nil + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + let iterator = NSFastEnumerationIterator(enumeration) + while let item = iterator.next() { + guard let object = item as? NSObject else { + continue + } + + if predicate(object) { + return true + } + } + + failureMessage.actualValue = nil + failureMessage.postfixMessage = "" + failureMessage.to = "to find object in collection that satisfies predicate" + return false + } + } + } +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/EndWith.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/EndWith.swift new file mode 100644 index 0000000..00c7e20 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/EndWith.swift @@ -0,0 +1,72 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence's last element +/// is equal to the expected value. +public func endWith(_ endingElement: T) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + + if let actualValue = try actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + var lastItem: T? + var item: T? + repeat { + lastItem = item + item = actualGenerator.next() + } while(item != nil) + + return lastItem == endingElement + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual collection's last element +/// is equal to the expected object. +public func endWith(_ endingElement: Any) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingElement)>" + guard let collection = try actualExpression.evaluate() else { return false } + guard collection.count > 0 else { return false } + #if os(Linux) + guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else { + return false + } + #else + let collectionValue = collection.object(at: collection.count - 1) as AnyObject + #endif + + return collectionValue.isEqual(endingElement) + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring +/// where the expected substring's location is the actual string's length minus the +/// expected substring's length. +public func endWith(_ endingSubstring: String) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingSubstring)>" + if let collection = try actualExpression.evaluate() { + return collection.hasSuffix(endingSubstring) + } + return false + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func endWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if let _ = actual as? String { + let expr = actualExpression.cast { $0 as? String } + return try! endWith(expected as! String).matches(expr, failureMessage: failureMessage) + } else { + let expr = actualExpression.cast { $0 as? NMBOrderedCollection } + return try! endWith(expected).matches(expr, failureMessage: failureMessage) + } + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Equal.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Equal.swift new file mode 100644 index 0000000..1dccfd0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Equal.swift @@ -0,0 +1,181 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is equal to the expected value. +/// Values can support equal by supporting the Equatable protocol. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + return false + } + return matches + } +} + +/// A Nimble matcher that succeeds when the actual value is equal to the expected value. +/// Values can support equal by supporting the Equatable protocol. +/// +/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). +public func equal(_ expectedValue: [T: C]?) -> NonNilMatcherFunc<[T: C]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + return false + } + return expectedValue! == actualValue! + } +} + +/// A Nimble matcher that succeeds when the actual collection is equal to the expected collection. +/// Items must implement the Equatable protocol. +public func equal(_ expectedValue: [T]?) -> NonNilMatcherFunc<[T]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + return false + } + return expectedValue! == actualValue! + } +} + +/// A Nimble matcher allowing comparison of collection with optional type +public func equal(_ expectedValue: [T?]) -> NonNilMatcherFunc<[T?]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + if let actualValue = try actualExpression.evaluate() { + if expectedValue.count != actualValue.count { + return false + } + + for (index, item) in actualValue.enumerated() { + let otherItem = expectedValue[index] + if item == nil && otherItem == nil { + continue + } else if item == nil && otherItem != nil { + return false + } else if item != nil && otherItem == nil { + return false + } else if item! != otherItem! { + return false + } + } + + return true + } else { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + + return false + } +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> NonNilMatcherFunc> { + return equal(expectedValue, stringify: { stringify($0) }) +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> NonNilMatcherFunc> { + return equal(expectedValue, stringify: { + if let set = $0 { + return stringify(Array(set).sorted { $0 < $1 }) + } else { + return "nil" + } + }) +} + +private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> NonNilMatcherFunc> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + + if let expectedValue = expectedValue { + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "<\(stringify(actualValue))>" + + if expectedValue == actualValue { + return true + } + + let missing = expectedValue.subtracting(actualValue) + if missing.count > 0 { + failureMessage.postfixActual += ", missing <\(stringify(missing))>" + } + + let extra = actualValue.subtracting(expectedValue) + if extra.count > 0 { + failureMessage.postfixActual += ", extra <\(stringify(extra))>" + } + } + } else { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + + return false + } +} + +public func ==(lhs: Expectation, rhs: T?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation, rhs: T?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T]>, rhs: [T]?) { + lhs.toNot(equal(rhs)) +} + +public func == (lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func != (lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation>, rhs: Set?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation>, rhs: Set?) { + lhs.toNot(equal(rhs)) +} + +public func ==(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.to(equal(rhs)) +} + +public func !=(lhs: Expectation<[T: C]>, rhs: [T: C]?) { + lhs.toNot(equal(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func equalMatcher(_ expected: NSObject) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + return try! equal(expected).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/HaveCount.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/HaveCount.swift new file mode 100644 index 0000000..5b24af2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/HaveCount.swift @@ -0,0 +1,57 @@ +import Foundation + +// The `haveCount` matchers do not print the full string representation of the collection value, +// instead they only print the type name and the expected count. This makes it easier to understand +// the reason for failed expectations. See: https://github.com/Quick/Nimble/issues/308. +// The representation of the collection content is provided in a new line as an `extendedMessage`. + +/// A Nimble matcher that succeeds when the actual Collection's count equals +/// the expected value +public func haveCount(_ expectedValue: T.IndexDistance) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + } +} + +/// A Nimble matcher that succeeds when the actual collection's count equals +/// the expected value +public func haveCount(_ expectedValue: Int) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))" + let result = expectedValue == actualValue.count + failureMessage.actualValue = "\(actualValue.count)" + failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))" + return result + } else { + return false + } + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func haveCountMatcher(_ expected: NSNumber) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + if let value = actualValue as? NMBCollection { + let expr = Expression(expression: ({ value as NMBCollection}), location: location) + return try! haveCount(expected.intValue).matches(expr, failureMessage: failureMessage) + } else if let actualValue = actualValue { + failureMessage.postfixMessage = "get type of NSArray, NSSet, NSDictionary, or NSHashTable" + failureMessage.actualValue = "\(String(describing: type(of: actualValue)))" + } + return false + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Match.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Match.swift new file mode 100644 index 0000000..7e80331 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/Match.swift @@ -0,0 +1,30 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual string satisfies the regular expression +/// described by the expected string. +public func match(_ expectedValue: String?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "match <\(stringify(expectedValue))>" + + if let actual = try actualExpression.evaluate() { + if let regexp = expectedValue { + return actual.range(of: regexp, options: .regularExpression) != nil + } + } + + return false + } +} + +#if _runtime(_ObjC) + +extension NMBObjCMatcher { + public class func matchMatcher(_ expected: NSString) -> NMBMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = actualExpression.cast { $0 as? String } + return try! match(expected.description).matches(actual, failureMessage: failureMessage) + } + } +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatchError.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatchError.swift new file mode 100644 index 0000000..2092cb6 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatchError.swift @@ -0,0 +1,26 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +public func matchError(_ error: T) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + return errorMatchesNonNilFieldsOrClosure(actualError, error: error) + } +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error of the specified type +public func matchError(_ errorType: T.Type) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, errorType: errorType) + return errorMatchesNonNilFieldsOrClosure(actualError, errorType: errorType) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift new file mode 100644 index 0000000..02d3245 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift @@ -0,0 +1,69 @@ +/// A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// @see NonNilMatcherFunc if you prefer to have this matcher fail when nil +/// values are recieved in an expectation. +/// +/// You may use this when implementing your own custom matchers. +/// +/// Use the Matcher protocol instead of this type to accept custom matchers as +/// input parameters. +/// @see allPass for an example that uses accepts other matchers as input. +public struct MatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try matcher(actualExpression, failureMessage) + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + return try !matcher(actualExpression, failureMessage) + } +} + +/// A convenience API to build matchers that don't need special negation +/// behavior. The toNot() behavior is the negation of to(). +/// +/// Unlike MatcherFunc, this will always fail if an expectation contains nil. +/// This applies regardless of using to() or toNot(). +/// +/// You may use this when implementing your own custom matchers. +/// +/// Use the Matcher protocol instead of this type to accept custom matchers as +/// input parameters. +/// @see allPass for an example that uses accepts other matchers as input. +public struct NonNilMatcherFunc: Matcher { + public let matcher: (Expression, FailureMessage) throws -> Bool + + public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { + self.matcher = matcher + } + + public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + let pass = try !matcher(actualExpression, failureMessage) + if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { + return false + } + return pass + } + + internal func attachNilErrorIfNeeded(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { + if try actualExpression.evaluate() == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + return true + } + return false + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift new file mode 100644 index 0000000..3f27ec1 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift @@ -0,0 +1,153 @@ +import Foundation +// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. +#if _runtime(_ObjC) + import CoreGraphics +#endif + +/// Implement this protocol to implement a custom matcher for Swift +public protocol Matcher { + associatedtype ValueType + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool +} + +#if _runtime(_ObjC) +/// Objective-C interface to the Swift variant of Matcher. +@objc public protocol NMBMatcher { + func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool + func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool +} +#endif + +#if _runtime(_ObjC) +/// Protocol for types that support contain() matcher. +@objc public protocol NMBContainer { + @objc(containsObject:) + func contains(_ anObject: Any) -> Bool +} + +// FIXME: NSHashTable can not conform to NMBContainer since swift-DEVELOPMENT-SNAPSHOT-2016-04-25-a +//extension NSHashTable : NMBContainer {} // Corelibs Foundation does not include this class yet +#else +public protocol NMBContainer { + func contains(_ anObject: Any) -> Bool +} +#endif + +extension NSArray : NMBContainer {} +extension NSSet : NMBContainer {} + +#if _runtime(_ObjC) +/// Protocol for types that support only beEmpty(), haveCount() matchers +@objc public protocol NMBCollection { + var count: Int { get } +} + +extension NSHashTable : NMBCollection {} // Corelibs Foundation does not include these classes yet +extension NSMapTable : NMBCollection {} +#else +public protocol NMBCollection { + var count: Int { get } +} +#endif + +extension NSSet : NMBCollection {} +extension NSIndexSet : NMBCollection {} +extension NSDictionary : NMBCollection {} + +#if _runtime(_ObjC) +/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers +@objc public protocol NMBOrderedCollection: NMBCollection { + @objc(objectAtIndex:) + func object(at index: Int) -> Any +} +#else +public protocol NMBOrderedCollection: NMBCollection { + func object(at index: Int) -> Any +} +#endif + +extension NSArray : NMBOrderedCollection {} + +public protocol NMBDoubleConvertible { + var doubleValue: CDouble { get } +} + +extension Double : NMBDoubleConvertible { + public var doubleValue: CDouble { + return self + } +} + +extension Float : NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension CGFloat: NMBDoubleConvertible { + public var doubleValue: CDouble { + return CDouble(self) + } +} + +extension NSNumber : NMBDoubleConvertible { +} + +private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS" + formatter.locale = Locale(identifier: "en_US_POSIX") + + return formatter +}() + +extension Date: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension NSDate: NMBDoubleConvertible { + public var doubleValue: CDouble { + return self.timeIntervalSinceReferenceDate + } +} + +extension Date: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: self) + } +} + +extension NSDate: TestOutputStringConvertible { + public var testDescription: String { + return dateFormatter.string(from: Date(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate)) + } +} + +/// Protocol for types to support beLessThan(), beLessThanOrEqualTo(), +/// beGreaterThan(), beGreaterThanOrEqualTo(), and equal() matchers. +/// +/// Types that conform to Swift's Comparable protocol will work implicitly too +#if _runtime(_ObjC) +@objc public protocol NMBComparable { + func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult +} +#else +// This should become obsolete once Corelibs Foundation adds Comparable conformance to NSNumber +public protocol NMBComparable { + func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult +} +#endif + +extension NSNumber : NMBComparable { + public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { + return compare(otherObject as! NSNumber) + } +} +extension NSString : NMBComparable { + public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { + return compare(otherObject as! String) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/PostNotification.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/PostNotification.swift new file mode 100644 index 0000000..ac8ee5a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/PostNotification.swift @@ -0,0 +1,70 @@ +import Foundation + +internal class NotificationCollector { + private(set) var observedNotifications: [Notification] + private let notificationCenter: NotificationCenter + #if _runtime(_ObjC) + private var token: AnyObject? + #else + private var token: NSObjectProtocol? + #endif + + required init(notificationCenter: NotificationCenter) { + self.notificationCenter = notificationCenter + self.observedNotifications = [] + } + + func startObserving() { + self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { [weak self] n in + // linux-swift gets confused by .append(n) + self?.observedNotifications.append(n) + } + } + + deinit { + #if _runtime(_ObjC) + if let token = self.token { + self.notificationCenter.removeObserver(token) + } + #else + if let token = self.token as? AnyObject { + self.notificationCenter.removeObserver(token) + } + #endif + } +} + +private let mainThread = pthread_self() + +let notificationCenterDefault = NotificationCenter.default + +public func postNotifications( + _ notificationsMatcher: T, + fromNotificationCenter center: NotificationCenter = notificationCenterDefault) + -> MatcherFunc + where T: Matcher, T.ValueType == [Notification] +{ + let _ = mainThread // Force lazy-loading of this value + let collector = NotificationCollector(notificationCenter: center) + collector.startObserving() + var once: Bool = false + return MatcherFunc { actualExpression, failureMessage in + let collectorNotificationsExpression = Expression(memoizedExpression: { _ in + return collector.observedNotifications + }, location: actualExpression.location, withoutCaching: true) + + assert(pthread_equal(mainThread, pthread_self()) != 0, "Only expecting closure to be evaluated on main thread.") + if !once { + once = true + _ = try actualExpression.evaluate() + } + + let match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage) + if collector.observedNotifications.isEmpty { + failureMessage.actualValue = "no notifications" + } else { + failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>" + } + return match + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/RaisesException.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/RaisesException.swift new file mode 100644 index 0000000..2867a1b --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/RaisesException.swift @@ -0,0 +1,183 @@ +import Foundation + +// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager +#if _runtime(_ObjC) && !SWIFT_PACKAGE + +/// A Nimble matcher that succeeds when the actual expression raises an +/// exception with the specified name, reason, and/or userInfo. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the raised exception. The closure only gets called when an exception +/// is raised. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func raiseException( + named: String? = nil, + reason: String? = nil, + userInfo: NSDictionary? = nil, + closure: ((NSException) -> Void)? = nil) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + + var exception: NSException? + let capture = NMBExceptionCapture(handler: ({ e in + exception = e + }), finally: nil) + + capture.tryBlock { + _ = try! actualExpression.evaluate() + return + } + + setFailureMessageForException(failureMessage, exception: exception, named: named, reason: reason, userInfo: userInfo, closure: closure) + return exceptionMatchesNonNilFieldsOrClosure(exception, named: named, reason: reason, userInfo: userInfo, closure: closure) + } +} + +internal func setFailureMessageForException( + _ failureMessage: FailureMessage, + exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) { + failureMessage.postfixMessage = "raise exception" + + if let named = named { + failureMessage.postfixMessage += " with name <\(named)>" + } + if let reason = reason { + failureMessage.postfixMessage += " with reason <\(reason)>" + } + if let userInfo = userInfo { + failureMessage.postfixMessage += " with userInfo <\(userInfo)>" + } + if let _ = closure { + failureMessage.postfixMessage += " that satisfies block" + } + if named == nil && reason == nil && userInfo == nil && closure == nil { + failureMessage.postfixMessage = "raise any exception" + } + + if let exception = exception { + failureMessage.actualValue = "\(String(describing: type(of: exception))) { name=\(exception.name), reason='\(stringify(exception.reason))', userInfo=\(stringify(exception.userInfo)) }" + } else { + failureMessage.actualValue = "no exception" + } +} + +internal func exceptionMatchesNonNilFieldsOrClosure( + _ exception: NSException?, + named: String?, + reason: String?, + userInfo: NSDictionary?, + closure: ((NSException) -> Void)?) -> Bool { + var matches = false + + if let exception = exception { + matches = true + + if let named = named, exception.name.rawValue != named { + matches = false + } + if reason != nil && exception.reason != reason { + matches = false + } + if let userInfo = userInfo, let exceptionUserInfo = exception.userInfo, + (exceptionUserInfo as NSDictionary) != userInfo { + matches = false + } + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(exception) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + + return matches +} + +public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher { + internal var _name: String? + internal var _reason: String? + internal var _userInfo: NSDictionary? + internal var _block: ((NSException) -> Void)? + + internal init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) { + _name = name + _reason = reason + _userInfo = userInfo + _block = block + } + + public func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + let block: () -> Any? = ({ _ = actualBlock(); return nil }) + let expr = Expression(expression: block, location: location) + + return try! raiseException( + named: _name, + reason: _reason, + userInfo: _userInfo, + closure: _block + ).matches(expr, failureMessage: failureMessage) + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + return !matches(actualBlock, failureMessage: failureMessage, location: location) + } + + public var named: (_ name: String) -> NMBObjCRaiseExceptionMatcher { + return ({ name in + return NMBObjCRaiseExceptionMatcher( + name: name, + reason: self._reason, + userInfo: self._userInfo, + block: self._block + ) + }) + } + + public var reason: (_ reason: String?) -> NMBObjCRaiseExceptionMatcher { + return ({ reason in + return NMBObjCRaiseExceptionMatcher( + name: self._name, + reason: reason, + userInfo: self._userInfo, + block: self._block + ) + }) + } + + public var userInfo: (_ userInfo: NSDictionary?) -> NMBObjCRaiseExceptionMatcher { + return ({ userInfo in + return NMBObjCRaiseExceptionMatcher( + name: self._name, + reason: self._reason, + userInfo: userInfo, + block: self._block + ) + }) + } + + public var satisfyingBlock: (_ block: ((NSException) -> Void)?) -> NMBObjCRaiseExceptionMatcher { + return ({ block in + return NMBObjCRaiseExceptionMatcher( + name: self._name, + reason: self._reason, + userInfo: self._userInfo, + block: block + ) + }) + } +} + +extension NMBObjCMatcher { + public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift new file mode 100644 index 0000000..6cef4c2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -0,0 +1,62 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value matches with any of the matchers +/// provided in the variable list of matchers. +public func satisfyAnyOf(_ matchers: U...) -> NonNilMatcherFunc + where U: Matcher, U.ValueType == T { + return satisfyAnyOf(matchers) +} + +internal func satisfyAnyOf(_ matchers: [U]) -> NonNilMatcherFunc + where U: Matcher, U.ValueType == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + let postfixMessages = NSMutableArray() + var matches = false + for matcher in matchers { + if try matcher.matches(actualExpression, failureMessage: failureMessage) { + matches = true + } + postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}")) + } + + failureMessage.postfixMessage = "match one of: " + postfixMessages.componentsJoined(by: ", or ") + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "\(actualValue)" + } + + return matches + } +} + +public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> NonNilMatcherFunc { + return satisfyAnyOf(left, right) +} + +public func || (left: MatcherFunc, right: MatcherFunc) -> NonNilMatcherFunc { + return satisfyAnyOf(left, right) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func satisfyAnyOfMatcher(_ matchers: [NMBObjCMatcher]) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + if matchers.isEmpty { + failureMessage.stringValue = "satisfyAnyOf must be called with at least one matcher" + return false + } + + var elementEvaluators = [NonNilMatcherFunc]() + for matcher in matchers { + let elementEvaluator: (Expression, FailureMessage) -> Bool = { + expression, failureMessage in + return matcher.matches({try! expression.evaluate()}, failureMessage: failureMessage, location: actualExpression.location) + } + + elementEvaluators.append(NonNilMatcherFunc(elementEvaluator)) + } + + return try! satisfyAnyOf(elementEvaluators).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift new file mode 100644 index 0000000..c847a1a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -0,0 +1,55 @@ +import Foundation + +public func throwAssertion() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + #if arch(x86_64) && _runtime(_ObjC) && !SWIFT_PACKAGE + failureMessage.postfixMessage = "throw an assertion" + failureMessage.actualValue = nil + + var succeeded = true + + let caughtException: BadInstructionException? = catchBadInstruction { + #if os(tvOS) + if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning { + print() + print("[Nimble Warning]: If you're getting stuck on a debugger breakpoint for a " + + "fatal error while using throwAssertion(), please disable 'Debug Executable' " + + "in your scheme. Go to 'Edit Scheme > Test > Info' and uncheck " + + "'Debug Executable'. If you've already done that, suppress this warning " + + "by setting `NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true`. " + + "This is required because the standard methods of catching assertions " + + "(mach APIs) are unavailable for tvOS. Instead, the same mechanism the " + + "debugger uses is the fallback method for tvOS." + ) + print() + NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true + } + #endif + do { + try actualExpression.evaluate() + } catch let error { + succeeded = false + failureMessage.postfixMessage += "; threw error instead <\(error)>" + } + } + + if !succeeded { + return false + } + + if caughtException == nil { + return false + } + + return true + #elseif SWIFT_PACKAGE + fatalError("The throwAssertion Nimble matcher does not currently support Swift CLI." + + " You can silence this error by placing the test case inside an #if !SWIFT_PACKAGE" + + " conditional statement") + #else + fatalError("The throwAssertion Nimble matcher can only run on x86_64 platforms with " + + "Objective-C (e.g. Mac, iPhone 5s or later simulators). You can silence this error " + + "by placing the test case inside an #if arch(x86_64) or _runtime(_ObjC) conditional statement") + #endif + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ThrowError.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ThrowError.swift new file mode 100644 index 0000000..151eb9a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Matchers/ThrowError.swift @@ -0,0 +1,53 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual expression throws an +/// error of the specified type or from the specified case. +/// +/// Errors are tried to be compared by their implementation of Equatable, +/// otherwise they fallback to comparision by _domain and _code. +/// +/// Alternatively, you can pass a closure to do any arbitrary custom matching +/// to the thrown error. The closure only gets called when an error was thrown. +/// +/// nil arguments indicates that the matcher should not attempt to match against +/// that parameter. +public func throwError( + _ error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, error: error, errorType: errorType, closure: closure) + return errorMatchesNonNilFieldsOrClosure(actualError, error: error, errorType: errorType, closure: closure) + } +} + +/// A Nimble matcher that succeeds when the actual expression throws any +/// error or when the passed closures' arbitrary custom matching succeeds. +/// +/// This duplication to it's generic adequate is required to allow to receive +/// values of the existential type `Error` in the closure. +/// +/// The closure only gets called when an error was thrown. +public func throwError( + closure: ((Error) -> Void)? = nil) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + return errorMatchesNonNilFieldsOrClosure(actualError, closure: closure) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Nimble.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Nimble.h new file mode 100644 index 0000000..790d16d --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Nimble.h @@ -0,0 +1,14 @@ +#import +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" +#import "DSL.h" + +#import "CwlCatchException.h" +#import "CwlCatchBadInstruction.h" + +#if !TARGET_OS_TV + #import "mach_excServer.h" +#endif + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Async.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Async.swift new file mode 100644 index 0000000..943fd30 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Async.swift @@ -0,0 +1,361 @@ +import CoreFoundation +import Dispatch +import Foundation + +#if !_runtime(_ObjC) + import CDispatch +#endif + +private let timeoutLeeway = DispatchTimeInterval.milliseconds(1) +private let pollLeeway = DispatchTimeInterval.milliseconds(1) + +/// Stores debugging information about callers +internal struct WaitingInfo: CustomStringConvertible { + let name: String + let file: FileString + let lineNumber: UInt + + var description: String { + return "\(name) at \(file):\(lineNumber)" + } +} + +internal protocol WaitLock { + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) + func releaseWaitingLock() + func isWaitingLocked() -> Bool +} + +internal class AssertionWaitLock: WaitLock { + private var currentWaiter: WaitingInfo? = nil + init() { } + + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) { + let info = WaitingInfo(name: fnName, file: file, lineNumber: line) + #if _runtime(_ObjC) + let isMainThread = Thread.isMainThread + #else + let isMainThread = _CFIsMainThread() + #endif + nimblePrecondition( + isMainThread, + "InvalidNimbleAPIUsage", + "\(fnName) can only run on the main thread." + ) + nimblePrecondition( + currentWaiter == nil, + "InvalidNimbleAPIUsage", + "Nested async expectations are not allowed to avoid creating flaky tests.\n\n" + + "The call to\n\t\(info)\n" + + "triggered this exception because\n\t\(currentWaiter!)\n" + + "is currently managing the main run loop." + ) + currentWaiter = info + } + + func isWaitingLocked() -> Bool { + return currentWaiter != nil + } + + func releaseWaitingLock() { + currentWaiter = nil + } +} + +internal enum AwaitResult { + /// Incomplete indicates None (aka - this value hasn't been fulfilled yet) + case incomplete + /// TimedOut indicates the result reached its defined timeout limit before returning + case timedOut + /// BlockedRunLoop indicates the main runloop is too busy processing other blocks to trigger + /// the timeout code. + /// + /// This may also mean the async code waiting upon may have never actually ran within the + /// required time because other timers & sources are running on the main run loop. + case blockedRunLoop + /// The async block successfully executed and returned a given result + case completed(T) + /// When a Swift Error is thrown + case errorThrown(Error) + /// When an Objective-C Exception is raised + case raisedException(NSException) + + func isIncomplete() -> Bool { + switch self { + case .incomplete: return true + default: return false + } + } + + func isCompleted() -> Bool { + switch self { + case .completed(_): return true + default: return false + } + } +} + +/// Holds the resulting value from an asynchronous expectation. +/// This class is thread-safe at receiving an "response" to this promise. +internal class AwaitPromise { + private(set) internal var asyncResult: AwaitResult = .incomplete + private var signal: DispatchSemaphore + + init() { + signal = DispatchSemaphore(value: 1) + } + + /// Resolves the promise with the given result if it has not been resolved. Repeated calls to + /// this method will resolve in a no-op. + /// + /// @returns a Bool that indicates if the async result was accepted or rejected because another + /// value was recieved first. + func resolveResult(_ result: AwaitResult) -> Bool { + if signal.wait(timeout: .now()) == .success { + self.asyncResult = result + return true + } else { + return false + } + } +} + +internal struct AwaitTrigger { + let timeoutSource: DispatchSourceTimer + let actionSource: DispatchSourceTimer? + let start: () throws -> Void +} + +/// Factory for building fully configured AwaitPromises and waiting for their results. +/// +/// This factory stores all the state for an async expectation so that Await doesn't +/// doesn't have to manage it. +internal class AwaitPromiseBuilder { + let awaiter: Awaiter + let waitLock: WaitLock + let trigger: AwaitTrigger + let promise: AwaitPromise + + internal init( + awaiter: Awaiter, + waitLock: WaitLock, + promise: AwaitPromise, + trigger: AwaitTrigger) { + self.awaiter = awaiter + self.waitLock = waitLock + self.promise = promise + self.trigger = trigger + } + + func timeout(_ timeoutInterval: TimeInterval, forcefullyAbortTimeout: TimeInterval) -> Self { + // = Discussion = + // + // There's a lot of technical decisions here that is useful to elaborate on. This is + // definitely more lower-level than the previous NSRunLoop based implementation. + // + // + // Why Dispatch Source? + // + // + // We're using a dispatch source to have better control of the run loop behavior. + // A timer source gives us deferred-timing control without having to rely as much on + // a run loop's traditional dispatching machinery (eg - NSTimers, DefaultRunLoopMode, etc.) + // which is ripe for getting corrupted by application code. + // + // And unlike dispatch_async(), we can control how likely our code gets prioritized to + // executed (see leeway parameter) + DISPATCH_TIMER_STRICT. + // + // This timer is assumed to run on the HIGH priority queue to ensure it maintains the + // highest priority over normal application / test code when possible. + // + // + // Run Loop Management + // + // In order to properly interrupt the waiting behavior performed by this factory class, + // this timer stops the main run loop to tell the waiter code that the result should be + // checked. + // + // In addition, stopping the run loop is used to halt code executed on the main run loop. + trigger.timeoutSource.scheduleOneshot( + deadline: DispatchTime.now() + timeoutInterval, + leeway: timeoutLeeway) + trigger.timeoutSource.setEventHandler { + guard self.promise.asyncResult.isIncomplete() else { return } + let timedOutSem = DispatchSemaphore(value: 0) + let semTimedOutOrBlocked = DispatchSemaphore(value: 0) + semTimedOutOrBlocked.signal() + let runLoop = CFRunLoopGetMain() + #if _runtime(_ObjC) + let runLoopMode = CFRunLoopMode.defaultMode.rawValue + #else + let runLoopMode = kCFRunLoopDefaultMode + #endif + CFRunLoopPerformBlock(runLoop, runLoopMode) { + if semTimedOutOrBlocked.wait(timeout: .now()) == .success { + timedOutSem.signal() + semTimedOutOrBlocked.signal() + if self.promise.resolveResult(.timedOut) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + // potentially interrupt blocking code on run loop to let timeout code run + CFRunLoopStop(runLoop) + let now = DispatchTime.now() + forcefullyAbortTimeout + let didNotTimeOut = timedOutSem.wait(timeout: now) != .success + let timeoutWasNotTriggered = semTimedOutOrBlocked.wait(timeout: .now()) == .success + if didNotTimeOut && timeoutWasNotTriggered { + if self.promise.resolveResult(.blockedRunLoop) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + return self + } + + /// Blocks for an asynchronous result. + /// + /// @discussion + /// This function must be executed on the main thread and cannot be nested. This is because + /// this function (and it's related methods) coordinate through the main run loop. Tampering + /// with the run loop can cause undesireable behavior. + /// + /// This method will return an AwaitResult in the following cases: + /// + /// - The main run loop is blocked by other operations and the async expectation cannot be + /// be stopped. + /// - The async expectation timed out + /// - The async expectation succeeded + /// - The async expectation raised an unexpected exception (objc) + /// - The async expectation raised an unexpected error (swift) + /// + /// The returned AwaitResult will NEVER be .incomplete. + func wait(_ fnName: String = #function, file: FileString = #file, line: UInt = #line) -> AwaitResult { + waitLock.acquireWaitingLock( + fnName, + file: file, + line: line) + + let capture = NMBExceptionCapture(handler: ({ exception in + _ = self.promise.resolveResult(.raisedException(exception)) + }), finally: ({ + self.waitLock.releaseWaitingLock() + })) + capture.tryBlock { + do { + try self.trigger.start() + } catch let error { + _ = self.promise.resolveResult(.errorThrown(error)) + } + self.trigger.timeoutSource.resume() + while self.promise.asyncResult.isIncomplete() { + // Stopping the run loop does not work unless we run only 1 mode + _ = RunLoop.current.run(mode: .defaultRunLoopMode, before: .distantFuture) + } + self.trigger.timeoutSource.suspend() + self.trigger.timeoutSource.cancel() + if let asyncSource = self.trigger.actionSource { + asyncSource.cancel() + } + } + + return promise.asyncResult + } +} + +internal class Awaiter { + let waitLock: WaitLock + let timeoutQueue: DispatchQueue + let asyncQueue: DispatchQueue + + internal init( + waitLock: WaitLock, + asyncQueue: DispatchQueue, + timeoutQueue: DispatchQueue) { + self.waitLock = waitLock + self.asyncQueue = asyncQueue + self.timeoutQueue = timeoutQueue + } + + private func createTimerSource(_ queue: DispatchQueue) -> DispatchSourceTimer { + return DispatchSource.makeTimerSource(flags: .strict, queue: queue) + } + + func performBlock( + _ closure: @escaping (@escaping (T) -> Void) throws -> Void) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + let timeoutSource = createTimerSource(timeoutQueue) + var completionCount = 0 + let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: nil) { + try closure { + completionCount += 1 + nimblePrecondition( + completionCount < 2, + "InvalidNimbleAPIUsage", + "Done closure's was called multiple times. waitUntil(..) expects its " + + "completion closure to only be called once.") + if promise.resolveResult(.completed($0)) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } + + func poll(_ pollInterval: TimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder { + let promise = AwaitPromise() + let timeoutSource = createTimerSource(timeoutQueue) + let asyncSource = createTimerSource(asyncQueue) + let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: asyncSource) { + let interval = DispatchTimeInterval.nanoseconds(Int(pollInterval * TimeInterval(NSEC_PER_SEC))) + asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway) + asyncSource.setEventHandler { + do { + if let result = try closure() { + if promise.resolveResult(.completed(result)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } catch let error { + if promise.resolveResult(.errorThrown(error)) { + CFRunLoopStop(CFRunLoopGetCurrent()) + } + } + } + asyncSource.resume() + } + + return AwaitPromiseBuilder( + awaiter: self, + waitLock: waitLock, + promise: promise, + trigger: trigger) + } +} + +internal func pollBlock( + pollInterval: TimeInterval, + timeoutInterval: TimeInterval, + file: FileString, + line: UInt, + fnName: String = #function, + expression: @escaping () throws -> Bool) -> AwaitResult { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let result = awaiter.poll(pollInterval) { () throws -> Bool? in + do { + if try expression() { + return true + } + return nil + } catch let error { + throw error + } + }.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line) + + return result +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Errors.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Errors.swift new file mode 100644 index 0000000..f376505 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Errors.swift @@ -0,0 +1,141 @@ +import Foundation + +// Generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + postfixMessageVerb: String = "throw", + actualError: Error?, + error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) { + failureMessage.postfixMessage = "\(postfixMessageVerb) error" + + if let error = error { + if let error = error as? CustomDebugStringConvertible { + failureMessage.postfixMessage += " <\(error.debugDescription)>" + } else { + failureMessage.postfixMessage += " <\(error)>" + } + } else if errorType != nil || closure != nil { + failureMessage.postfixMessage += " from type <\(T.self)>" + } + if let _ = closure { + failureMessage.postfixMessage += " that satisfies block" + } + if error == nil && errorType == nil && closure == nil { + failureMessage.postfixMessage = "\(postfixMessageVerb) any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} + +internal func errorMatchesExpectedError( + _ actualError: Error, + expectedError: T) -> Bool { + return actualError._domain == expectedError._domain + && actualError._code == expectedError._code +} + +internal func errorMatchesExpectedError( + _ actualError: Error, + expectedError: T) -> Bool + where T: Equatable { + if let actualError = actualError as? T { + return actualError == expectedError + } + return false +} + +internal func errorMatchesNonNilFieldsOrClosure( + _ actualError: Error?, + error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) -> Bool { + var matches = false + + if let actualError = actualError { + matches = true + + if let error = error { + if !errorMatchesExpectedError(actualError, expectedError: error) { + matches = false + } + } + if let actualError = actualError as? T { + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError as T) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } else if errorType != nil { + matches = (actualError is T) + // The closure expects another ErrorProtocol as argument, so this + // is _supposed_ to fail, so that it becomes more obvious. + if let closure = closure { + let assertions = gatherExpectations { + if let actual = actualError as? T { + closure(actual) + } + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + } + + return matches +} + +// Non-generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + actualError: Error?, + closure: ((Error) -> Void)?) { + failureMessage.postfixMessage = "throw error" + + if let _ = closure { + failureMessage.postfixMessage += " that satisfies block" + } else { + failureMessage.postfixMessage = "throw any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} + +internal func errorMatchesNonNilFieldsOrClosure( + _ actualError: Error?, + closure: ((Error) -> Void)?) -> Bool { + var matches = false + + if let actualError = actualError { + matches = true + + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } + + return matches +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Functional.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Functional.swift new file mode 100644 index 0000000..6c5126a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Functional.swift @@ -0,0 +1,12 @@ +import Foundation + +extension Sequence { + internal func all(_ fn: (Iterator.Element) -> Bool) -> Bool { + for item in self { + if !fn(item) { + return false + } + } + return true + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/SourceLocation.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/SourceLocation.swift new file mode 100644 index 0000000..4e37aef --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/SourceLocation.swift @@ -0,0 +1,31 @@ +import Foundation + +// Ideally we would always use `StaticString` as the type for tracking the file name +// that expectations originate from, for consistency with `assert` etc. from the +// stdlib, and because recent versions of the XCTest overlay require `StaticString` +// when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we +// have to use `String` instead because StaticString can't be generated from Objective-C +#if SWIFT_PACKAGE +public typealias FileString = StaticString +#else +public typealias FileString = String +#endif + +public final class SourceLocation: NSObject { + public let file: FileString + public let line: UInt + + override init() { + file = "Unknown File" + line = 0 + } + + init(file: FileString, line: UInt) { + self.file = file + self.line = line + } + + override public var description: String { + return "\(file):\(line)" + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Stringers.swift b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Stringers.swift new file mode 100644 index 0000000..8a15c4c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/Nimble/Utils/Stringers.swift @@ -0,0 +1,212 @@ +import Foundation + +internal func identityAsString(_ value: Any?) -> String { + let anyObject: AnyObject? +#if os(Linux) + anyObject = value as? AnyObject +#else + anyObject = value as AnyObject? +#endif + if let value = anyObject { + return NSString(format: "<%p>", unsafeBitCast(value, to: Int.self)).description + } else { + return "nil" + } +} + +internal func arrayAsString(_ items: [T], joiner: String = ", ") -> String { + return items.reduce("") { accum, item in + let prefix = (accum.isEmpty ? "" : joiner) + return accum + prefix + "\(stringify(item))" + } +} + +/// A type with a customized test output text representation. +/// +/// This textual representation is produced when values will be +/// printed in test runs, and may be useful when producing +/// error messages in custom matchers. +/// +/// - SeeAlso: `CustomDebugStringConvertible` +public protocol TestOutputStringConvertible { + var testDescription: String { get } +} + +extension Double: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +extension Float: TestOutputStringConvertible { + public var testDescription: String { + return NSNumber(value: self).testDescription + } +} + +extension NSNumber: TestOutputStringConvertible { + // This is using `NSString(format:)` instead of + // `String(format:)` because the latter somehow breaks + // the travis CI build on linux. + public var testDescription: String { + let description = self.description + + if description.contains(".") { + // Travis linux swiftpm build doesn't like casting String to NSString, + // which is why this annoying nested initializer thing is here. + // Maybe this will change in a future snapshot. + let decimalPlaces = NSString(string: NSString(string: description) + .components(separatedBy: ".")[1]) + + // SeeAlso: https://bugs.swift.org/browse/SR-1464 + switch decimalPlaces.length { + case 1: + return NSString(format: "%0.1f", self.doubleValue).description + case 2: + return NSString(format: "%0.2f", self.doubleValue).description + case 3: + return NSString(format: "%0.3f", self.doubleValue).description + default: + return NSString(format: "%0.4f", self.doubleValue).description + } + } + return self.description + } +} + +extension Array: TestOutputStringConvertible { + public var testDescription: String { + let list = self.map(Nimble.stringify).joined(separator: ", ") + return "[\(list)]" + } +} + +extension AnySequence: TestOutputStringConvertible { + public var testDescription: String { + let generator = self.makeIterator() + var strings = [String]() + var value: AnySequence.Iterator.Element? + + repeat { + value = generator.next() + if let value = value { + strings.append(stringify(value)) + } + } while value != nil + + let list = strings.joined(separator: ", ") + return "[\(list)]" + } +} + +extension NSArray: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension NSIndexSet: TestOutputStringConvertible { + public var testDescription: String { + let list = Array(self).map(Nimble.stringify).joined(separator: ", ") + return "(\(list))" + } +} + +extension String: TestOutputStringConvertible { + public var testDescription: String { + return self + } +} + +extension Data: TestOutputStringConvertible { + public var testDescription: String { + #if os(Linux) + // FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11-16) + return "Data" + #else + return "Data" + #endif + } +} + +/// +/// Returns a string appropriate for displaying in test output +/// from the provided value. +/// +/// - parameter value: A value that will show up in a test's output. +/// +/// - returns: The string that is returned can be +/// customized per type by conforming a type to the `TestOutputStringConvertible` +/// protocol. When stringifying a non-`TestOutputStringConvertible` type, this +/// function will return the value's debug description and then its +/// normal description if available and in that order. Otherwise it +/// will return the result of constructing a string from the value. +/// +/// - SeeAlso: `TestOutputStringConvertible` +public func stringify(_ value: T) -> String { + if let value = value as? TestOutputStringConvertible { + return value.testDescription + } + + if let value = value as? CustomDebugStringConvertible { + return value.debugDescription + } + + return String(describing: value) +} + +/// -SeeAlso: `stringify(value: T)` +public func stringify(_ value: T?) -> String { + if let unboxed = value { + return stringify(unboxed) + } + return "nil" +} + +#if _runtime(_ObjC) +@objc public class NMBStringer: NSObject { + @objc public class func stringify(_ obj: Any?) -> String { + return Nimble.stringify(obj) + } +} +#endif + +// MARK: Collection Type Stringers + +/// Attempts to generate a pretty type string for a given value. If the value is of a Objective-C +/// collection type, or a subclass thereof, (e.g. `NSArray`, `NSDictionary`, etc.). +/// This function will return the type name of the root class of the class cluster for better +/// readability (e.g. `NSArray` instead of `__NSArrayI`). +/// +/// For values that don't have a type of an Objective-C collection, this function returns the +/// default type description. +/// +/// - parameter value: A value that will be used to determine a type name. +/// +/// - returns: The name of the class cluster root class for Objective-C collection types, or the +/// the `dynamicType` of the value for values of any other type. +public func prettyCollectionType(_ value: T) -> String { + switch value { + case is NSArray: + return String(describing: NSArray.self) + case is NSDictionary: + return String(describing: NSDictionary.self) + case is NSSet: + return String(describing: NSSet.self) + case is NSIndexSet: + return String(describing: NSIndexSet.self) + default: + return String(describing: value) + } +} + +/// Returns the type name for a given collection type. This overload is used by Swift +/// collection types. +/// +/// - parameter collection: A Swift `CollectionType` value. +/// +/// - returns: A string representing the `dynamicType` of the value. +public func prettyCollectionType(_ collection: T) -> String { + return String(describing: type(of: collection)) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h new file mode 100644 index 0000000..5d416e4 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h @@ -0,0 +1,9 @@ +#import +#import + +SWIFT_CLASS("_TtC6Nimble22CurrentTestCaseTracker") +@interface CurrentTestCaseTracker : NSObject ++ (CurrentTestCaseTracker *)sharedInstance; +@end + +@interface CurrentTestCaseTracker (Register) @end diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/DSL.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/DSL.h new file mode 100644 index 0000000..2089607 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/DSL.h @@ -0,0 +1,381 @@ +#import + +@class NMBExpectation; +@class NMBObjCBeCloseToMatcher; +@class NMBObjCRaiseExceptionMatcher; +@protocol NMBMatcher; + + +NS_ASSUME_NONNULL_BEGIN + + +#define NIMBLE_OVERLOADABLE __attribute__((overloadable)) +#define NIMBLE_EXPORT FOUNDATION_EXPORT +#define NIMBLE_EXPORT_INLINE FOUNDATION_STATIC_INLINE + +#define NIMBLE_VALUE_OF(VAL) ({ \ + __typeof__((VAL)) val = (VAL); \ + [NSValue valueWithBytes:&val objCType:@encode(__typeof__((VAL)))]; \ +}) + +#ifdef NIMBLE_DISABLE_SHORT_SYNTAX +#define NIMBLE_SHORT(PROTO, ORIGINAL) +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) +#else +#define NIMBLE_SHORT(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE PROTO { return (ORIGINAL); } +#define NIMBLE_SHORT_OVERLOADED(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE NIMBLE_OVERLOADABLE PROTO { return (ORIGINAL); } +#endif + + + +#define DEFINE_NMB_EXPECT_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBExpectation *NMB_expect(TYPE(^actualBlock)(), NSString *file, NSUInteger line) { \ + return NMB_expect(^id { return EXPR; }, file, line); \ + } + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + NMBExpectation *NMB_expect(id(^actualBlock)(), NSString *file, NSUInteger line); + + // overloaded dispatch for nils - expect(nil) + DEFINE_NMB_EXPECT_OVERLOAD(void*, nil) + DEFINE_NMB_EXPECT_OVERLOAD(NSRange, NIMBLE_VALUE_OF(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned int, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(float, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(double, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned long long, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(unsigned char, @(actualBlock())) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_NMB_EXPECT_OVERLOAD(BOOL, @(actualBlock())) + DEFINE_NMB_EXPECT_OVERLOAD(char *, @(actualBlock())) + + +#undef DEFINE_NMB_EXPECT_OVERLOAD + + + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(), NSString *file, NSUInteger line); + + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_equal(TYPE expectedValue) { \ + return NMB_equal((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id equal(TYPE expectedValue), NMB_equal(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_equal(__nullable id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id equal(__nullable id expectedValue), + NMB_equal(expectedValue)); + + // overloaded dispatch for nils - expect(nil) + DEFINE_OVERLOAD(void*__nullable, (id)nil) + DEFINE_OVERLOAD(NSRange, NIMBLE_VALUE_OF(expectedValue)) + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + // bool doesn't get the compiler to dispatch to BOOL types, but using BOOL here seems to allow + // the compiler to dispatch to bool. + DEFINE_OVERLOAD(BOOL, @(expectedValue)) + DEFINE_OVERLOAD(char *, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_haveCount(TYPE expectedValue) { \ + return NMB_haveCount((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id haveCount(TYPE expectedValue), \ + NMB_haveCount(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_haveCount(id expectedValue); + + NIMBLE_SHORT_OVERLOADED(id haveCount(id expectedValue), + NMB_haveCount(expectedValue)); + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + NMBObjCBeCloseToMatcher *NMB_beCloseTo(TYPE expectedValue) { \ + return NMB_beCloseTo((NSNumber *)(EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(TYPE expectedValue), \ + NMB_beCloseTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue); + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(NSNumber *expectedValue), + NMB_beCloseTo(expectedValue)); + + // it would be better to only overload float & double, but zero becomes ambigious + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAnInstanceOf(Class expectedClass) { + return NMB_beAnInstanceOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass); +NIMBLE_EXPORT_INLINE id beAKindOf(Class expectedClass) { + return NMB_beAKindOf(expectedClass); +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring); +NIMBLE_EXPORT_INLINE id beginWith(id itemElementOrSubstring) { + return NMB_beginWith(itemElementOrSubstring); +} + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThan(TYPE expectedValue) { \ + return NMB_beGreaterThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThan(NSNumber *expectedValue) { + return NMB_beGreaterThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beGreaterThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beGreaterThanOrEqualTo(TYPE expectedValue), \ + NMB_beGreaterThanOrEqualTo(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beGreaterThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance); +NIMBLE_SHORT(id beIdenticalTo(id expectedInstance), + NMB_beIdenticalTo(expectedInstance)); + +NIMBLE_EXPORT id NMB_be(id expectedInstance); +NIMBLE_SHORT(id be(id expectedInstance), + NMB_be(expectedInstance)); + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThan(TYPE expectedValue) { \ + return NMB_beLessThan((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThan(TYPE expectedValue), \ + NMB_beLessThan(expectedValue)); + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThan(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThan(NSNumber *expectedValue) { + return NMB_beLessThan(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + + +#define DEFINE_OVERLOAD(TYPE, EXPR) \ + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ + id NMB_beLessThanOrEqualTo(TYPE expectedValue) { \ + return NMB_beLessThanOrEqualTo((EXPR)); \ + } \ + NIMBLE_SHORT_OVERLOADED(id beLessThanOrEqualTo(TYPE expectedValue), \ + NMB_beLessThanOrEqualTo(expectedValue)); + + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + id NMB_beLessThanOrEqualTo(NSNumber *expectedValue); + + NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE + id beLessThanOrEqualTo(NSNumber *expectedValue) { + return NMB_beLessThanOrEqualTo(expectedValue); + } + + DEFINE_OVERLOAD(long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long, @(expectedValue)) + DEFINE_OVERLOAD(int, @(expectedValue)) + DEFINE_OVERLOAD(unsigned int, @(expectedValue)) + DEFINE_OVERLOAD(float, @(expectedValue)) + DEFINE_OVERLOAD(double, @(expectedValue)) + DEFINE_OVERLOAD(long long, @(expectedValue)) + DEFINE_OVERLOAD(unsigned long long, @(expectedValue)) + DEFINE_OVERLOAD(char, @(expectedValue)) + DEFINE_OVERLOAD(unsigned char, @(expectedValue)) + +#undef DEFINE_OVERLOAD + +NIMBLE_EXPORT id NMB_beTruthy(void); +NIMBLE_SHORT(id beTruthy(void), + NMB_beTruthy()); + +NIMBLE_EXPORT id NMB_beFalsy(void); +NIMBLE_SHORT(id beFalsy(void), + NMB_beFalsy()); + +NIMBLE_EXPORT id NMB_beTrue(void); +NIMBLE_SHORT(id beTrue(void), + NMB_beTrue()); + +NIMBLE_EXPORT id NMB_beFalse(void); +NIMBLE_SHORT(id beFalse(void), + NMB_beFalse()); + +NIMBLE_EXPORT id NMB_beNil(void); +NIMBLE_SHORT(id beNil(void), + NMB_beNil()); + +NIMBLE_EXPORT id NMB_beEmpty(void); +NIMBLE_SHORT(id beEmpty(void), + NMB_beEmpty()); + +NIMBLE_EXPORT id NMB_containWithNilTermination(id itemOrSubstring, ...) NS_REQUIRES_NIL_TERMINATION; +#define NMB_contain(...) NMB_containWithNilTermination(__VA_ARGS__, nil) +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define contain(...) NMB_contain(__VA_ARGS__) +#endif + +NIMBLE_EXPORT id NMB_containElementSatisfying(BOOL(^predicate)(id)); +NIMBLE_SHORT(id containElementSatisfying(BOOL(^predicate)(id)), + NMB_containElementSatisfying(predicate)); + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring); +NIMBLE_SHORT(id endWith(id itemElementOrSubstring), + NMB_endWith(itemElementOrSubstring)); + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void); +NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void), + NMB_raiseException()); + +NIMBLE_EXPORT id NMB_match(id expectedValue); +NIMBLE_SHORT(id match(id expectedValue), + NMB_match(expectedValue)); + +NIMBLE_EXPORT id NMB_allPass(id matcher); +NIMBLE_SHORT(id allPass(id matcher), + NMB_allPass(matcher)); + +NIMBLE_EXPORT id NMB_satisfyAnyOfWithMatchers(id matchers); +#define NMB_satisfyAnyOf(...) NMB_satisfyAnyOfWithMatchers(@[__VA_ARGS__]) +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define satisfyAnyOf(...) NMB_satisfyAnyOf(__VA_ARGS__) +#endif + +// In order to preserve breakpoint behavior despite using macros to fill in __FILE__ and __LINE__, +// define a builder that populates __FILE__ and __LINE__, and returns a block that takes timeout +// and action arguments. See https://github.com/Quick/Quick/pull/185 for details. +typedef void (^NMBWaitUntilTimeoutBlock)(NSTimeInterval timeout, void (^action)(void (^)(void))); +typedef void (^NMBWaitUntilBlock)(void (^action)(void (^)(void))); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line); +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line); + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line); + +#define NMB_waitUntilTimeout NMB_waitUntilTimeoutBuilder(@(__FILE__), __LINE__) +#define NMB_waitUntil NMB_waitUntilBuilder(@(__FILE__), __LINE__) + +#ifndef NIMBLE_DISABLE_SHORT_SYNTAX +#define expect(...) NMB_expect(^{ return (__VA_ARGS__); }, @(__FILE__), __LINE__) +#define expectAction(BLOCK) NMB_expectAction((BLOCK), @(__FILE__), __LINE__) +#define failWithMessage(msg) NMB_failWithMessage(msg, @(__FILE__), __LINE__) +#define fail() failWithMessage(@"fail() always fails") + + +#define waitUntilTimeout NMB_waitUntilTimeout +#define waitUntil NMB_waitUntil + +#undef NIMBLE_VALUE_OF + +#endif + +NS_ASSUME_NONNULL_END diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/DSL.m b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/DSL.m new file mode 100644 index 0000000..31ff810 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/DSL.m @@ -0,0 +1,160 @@ +#import +#import + +SWIFT_CLASS("_TtC6Nimble7NMBWait") +@interface NMBWait : NSObject + ++ (void)untilTimeout:(NSTimeInterval)timeout file:(NSString *)file line:(NSUInteger)line action:(void(^)())action; ++ (void)untilFile:(NSString *)file line:(NSUInteger)line action:(void(^)())action; + +@end + + +NS_ASSUME_NONNULL_BEGIN + + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBExpectation *__nonnull NMB_expect(id __nullable(^actualBlock)(), NSString *__nonnull file, NSUInteger line) { + return [[NMBExpectation alloc] initWithActualBlock:actualBlock + negative:NO + file:file + line:line]; +} + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(), NSString *file, NSUInteger line) { + return NMB_expect(^id{ + actualBlock(); + return nil; + }, file, line); +} + +NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger line) { + return [NMBExpectation failWithMessage:msg file:file line:line]; +} + +NIMBLE_EXPORT id NMB_beAnInstanceOf(Class expectedClass) { + return [NMBObjCMatcher beAnInstanceOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT id NMB_beAKindOf(Class expectedClass) { + return [NMBObjCMatcher beAKindOfMatcher:expectedClass]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beCloseToMatcher:expectedValue within:0.001]; +} + +NIMBLE_EXPORT id NMB_beginWith(id itemElementOrSubstring) { + return [NMBObjCMatcher beginWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beGreaterThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beIdenticalTo(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT id NMB_be(id expectedInstance) { + return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThan(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_beLessThanOrEqualTo(NSNumber *expectedValue) { + return [NMBObjCMatcher beLessThanOrEqualToMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_beTruthy() { + return [NMBObjCMatcher beTruthyMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalsy() { + return [NMBObjCMatcher beFalsyMatcher]; +} + +NIMBLE_EXPORT id NMB_beTrue() { + return [NMBObjCMatcher beTrueMatcher]; +} + +NIMBLE_EXPORT id NMB_beFalse() { + return [NMBObjCMatcher beFalseMatcher]; +} + +NIMBLE_EXPORT id NMB_beNil() { + return [NMBObjCMatcher beNilMatcher]; +} + +NIMBLE_EXPORT id NMB_beEmpty() { + return [NMBObjCMatcher beEmptyMatcher]; +} + +NIMBLE_EXPORT id NMB_containWithNilTermination(id itemOrSubstring, ...) { + NSMutableArray *itemOrSubstringArray = [NSMutableArray array]; + + if (itemOrSubstring) { + [itemOrSubstringArray addObject:itemOrSubstring]; + + va_list args; + va_start(args, itemOrSubstring); + id next; + while ((next = va_arg(args, id))) { + [itemOrSubstringArray addObject:next]; + } + va_end(args); + } + + return [NMBObjCMatcher containMatcher:itemOrSubstringArray]; +} + +NIMBLE_EXPORT id NMB_containElementSatisfying(BOOL(^predicate)(id)) { + return [NMBObjCMatcher containElementSatisfyingMatcher:predicate]; +} + +NIMBLE_EXPORT id NMB_endWith(id itemElementOrSubstring) { + return [NMBObjCMatcher endWithMatcher:itemElementOrSubstring]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_equal(__nullable id expectedValue) { + return [NMBObjCMatcher equalMatcher:expectedValue]; +} + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE id NMB_haveCount(id expectedValue) { + return [NMBObjCMatcher haveCountMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_match(id expectedValue) { + return [NMBObjCMatcher matchMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_allPass(id expectedValue) { + return [NMBObjCMatcher allPassMatcher:expectedValue]; +} + +NIMBLE_EXPORT id NMB_satisfyAnyOfWithMatchers(id matchers) { + return [NMBObjCMatcher satisfyAnyOfMatcher:matchers]; +} + +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException() { + return [NMBObjCMatcher raiseExceptionMatcher]; +} + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line) { + return ^(NSTimeInterval timeout, void (^action)(void (^)(void))) { + [NMBWait untilTimeout:timeout file:file line:line action:action]; + }; +} + +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line) { + return ^(void (^action)(void (^)(void))) { + [NMBWait untilFile:file line:line action:action]; + }; +} + +NS_ASSUME_NONNULL_END diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h new file mode 100644 index 0000000..d2a54d2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h @@ -0,0 +1,11 @@ +#import +#import + +@interface NMBExceptionCapture : NSObject + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)())finally; +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)())unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); + +@end + +typedef void(^NMBSourceCallbackBlock)(BOOL successful); diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m new file mode 100644 index 0000000..0a882b7 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m @@ -0,0 +1,35 @@ +#import "NMBExceptionCapture.h" + +@interface NMBExceptionCapture () +@property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable); +@property (nonatomic, copy) void(^ _Nullable finally)(); +@end + +@implementation NMBExceptionCapture + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)())finally { + self = [super init]; + if (self) { + self.handler = handler; + self.finally = finally; + } + return self; +} + +- (void)tryBlock:(void(^ _Nonnull)())unsafeBlock { + @try { + unsafeBlock(); + } + @catch (NSException *exception) { + if (self.handler) { + self.handler(exception); + } + } + @finally { + if (self.finally) { + self.finally(); + } + } +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.h b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.h new file mode 100644 index 0000000..e5d5ddd --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.h @@ -0,0 +1,18 @@ +@class NSString; + +/** + * Returns a string appropriate for displaying in test output + * from the provided value. + * + * @param value A value that will show up in a test's output. + * + * @return The string that is returned can be + * customized per type by conforming a type to the `TestOutputStringConvertible` + * protocol. When stringifying a non-`TestOutputStringConvertible` type, this + * function will return the value's debug description and then its + * normal description if available and in that order. Otherwise it + * will return the result of constructing a string from the value. + * + * @see `TestOutputStringConvertible` + */ +extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result)); diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.m b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.m new file mode 100644 index 0000000..329d39a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.m @@ -0,0 +1,6 @@ +#import "NMBStringify.h" +#import + +NSString *_Nonnull NMBStringify(id _Nullable anyObject) { + return [NMBStringer stringify:anyObject]; +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m new file mode 100644 index 0000000..35f26fd --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m @@ -0,0 +1,78 @@ +#import "CurrentTestCaseTracker.h" +#import +#import + +#pragma mark - Method Swizzling + +/// Swaps the implementations between two instance methods. +/// +/// @param class The class containing `originalSelector`. +/// @param originalSelector Original method to replace. +/// @param replacementSelector Replacement method. +void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) { + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method replacementMethod = class_getInstanceMethod(class, replacementSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(replacementMethod), + method_getTypeEncoding(replacementMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + replacementSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, replacementMethod); + } +} + +#pragma mark - Private + +@interface XCTestObservationCenter (Private) +- (void)_addLegacyTestObserver:(id)observer; +@end + +@implementation XCTestObservationCenter (Register) + +/// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary +/// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early +/// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output. +/// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer, +/// falling back to registering after the first normal observer if this private method ever changes. ++ (void)load { + if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) { + // Swizzle -_addLegacyTestObserver: + swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:)); + } else { + // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented + swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:)); + } +} + +#pragma mark - Replacement Methods + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +- (void)NMB_original__addLegacyTestObserver:(id)observer { + [self NMB_original__addLegacyTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +/// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. +/// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3) +- (void)NMB_original_addTestObserver:(id)observer { + [self NMB_original_addTestObserver:observer]; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]]; + }); +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/License.txt b/Students/Benny/Les 1 OCMock/Pods/OCMock/License.txt new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/License.txt @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/README.md b/Students/Benny/Les 1 OCMock/Pods/OCMock/README.md new file mode 100644 index 0000000..948822e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/README.md @@ -0,0 +1,10 @@ +OCMock +====== + +OCMock is an Objective-C implementation of mock objects. + +For downloads, documentation, and support please visit [ocmock.org][]. + +[![Build Status](https://travis-ci.org/erikdoe/ocmock.svg?branch=master)](https://travis-ci.org/erikdoe/ocmock) + + [ocmock.org]: http://ocmock.org/ diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSInvocation+OCMAdditions.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSInvocation+OCMAdditions.h new file mode 100644 index 0000000..3db7005 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSInvocation+OCMAdditions.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface NSInvocation(OCMAdditions) + ++ (NSInvocation *)invocationForBlock:(id)block withArguments:(NSArray *)arguments; + +- (void)retainObjectArgumentsExcludingObject:(id)objectToExclude; + +- (id)getArgumentAtIndexAsObject:(NSInteger)argIndex; + +- (NSString *)invocationDescription; + +- (NSString *)argumentDescriptionAtIndex:(NSInteger)argIndex; + +- (NSString *)objectDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)charDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)unsignedCharDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)intDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)unsignedIntDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)shortDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)unsignedShortDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)longDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)unsignedLongDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)longLongDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)unsignedLongLongDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)doubleDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)floatDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)structDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)pointerDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)cStringDescriptionAtIndex:(NSInteger)anInt; +- (NSString *)selectorDescriptionAtIndex:(NSInteger)anInt; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSInvocation+OCMAdditions.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSInvocation+OCMAdditions.m new file mode 100644 index 0000000..49a9675 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSInvocation+OCMAdditions.m @@ -0,0 +1,520 @@ +/* + * Copyright (c) 2006-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "NSInvocation+OCMAdditions.h" +#import "OCMFunctionsPrivate.h" +#import "NSMethodSignature+OCMAdditions.h" + + +@implementation NSInvocation(OCMAdditions) + ++ (NSInvocation *)invocationForBlock:(id)block withArguments:(NSArray *)arguments +{ + NSMethodSignature *sig = [NSMethodSignature signatureForBlock:block]; + NSInvocation *inv = [self invocationWithMethodSignature:sig]; + + NSUInteger numArgsRequired = sig.numberOfArguments - 1; + if((arguments != nil) && ([arguments count] != numArgsRequired)) + [NSException raise:NSInvalidArgumentException format:@"Specified too few arguments for block; expected %lu arguments.", (unsigned long) numArgsRequired]; + + for(NSUInteger i = 0, j = 1; i < numArgsRequired; ++i, ++j) + { + id arg = [arguments objectAtIndex:i]; + [inv setArgumentWithObject:arg atIndex:j]; + } + + return inv; + +} + + +static NSString *const OCMRetainedObjectArgumentsKey = @"OCMRetainedObjectArgumentsKey"; + +- (void)retainObjectArgumentsExcludingObject:(id)objectToExclude +{ + if(objc_getAssociatedObject(self, OCMRetainedObjectArgumentsKey) != nil) + { + // looks like we've retained the arguments already; do nothing else + return; + } + + NSMutableArray *retainedArguments = [[NSMutableArray alloc] init]; + + id target = [self target]; + if((target != nil) && (target != objectToExclude) && !object_isClass(target)) + { + // Bad things will happen if the target is a block since it's not being + // copied. There isn't a very good way to tell if an invocation's target + // is a block though (the argument type at index 0 is always "@" even if + // the target is a Class or block), and in practice it's OK since you + // can't mock a block. + [retainedArguments addObject:target]; + } + + NSUInteger numberOfArguments = [[self methodSignature] numberOfArguments]; + for(NSUInteger index = 2; index < numberOfArguments; index++) + { + const char *argumentType = [[self methodSignature] getArgumentTypeAtIndex:index]; + if(OCMIsObjectType(argumentType) && !OCMIsClassType(argumentType)) + { + id argument; + [self getArgument:&argument atIndex:index]; + if((argument != nil) && (argument != objectToExclude)) + { + if(OCMIsBlockType(argumentType)) + { + // block types need to be copied in case they're stack blocks + id blockArgument = [argument copy]; + [retainedArguments addObject:blockArgument]; + [blockArgument release]; + } + else + { + [retainedArguments addObject:argument]; + } + } + } + } + + const char *returnType = [[self methodSignature] methodReturnType]; + if(OCMIsObjectType(returnType) && !OCMIsClassType(returnType)) + { + id returnValue; + [self getReturnValue:&returnValue]; + if((returnValue != nil) && (returnValue != objectToExclude)) + { + if(OCMIsBlockType(returnType)) + { + id blockReturnValue = [returnValue copy]; + [retainedArguments addObject:blockReturnValue]; + [blockReturnValue release]; + } + else + { + [retainedArguments addObject:returnValue]; + } + } + } + + objc_setAssociatedObject(self, OCMRetainedObjectArgumentsKey, retainedArguments, OBJC_ASSOCIATION_RETAIN); + [retainedArguments release]; +} + + +- (void)setArgumentWithObject:(id)arg atIndex:(NSInteger)idx +{ + const char *typeEncoding = [[self methodSignature] getArgumentTypeAtIndex:idx]; + if((arg == nil) || [arg isKindOfClass:[NSNull class]]) + { + if(typeEncoding[0] == '^') + { + void *nullPtr = NULL; + [self setArgument:&nullPtr atIndex:idx]; + } + else if(typeEncoding[0] == '@') + { + id nilObj = nil; + [self setArgument:&nilObj atIndex:idx]; + } + else if(OCMNumberTypeForObjCType(typeEncoding)) + { + NSUInteger argSize; + NSGetSizeAndAlignment(typeEncoding, NULL, &argSize); + void *argBuffer = calloc(1, argSize); + [self setArgument:argBuffer atIndex:idx]; + free(argBuffer); + } + else + { + [NSException raise:NSInvalidArgumentException format:@"Unable to create default value for type '%s'.", typeEncoding]; + } + } + else if(OCMIsObjectType(typeEncoding)) + { + [self setArgument:&arg atIndex:idx]; + } + else + { + if(![arg isKindOfClass:[NSValue class]]) + [NSException raise:NSInvalidArgumentException format:@"Argument '%@' should be boxed in NSValue.", arg]; + + char const *valEncoding = [arg objCType]; + + /// @note Here we allow any data pointer to be passed as a void pointer and + /// any numerical types to be passed as arguments to the block. + BOOL takesVoidPtr = !strcmp(typeEncoding, "^v") && valEncoding[0] == '^'; + BOOL takesNumber = OCMNumberTypeForObjCType(typeEncoding) && OCMNumberTypeForObjCType(valEncoding); + + if(!takesVoidPtr && !takesNumber && !OCMEqualTypesAllowingOpaqueStructs(typeEncoding, valEncoding)) + [NSException raise:NSInvalidArgumentException format:@"Argument type mismatch; type of argument required is '%s' but type of value provided is '%s'", typeEncoding, valEncoding]; + + NSUInteger argSize; + NSGetSizeAndAlignment(typeEncoding, &argSize, NULL); + void *argBuffer = malloc(argSize); + [arg getValue:argBuffer]; + [self setArgument:argBuffer atIndex:idx]; + free(argBuffer); + } + +} + + +- (id)getArgumentAtIndexAsObject:(NSInteger)argIndex +{ + const char *argType = OCMTypeWithoutQualifiers([[self methodSignature] getArgumentTypeAtIndex:(NSUInteger)argIndex]); + + if((strlen(argType) > 1) && (strchr("{^", argType[0]) == NULL) && (strcmp("@?", argType) != 0)) + [NSException raise:NSInvalidArgumentException format:@"Cannot handle argument type '%s'.", argType]; + + if(OCMIsObjectType(argType)) + { + id value; + [self getArgument:&value atIndex:argIndex]; + return value; + } + + switch(argType[0]) + { + case ':': + { + SEL s = (SEL)0; + [self getArgument:&s atIndex:argIndex]; + return [NSValue valueWithBytes:&s objCType:":"]; + } + case 'i': + { + int value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 's': + { + short value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'l': + { + long value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'q': + { + long long value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'c': + { + char value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'C': + { + unsigned char value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'I': + { + unsigned int value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'S': + { + unsigned short value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'L': + { + unsigned long value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'Q': + { + unsigned long long value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'f': + { + float value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'd': + { + double value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case 'D': + { + long double value; + [self getArgument:&value atIndex:argIndex]; + return [NSValue valueWithBytes:&value objCType:@encode(__typeof__(value))]; + } + case 'B': + { + bool value; + [self getArgument:&value atIndex:argIndex]; + return @(value); + } + case '^': + case '*': + { + void *value = NULL; + [self getArgument:&value atIndex:argIndex]; + return [NSValue valueWithPointer:value]; + } + case '{': // structure + { + NSUInteger argSize; + NSGetSizeAndAlignment([[self methodSignature] getArgumentTypeAtIndex:(NSUInteger)argIndex], &argSize, NULL); + if(argSize == 0) // TODO: Can this happen? Is frameLength a good choice in that case? + argSize = [[self methodSignature] frameLength]; + NSMutableData *argumentData = [[[NSMutableData alloc] initWithLength:argSize] autorelease]; + [self getArgument:[argumentData mutableBytes] atIndex:argIndex]; + return [NSValue valueWithBytes:[argumentData bytes] objCType:argType]; + } + + } + [NSException raise:NSInvalidArgumentException format:@"Argument type '%s' not supported", argType]; + return nil; +} + +- (NSString *)invocationDescription +{ + NSMethodSignature *methodSignature = [self methodSignature]; + NSUInteger numberOfArgs = [methodSignature numberOfArguments]; + + if (numberOfArgs == 2) + return NSStringFromSelector([self selector]); + + NSArray *selectorParts = [NSStringFromSelector([self selector]) componentsSeparatedByString:@":"]; + NSMutableString *description = [[NSMutableString alloc] init]; + NSUInteger i; + for(i = 2; i < numberOfArgs; i++) + { + [description appendFormat:@"%@%@:", (i > 2 ? @" " : @""), [selectorParts objectAtIndex:(i - 2)]]; + [description appendString:[self argumentDescriptionAtIndex:(NSInteger)i]]; + } + + return [description autorelease]; +} + +- (NSString *)argumentDescriptionAtIndex:(NSInteger)argIndex +{ + const char *argType = OCMTypeWithoutQualifiers([[self methodSignature] getArgumentTypeAtIndex:(NSUInteger)argIndex]); + + switch(*argType) + { + case '@': return [self objectDescriptionAtIndex:argIndex]; + case 'B': return [self boolDescriptionAtIndex:argIndex]; + case 'c': return [self charDescriptionAtIndex:argIndex]; + case 'C': return [self unsignedCharDescriptionAtIndex:argIndex]; + case 'i': return [self intDescriptionAtIndex:argIndex]; + case 'I': return [self unsignedIntDescriptionAtIndex:argIndex]; + case 's': return [self shortDescriptionAtIndex:argIndex]; + case 'S': return [self unsignedShortDescriptionAtIndex:argIndex]; + case 'l': return [self longDescriptionAtIndex:argIndex]; + case 'L': return [self unsignedLongDescriptionAtIndex:argIndex]; + case 'q': return [self longLongDescriptionAtIndex:argIndex]; + case 'Q': return [self unsignedLongLongDescriptionAtIndex:argIndex]; + case 'd': return [self doubleDescriptionAtIndex:argIndex]; + case 'f': return [self floatDescriptionAtIndex:argIndex]; + case 'D': return [self longDoubleDescriptionAtIndex:argIndex]; + case '{': return [self structDescriptionAtIndex:argIndex]; + case '^': return [self pointerDescriptionAtIndex:argIndex]; + case '*': return [self cStringDescriptionAtIndex:argIndex]; + case ':': return [self selectorDescriptionAtIndex:argIndex]; + default: return [@""]; // avoid confusion with trigraphs... + } + +} + + +- (NSString *)objectDescriptionAtIndex:(NSInteger)anInt +{ + id object; + + [self getArgument:&object atIndex:anInt]; + if (object == nil) + return @"nil"; + else if(![object isProxy] && [object isKindOfClass:[NSString class]]) + return [NSString stringWithFormat:@"@\"%@\"", [object description]]; + else + // The description cannot be nil, if it is then replace it + return [object description] ?: @""; +} + +- (NSString *)boolDescriptionAtIndex:(NSInteger)anInt +{ + bool value; + [self getArgument:&value atIndex:anInt]; + return value? @"YES" : @"NO"; +} + +- (NSString *)charDescriptionAtIndex:(NSInteger)anInt +{ + unsigned char buffer[128]; + memset(buffer, 0x0, 128); + + [self getArgument:&buffer atIndex:anInt]; + + // If there's only one character in the buffer, and it's 0 or 1, then we have a BOOL + if (buffer[1] == '\0' && (buffer[0] == 0 || buffer[0] == 1)) + return (buffer[0] == 1 ? @"YES" : @"NO"); + else + return [NSString stringWithFormat:@"'%c'", *buffer]; +} + +- (NSString *)unsignedCharDescriptionAtIndex:(NSInteger)anInt +{ + unsigned char buffer[128]; + memset(buffer, 0x0, 128); + + [self getArgument:&buffer atIndex:anInt]; + return [NSString stringWithFormat:@"'%c'", *buffer]; +} + +- (NSString *)intDescriptionAtIndex:(NSInteger)anInt +{ + int intValue; + + [self getArgument:&intValue atIndex:anInt]; + return [NSString stringWithFormat:@"%d", intValue]; +} + +- (NSString *)unsignedIntDescriptionAtIndex:(NSInteger)anInt +{ + unsigned int intValue; + + [self getArgument:&intValue atIndex:anInt]; + return [NSString stringWithFormat:@"%d", intValue]; +} + +- (NSString *)shortDescriptionAtIndex:(NSInteger)anInt +{ + short shortValue; + + [self getArgument:&shortValue atIndex:anInt]; + return [NSString stringWithFormat:@"%hi", shortValue]; +} + +- (NSString *)unsignedShortDescriptionAtIndex:(NSInteger)anInt +{ + unsigned short shortValue; + + [self getArgument:&shortValue atIndex:anInt]; + return [NSString stringWithFormat:@"%hu", shortValue]; +} + +- (NSString *)longDescriptionAtIndex:(NSInteger)anInt +{ + long longValue; + + [self getArgument:&longValue atIndex:anInt]; + return [NSString stringWithFormat:@"%ld", longValue]; +} + +- (NSString *)unsignedLongDescriptionAtIndex:(NSInteger)anInt +{ + unsigned long longValue; + + [self getArgument:&longValue atIndex:anInt]; + return [NSString stringWithFormat:@"%lu", longValue]; +} + +- (NSString *)longLongDescriptionAtIndex:(NSInteger)anInt +{ + long long longLongValue; + + [self getArgument:&longLongValue atIndex:anInt]; + return [NSString stringWithFormat:@"%qi", longLongValue]; +} + +- (NSString *)unsignedLongLongDescriptionAtIndex:(NSInteger)anInt +{ + unsigned long long longLongValue; + + [self getArgument:&longLongValue atIndex:anInt]; + return [NSString stringWithFormat:@"%qu", longLongValue]; +} + +- (NSString *)doubleDescriptionAtIndex:(NSInteger)anInt +{ + double doubleValue; + + [self getArgument:&doubleValue atIndex:anInt]; + return [NSString stringWithFormat:@"%f", doubleValue]; +} + +- (NSString *)floatDescriptionAtIndex:(NSInteger)anInt +{ + float floatValue; + + [self getArgument:&floatValue atIndex:anInt]; + return [NSString stringWithFormat:@"%f", floatValue]; +} + +- (NSString *)longDoubleDescriptionAtIndex:(NSInteger)anInt +{ + long double longDoubleValue; + + [self getArgument:&longDoubleValue atIndex:anInt]; + return [NSString stringWithFormat:@"%Lf", longDoubleValue]; +} + +- (NSString *)structDescriptionAtIndex:(NSInteger)anInt +{ + return [NSString stringWithFormat:@"(%@)", [[self getArgumentAtIndexAsObject:anInt] description]]; +} + +- (NSString *)pointerDescriptionAtIndex:(NSInteger)anInt +{ + void *buffer; + + [self getArgument:&buffer atIndex:anInt]; + return [NSString stringWithFormat:@"%p", buffer]; +} + +- (NSString *)cStringDescriptionAtIndex:(NSInteger)anInt +{ + char buffer[104]; + char *cStringPtr; + + [self getArgument:&cStringPtr atIndex:anInt]; + strlcpy(buffer, cStringPtr, sizeof(buffer)); + strlcpy(buffer + 100, "...", (sizeof(buffer) - 100)); + return [NSString stringWithFormat:@"\"%s\"", buffer]; +} + +- (NSString *)selectorDescriptionAtIndex:(NSInteger)anInt +{ + SEL selectorValue; + + [self getArgument:&selectorValue atIndex:anInt]; + return [NSString stringWithFormat:@"@selector(%@)", NSStringFromSelector(selectorValue)]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSMethodSignature+OCMAdditions.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSMethodSignature+OCMAdditions.h new file mode 100644 index 0000000..d01f5fd --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSMethodSignature+OCMAdditions.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface NSMethodSignature(OCMAdditions) + ++ (NSMethodSignature *)signatureForDynamicPropertyAccessedWithSelector:(SEL)selector inClass:(Class)aClass; ++ (NSMethodSignature *)signatureForBlock:(id)block; + +- (BOOL)usesSpecialStructureReturn; + +- (NSString *)fullTypeString; +- (const char *)fullObjCTypes; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSMethodSignature+OCMAdditions.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSMethodSignature+OCMAdditions.m new file mode 100644 index 0000000..bc043b2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSMethodSignature+OCMAdditions.m @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "NSMethodSignature+OCMAdditions.h" +#import "OCMFunctionsPrivate.h" +#import + + +@implementation NSMethodSignature(OCMAdditions) + +#pragma mark Signatures for dynamic properties + ++ (NSMethodSignature *)signatureForDynamicPropertyAccessedWithSelector:(SEL)selector inClass:(Class)aClass +{ + BOOL isGetter = YES; + objc_property_t property = [self propertyMatchingSelector:selector inClass:aClass isGetter:&isGetter]; + if(property == NULL) + return nil; + + const char *propertyAttributesString = property_getAttributes(property); + NSArray *propertyAttributes = [[NSString stringWithCString:propertyAttributesString + encoding:NSASCIIStringEncoding] componentsSeparatedByString:@","]; + NSString *typeStr = nil; + BOOL isDynamic = NO; + for(NSString *attribute in propertyAttributes) + { + if([attribute isEqualToString:@"D"]) + isDynamic = YES; + else if([attribute hasPrefix:@"T"]) + typeStr = [attribute substringFromIndex:1]; + } + + if(!isDynamic) + return nil; + + NSRange r = [typeStr rangeOfString:@"\""]; // incomplete workaround to deal with structs + if(r.location != NSNotFound) + typeStr = [typeStr substringToIndex:r.location]; + + NSString *sigStringFormat = isGetter ? @"%@@:" : @"v@:%@"; + const char *sigCString = [[NSString stringWithFormat:sigStringFormat, typeStr] cStringUsingEncoding:NSASCIIStringEncoding]; + return [NSMethodSignature signatureWithObjCTypes:sigCString]; +} + + ++ (objc_property_t)propertyMatchingSelector:(SEL)selector inClass:(Class)aClass isGetter:(BOOL *)isGetterPtr +{ + NSString *propertyName = NSStringFromSelector(selector); + + // first try selector as is aassuming it's a getter + objc_property_t property = class_getProperty(aClass, [propertyName cStringUsingEncoding:NSASCIIStringEncoding]); + if(property != NULL) + { + *isGetterPtr = YES; + return property; + } + + // try setter next if selector starts with "set" + if([propertyName hasPrefix:@"set"]) + { + propertyName = [propertyName substringFromIndex:@"set".length]; + propertyName = [propertyName stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[propertyName substringToIndex:1] lowercaseString]]; + if([propertyName hasSuffix:@":"]) + propertyName = [propertyName substringToIndex:[propertyName length] - 1]; + + property = class_getProperty(aClass, [propertyName cStringUsingEncoding:NSASCIIStringEncoding]); + if(property != NULL) + { + *isGetterPtr = NO; + return property; + } + } + + // search through properties with custom getter/setter that corresponds to selector + unsigned int propertiesCount = 0; + objc_property_t *allProperties = class_copyPropertyList(aClass, &propertiesCount); + for(unsigned int i = 0 ; i < propertiesCount; i++) + { + NSArray *propertyAttributes = [[NSString stringWithCString:property_getAttributes(allProperties[i]) + encoding:NSASCIIStringEncoding] componentsSeparatedByString:@","]; + for(NSString *attribute in propertyAttributes) + { + if(([attribute hasPrefix:@"G"] || [attribute hasPrefix:@"S"]) && + [[attribute substringFromIndex:1] isEqualToString:propertyName]) + { + *isGetterPtr = ![attribute hasPrefix:@"S"]; + property = allProperties[i]; + i = propertiesCount; + break; + } + } + } + free(allProperties); + + return property; +} + + +#pragma mark Signatures for blocks + +struct OCMBlockDef +{ + void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int flags; + int reserved; + void (*invoke)(void *, ...); + struct block_descriptor { + unsigned long int reserved; // NULL + unsigned long int size; // sizeof(struct Block_literal_1) + // optional helper functions + void (*copy_helper)(void *dst, void *src); // IFF (1<<25) + void (*dispose_helper)(void *src); // IFF (1<<25) + // required ABI.2010.3.16 + const char *signature; // IFF (1<<30) + } *descriptor; +}; + +enum +{ + OCMBlockDescriptionFlagsHasCopyDispose = (1 << 25), + OCMBlockDescriptionFlagsHasSignature = (1 << 30) +}; + + ++ (NSMethodSignature *)signatureForBlock:(id)block +{ + /* For a more complete implementation of parsing the block data structure see: + * + * https://github.com/ebf/CTObjectiveCRuntimeAdditions/tree/master/CTObjectiveCRuntimeAdditions/CTObjectiveCRuntimeAdditions + */ + + struct OCMBlockDef *blockRef = (__bridge struct OCMBlockDef *)block; + + if(!(blockRef->flags & OCMBlockDescriptionFlagsHasSignature)) + return nil; + + void *signatureLocation = blockRef->descriptor; + signatureLocation += sizeof(unsigned long int); + signatureLocation += sizeof(unsigned long int); + if(blockRef->flags & OCMBlockDescriptionFlagsHasCopyDispose) + { + signatureLocation += sizeof(void(*)(void *dst, void *src)); + signatureLocation += sizeof(void (*)(void *src)); + } + + const char *signature = (*(const char **)signatureLocation); + return [NSMethodSignature signatureWithObjCTypes:signature]; +} + + +#pragma mark Extended attributes + +- (BOOL)usesSpecialStructureReturn +{ + const char *types = OCMTypeWithoutQualifiers([self methodReturnType]); + + if((types == NULL) || (types[0] != '{')) + return NO; + + /* In some cases structures are returned by ref. The rules are complex and depend on the + architecture, see: + + http://sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html + http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/000-Introduction/introduction.html + https://github.com/atgreen/libffi/blob/master/src/x86/ffi64.c + http://www.uclibc.org/docs/psABI-x86_64.pdf + http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf + + NSMethodSignature knows the details but has no API to return it, though it is in + the debugDescription. Horribly kludgy. + */ + NSRange range = [[self debugDescription] rangeOfString:@"is special struct return? YES"]; + return range.length > 0; +} + + +- (NSString *)fullTypeString +{ + NSMutableString *typeString = [NSMutableString string]; + [typeString appendFormat:@"%s", [self methodReturnType]]; + for (NSUInteger i=0; i<[self numberOfArguments]; i++) + [typeString appendFormat:@"%s", [self getArgumentTypeAtIndex:i]]; + return typeString; +} + + +- (const char *)fullObjCTypes +{ + return [[self fullTypeString] UTF8String]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSNotificationCenter+OCMAdditions.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSNotificationCenter+OCMAdditions.h new file mode 100644 index 0000000..7d58aab --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSNotificationCenter+OCMAdditions.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@class OCObserverMockObject; + + +@interface NSNotificationCenter(OCMAdditions) + +- (void)addMockObserver:(OCObserverMockObject *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSNotificationCenter+OCMAdditions.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSNotificationCenter+OCMAdditions.m new file mode 100644 index 0000000..f758764 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSNotificationCenter+OCMAdditions.m @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "NSNotificationCenter+OCMAdditions.h" +#import "OCObserverMockObject.h" + + +@implementation NSNotificationCenter(OCMAdditions) + +- (void)addMockObserver:(OCObserverMockObject *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender +{ + [notificationObserver autoRemoveFromCenter:self]; + [self addObserver:notificationObserver selector:@selector(handleNotification:) name:notificationName object:notificationSender]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSObject+OCMAdditions.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSObject+OCMAdditions.h new file mode 100644 index 0000000..519fde9 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSObject+OCMAdditions.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface NSObject(OCMAdditions) + ++ (IMP)instanceMethodForwarderForSelector:(SEL)aSelector; ++ (void)enumerateMethodsInClass:(Class)aClass usingBlock:(void (^)(Class cls, SEL sel))aBlock; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSObject+OCMAdditions.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSObject+OCMAdditions.m new file mode 100644 index 0000000..8f3c391 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSObject+OCMAdditions.m @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "NSObject+OCMAdditions.h" +#import "NSMethodSignature+OCMAdditions.h" +#import + +@implementation NSObject(OCMAdditions) + ++ (IMP)instanceMethodForwarderForSelector:(SEL)aSelector +{ + // use sel_registerName() and not @selector to avoid warning + SEL selectorWithNoImplementation = sel_registerName("methodWhichMustNotExist::::"); + +#ifndef __arm64__ + static NSMutableDictionary *_OCMReturnTypeCache; + + if(_OCMReturnTypeCache == nil) + _OCMReturnTypeCache = [[NSMutableDictionary alloc] init]; + + BOOL needsStructureReturn; + void *rawCacheKey[2] = { (void *)self, aSelector }; + NSData *cacheKey = [NSData dataWithBytes:rawCacheKey length:sizeof(rawCacheKey)]; + NSNumber *cachedValue = [_OCMReturnTypeCache objectForKey:cacheKey]; + + if(cachedValue == nil) + { + NSMethodSignature *sig = [self instanceMethodSignatureForSelector:aSelector]; + needsStructureReturn = [sig usesSpecialStructureReturn]; + [_OCMReturnTypeCache setObject:@(needsStructureReturn) forKey:cacheKey]; + } + else + { + needsStructureReturn = [cachedValue boolValue]; + } + + if(needsStructureReturn) + return class_getMethodImplementation_stret([NSObject class], selectorWithNoImplementation); +#endif + + return class_getMethodImplementation([NSObject class], selectorWithNoImplementation); +} + + ++ (void)enumerateMethodsInClass:(Class)aClass usingBlock:(void (^)(Class cls, SEL sel))aBlock +{ + for(Class cls = aClass; cls != nil; cls = class_getSuperclass(cls)) + { + Method *methodList = class_copyMethodList(cls, NULL); + if(methodList == NULL) + continue; + + for(Method *mPtr = methodList; *mPtr != NULL; mPtr++) + { + SEL sel = method_getName(*mPtr); + aBlock(cls, sel); + } + free(methodList); + } +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSValue+OCMAdditions.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSValue+OCMAdditions.h new file mode 100644 index 0000000..d6977af --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSValue+OCMAdditions.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface NSValue(OCMAdditions) + +- (BOOL)getBytes:(void *)outputBuf objCType:(const char *)targetType; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSValue+OCMAdditions.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSValue+OCMAdditions.m new file mode 100644 index 0000000..b3aa293 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/NSValue+OCMAdditions.m @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "NSValue+OCMAdditions.h" +#import "OCMFunctionsPrivate.h" + +@implementation NSValue(OCMAdditions) + +static NSNumber *OCMNumberForValue(NSValue *value) +{ +#define CREATE_NUM(_type) ({ _type _v; [value getValue:&_v]; @(_v); }) + switch([value objCType][0]) + { + case 'c': return CREATE_NUM(char); + case 'C': return CREATE_NUM(unsigned char); + case 'B': return CREATE_NUM(bool); + case 's': return CREATE_NUM(short); + case 'S': return CREATE_NUM(unsigned short); + case 'i': return CREATE_NUM(int); + case 'I': return CREATE_NUM(unsigned int); + case 'l': return CREATE_NUM(long); + case 'L': return CREATE_NUM(unsigned long); + case 'q': return CREATE_NUM(long long); + case 'Q': return CREATE_NUM(unsigned long long); + case 'f': return CREATE_NUM(float); + case 'd': return CREATE_NUM(double); + default: return nil; + } +} + + +- (BOOL)getBytes:(void *)outputBuf objCType:(const char *)targetType +{ + /* + * See if they are similar number types, and if we can convert losslessly between them. + * For the most part, we set things up to use CFNumberGetValue, which returns false if + * conversion will be lossy. + */ + CFNumberType inputType = OCMNumberTypeForObjCType([self objCType]); + CFNumberType outputType = OCMNumberTypeForObjCType(targetType); + + if(inputType == 0 || outputType == 0) // one or both are non-number types + return NO; + + NSNumber *inputNumber = [self isKindOfClass:[NSNumber class]] ? (NSNumber *)self : OCMNumberForValue(self); + + /* + * Due to some legacy, back-compatible requirements in CFNumber.c, CFNumberGetValue can return true for + * some conversions which should not be allowed (by reading source, conversions from integer types to + * 8-bit or 16-bit integer types). So, check ourselves. + */ + long long min; + long long max; + long long val = [inputNumber longLongValue]; + switch(targetType[0]) + { + case 'B': + case 'c': min = CHAR_MIN; max = CHAR_MAX; break; + case 'C': min = 0; max = UCHAR_MAX; break; + case 's': min = SHRT_MIN; max = SHRT_MAX; break; + case 'S': min = 0; max = USHRT_MAX; break; + default: min = LLONG_MIN; max = LLONG_MAX; break; + } + if(val < min || val > max) + return NO; + + /* Get the number, and return NO if the value was out of range or conversion was lossy */ + return CFNumberGetValue((CFNumberRef)inputNumber, outputType, outputBuf); +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCClassMockObject.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCClassMockObject.h new file mode 100644 index 0000000..29c67f1 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCClassMockObject.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2005-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCClassMockObject : OCMockObject +{ + Class mockedClass; + Class originalMetaClass; +} + +- (id)initWithClass:(Class)aClass; + +- (Class)mockedClass; +- (Class)mockObjectClass; // since -class returns the mockedClass + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCClassMockObject.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCClassMockObject.m new file mode 100644 index 0000000..0555b80 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCClassMockObject.m @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2005-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCClassMockObject.h" +#import "NSObject+OCMAdditions.h" +#import "OCMFunctionsPrivate.h" +#import "OCMInvocationStub.h" +#import "NSMethodSignature+OCMAdditions.h" + +@implementation OCClassMockObject + +#pragma mark Initialisers, description, accessors, etc. + +- (id)initWithClass:(Class)aClass +{ + NSParameterAssert(aClass != nil); + [super init]; + mockedClass = aClass; + [self prepareClassForClassMethodMocking]; + return self; +} + +- (void)dealloc +{ + [self stopMocking]; + [super dealloc]; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"OCMockObject(%@)", NSStringFromClass(mockedClass)]; +} + +- (Class)mockedClass +{ + return mockedClass; +} + +#pragma mark Extending/overriding superclass behaviour + +- (void)stopMocking +{ + if(originalMetaClass != nil) + { + /* The mocked class has the meta class of a dynamically created subclass as its meta class, + but we need a reference to the subclass to dispose it. Asking the meta class for its + class name returns the actual class name, which we can then use to look up the class... + */ + const char *createdSubclassName = object_getClassName(mockedClass); + Class createdSubclass = objc_lookUpClass(createdSubclassName); + + [self restoreMetaClass]; + + objc_disposeClassPair(createdSubclass); + } + [super stopMocking]; +} + +- (void)restoreMetaClass +{ + OCMSetAssociatedMockForClass(nil, mockedClass); + object_setClass(mockedClass, originalMetaClass); + originalMetaClass = nil; +} + +- (void)addStub:(OCMInvocationStub *)aStub +{ + [super addStub:aStub]; + if([aStub recordedAsClassMethod]) + [self setupForwarderForClassMethodSelector:[[aStub recordedInvocation] selector]]; +} + + +#pragma mark Class method mocking + +- (void)prepareClassForClassMethodMocking +{ + /* the runtime and OCMock depend on string and array; we don't intercept methods on them to avoid endless loops */ + if([[mockedClass class] isSubclassOfClass:[NSString class]] || [[mockedClass class] isSubclassOfClass:[NSArray class]]) + return; + + /* if there is another mock for this exact class, stop it */ + id otherMock = OCMGetAssociatedMockForClass(mockedClass, NO); + if(otherMock != nil) + [otherMock restoreMetaClass]; + + OCMSetAssociatedMockForClass(self, mockedClass); + + /* dynamically create a subclass and use its meta class as the meta class for the mocked class */ + Class subclass = OCMCreateSubclass(mockedClass, mockedClass); + originalMetaClass = object_getClass(mockedClass); + id newMetaClass = object_getClass(subclass); + + /* create a dummy initialize method */ + Method myDummyInitializeMethod = class_getInstanceMethod([self mockObjectClass], @selector(initializeForClassObject)); + const char *initializeTypes = method_getTypeEncoding(myDummyInitializeMethod); + IMP myDummyInitializeIMP = method_getImplementation(myDummyInitializeMethod); + class_addMethod(newMetaClass, @selector(initialize), myDummyInitializeIMP, initializeTypes); + + object_setClass(mockedClass, newMetaClass); // only after dummy initialize is installed (iOS9) + + /* point forwardInvocation: of the object to the implementation in the mock */ + Method myForwardMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardInvocationForClassObject:)); + IMP myForwardIMP = method_getImplementation(myForwardMethod); + class_addMethod(newMetaClass, @selector(forwardInvocation:), myForwardIMP, method_getTypeEncoding(myForwardMethod)); + + + /* adding forwarder for most class methods (instance methods on meta class) to allow for verify after run */ + NSArray *methodBlackList = @[@"class", @"forwardingTargetForSelector:", @"methodSignatureForSelector:", @"forwardInvocation:", @"isBlock", + @"instanceMethodForwarderForSelector:", @"instanceMethodSignatureForSelector:"]; + [NSObject enumerateMethodsInClass:originalMetaClass usingBlock:^(Class cls, SEL sel) { + if((cls == object_getClass([NSObject class])) || (cls == [NSObject class]) || (cls == object_getClass(cls))) + return; + NSString *className = NSStringFromClass(cls); + NSString *selName = NSStringFromSelector(sel); + if(([className hasPrefix:@"NS"] || [className hasPrefix:@"UI"]) && + ([selName hasPrefix:@"_"] || [selName hasSuffix:@"_"])) + return; + if([methodBlackList containsObject:selName]) + return; + @try + { + [self setupForwarderForClassMethodSelector:sel]; + } + @catch(NSException *e) + { + // ignore for now + } + }]; +} + +- (void)setupForwarderForClassMethodSelector:(SEL)selector +{ + SEL aliasSelector = OCMAliasForOriginalSelector(selector); + if(class_getClassMethod(mockedClass, aliasSelector) != NULL) + return; + + Method originalMethod = class_getClassMethod(mockedClass, selector); + IMP originalIMP = method_getImplementation(originalMethod); + const char *types = method_getTypeEncoding(originalMethod); + + Class metaClass = object_getClass(mockedClass); + IMP forwarderIMP = [originalMetaClass instanceMethodForwarderForSelector:selector]; + class_replaceMethod(metaClass, selector, forwarderIMP, types); + class_addMethod(metaClass, aliasSelector, originalIMP, types); +} + + +- (void)forwardInvocationForClassObject:(NSInvocation *)anInvocation +{ + // in here "self" is a reference to the real class, not the mock + OCClassMockObject *mock = OCMGetAssociatedMockForClass((Class) self, YES); + if(mock == nil) + { + [NSException raise:NSInternalInconsistencyException format:@"No mock for class %@", NSStringFromClass((Class)self)]; + } + if([mock handleInvocation:anInvocation] == NO) + { + [anInvocation setSelector:OCMAliasForOriginalSelector([anInvocation selector])]; + [anInvocation invoke]; + } +} + +- (void)initializeForClassObject +{ + // we really just want to have an implementation so that the superclass's is not called +} + + +#pragma mark Proxy API + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + NSMethodSignature *signature = [mockedClass instanceMethodSignatureForSelector:aSelector]; + if(signature == nil) + { + signature = [NSMethodSignature signatureForDynamicPropertyAccessedWithSelector:aSelector inClass:mockedClass]; + } + return signature; +} + +- (Class)mockObjectClass +{ + return [super class]; +} + +- (Class)class +{ + return mockedClass; +} + +- (BOOL)respondsToSelector:(SEL)selector +{ + return [mockedClass instancesRespondToSelector:selector]; +} + +- (BOOL)isKindOfClass:(Class)aClass +{ + return [mockedClass isSubclassOfClass:aClass]; +} + +- (BOOL)conformsToProtocol:(Protocol *)aProtocol +{ + Class clazz = mockedClass; + while (clazz != nil) { + if (class_conformsToProtocol(clazz, aProtocol)) { + return YES; + } + clazz = class_getSuperclass(clazz); + } + return NO; +} + +@end + + +#pragma mark - + +/** + taken from: + `class-dump -f isNS /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/Frameworks/CoreFoundation.framework` + + @interface NSObject (__NSIsKinds) + - (_Bool)isNSValue__; + - (_Bool)isNSTimeZone__; + - (_Bool)isNSString__; + - (_Bool)isNSSet__; + - (_Bool)isNSOrderedSet__; + - (_Bool)isNSNumber__; + - (_Bool)isNSDictionary__; + - (_Bool)isNSDate__; + - (_Bool)isNSData__; + - (_Bool)isNSArray__; + */ + +@implementation OCClassMockObject(NSIsKindsImplementation) + +- (BOOL)isNSValue__ +{ + return [mockedClass isSubclassOfClass:[NSValue class]]; +} + +- (BOOL)isNSTimeZone__ +{ + return [mockedClass isSubclassOfClass:[NSTimeZone class]]; +} + +- (BOOL)isNSSet__ +{ + return [mockedClass isSubclassOfClass:[NSSet class]]; +} + +- (BOOL)isNSOrderedSet__ +{ + return [mockedClass isSubclassOfClass:[NSOrderedSet class]]; +} + +- (BOOL)isNSNumber__ +{ + return [mockedClass isSubclassOfClass:[NSNumber class]]; +} + +- (BOOL)isNSDate__ +{ + return [mockedClass isSubclassOfClass:[NSDate class]]; +} + +- (BOOL)isNSString__ +{ + return [mockedClass isSubclassOfClass:[NSString class]]; +} + +- (BOOL)isNSDictionary__ +{ + return [mockedClass isSubclassOfClass:[NSDictionary class]]; +} + +- (BOOL)isNSData__ +{ + return [mockedClass isSubclassOfClass:[NSData class]]; +} + +- (BOOL)isNSArray__ +{ + return [mockedClass isSubclassOfClass:[NSArray class]]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArg.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArg.h new file mode 100644 index 0000000..6df735e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArg.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMArg : NSObject + +// constraining arguments + ++ (id)any; ++ (SEL)anySelector; ++ (void *)anyPointer; ++ (id __autoreleasing *)anyObjectRef; ++ (id)isNil; ++ (id)isNotNil; ++ (id)isEqual:(id)value; ++ (id)isNotEqual:(id)value; ++ (id)isKindOfClass:(Class)cls; ++ (id)checkWithSelector:(SEL)selector onObject:(id)anObject; ++ (id)checkWithBlock:(BOOL (^)(id obj))block; + +// manipulating arguments + ++ (id *)setTo:(id)value; ++ (void *)setToValue:(NSValue *)value; ++ (id)invokeBlock; ++ (id)invokeBlockWithArgs:(id)first,... NS_REQUIRES_NIL_TERMINATION; + ++ (id)defaultValue; + +// internal use only + ++ (id)resolveSpecialValues:(NSValue *)value; + +@end + +#define OCMOCK_ANY [OCMArg any] + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + #define OCMOCK_VALUE(variable) \ + ({ __typeof__(variable) __v = (variable); [NSValue value:&__v withObjCType:@encode(__typeof__(__v))]; }) +#else + #define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(__typeof__(variable))] +#endif + diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArg.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArg.m new file mode 100644 index 0000000..6a90120 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArg.m @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import +#import +#import "OCMPassByRefSetter.h" +#import "OCMBlockArgCaller.h" + +@implementation OCMArg + ++ (id)any +{ + return [OCMAnyConstraint constraint]; +} + ++ (void *)anyPointer +{ + return (void *)0x01234567; +} + ++ (id __autoreleasing *)anyObjectRef +{ + return (id *)0x01234567; +} + ++ (SEL)anySelector +{ + return NSSelectorFromString(@"aSelectorThatMatchesAnySelector"); +} + ++ (id)isNil +{ + return [OCMIsNilConstraint constraint]; +} + ++ (id)isNotNil +{ + return [OCMIsNotNilConstraint constraint]; +} + ++ (id)isEqual:(id)value +{ + return value; +} + ++ (id)isNotEqual:(id)value +{ + OCMIsNotEqualConstraint *constraint = [OCMIsNotEqualConstraint constraint]; + constraint->testValue = value; + return constraint; +} + ++ (id)isKindOfClass:(Class)cls +{ + return [[[OCMBlockConstraint alloc] initWithConstraintBlock:^BOOL(id obj) { + return [obj isKindOfClass:cls]; + }] autorelease]; +} + ++ (id)checkWithSelector:(SEL)selector onObject:(id)anObject +{ + return [OCMConstraint constraintWithSelector:selector onObject:anObject]; +} + ++ (id)checkWithBlock:(BOOL (^)(id))block +{ + return [[[OCMBlockConstraint alloc] initWithConstraintBlock:block] autorelease]; +} + ++ (id *)setTo:(id)value +{ + return (id *)[[[OCMPassByRefSetter alloc] initWithValue:value] autorelease]; +} + ++ (void *)setToValue:(NSValue *)value +{ + return (id *)[[[OCMPassByRefSetter alloc] initWithValue:value] autorelease]; +} + ++ (id)invokeBlock +{ + return [[[OCMBlockArgCaller alloc] init] autorelease]; +} + ++ (id)invokeBlockWithArgs:(id)first,... NS_REQUIRES_NIL_TERMINATION +{ + + NSMutableArray *params = [NSMutableArray array]; + va_list args; + if(first) + { + [params addObject:first]; + va_start(args, first); + id obj; + while((obj = va_arg(args, id))) + { + [params addObject:obj]; + } + va_end(args); + } + return [[[OCMBlockArgCaller alloc] initWithBlockArguments:params] autorelease]; + +} + ++ (id)defaultValue +{ + return [NSNull null]; +} + + ++ (id)resolveSpecialValues:(NSValue *)value +{ + const char *type = [value objCType]; + if(type[0] == '^') + { + void *pointer = [value pointerValue]; + if(pointer == (void *)0x01234567) + return [OCMArg any]; + if((pointer != NULL) && (object_getClass((id)pointer) == [OCMPassByRefSetter class])) + return (id)pointer; + } + else if(type[0] == ':') + { + SEL selector; + [value getValue:&selector]; + if(selector == NSSelectorFromString(@"aSelectorThatMatchesAnySelector")) + return [OCMArg any]; + } + return value; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArgAction.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArgAction.h new file mode 100644 index 0000000..15fc62c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArgAction.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMArgAction : NSObject + +- (void)handleArgument:(id)argument; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArgAction.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArgAction.m new file mode 100644 index 0000000..ff1b831 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMArgAction.m @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMArgAction.h" + + +@implementation OCMArgAction + +- (void)handleArgument:(id)argument +{ + +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockArgCaller.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockArgCaller.h new file mode 100644 index 0000000..3c63a91 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockArgCaller.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMArgAction.h" + +@interface OCMBlockArgCaller : OCMArgAction +{ + NSArray *arguments; +} + +- (instancetype)initWithBlockArguments:(NSArray *)someArgs; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockArgCaller.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockArgCaller.m new file mode 100644 index 0000000..aac0618 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockArgCaller.m @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMBlockArgCaller.h" +#import "NSInvocation+OCMAdditions.h" + + +@implementation OCMBlockArgCaller + +- (instancetype)initWithBlockArguments:(NSArray *)someArgs +{ + self = [super init]; + if(self) + { + arguments = [someArgs copy]; + } + return self; +} + +- (void)dealloc +{ + [arguments release]; + [super dealloc]; +} + +- (id)copyWithZone:(NSZone *)zone +{ + return [self retain]; +} + +- (void)handleArgument:(id)aBlock +{ + if(aBlock) + { + NSInvocation *inv = [NSInvocation invocationForBlock:aBlock withArguments:arguments]; + [inv invokeWithTarget:aBlock]; + } +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockCaller.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockCaller.h new file mode 100644 index 0000000..fab09a3 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockCaller.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + + +@interface OCMBlockCaller : NSObject +{ + void (^block)(NSInvocation *); +} + +- (id)initWithCallBlock:(void (^)(NSInvocation *))theBlock; + +- (void)handleInvocation:(NSInvocation *)anInvocation; + +@end + diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockCaller.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockCaller.m new file mode 100644 index 0000000..a5aaea8 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBlockCaller.m @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMBlockCaller.h" + + +@implementation OCMBlockCaller + +-(id)initWithCallBlock:(void (^)(NSInvocation *))theBlock +{ + if ((self = [super init])) + { + block = [theBlock copy]; + } + + return self; +} + +-(void)dealloc +{ + [block release]; + [super dealloc]; +} + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + if (block != nil) + { + block(anInvocation); + } +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBoxedReturnValueProvider.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBoxedReturnValueProvider.h new file mode 100644 index 0000000..f4728a2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBoxedReturnValueProvider.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMReturnValueProvider.h" + +@interface OCMBoxedReturnValueProvider : OCMReturnValueProvider +{ +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBoxedReturnValueProvider.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBoxedReturnValueProvider.m new file mode 100644 index 0000000..b2b016f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMBoxedReturnValueProvider.m @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMBoxedReturnValueProvider.h" +#import "OCMFunctionsPrivate.h" +#import "NSValue+OCMAdditions.h" + +@implementation OCMBoxedReturnValueProvider + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + const char *returnType = [[anInvocation methodSignature] methodReturnType]; + NSUInteger returnTypeSize = [[anInvocation methodSignature] methodReturnLength]; + char valueBuffer[returnTypeSize]; + NSValue *returnValueAsNSValue = (NSValue *)returnValue; + + if([self isMethodReturnType:returnType compatibleWithValueType:[returnValueAsNSValue objCType]]) + { + [returnValueAsNSValue getValue:valueBuffer]; + [anInvocation setReturnValue:valueBuffer]; + } + else if([returnValueAsNSValue getBytes:valueBuffer objCType:returnType]) + { + [anInvocation setReturnValue:valueBuffer]; + } + else + { + [NSException raise:NSInvalidArgumentException + format:@"Return value cannot be used for method; method signature declares '%s' but value is '%s'.", returnType, [returnValueAsNSValue objCType]]; + } +} + + +- (BOOL)isMethodReturnType:(const char *)returnType compatibleWithValueType:(const char *)valueType +{ + /* Same types are obviously compatible */ + if(strcmp(returnType, valueType) == 0) + return YES; + + /* Allow void* for methods that return id, mainly to be able to handle nil */ + if(strcmp(returnType, @encode(id)) == 0 && strcmp(valueType, @encode(void *)) == 0) + return YES; + + return OCMEqualTypesAllowingOpaqueStructs(returnType, valueType); +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMConstraint.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMConstraint.h new file mode 100644 index 0000000..19fc1a7 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMConstraint.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2007-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + + +@interface OCMConstraint : NSObject + ++ (instancetype)constraint; +- (BOOL)evaluate:(id)value; + +// if you are looking for any, isNil, etc, they have moved to OCMArg + +// try to use [OCMArg checkWith...] instead of the constraintWith... methods below + ++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject; ++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue; + + +@end + +@interface OCMAnyConstraint : OCMConstraint +@end + +@interface OCMIsNilConstraint : OCMConstraint +@end + +@interface OCMIsNotNilConstraint : OCMConstraint +@end + +@interface OCMIsNotEqualConstraint : OCMConstraint +{ + @public + id testValue; +} + +@end + +@interface OCMInvocationConstraint : OCMConstraint +{ + @public + NSInvocation *invocation; +} + +@end + +@interface OCMBlockConstraint : OCMConstraint +{ + BOOL (^block)(id); +} + +- (instancetype)initWithConstraintBlock:(BOOL (^)(id))block; + +@end + + +#define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self] +#define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)] diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMConstraint.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMConstraint.m new file mode 100644 index 0000000..cc1204f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMConstraint.m @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2007-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + + +@implementation OCMConstraint + ++ (instancetype)constraint +{ + return [[[self alloc] init] autorelease]; +} + +- (BOOL)evaluate:(id)value +{ + return NO; +} + +- (id)copyWithZone:(struct _NSZone *)zone +{ + return [self retain]; +} + ++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject +{ + OCMInvocationConstraint *constraint = [OCMInvocationConstraint constraint]; + NSMethodSignature *signature = [anObject methodSignatureForSelector:aSelector]; + if(signature == nil) + [NSException raise:NSInvalidArgumentException format:@"Unkown selector %@ used in constraint.", NSStringFromSelector(aSelector)]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setTarget:anObject]; + [invocation setSelector:aSelector]; + constraint->invocation = invocation; + return constraint; +} + ++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue +{ + OCMInvocationConstraint *constraint = [self constraintWithSelector:aSelector onObject:anObject]; + if([[constraint->invocation methodSignature] numberOfArguments] < 4) + [NSException raise:NSInvalidArgumentException format:@"Constraint with value requires selector with two arguments."]; + [constraint->invocation setArgument:&aValue atIndex:3]; + return constraint; +} + + +@end + + + +#pragma mark - + +@implementation OCMAnyConstraint + +- (BOOL)evaluate:(id)value +{ + return YES; +} + +@end + + + +#pragma mark - + +@implementation OCMIsNilConstraint + +- (BOOL)evaluate:(id)value +{ + return value == nil; +} + +@end + + + +#pragma mark - + +@implementation OCMIsNotNilConstraint + +- (BOOL)evaluate:(id)value +{ + return value != nil; +} + +@end + + + +#pragma mark - + +@implementation OCMIsNotEqualConstraint + +- (BOOL)evaluate:(id)value +{ + return ![value isEqual:testValue]; +} + +@end + + + +#pragma mark - + +@implementation OCMInvocationConstraint + +- (BOOL)evaluate:(id)value +{ + [invocation setArgument:&value atIndex:2]; // should test if constraint takes arg + [invocation invoke]; + BOOL returnValue; + [invocation getReturnValue:&returnValue]; + return returnValue; +} + +@end + +#pragma mark - + +@implementation OCMBlockConstraint + +- (instancetype)initWithConstraintBlock:(BOOL (^)(id))aBlock +{ + if ((self = [super init])) + { + block = [aBlock copy]; + } + + return self; +} + +- (void)dealloc { + [block release]; + [super dealloc]; +} + +- (BOOL)evaluate:(id)value +{ + return block ? block(value) : NO; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExceptionReturnValueProvider.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExceptionReturnValueProvider.h new file mode 100644 index 0000000..793c4fd --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExceptionReturnValueProvider.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMReturnValueProvider.h" + +extern NSString *OCMStubbedException; + +@interface OCMExceptionReturnValueProvider : OCMReturnValueProvider +{ +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExceptionReturnValueProvider.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExceptionReturnValueProvider.m new file mode 100644 index 0000000..17dad5d --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExceptionReturnValueProvider.m @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMExceptionReturnValueProvider.h" + + +@implementation OCMExceptionReturnValueProvider + +NSString *OCMStubbedException = @"OCMStubbedException"; + + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + [[NSException exceptionWithName:OCMStubbedException reason:@"Exception stubbed in test." userInfo:@{ @"exception": returnValue }] raise]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExpectationRecorder.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExpectationRecorder.h new file mode 100644 index 0000000..d6de3c0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExpectationRecorder.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2004-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMExpectationRecorder : OCMStubRecorder + +- (id)never; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExpectationRecorder.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExpectationRecorder.m new file mode 100644 index 0000000..07f13d1 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMExpectationRecorder.m @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMExpectationRecorder.h" +#import "OCMInvocationExpectation.h" + +@implementation OCMExpectationRecorder + +#pragma mark Initialisers, description, accessors, etc. + +- (id)init +{ + self = [super init]; + [invocationMatcher release]; + invocationMatcher = [[OCMInvocationExpectation alloc] init]; + return self; +} + +- (OCMInvocationExpectation *)expectation +{ + return (OCMInvocationExpectation *)invocationMatcher; +} + + +#pragma mark Modifying the expectation + +- (id)never +{ + [[self expectation] setMatchAndReject:YES]; + return self; +} + + +#pragma mark Finishing recording + +- (void)forwardInvocation:(NSInvocation *)anInvocation +{ + [super forwardInvocation:anInvocation]; + [mockObject addExpectation:[self expectation]]; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctions.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctions.h new file mode 100644 index 0000000..b0c2df3 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctions.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + + +#if defined(__cplusplus) +#define OCMOCK_EXTERN extern "C" +#else +#define OCMOCK_EXTERN extern +#endif + + +OCMOCK_EXTERN BOOL OCMIsObjectType(const char *objCType); diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctions.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctions.m new file mode 100644 index 0000000..c3a96f8 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctions.m @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCMFunctionsPrivate.h" +#import "OCMLocation.h" +#import "OCClassMockObject.h" +#import "OCPartialMockObject.h" + + +#pragma mark Known private API + +@interface NSException(OCMKnownExceptionMethods) ++ (NSException *)failureInFile:(NSString *)file atLine:(int)line withDescription:(NSString *)formatString, ...; +@end + +@interface NSObject(OCMKnownTestCaseMethods) +- (void)recordFailureWithDescription:(NSString *)description inFile:(NSString *)file atLine:(NSUInteger)line expected:(BOOL)expected; +- (void)failWithException:(NSException *)exception; +@end + + +#pragma mark Functions related to ObjC type system + +const char *OCMTypeWithoutQualifiers(const char *objCType) +{ + while(strchr("rnNoORV", objCType[0]) != NULL) + objCType += 1; + return objCType; +} + + +static BOOL OCMIsUnqualifiedClassType(const char *unqualifiedObjCType) +{ + return (strcmp(unqualifiedObjCType, @encode(Class)) == 0); +} + +BOOL OCMIsClassType(const char *objCType) +{ + return OCMIsUnqualifiedClassType(OCMTypeWithoutQualifiers(objCType)); +} + + +static BOOL OCMIsUnqualifiedBlockType(const char *unqualifiedObjCType) +{ + char blockType[] = @encode(void(^)()); + if(strcmp(unqualifiedObjCType, blockType) == 0) + return YES; + + // sometimes block argument/return types are tacked onto the type, in angle brackets + if(strncmp(unqualifiedObjCType, blockType, sizeof(blockType) - 1) == 0 && unqualifiedObjCType[sizeof(blockType) - 1] == '<') + return YES; + + return NO; +} + +BOOL OCMIsBlockType(const char *objCType) +{ + return OCMIsUnqualifiedBlockType(OCMTypeWithoutQualifiers(objCType)); +} + + +BOOL OCMIsObjectType(const char *objCType) +{ + const char *unqualifiedObjCType = OCMTypeWithoutQualifiers(objCType); + + char objectType[] = @encode(id); + if(strcmp(unqualifiedObjCType, objectType) == 0 || OCMIsUnqualifiedClassType(unqualifiedObjCType)) + return YES; + + // sometimes the name of an object's class is tacked onto the type, in double quotes + if(strncmp(unqualifiedObjCType, objectType, sizeof(objectType) - 1) == 0 && unqualifiedObjCType[sizeof(objectType) - 1] == '"') + return YES; + + // if the returnType is a typedef to an object, it has the form ^{OriginClass=#} + NSString *regexString = @"^\\^\\{(.*)=#.*\\}"; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:NULL]; + NSString *type = [NSString stringWithCString:unqualifiedObjCType encoding:NSASCIIStringEncoding]; + if([regex numberOfMatchesInString:type options:0 range:NSMakeRange(0, type.length)] > 0) + return YES; + + // if the return type is a block we treat it like an object + return OCMIsUnqualifiedBlockType(unqualifiedObjCType); +} + + +CFNumberType OCMNumberTypeForObjCType(const char *objcType) +{ + switch (objcType[0]) + { + case 'c': return kCFNumberCharType; + case 'C': return kCFNumberCharType; + case 'B': return kCFNumberCharType; + case 's': return kCFNumberShortType; + case 'S': return kCFNumberShortType; + case 'i': return kCFNumberIntType; + case 'I': return kCFNumberIntType; + case 'l': return kCFNumberLongType; + case 'L': return kCFNumberLongType; + case 'q': return kCFNumberLongLongType; + case 'Q': return kCFNumberLongLongType; + case 'f': return kCFNumberFloatType; + case 'd': return kCFNumberDoubleType; + default: return 0; + } +} + +/* + * Sometimes an external type is an opaque struct (which will have an @encode of "{structName}" + * or "{structName=}") but the actual method return type, or property type, will know the contents + * of the struct (so will have an objcType of say "{structName=iiSS}". This function will determine + * those are equal provided they have the same structure name, otherwise everything else will be + * compared textually. This can happen particularly for pointers to such structures, which still + * encode what is being pointed to. + * + * In addition, this funtion will consider structures with unknown names, encoded as "{?=}, equal to + * structures with any name. This means that "{?=dd}" and "{foo=dd}", and even "{?=}" and "{foo=dd}", + * are considered equal. + * + * For some types some runtime functions throw exceptions, which is why we wrap this in an + * exception handler just below. + */ +static BOOL OCMEqualTypesAllowingOpaqueStructsInternal(const char *type1, const char *type2) +{ + type1 = OCMTypeWithoutQualifiers(type1); + type2 = OCMTypeWithoutQualifiers(type2); + + switch (type1[0]) + { + case '{': + case '(': + { + if (type2[0] != type1[0]) + return NO; + char endChar = type1[0] == '{'? '}' : ')'; + + const char *type1End = strchr(type1, endChar); + const char *type2End = strchr(type2, endChar); + const char *type1Equals = strchr(type1, '='); + const char *type2Equals = strchr(type2, '='); + + /* Opaque types either don't have an equals sign (just the name and the end brace), or + * empty content after the equals sign. + * We want that to compare the same as a type of the same name but with the content. + */ + BOOL type1Opaque = (type1Equals == NULL || (type1End < type1Equals) || type1Equals[1] == endChar); + BOOL type2Opaque = (type2Equals == NULL || (type2End < type2Equals) || type2Equals[1] == endChar); + const char *type1NameEnd = (type1Equals == NULL || (type1End < type1Equals)) ? type1End : type1Equals; + const char *type2NameEnd = (type2Equals == NULL || (type2End < type2Equals)) ? type2End : type2Equals; + intptr_t type1NameLen = type1NameEnd - type1; + intptr_t type2NameLen = type2NameEnd - type2; + + /* If the names are not equal and neither of the names is a question mark, return NO */ + if ((type1NameLen != type2NameLen || strncmp(type1, type2, type1NameLen)) && + !((type1NameLen == 2) && (type1[1] == '?')) && !((type2NameLen == 2) && (type2[1] == '?'))) + return NO; + + /* If the same name, and at least one is opaque, that is close enough. */ + if (type1Opaque || type2Opaque) + return YES; + + /* Otherwise, compare all the elements. Use NSGetSizeAndAlignment to walk through the struct elements. */ + type1 = type1Equals + 1; + type2 = type2Equals + 1; + while (type1[0] != endChar && type1[0] != '\0') + { + if (!OCMEqualTypesAllowingOpaqueStructs(type1, type2)) + return NO; + type1 = NSGetSizeAndAlignment(type1, NULL, NULL); + type2 = NSGetSizeAndAlignment(type2, NULL, NULL); + } + return YES; + } + case '^': + /* for a pointer, make sure the other is a pointer, then recursively compare the rest */ + if (type2[0] != type1[0]) + return NO; + return OCMEqualTypesAllowingOpaqueStructs(type1 + 1, type2 + 1); + + case '?': + return type2[0] == '?'; + + case '\0': + return type2[0] == '\0'; + + default: + { + // Move the type pointers past the current types, then compare that region + const char *afterType1 = NSGetSizeAndAlignment(type1, NULL, NULL); + const char *afterType2 = NSGetSizeAndAlignment(type2, NULL, NULL); + intptr_t type1Len = afterType1 - type1; + intptr_t type2Len = afterType2 - type2; + + return (type1Len == type2Len && (strncmp(type1, type2, type1Len) == 0)); + } + } +} + +BOOL OCMEqualTypesAllowingOpaqueStructs(const char *type1, const char *type2) +{ + @try + { + return OCMEqualTypesAllowingOpaqueStructsInternal(type1, type2); + } + @catch (NSException *e) + { + /* Probably a bitfield or something that NSGetSizeAndAlignment chokes on, oh well */ + return NO; + } +} + + +#pragma mark Creating classes + +Class OCMCreateSubclass(Class class, void *ref) +{ + const char *className = [[NSString stringWithFormat:@"%@-%p-%u", NSStringFromClass(class), ref, arc4random()] UTF8String]; + Class subclass = objc_allocateClassPair(class, className, 0); + objc_registerClassPair(subclass); + return subclass; +} + + +#pragma mark Alias for renaming real methods + +static NSString *const OCMRealMethodAliasPrefix = @"ocmock_replaced_"; +static const char *const OCMRealMethodAliasPrefixCString = "ocmock_replaced_"; + +BOOL OCMIsAliasSelector(SEL selector) +{ + return [NSStringFromSelector(selector) hasPrefix:OCMRealMethodAliasPrefix]; +} + +SEL OCMAliasForOriginalSelector(SEL selector) +{ + char aliasName[2048]; + const char *originalName = sel_getName(selector); + strlcpy(aliasName, OCMRealMethodAliasPrefixCString, sizeof(aliasName)); + strlcat(aliasName, originalName, sizeof(aliasName)); + return sel_registerName(aliasName); +} + +SEL OCMOriginalSelectorForAlias(SEL selector) +{ + if(!OCMIsAliasSelector(selector)) + [NSException raise:NSInvalidArgumentException format:@"Not an alias selector; found %@", NSStringFromSelector(selector)]; + NSString *string = NSStringFromSelector(selector); + return NSSelectorFromString([string substringFromIndex:[OCMRealMethodAliasPrefix length]]); +} + + +#pragma mark Wrappers around associative references + +static NSString *const OCMClassMethodMockObjectKey = @"OCMClassMethodMockObjectKey"; + +void OCMSetAssociatedMockForClass(OCClassMockObject *mock, Class aClass) +{ + if((mock != nil) && (objc_getAssociatedObject(aClass, OCMClassMethodMockObjectKey) != nil)) + [NSException raise:NSInternalInconsistencyException format:@"Another mock is already associated with class %@", NSStringFromClass(aClass)]; + objc_setAssociatedObject(aClass, OCMClassMethodMockObjectKey, mock, OBJC_ASSOCIATION_ASSIGN); +} + +OCClassMockObject *OCMGetAssociatedMockForClass(Class aClass, BOOL includeSuperclasses) +{ + OCClassMockObject *mock = nil; + do + { + mock = objc_getAssociatedObject(aClass, OCMClassMethodMockObjectKey); + aClass = class_getSuperclass(aClass); + } + while((mock == nil) && (aClass != nil) && includeSuperclasses); + return mock; +} + +static NSString *const OCMPartialMockObjectKey = @"OCMPartialMockObjectKey"; + +void OCMSetAssociatedMockForObject(OCClassMockObject *mock, id anObject) +{ + if((mock != nil) && (objc_getAssociatedObject(anObject, OCMPartialMockObjectKey) != nil)) + [NSException raise:NSInternalInconsistencyException format:@"Another mock is already associated with object %@", anObject]; + objc_setAssociatedObject(anObject, OCMPartialMockObjectKey, mock, OBJC_ASSOCIATION_ASSIGN); +} + +OCPartialMockObject *OCMGetAssociatedMockForObject(id anObject) +{ + return objc_getAssociatedObject(anObject, OCMPartialMockObjectKey); +} + + +#pragma mark Functions related to IDE error reporting + +void OCMReportFailure(OCMLocation *loc, NSString *description) +{ + id testCase = [loc testCase]; + if((testCase != nil) && [testCase respondsToSelector:@selector(recordFailureWithDescription:inFile:atLine:expected:)]) + { + [testCase recordFailureWithDescription:description inFile:[loc file] atLine:[loc line] expected:NO]; + } + else if((testCase != nil) && [testCase respondsToSelector:@selector(failWithException:)]) + { + NSException *exception = nil; + if([NSException instancesRespondToSelector:@selector(failureInFile:atLine:withDescription:)]) + { + exception = [NSException failureInFile:[loc file] atLine:(int)[loc line] withDescription:description]; + } + else + { + NSString *reason = [NSString stringWithFormat:@"%@:%lu %@", [loc file], (unsigned long)[loc line], description]; + exception = [NSException exceptionWithName:@"OCMockTestFailure" reason:reason userInfo:nil]; + } + [testCase failWithException:exception]; + } + else if(loc != nil) + { + NSLog(@"%@:%lu %@", [loc file], (unsigned long)[loc line], description); + NSString *reason = [NSString stringWithFormat:@"%@:%lu %@", [loc file], (unsigned long)[loc line], description]; + [[NSException exceptionWithName:@"OCMockTestFailure" reason:reason userInfo:nil] raise]; + + } + else + { + NSLog(@"%@", description); + [[NSException exceptionWithName:@"OCMockTestFailure" reason:description userInfo:nil] raise]; + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctionsPrivate.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctionsPrivate.h new file mode 100644 index 0000000..1984c22 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMFunctionsPrivate.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@class OCMLocation; +@class OCClassMockObject; +@class OCPartialMockObject; + + +BOOL OCMIsClassType(const char *objCType); +BOOL OCMIsBlockType(const char *objCType); +BOOL OCMIsObjectType(const char *objCType); +const char *OCMTypeWithoutQualifiers(const char *objCType); +BOOL OCMEqualTypesAllowingOpaqueStructs(const char *type1, const char *type2); +CFNumberType OCMNumberTypeForObjCType(const char *objcType); + +Class OCMCreateSubclass(Class cls, void *ref); + +BOOL OCMIsAliasSelector(SEL selector); +SEL OCMAliasForOriginalSelector(SEL selector); +SEL OCMOriginalSelectorForAlias(SEL selector); + +void OCMSetAssociatedMockForClass(OCClassMockObject *mock, Class aClass); +OCClassMockObject *OCMGetAssociatedMockForClass(Class aClass, BOOL includeSuperclasses); + +void OCMSetAssociatedMockForObject(OCClassMockObject *mock, id anObject); +OCPartialMockObject *OCMGetAssociatedMockForObject(id anObject); + +void OCMReportFailure(OCMLocation *loc, NSString *description); diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMIndirectReturnValueProvider.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMIndirectReturnValueProvider.h new file mode 100644 index 0000000..a6cd759 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMIndirectReturnValueProvider.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMIndirectReturnValueProvider : NSObject +{ + id provider; + SEL selector; +} + +- (id)initWithProvider:(id)aProvider andSelector:(SEL)aSelector; + +- (void)handleInvocation:(NSInvocation *)anInvocation; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMIndirectReturnValueProvider.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMIndirectReturnValueProvider.m new file mode 100644 index 0000000..b7c07a0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMIndirectReturnValueProvider.m @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "NSMethodSignature+OCMAdditions.h" +#import "OCMIndirectReturnValueProvider.h" +#import "NSInvocation+OCMAdditions.h" + + +@implementation OCMIndirectReturnValueProvider + +- (id)initWithProvider:(id)aProvider andSelector:(SEL)aSelector +{ + if ((self = [super init])) + { + provider = [aProvider retain]; + selector = aSelector; + } + + return self; +} + +- (void)dealloc +{ + [provider release]; + [super dealloc]; +} + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + id originalTarget = [anInvocation target]; + SEL originalSelector = [anInvocation selector]; + + [anInvocation setTarget:provider]; + [anInvocation setSelector:selector]; + [anInvocation invoke]; + + [anInvocation setTarget:originalTarget]; + [anInvocation setSelector:originalSelector]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationExpectation.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationExpectation.h new file mode 100644 index 0000000..5a65719 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationExpectation.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMInvocationStub.h" + +@interface OCMInvocationExpectation : OCMInvocationStub +{ + BOOL matchAndReject; + BOOL isSatisfied; +} + +- (void)setMatchAndReject:(BOOL)flag; +- (BOOL)isMatchAndReject; + +- (BOOL)isSatisfied; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationExpectation.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationExpectation.m new file mode 100644 index 0000000..a6846d9 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationExpectation.m @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMInvocationExpectation.h" +#import "NSInvocation+OCMAdditions.h" + + +@implementation OCMInvocationExpectation + +- (void)setMatchAndReject:(BOOL)flag +{ + matchAndReject = flag; + if(matchAndReject) + isSatisfied = YES; +} + +- (BOOL)isMatchAndReject +{ + return matchAndReject; +} + +- (BOOL)isSatisfied +{ + return isSatisfied; +} + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + [super handleInvocation:anInvocation]; + + if(matchAndReject) + { + isSatisfied = NO; + [NSException raise:NSInternalInconsistencyException format:@"%@: explicitly disallowed method invoked: %@", + [self description], [anInvocation invocationDescription]]; + } + else + { + isSatisfied = YES; + } +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationMatcher.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationMatcher.h new file mode 100644 index 0000000..460b95a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationMatcher.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMInvocationMatcher : NSObject +{ + NSInvocation *recordedInvocation; + BOOL recordedAsClassMethod; + BOOL ignoreNonObjectArgs; +} + +- (void)setInvocation:(NSInvocation *)anInvocation; +- (NSInvocation *)recordedInvocation; + +- (void)setRecordedAsClassMethod:(BOOL)flag; +- (BOOL)recordedAsClassMethod; + +- (void)setIgnoreNonObjectArgs:(BOOL)flag; + +- (BOOL)matchesSelector:(SEL)aSelector; +- (BOOL)matchesInvocation:(NSInvocation *)anInvocation; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationMatcher.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationMatcher.m new file mode 100644 index 0000000..56ed3b9 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationMatcher.m @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import +#import +#import "OCMPassByRefSetter.h" +#import "NSInvocation+OCMAdditions.h" +#import "OCMInvocationMatcher.h" +#import "OCClassMockObject.h" +#import "OCMFunctionsPrivate.h" +#import "OCMBlockArgCaller.h" + + +@interface NSObject(HCMatcherDummy) +- (BOOL)matches:(id)item; +@end + + +@implementation OCMInvocationMatcher + +- (void)dealloc +{ + [recordedInvocation release]; + [super dealloc]; +} + +- (void)setInvocation:(NSInvocation *)anInvocation +{ + [recordedInvocation release]; + // Don't do a regular -retainArguments on the invocation that we use for matching. NSInvocation + // effectively does an strcpy on char* arguments which messes up matching them literally and blows + // up with anyPointer (in strlen since it's not actually a C string). Also on the off-chance that + // anInvocation contains self as an argument, -retainArguments would create a retain cycle. + [anInvocation retainObjectArgumentsExcludingObject:self]; + recordedInvocation = [anInvocation retain]; +} + +- (void)setRecordedAsClassMethod:(BOOL)flag +{ + recordedAsClassMethod = flag; +} + +- (BOOL)recordedAsClassMethod +{ + return recordedAsClassMethod; +} + +- (void)setIgnoreNonObjectArgs:(BOOL)flag +{ + ignoreNonObjectArgs = flag; +} + +- (NSString *)description +{ + return [recordedInvocation invocationDescription]; +} + +- (NSInvocation *)recordedInvocation +{ + return recordedInvocation; +} + +- (BOOL)matchesSelector:(SEL)sel +{ + if(sel == [recordedInvocation selector]) + return YES; + if(OCMIsAliasSelector(sel) && + OCMOriginalSelectorForAlias(sel) == [recordedInvocation selector]) + return YES; + + return NO; +} + +- (BOOL)matchesInvocation:(NSInvocation *)anInvocation +{ + id target = [anInvocation target]; + BOOL isClassMethodInvocation = (target != nil) && (target == [target class]); + if(isClassMethodInvocation != recordedAsClassMethod) + return NO; + + if(![self matchesSelector:[anInvocation selector]]) + return NO; + + NSMethodSignature *signature = [recordedInvocation methodSignature]; + NSUInteger n = [signature numberOfArguments]; + for(NSUInteger i = 2; i < n; i++) + { + if(ignoreNonObjectArgs && !OCMIsObjectType([signature getArgumentTypeAtIndex:i])) + { + continue; + } + + id recordedArg = [recordedInvocation getArgumentAtIndexAsObject:i]; + id passedArg = [anInvocation getArgumentAtIndexAsObject:i]; + + if([recordedArg isProxy]) + { + if(![recordedArg isEqual:passedArg]) + return NO; + continue; + } + + if([recordedArg isKindOfClass:[NSValue class]]) + recordedArg = [OCMArg resolveSpecialValues:recordedArg]; + + if([recordedArg isKindOfClass:[OCMConstraint class]]) + { + if([recordedArg evaluate:passedArg] == NO) + return NO; + } + else if([recordedArg isKindOfClass:[OCMArgAction class]]) + { + // ignore, will be dealt with in handleInvocation: where applicable + } + else if([recordedArg conformsToProtocol:objc_getProtocol("HCMatcher")]) + { + if([recordedArg matches:passedArg] == NO) + return NO; + } + else + { + if(([recordedArg class] == [NSNumber class]) && + ([(NSNumber*)recordedArg compare:(NSNumber*)passedArg] != NSOrderedSame)) + return NO; + if(([recordedArg isEqual:passedArg] == NO) && + !((recordedArg == nil) && (passedArg == nil))) + return NO; + } + } + return YES; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationStub.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationStub.h new file mode 100644 index 0000000..987f31f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationStub.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMInvocationMatcher.h" + +@interface OCMInvocationStub : OCMInvocationMatcher +{ + NSMutableArray *invocationActions; +} + +- (void)addInvocationAction:(id)anAction; +- (NSArray *)invocationActions; + +- (void)handleInvocation:(NSInvocation *)anInvocation; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationStub.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationStub.m new file mode 100644 index 0000000..3c260be --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMInvocationStub.m @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMInvocationStub.h" +#import "OCMFunctionsPrivate.h" +#import "OCMArg.h" +#import "OCMArgAction.h" +#import "NSInvocation+OCMAdditions.h" + +@implementation OCMInvocationStub + +- (id)init +{ + self = [super init]; + invocationActions = [[NSMutableArray alloc] init]; + return self; +} + +- (void)dealloc +{ + [invocationActions release]; + [super dealloc]; +} + + +- (void)addInvocationAction:(id)anAction +{ + [invocationActions addObject:anAction]; +} + +- (NSArray *)invocationActions +{ + return invocationActions; +} + + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + NSMethodSignature *signature = [recordedInvocation methodSignature]; + NSUInteger n = [signature numberOfArguments]; + for(NSUInteger i = 2; i < n; i++) + { + id recordedArg = [recordedInvocation getArgumentAtIndexAsObject:i]; + id passedArg = [anInvocation getArgumentAtIndexAsObject:i]; + + if([recordedArg isProxy]) + continue; + + if([recordedArg isKindOfClass:[NSValue class]]) + recordedArg = [OCMArg resolveSpecialValues:recordedArg]; + + if(![recordedArg isKindOfClass:[OCMArgAction class]]) + continue; + + [recordedArg handleArgument:passedArg]; + } + + [invocationActions makeObjectsPerformSelector:@selector(handleInvocation:) withObject:anInvocation]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMLocation.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMLocation.h new file mode 100644 index 0000000..7870c52 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMLocation.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCMFunctions.h" + + +@interface OCMLocation : NSObject +{ + id testCase; + NSString *file; + NSUInteger line; +} + ++ (instancetype)locationWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine; + +- (instancetype)initWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine; + +- (id)testCase; +- (NSString *)file; +- (NSUInteger)line; + +@end + +OCMOCK_EXTERN OCMLocation *OCMMakeLocation(id testCase, const char *file, int line); diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMLocation.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMLocation.m new file mode 100644 index 0000000..59ca3bd --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMLocation.m @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMLocation.h" + +@implementation OCMLocation + ++ (instancetype)locationWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine +{ + return [[[OCMLocation alloc] initWithTestCase:aTestCase file:aFile line:aLine] autorelease]; +} + +- (instancetype)initWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine +{ + if ((self = [super init])) + { + testCase = aTestCase; + file = [aFile retain]; + line = aLine; + } + + return self; +} + +- (void)dealloc +{ + [file release]; + [super dealloc]; +} + +- (id)testCase +{ + return testCase; +} + +- (NSString *)file +{ + return file; +} + +- (NSUInteger)line +{ + return line; +} + +@end + + +OCMLocation *OCMMakeLocation(id testCase, const char *fileCString, int line) +{ + return [OCMLocation locationWithTestCase:testCase file:[NSString stringWithUTF8String:fileCString] line:line]; +} + diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMMacroState.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMMacroState.h new file mode 100644 index 0000000..dba41be --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMMacroState.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@class OCMLocation; +@class OCMRecorder; +@class OCMStubRecorder; +@class OCMockObject; + + +@interface OCMMacroState : NSObject +{ + OCMRecorder *recorder; +} + ++ (void)beginStubMacro; ++ (OCMStubRecorder *)endStubMacro; + ++ (void)beginExpectMacro; ++ (OCMStubRecorder *)endExpectMacro; + ++ (void)beginRejectMacro; ++ (OCMStubRecorder *)endRejectMacro; + ++ (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation; ++ (void)endVerifyMacro; + ++ (OCMMacroState *)globalState; + +- (OCMRecorder *)recorder; + +- (void)switchToClassMethod; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMMacroState.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMMacroState.m new file mode 100644 index 0000000..d50873b --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMMacroState.m @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMMacroState.h" +#import "OCMStubRecorder.h" +#import "OCMockObject.h" +#import "OCMExpectationRecorder.h" +#import "OCMVerifier.h" +#import "OCMInvocationMatcher.h" + + +@implementation OCMMacroState + +static NSString *const OCMGlobalStateKey = @"OCMGlobalStateKey"; + +#pragma mark Methods to begin/end macros + ++ (void)beginStubMacro +{ + OCMStubRecorder *recorder = [[[OCMStubRecorder alloc] init] autorelease]; + OCMMacroState *macroState = [[OCMMacroState alloc] initWithRecorder:recorder]; + [NSThread currentThread].threadDictionary[OCMGlobalStateKey] = macroState; + [macroState release]; +} + ++ (OCMStubRecorder *)endStubMacro +{ + NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; + OCMMacroState *globalState = threadDictionary[OCMGlobalStateKey]; + OCMStubRecorder *recorder = [(OCMStubRecorder *)[globalState recorder] retain]; + [threadDictionary removeObjectForKey:OCMGlobalStateKey]; + return [recorder autorelease]; +} + + ++ (void)beginExpectMacro +{ + OCMExpectationRecorder *recorder = [[[OCMExpectationRecorder alloc] init] autorelease]; + OCMMacroState *macroState = [[OCMMacroState alloc] initWithRecorder:recorder]; + [NSThread currentThread].threadDictionary[OCMGlobalStateKey] = macroState; + [macroState release]; +} + ++ (OCMStubRecorder *)endExpectMacro +{ + return [self endStubMacro]; +} + + ++ (void)beginRejectMacro +{ + OCMExpectationRecorder *recorder = [[[OCMExpectationRecorder alloc] init] autorelease]; + [recorder never]; + OCMMacroState *macroState = [[OCMMacroState alloc] initWithRecorder:recorder]; + [NSThread currentThread].threadDictionary[OCMGlobalStateKey] = macroState; + [macroState release]; +} + ++ (OCMStubRecorder *)endRejectMacro +{ + return [self endStubMacro]; +} + + ++ (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation +{ + OCMVerifier *recorder = [[[OCMVerifier alloc] init] autorelease]; + [recorder setLocation:aLocation]; + OCMMacroState *macroState = [[OCMMacroState alloc] initWithRecorder:recorder]; + [NSThread currentThread].threadDictionary[OCMGlobalStateKey] = macroState; + [macroState release]; +} + ++ (void)endVerifyMacro +{ + [[NSThread currentThread].threadDictionary removeObjectForKey:OCMGlobalStateKey]; +} + + +#pragma mark Accessing global state + ++ (OCMMacroState *)globalState +{ + return [NSThread currentThread].threadDictionary[OCMGlobalStateKey]; +} + + +#pragma mark Init, dealloc, accessors + +- (id)initWithRecorder:(OCMRecorder *)aRecorder +{ + if ((self = [super init])) + { + recorder = [aRecorder retain]; + } + + return self; +} + +- (void)dealloc +{ + [recorder release]; + NSAssert([NSThread currentThread].threadDictionary[OCMGlobalStateKey] != self, @"Unexpected dealloc while set as the global state"); + [super dealloc]; +} + +- (OCMRecorder *)recorder +{ + return recorder; +} + + +#pragma mark Changing the recorder + +- (void)switchToClassMethod +{ + [recorder classMethod]; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMNotificationPoster.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMNotificationPoster.h new file mode 100644 index 0000000..40564b4 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMNotificationPoster.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMNotificationPoster : NSObject +{ + NSNotification *notification; +} + +- (id)initWithNotification:(id)aNotification; + +- (void)handleInvocation:(NSInvocation *)anInvocation; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMNotificationPoster.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMNotificationPoster.m new file mode 100644 index 0000000..0753b27 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMNotificationPoster.m @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMNotificationPoster.h" + + +@implementation OCMNotificationPoster + +- (id)initWithNotification:(id)aNotification +{ + if ((self = [super init])) + { + notification = [aNotification retain]; + } + + return self; +} + +- (void)dealloc +{ + [notification release]; + [super dealloc]; +} + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + [[NSNotificationCenter defaultCenter] postNotification:notification]; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMObserverRecorder.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMObserverRecorder.h new file mode 100644 index 0000000..a6ae5bf --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMObserverRecorder.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMObserverRecorder : NSObject +{ + NSNotification *recordedNotification; +} + +- (NSNotification *)notificationWithName:(NSString *)name object:(id)sender; + +- (NSNotification *)notificationWithName:(NSString *)name object:(id)sender userInfo:(NSDictionary *)userInfo; + +- (BOOL)matchesNotification:(NSNotification *)aNotification; + +- (BOOL)argument:(id)expectedArg matchesArgument:(id)observedArg; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMObserverRecorder.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMObserverRecorder.m new file mode 100644 index 0000000..921c0ec --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMObserverRecorder.m @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import +#import "NSInvocation+OCMAdditions.h" +#import "OCMObserverRecorder.h" + +@interface NSObject(HCMatcherDummy) +- (BOOL)matches:(id)item; +@end + +#pragma mark - + + +@implementation OCMObserverRecorder + +#pragma mark Initialisers, description, accessors, etc. + +- (void)dealloc +{ + [recordedNotification release]; + [super dealloc]; +} + + +#pragma mark Recording + +- (NSNotification *)notificationWithName:(NSString *)name object:(id)sender +{ + recordedNotification = [[NSNotification notificationWithName:name object:sender] retain]; + return nil; +} + +- (NSNotification *)notificationWithName:(NSString *)name object:(id)sender userInfo:(NSDictionary *)userInfo +{ + recordedNotification = [[NSNotification notificationWithName:name object:sender userInfo:userInfo] retain]; + return nil; +} + + +#pragma mark Verification + +- (BOOL)matchesNotification:(NSNotification *)aNotification +{ + return [self argument:[recordedNotification name] matchesArgument:[aNotification name]] && + [self argument:[recordedNotification object] matchesArgument:[aNotification object]] && + [self argument:[recordedNotification userInfo] matchesArgument:[aNotification userInfo]]; +} + +- (BOOL)argument:(id)expectedArg matchesArgument:(id)observedArg +{ + if([expectedArg isKindOfClass:[OCMConstraint class]]) + { + return [expectedArg evaluate:observedArg]; + } + else if([expectedArg conformsToProtocol:objc_getProtocol("HCMatcher")]) + { + return [expectedArg matches:observedArg]; + } + else if (expectedArg == observedArg) + { + return YES; + } + else if (expectedArg == nil || observedArg == nil) + { + return NO; + } + else + { + return [expectedArg isEqual:observedArg]; + } +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMPassByRefSetter.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMPassByRefSetter.h new file mode 100644 index 0000000..bd0d546 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMPassByRefSetter.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMArgAction.h" + +@interface OCMPassByRefSetter : OCMArgAction +{ + id value; +} + +- (id)initWithValue:(id)value; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMPassByRefSetter.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMPassByRefSetter.m new file mode 100644 index 0000000..2714141 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMPassByRefSetter.m @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMPassByRefSetter.h" + + +@implementation OCMPassByRefSetter + +- (id)initWithValue:(id)aValue +{ + if ((self = [super init])) + { + value = [aValue retain]; + } + + return self; +} + +- (void)dealloc +{ + [value release]; + [super dealloc]; +} + +- (void)handleArgument:(id)arg +{ + void *pointerValue = [arg pointerValue]; + if(pointerValue != NULL) + { + if([value isKindOfClass:[NSValue class]]) + [(NSValue *)value getValue:pointerValue]; + else + *(id *)pointerValue = value; + } +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRealObjectForwarder.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRealObjectForwarder.h new file mode 100644 index 0000000..92485f1 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRealObjectForwarder.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMRealObjectForwarder : NSObject +{ +} + +- (void)handleInvocation:(NSInvocation *)anInvocation; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRealObjectForwarder.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRealObjectForwarder.m new file mode 100644 index 0000000..c081a27 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRealObjectForwarder.m @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCPartialMockObject.h" +#import "OCMRealObjectForwarder.h" +#import "OCMFunctionsPrivate.h" + + +@implementation OCMRealObjectForwarder + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + id invocationTarget = [anInvocation target]; + + [anInvocation setSelector:OCMAliasForOriginalSelector([anInvocation selector])]; + if ([invocationTarget isProxy]) + { + if (class_getInstanceMethod([invocationTarget mockObjectClass], @selector(realObject))) + { + // the method has been invoked on the mock, we need to change the target to the real object + [anInvocation setTarget:[(OCPartialMockObject *)invocationTarget realObject]]; + } + else + { + [NSException raise:NSInternalInconsistencyException + format:@"Method andForwardToRealObject can only be used with partial mocks and class methods."]; + } + } + + [anInvocation invoke]; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRecorder.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRecorder.h new file mode 100644 index 0000000..9670d08 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRecorder.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@class OCMockObject; +@class OCMInvocationMatcher; + + +@interface OCMRecorder : NSProxy +{ + OCMockObject *mockObject; + OCMInvocationMatcher *invocationMatcher; +} + +- (instancetype)init; +- (instancetype)initWithMockObject:(OCMockObject *)aMockObject; + +- (void)setMockObject:(OCMockObject *)aMockObject; + +- (OCMInvocationMatcher *)invocationMatcher; + +- (id)classMethod; +- (id)ignoringNonObjectArgs; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRecorder.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRecorder.m new file mode 100644 index 0000000..273563a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMRecorder.m @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCMRecorder.h" +#import "OCMockObject.h" +#import "OCMInvocationMatcher.h" +#import "OCClassMockObject.h" + +@implementation OCMRecorder + +- (instancetype)init +{ + // no super, we're inheriting from NSProxy + return self; +} + +- (instancetype)initWithMockObject:(OCMockObject *)aMockObject +{ + [self init]; + [self setMockObject:aMockObject]; + return self; +} + +- (void)setMockObject:(OCMockObject *)aMockObject +{ + mockObject = aMockObject; +} + +- (void)dealloc +{ + [invocationMatcher release]; + [super dealloc]; +} + +- (NSString *)description +{ + return [invocationMatcher description]; +} + +- (OCMInvocationMatcher *)invocationMatcher +{ + return invocationMatcher; +} + + +#pragma mark Modifying the matcher + +- (id)classMethod +{ + // should we handle the case where this is called with a mock that isn't a class mock? + [invocationMatcher setRecordedAsClassMethod:YES]; + return self; +} + +- (id)ignoringNonObjectArgs +{ + [invocationMatcher setIgnoreNonObjectArgs:YES]; + return self; +} + + +#pragma mark Recording the actual invocation + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + if([invocationMatcher recordedAsClassMethod]) + return [[(OCClassMockObject *)mockObject mockedClass] methodSignatureForSelector:aSelector]; + + NSMethodSignature *signature = [mockObject methodSignatureForSelector:aSelector]; + if(signature == nil) + { + // if we're a working with a class mock and there is a class method, auto-switch + if(([object_getClass(mockObject) isSubclassOfClass:[OCClassMockObject class]]) && + ([[(OCClassMockObject *)mockObject mockedClass] respondsToSelector:aSelector])) + { + [self classMethod]; + signature = [self methodSignatureForSelector:aSelector]; + } + } + return signature; +} + +- (void)forwardInvocation:(NSInvocation *)anInvocation +{ + [anInvocation setTarget:nil]; + [invocationMatcher setInvocation:anInvocation]; +} + +- (void)doesNotRecognizeSelector:(SEL)aSelector +{ + [NSException raise:NSInvalidArgumentException format:@"%@: cannot stub/expect/verify method '%@' because no such method exists in the mocked class.", mockObject, NSStringFromSelector(aSelector)]; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMReturnValueProvider.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMReturnValueProvider.h new file mode 100644 index 0000000..673b40f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMReturnValueProvider.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCMReturnValueProvider : NSObject +{ + id returnValue; +} + +- (instancetype)initWithValue:(id)aValue; + +- (void)handleInvocation:(NSInvocation *)anInvocation; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMReturnValueProvider.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMReturnValueProvider.m new file mode 100644 index 0000000..ed8dfec --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMReturnValueProvider.m @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "NSMethodSignature+OCMAdditions.h" +#import "OCMReturnValueProvider.h" +#import "OCMFunctions.h" + + +@implementation OCMReturnValueProvider + +- (instancetype)initWithValue:(id)aValue +{ + if ((self = [super init])) + { + returnValue = [aValue retain]; + } + + return self; +} + +- (void)dealloc +{ + [returnValue release]; + [super dealloc]; +} + +- (void)handleInvocation:(NSInvocation *)anInvocation +{ + if(!OCMIsObjectType([[anInvocation methodSignature] methodReturnType])) + { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Expected invocation with object return type. Did you mean to use andReturnValue: instead?" userInfo:nil]; + } + NSString *sel = NSStringFromSelector([anInvocation selector]); + if([sel hasPrefix:@"alloc"] || [sel hasPrefix:@"new"] || [sel hasPrefix:@"copy"] || [sel hasPrefix:@"mutableCopy"]) + { + // methods that "create" an object return it with an extra retain count + [returnValue retain]; + } + [anInvocation setReturnValue:&returnValue]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMStubRecorder.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMStubRecorder.h new file mode 100644 index 0000000..e32029f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMStubRecorder.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import +#import + +@interface OCMStubRecorder : OCMRecorder + +- (id)andReturn:(id)anObject; +- (id)andReturnValue:(NSValue *)aValue; +- (id)andThrow:(NSException *)anException; +- (id)andPost:(NSNotification *)aNotification; +- (id)andCall:(SEL)selector onObject:(id)anObject; +- (id)andDo:(void (^)(NSInvocation *invocation))block; +- (id)andForwardToRealObject; + +@end + + +@interface OCMStubRecorder (Properties) + +#define andReturn(aValue) _andReturn(({ \ + __typeof__(aValue) _val = (aValue); \ + NSValue *_nsval = [NSValue value:&_val withObjCType:@encode(__typeof__(_val))]; \ + if (OCMIsObjectType(@encode(__typeof(_val)))) { \ + objc_setAssociatedObject(_nsval, "OCMAssociatedBoxedValue", *(__unsafe_unretained id *) (void *) &_val, OBJC_ASSOCIATION_RETAIN); \ + } \ + _nsval; \ +})) +@property (nonatomic, readonly) OCMStubRecorder *(^ _andReturn)(NSValue *); + +#define andThrow(anException) _andThrow(anException) +@property (nonatomic, readonly) OCMStubRecorder *(^ _andThrow)(NSException *); + +#define andPost(aNotification) _andPost(aNotification) +@property (nonatomic, readonly) OCMStubRecorder *(^ _andPost)(NSNotification *); + +#define andCall(anObject, aSelector) _andCall(anObject, aSelector) +@property (nonatomic, readonly) OCMStubRecorder *(^ _andCall)(id, SEL); + +#define andDo(aBlock) _andDo(aBlock) +@property (nonatomic, readonly) OCMStubRecorder *(^ _andDo)(void (^)(NSInvocation *)); + +#define andForwardToRealObject() _andForwardToRealObject() +@property (nonatomic, readonly) OCMStubRecorder *(^ _andForwardToRealObject)(void); + +@end + + + diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMStubRecorder.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMStubRecorder.m new file mode 100644 index 0000000..537f6e3 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMStubRecorder.m @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2004-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMStubRecorder.h" +#import "OCClassMockObject.h" +#import "OCMReturnValueProvider.h" +#import "OCMBoxedReturnValueProvider.h" +#import "OCMExceptionReturnValueProvider.h" +#import "OCMIndirectReturnValueProvider.h" +#import "OCMNotificationPoster.h" +#import "OCMBlockCaller.h" +#import "OCMRealObjectForwarder.h" +#import "OCMFunctions.h" +#import "OCMInvocationStub.h" + + +@implementation OCMStubRecorder + +#pragma mark Initialisers, description, accessors, etc. + +- (id)init +{ + if(invocationMatcher != nil) + [NSException raise:NSInternalInconsistencyException format:@"** Method init invoked twice on stub recorder. Are you trying to mock the init method? This is currently not supported."]; + + self = [super init]; + invocationMatcher = [[OCMInvocationStub alloc] init]; + return self; +} + +- (OCMInvocationStub *)stub +{ + return (OCMInvocationStub *)invocationMatcher; +} + + +#pragma mark Recording invocation actions + +- (id)andReturn:(id)anObject +{ + [[self stub] addInvocationAction:[[[OCMReturnValueProvider alloc] initWithValue:anObject] autorelease]]; + return self; +} + +- (id)andReturnValue:(NSValue *)aValue +{ + [[self stub] addInvocationAction:[[[OCMBoxedReturnValueProvider alloc] initWithValue:aValue] autorelease]]; + return self; +} + +- (id)andThrow:(NSException *)anException +{ + [[self stub] addInvocationAction:[[[OCMExceptionReturnValueProvider alloc] initWithValue:anException] autorelease]]; + return self; +} + +- (id)andPost:(NSNotification *)aNotification +{ + [[self stub] addInvocationAction:[[[OCMNotificationPoster alloc] initWithNotification:aNotification] autorelease]]; + return self; +} + +- (id)andCall:(SEL)selector onObject:(id)anObject +{ + [[self stub] addInvocationAction:[[[OCMIndirectReturnValueProvider alloc] initWithProvider:anObject andSelector:selector] autorelease]]; + return self; +} + +- (id)andDo:(void (^)(NSInvocation *))aBlock +{ + [[self stub] addInvocationAction:[[[OCMBlockCaller alloc] initWithCallBlock:aBlock] autorelease]]; + return self; +} + +- (id)andForwardToRealObject +{ + [[self stub] addInvocationAction:[[[OCMRealObjectForwarder alloc] init] autorelease]]; + return self; +} + + +#pragma mark Finishing recording + +- (void)forwardInvocation:(NSInvocation *)anInvocation +{ + [super forwardInvocation:anInvocation]; + [mockObject addStub:[self stub]]; +} + + +@end + + +@implementation OCMStubRecorder (Properties) + +@dynamic _andReturn; + +- (OCMStubRecorder *(^)(NSValue *))_andReturn +{ + id (^theBlock)(id) = ^ (NSValue *aValue) + { + if(OCMIsObjectType([aValue objCType])) + { + NSValue *objValue = nil; + [aValue getValue:&objValue]; + return [self andReturn:objValue]; + } + else + { + return [self andReturnValue:aValue]; + } + }; + return [[theBlock copy] autorelease]; +} + + +@dynamic _andThrow; + +- (OCMStubRecorder *(^)(NSException *))_andThrow +{ + id (^theBlock)(id) = ^ (NSException * anException) + { + return [self andThrow:anException]; + }; + return [[theBlock copy] autorelease]; +} + + +@dynamic _andPost; + +- (OCMStubRecorder *(^)(NSNotification *))_andPost +{ + id (^theBlock)(id) = ^ (NSNotification * aNotification) + { + return [self andPost:aNotification]; + }; + return [[theBlock copy] autorelease]; +} + + +@dynamic _andCall; + +- (OCMStubRecorder *(^)(id, SEL))_andCall +{ + id (^theBlock)(id, SEL) = ^ (id anObject, SEL aSelector) + { + return [self andCall:aSelector onObject:anObject]; + }; + return [[theBlock copy] autorelease]; +} + + +@dynamic _andDo; + +- (OCMStubRecorder *(^)(void (^)(NSInvocation *)))_andDo +{ + id (^theBlock)(void (^)(NSInvocation *)) = ^ (void (^ blockToCall)(NSInvocation *)) + { + return [self andDo:blockToCall]; + }; + return [[theBlock copy] autorelease]; +} + + +@dynamic _andForwardToRealObject; + +- (OCMStubRecorder *(^)(void))_andForwardToRealObject +{ + id (^theBlock)(void) = ^ (void) + { + return [self andForwardToRealObject]; + }; + return [[theBlock copy] autorelease]; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMVerifier.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMVerifier.h new file mode 100644 index 0000000..3fda12e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMVerifier.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCMRecorder.h" +#import "OCMLocation.h" + + +@interface OCMVerifier : OCMRecorder + +@property(retain) OCMLocation *location; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMVerifier.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMVerifier.m new file mode 100644 index 0000000..0d07a76 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMVerifier.m @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCMVerifier.h" +#import "OCMockObject.h" +#import "OCMLocation.h" +#import "OCMInvocationMatcher.h" + + +@implementation OCMVerifier + +- (id)init +{ + if ((self = [super init])) + { + invocationMatcher = [[OCMInvocationMatcher alloc] init]; + } + + return self; +} + +- (void)forwardInvocation:(NSInvocation *)anInvocation +{ + [super forwardInvocation:anInvocation]; + [mockObject verifyInvocation:invocationMatcher atLocation:self.location]; +} + +- (void)dealloc +{ + [_location release]; + [super dealloc]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMock.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMock.h new file mode 100644 index 0000000..9d55813 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMock.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +#define OCMClassMock(cls) [OCMockObject niceMockForClass:cls] + +#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls] + +#define OCMProtocolMock(protocol) [OCMockObject niceMockForProtocol:protocol] + +#define OCMStrictProtocolMock(protocol) [OCMockObject mockForProtocol:protocol] + +#define OCMPartialMock(obj) [OCMockObject partialMockForObject:obj] + +#define OCMObserverMock() [OCMockObject observerMock] + + +#define OCMStub(invocation) \ +({ \ + _OCMSilenceWarnings( \ + [OCMMacroState beginStubMacro]; \ + OCMStubRecorder *recorder = nil; \ + @try{ \ + invocation; \ + }@finally{ \ + recorder = [OCMMacroState endStubMacro]; \ + } \ + recorder; \ + ); \ +}) + +#define OCMExpect(invocation) \ +({ \ + _OCMSilenceWarnings( \ + [OCMMacroState beginExpectMacro]; \ + OCMStubRecorder *recorder = nil; \ + @try{ \ + invocation; \ + }@finally{ \ + recorder = [OCMMacroState endExpectMacro]; \ + } \ + recorder; \ + ); \ +}) + +#define OCMReject(invocation) \ +({ \ + _OCMSilenceWarnings( \ + [OCMMacroState beginRejectMacro]; \ + OCMStubRecorder *recorder = nil; \ + @try{ \ + invocation; \ + }@finally{ \ + recorder = [OCMMacroState endRejectMacro]; \ + } \ + recorder; \ + ); \ +}) + +#define ClassMethod(invocation) \ + _OCMSilenceWarnings( \ + [[OCMMacroState globalState] switchToClassMethod]; \ + invocation; \ + ); + + +#define OCMVerifyAll(mock) [mock verifyAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)] + +#define OCMVerifyAllWithDelay(mock, delay) [mock verifyWithDelay:delay atLocation:OCMMakeLocation(self, __FILE__, __LINE__)] + +#define OCMVerify(invocation) \ +({ \ + _OCMSilenceWarnings( \ + [OCMMacroState beginVerifyMacroAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]; \ + @try{ \ + invocation; \ + }@finally{ \ + [OCMMacroState endVerifyMacro]; \ + } \ + ); \ +}) + +#define _OCMSilenceWarnings(macro) \ +({ \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunused-value\"") \ + _Pragma("clang diagnostic ignored \"-Wunused-getter-return-value\"") \ + macro \ + _Pragma("clang diagnostic pop") \ +}) diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMockObject.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMockObject.h new file mode 100644 index 0000000..31f7ac4 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMockObject.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@class OCMLocation; +@class OCMInvocationStub; +@class OCMStubRecorder; +@class OCMInvocationMatcher; +@class OCMInvocationExpectation; + + +@interface OCMockObject : NSProxy +{ + BOOL isNice; + BOOL expectationOrderMatters; + NSMutableArray *stubs; + NSMutableArray *expectations; + NSMutableArray *exceptions; + NSMutableArray *invocations; +} + ++ (id)mockForClass:(Class)aClass; ++ (id)mockForProtocol:(Protocol *)aProtocol; ++ (id)partialMockForObject:(NSObject *)anObject; + ++ (id)niceMockForClass:(Class)aClass; ++ (id)niceMockForProtocol:(Protocol *)aProtocol; + ++ (id)observerMock; + +- (instancetype)init; + +- (void)setExpectationOrderMatters:(BOOL)flag; + +- (id)stub; +- (id)expect; +- (id)reject; + +- (id)verify; +- (id)verifyAtLocation:(OCMLocation *)location; + +- (void)verifyWithDelay:(NSTimeInterval)delay; +- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location; + +- (void)stopMocking; + +// internal use only + +- (void)addStub:(OCMInvocationStub *)aStub; +- (void)addExpectation:(OCMInvocationExpectation *)anExpectation; + +- (BOOL)handleInvocation:(NSInvocation *)anInvocation; +- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation; +- (BOOL)handleSelector:(SEL)sel; + +- (void)verifyInvocation:(OCMInvocationMatcher *)matcher; +- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location; + +@end + diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMockObject.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMockObject.m new file mode 100644 index 0000000..b3e3873 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCMockObject.m @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2004-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCClassMockObject.h" +#import "OCProtocolMockObject.h" +#import "OCPartialMockObject.h" +#import "OCObserverMockObject.h" +#import "OCMStubRecorder.h" +#import +#import "NSInvocation+OCMAdditions.h" +#import "OCMInvocationMatcher.h" +#import "OCMMacroState.h" +#import "OCMFunctionsPrivate.h" +#import "OCMVerifier.h" +#import "OCMInvocationExpectation.h" +#import "OCMExceptionReturnValueProvider.h" +#import "OCMExpectationRecorder.h" + + +@implementation OCMockObject + +#pragma mark Class initialisation + ++ (void)initialize +{ + if([[NSInvocation class] instanceMethodSignatureForSelector:@selector(getArgumentAtIndexAsObject:)] == NULL) + [NSException raise:NSInternalInconsistencyException format:@"** Expected method not present; the method getArgumentAtIndexAsObject: is not implemented by NSInvocation. If you see this exception it is likely that you are using the static library version of OCMock and your project is not configured correctly to load categories from static libraries. Did you forget to add the -ObjC linker flag?"]; +} + + +#pragma mark Factory methods + ++ (id)mockForClass:(Class)aClass +{ + return [[[OCClassMockObject alloc] initWithClass:aClass] autorelease]; +} + ++ (id)mockForProtocol:(Protocol *)aProtocol +{ + return [[[OCProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease]; +} + ++ (id)partialMockForObject:(NSObject *)anObject +{ + return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease]; +} + + ++ (id)niceMockForClass:(Class)aClass +{ + return [self _makeNice:[self mockForClass:aClass]]; +} + ++ (id)niceMockForProtocol:(Protocol *)aProtocol +{ + return [self _makeNice:[self mockForProtocol:aProtocol]]; +} + + ++ (id)_makeNice:(OCMockObject *)mock +{ + mock->isNice = YES; + return mock; +} + + ++ (id)observerMock +{ + return [[[OCObserverMockObject alloc] init] autorelease]; +} + + +#pragma mark Initialisers, description, accessors, etc. + +- (instancetype)init +{ + // check if we are called from inside a macro + OCMRecorder *recorder = [[OCMMacroState globalState] recorder]; + if(recorder != nil) + { + [recorder setMockObject:self]; + return (id)[recorder init]; + } + + // no [super init], we're inheriting from NSProxy + expectationOrderMatters = NO; + stubs = [[NSMutableArray alloc] init]; + expectations = [[NSMutableArray alloc] init]; + exceptions = [[NSMutableArray alloc] init]; + invocations = [[NSMutableArray alloc] init]; + return self; +} + +- (void)dealloc +{ + [stubs release]; + [expectations release]; + [exceptions release]; + [invocations release]; + [super dealloc]; +} + +- (NSString *)description +{ + return @"OCMockObject"; +} + +- (void)addStub:(OCMInvocationStub *)aStub +{ + @synchronized(stubs) + { + [stubs addObject:aStub]; + } +} + +- (void)addExpectation:(OCMInvocationExpectation *)anExpectation +{ + @synchronized(expectations) + { + [expectations addObject:anExpectation]; + } +} + + +#pragma mark Public API + +- (void)setExpectationOrderMatters:(BOOL)flag +{ + expectationOrderMatters = flag; +} + +- (void)stopMocking +{ + // no-op for mock objects that are not class object or partial mocks +} + + +- (id)stub +{ + return [[[OCMStubRecorder alloc] initWithMockObject:self] autorelease]; +} + +- (id)expect +{ + return [[[OCMExpectationRecorder alloc] initWithMockObject:self] autorelease]; +} + +- (id)reject +{ + return [[self expect] never]; +} + + +- (id)verify +{ + return [self verifyAtLocation:nil]; +} + +- (id)verifyAtLocation:(OCMLocation *)location +{ + NSMutableArray *unsatisfiedExpectations = [NSMutableArray array]; + @synchronized(expectations) + { + for(OCMInvocationExpectation *e in expectations) + { + if(![e isSatisfied]) + [unsatisfiedExpectations addObject:e]; + } + } + + if([unsatisfiedExpectations count] == 1) + { + NSString *description = [NSString stringWithFormat:@"%@: expected method was not invoked: %@", + [self description], [[unsatisfiedExpectations objectAtIndex:0] description]]; + OCMReportFailure(location, description); + } + else if([unsatisfiedExpectations count] > 0) + { + NSString *description = [NSString stringWithFormat:@"%@: %@ expected methods were not invoked: %@", + [self description], @([unsatisfiedExpectations count]), [self _stubDescriptions:YES]]; + OCMReportFailure(location, description); + } + + OCMInvocationExpectation *firstException = nil; + @synchronized(exceptions) + { + firstException = [exceptions.firstObject retain]; + } + if(firstException) + { + NSString *description = [NSString stringWithFormat:@"%@: %@ (This is a strict mock failure that was ignored when it actually occurred.)", + [self description], [firstException description]]; + OCMReportFailure(location, description); + } + [firstException release]; + + return [[[OCMVerifier alloc] initWithMockObject:self] autorelease]; +} + + +- (void)verifyWithDelay:(NSTimeInterval)delay +{ + [self verifyWithDelay:delay atLocation:nil]; +} + +- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location +{ + NSTimeInterval step = 0.01; + while(delay > 0) + { + @synchronized(expectations) + { + BOOL allExpectationsAreMatchAndReject = YES; + for(OCMInvocationExpectation *expectation in expectations) + { + if(![expectation isMatchAndReject]) + { + allExpectationsAreMatchAndReject = NO; + break; + } + } + if(allExpectationsAreMatchAndReject) + break; + } + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:MIN(step, delay)]]; + delay -= step; + step *= 2; + } + [self verifyAtLocation:location]; +} + + +#pragma mark Verify after running + +- (void)verifyInvocation:(OCMInvocationMatcher *)matcher +{ + [self verifyInvocation:matcher atLocation:nil]; +} + +- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location +{ + @synchronized(invocations) + { + for(NSInvocation *invocation in invocations) + { + if([matcher matchesInvocation:invocation]) + return; + } + } + NSString *description = [NSString stringWithFormat:@"%@: Method %@ was not invoked.", + [self description], [matcher description]]; + + OCMReportFailure(location, description); +} + + +#pragma mark Handling invocations + +- (id)forwardingTargetForSelector:(SEL)aSelector +{ + if([OCMMacroState globalState] != nil) + { + OCMRecorder *recorder = [[OCMMacroState globalState] recorder]; + [recorder setMockObject:self]; + return recorder; + } + return nil; +} + + +- (BOOL)handleSelector:(SEL)sel +{ + @synchronized(stubs) + { + for(OCMInvocationStub *recorder in stubs) + if([recorder matchesSelector:sel]) + return YES; + } + return NO; +} + +- (void)forwardInvocation:(NSInvocation *)anInvocation +{ + @try + { + if([self handleInvocation:anInvocation] == NO) + [self handleUnRecordedInvocation:anInvocation]; + } + @catch(NSException *e) + { + if([[e name] isEqualToString:OCMStubbedException]) + { + e = [[e userInfo] objectForKey:@"exception"]; + } + else + { + // add non-stubbed method to list of exceptions to be re-raised in verify + @synchronized(exceptions) + { + [exceptions addObject:e]; + } + } + [e raise]; + } +} + +- (BOOL)handleInvocation:(NSInvocation *)anInvocation +{ + @synchronized(invocations) + { + // We can't do a normal retain arguments on anInvocation because its target/arguments/return + // value could be self. That would produce a retain cycle self->invocations->anInvocation->self. + // However we need to retain everything on anInvocation that isn't self because we expect them to + // stick around after this method returns. Use our special method to retain just what's needed. + [anInvocation retainObjectArgumentsExcludingObject:self]; + [invocations addObject:anInvocation]; + } + + OCMInvocationStub *stub = nil; + @synchronized(stubs) + { + for(stub in stubs) + { + // If the stub forwards its invocation to the real object, then we don't want to do handleInvocation: yet, since forwarding the invocation to the real object could call a method that is expected to happen after this one, which is bad if expectationOrderMatters is YES + if([stub matchesInvocation:anInvocation]) + break; + } + // Retain the stub in case it ends up being removed from stubs and expectations, since we still have to call handleInvocation on the stub at the end + [stub retain]; + } + if(stub == nil) + return NO; + + BOOL removeStub = NO; + @synchronized(expectations) + { + if([expectations containsObject:stub]) + { + OCMInvocationExpectation *expectation = [self _nextExpectedInvocation]; + if(expectationOrderMatters && (expectation != stub)) + { + [NSException raise:NSInternalInconsistencyException format:@"%@: unexpected method invoked: %@\n\texpected:\t%@", + [self description], [stub description], [[expectations objectAtIndex:0] description]]; + } + + // We can't check isSatisfied yet, since the stub won't be satisfied until we call handleInvocation:, and we don't want to call handleInvocation: yes for the reason in the comment above, since we'll still have the current expectation in the expectations array, which will cause an exception if expectationOrderMatters is YES and we're not ready for any future expected methods to be called yet + if(![(OCMInvocationExpectation *)stub isMatchAndReject]) + { + [expectations removeObject:stub]; + removeStub = YES; + } + } + } + if(removeStub) + { + @synchronized(stubs) + { + [stubs removeObject:stub]; + } + } + [stub handleInvocation:anInvocation]; + [stub release]; + + return YES; +} + +// Must be synchronized on expectations when calling this method. +- (OCMInvocationExpectation *)_nextExpectedInvocation +{ + for(OCMInvocationExpectation *expectation in expectations) + if(![expectation isMatchAndReject]) + return expectation; + return nil; +} + +- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation +{ + if(isNice == NO) + { + [NSException raise:NSInternalInconsistencyException format:@"%@: unexpected method invoked: %@ %@", + [self description], [anInvocation invocationDescription], [self _stubDescriptions:NO]]; + } +} + +- (void)doesNotRecognizeSelector:(SEL)aSelector __unused +{ + if([OCMMacroState globalState] != nil) + { + // we can't do anything clever with the macro state because we must raise an exception here + [NSException raise:NSInvalidArgumentException format:@"%@: Cannot stub/expect/verify method '%@' because no such method exists in the mocked class.", + [self description], NSStringFromSelector(aSelector)]; + } + else + { + [NSException raise:NSInvalidArgumentException format:@"-[%@ %@]: unrecognized selector sent to instance %p", + [self description], NSStringFromSelector(aSelector), (void *)self]; + } +} + + +#pragma mark Helper methods + +- (NSString *)_stubDescriptions:(BOOL)onlyExpectations +{ + NSMutableString *outputString = [NSMutableString string]; + NSArray *stubsCopy = nil; + @synchronized(stubs) + { + stubsCopy = [stubs copy]; + } + for(OCMStubRecorder *stub in stubsCopy) + { + BOOL expectationsContainStub = NO; + @synchronized(expectations) + { + expectationsContainStub = [expectations containsObject:stub]; + } + + NSString *prefix = @""; + + if(onlyExpectations) + { + if(expectationsContainStub == NO) + continue; + } + else + { + if(expectationsContainStub) + prefix = @"expected:\t"; + else + prefix = @"stubbed:\t"; + } + [outputString appendFormat:@"\n\t%@%@", prefix, [stub description]]; + } + [stubsCopy release]; + return outputString; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCObserverMockObject.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCObserverMockObject.h new file mode 100644 index 0000000..3cbcd3c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCObserverMockObject.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@class OCMLocation; + + +@interface OCObserverMockObject : NSObject +{ + BOOL expectationOrderMatters; + NSMutableArray *recorders; + NSMutableArray *centers; +} + +- (void)setExpectationOrderMatters:(BOOL)flag; + +- (id)expect; + +- (void)verify; +- (void)verifyAtLocation:(OCMLocation *)location; + +- (void)handleNotification:(NSNotification *)aNotification; + +// internal use + +- (void)autoRemoveFromCenter:(NSNotificationCenter *)aCenter; +- (NSNotification *)notificationWithName:(NSString *)name object:(id)sender; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCObserverMockObject.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCObserverMockObject.m new file mode 100644 index 0000000..8e1fe06 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCObserverMockObject.m @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCObserverMockObject.h" +#import "OCMObserverRecorder.h" +#import "OCMLocation.h" +#import "OCMFunctionsPrivate.h" + + +@implementation OCObserverMockObject + +#pragma mark Initialisers, description, accessors, etc. + +- (id)init +{ + if ((self = [super init])) + { + recorders = [[NSMutableArray alloc] init]; + centers = [[NSMutableArray alloc] init]; + } + + return self; +} + +- (id)retain +{ + return [super retain]; +} + +- (void)dealloc +{ + for(NSNotificationCenter *c in centers) + [c removeObserver:self]; + [centers release]; + [recorders release]; + [super dealloc]; +} + +- (NSString *)description +{ + return @"OCMockObserver"; +} + +- (void)setExpectationOrderMatters:(BOOL)flag +{ + expectationOrderMatters = flag; +} + +- (void)autoRemoveFromCenter:(NSNotificationCenter *)aCenter +{ + @synchronized(centers) + { + [centers addObject:aCenter]; + } +} + + +#pragma mark Public API + +- (id)expect +{ + OCMObserverRecorder *recorder = [[[OCMObserverRecorder alloc] init] autorelease]; + @synchronized(recorders) + { + [recorders addObject:recorder]; + } + return recorder; +} + +- (void)verify +{ + [self verifyAtLocation:nil]; +} + +- (void)verifyAtLocation:(OCMLocation *)location +{ + @synchronized(recorders) + { + if([recorders count] == 1) + { + NSString *description = [NSString stringWithFormat:@"%@: expected notification was not observed: %@", + [self description], [[recorders lastObject] description]]; + OCMReportFailure(location, description); + } + else if([recorders count] > 0) + { + NSString *description = [NSString stringWithFormat:@"%@ : %@ expected notifications were not observed.", + [self description], @([recorders count])]; + OCMReportFailure(location, description); + } + } +} + + +#pragma mark Receiving recording requests via macro + +- (NSNotification *)notificationWithName:(NSString *)name object:(id)sender +{ + return [[self expect] notificationWithName:name object:sender]; +} + +- (NSNotification *)notificationWithName:(NSString *)name object:(id)sender userInfo:(NSDictionary *)userInfo +{ + return [[self expect] notificationWithName:name object:sender userInfo:userInfo]; +} + + +#pragma mark Receiving notifications + +- (void)handleNotification:(NSNotification *)aNotification +{ + @synchronized(recorders) + { + NSUInteger i, limit; + + limit = expectationOrderMatters ? 1 : [recorders count]; + for(i = 0; i < limit; i++) + { + if([[recorders objectAtIndex:i] matchesNotification:aNotification]) + { + [recorders removeObjectAtIndex:i]; + return; + } + } + } + [NSException raise:NSInternalInconsistencyException format:@"%@: unexpected notification observed: %@", [self description], + [aNotification description]]; +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCPartialMockObject.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCPartialMockObject.h new file mode 100644 index 0000000..5a8fd0e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCPartialMockObject.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import "OCClassMockObject.h" + +@interface OCPartialMockObject : OCClassMockObject +{ + NSObject *realObject; +} + +- (id)initWithObject:(NSObject *)anObject; + +- (NSObject *)realObject; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCPartialMockObject.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCPartialMockObject.m new file mode 100644 index 0000000..1298ba2 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCPartialMockObject.m @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2009-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "OCMockObject.h" +#import "OCPartialMockObject.h" +#import "NSMethodSignature+OCMAdditions.h" +#import "NSObject+OCMAdditions.h" +#import "OCMFunctionsPrivate.h" +#import "OCMInvocationStub.h" + + +@implementation OCPartialMockObject + +#pragma mark Initialisers, description, accessors, etc. + +- (id)initWithObject:(NSObject *)anObject +{ + NSParameterAssert(anObject != nil); + Class const class = [self classToSubclassForObject:anObject]; + [self assertClassIsSupported:class]; + [super initWithClass:class]; + realObject = [anObject retain]; + [self prepareObjectForInstanceMethodMocking]; + return self; +} + +- (void)dealloc +{ + [self stopMocking]; + [realObject release]; + [super dealloc]; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"OCPartialMockObject(%@)", NSStringFromClass(mockedClass)]; +} + +- (NSObject *)realObject +{ + return realObject; +} + +#pragma mark Helper methods + +- (void)assertClassIsSupported:(Class)class +{ + NSString *classname = NSStringFromClass(class); + NSString *reason = nil; + if([classname hasPrefix:@"__NSTagged"] || [classname hasPrefix:@"NSTagged"]) + reason = [NSString stringWithFormat:@"OCMock does not support partially mocking tagged classes; got %@", classname]; + else if([classname hasPrefix:@"__NSCF"]) + reason = [NSString stringWithFormat:@"OCMock does not support partially mocking toll-free bridged classes; got %@", classname]; + + if(reason != nil) + [[NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil] raise]; +} + +- (Class)classToSubclassForObject:(id)object +{ + /* object_getClass() gives us the actual class backing the object, whereas [object class] + * is sometimes overridden, by KVO or CoreData, for example, to return a subclass. + * + * With KVO, if we replace and subclass the actual class, as returned by object_getClass(), + * we lose notifications. So, in that case only, we return the class reported by the class + * method. + */ + + if([object observationInfo] != NULL) + return [object class]; + + return object_getClass(object); +} + +#pragma mark Extending/overriding superclass behaviour + +- (void)stopMocking +{ + if(realObject != nil) + { + Class partialMockClass = object_getClass(realObject); + OCMSetAssociatedMockForObject(nil, realObject); + object_setClass(realObject, [self mockedClass]); + [realObject release]; + realObject = nil; + objc_disposeClassPair(partialMockClass); + } + [super stopMocking]; +} + +- (void)addStub:(OCMInvocationStub *)aStub +{ + [super addStub:aStub]; + if(![aStub recordedAsClassMethod]) + [self setupForwarderForSelector:[[aStub recordedInvocation] selector]]; +} + +- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation +{ + [anInvocation invokeWithTarget:realObject]; +} + + +#pragma mark Subclass management + +- (void)prepareObjectForInstanceMethodMocking +{ + OCMSetAssociatedMockForObject(self, realObject); + + /* dynamically create a subclass and set it as the class of the object */ + Class subclass = OCMCreateSubclass(mockedClass, realObject); + object_setClass(realObject, subclass); + + /* point forwardInvocation: of the object to the implementation in the mock */ + Method myForwardMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardInvocationForRealObject:)); + IMP myForwardIMP = method_getImplementation(myForwardMethod); + class_addMethod(subclass, @selector(forwardInvocation:), myForwardIMP, method_getTypeEncoding(myForwardMethod)); + + /* do the same for forwardingTargetForSelector, remember existing imp with alias selector */ + Method myForwardingTargetMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardingTargetForSelectorForRealObject:)); + IMP myForwardingTargetIMP = method_getImplementation(myForwardingTargetMethod); + IMP originalForwardingTargetIMP = [mockedClass instanceMethodForSelector:@selector(forwardingTargetForSelector:)]; + class_addMethod(subclass, @selector(forwardingTargetForSelector:), myForwardingTargetIMP, method_getTypeEncoding(myForwardingTargetMethod)); + class_addMethod(subclass, @selector(ocmock_replaced_forwardingTargetForSelector:), originalForwardingTargetIMP, method_getTypeEncoding(myForwardingTargetMethod)); + + /* We also override the -class method to return the original class */ + Method myObjectClassMethod = class_getInstanceMethod([self mockObjectClass], @selector(classForRealObject)); + const char *objectClassTypes = method_getTypeEncoding(myObjectClassMethod); + IMP myObjectClassImp = method_getImplementation(myObjectClassMethod); + class_addMethod(subclass, @selector(class), myObjectClassImp, objectClassTypes); + + /* Adding forwarder for most instance methods to allow for verify after run */ + NSArray *methodBlackList = @[@"class", @"forwardingTargetForSelector:", @"methodSignatureForSelector:", @"forwardInvocation:", + @"allowsWeakReference", @"retainWeakReference", @"isBlock", @"retainCount", @"retain", @"release", @"autorelease"]; + [NSObject enumerateMethodsInClass:mockedClass usingBlock:^(Class cls, SEL sel) { + if((cls == [NSObject class]) || (cls == [NSProxy class])) + return; + NSString *className = NSStringFromClass(cls); + NSString *selName = NSStringFromSelector(sel); + if(([className hasPrefix:@"NS"] || [className hasPrefix:@"UI"]) && + ([selName hasPrefix:@"_"] || [selName hasSuffix:@"_"])) + return; + if([methodBlackList containsObject:selName]) + return; + @try + { + [self setupForwarderForSelector:sel]; + } + @catch(NSException *e) + { + // ignore for now + } + }]; +} + +- (void)setupForwarderForSelector:(SEL)sel +{ + SEL aliasSelector = OCMAliasForOriginalSelector(sel); + if(class_getInstanceMethod(object_getClass(realObject), aliasSelector) != NULL) + return; + + Method originalMethod = class_getInstanceMethod(mockedClass, sel); + IMP originalIMP = method_getImplementation(originalMethod); + const char *types = method_getTypeEncoding(originalMethod); + /* Might be NULL if the selector is forwarded to another class */ + // TODO: check the fallback implementation is actually sufficient + if(types == NULL) + types = ([[mockedClass instanceMethodSignatureForSelector:sel] fullObjCTypes]); + + Class subclass = object_getClass([self realObject]); + IMP forwarderIMP = [mockedClass instanceMethodForwarderForSelector:sel]; + class_replaceMethod(subclass, sel, forwarderIMP, types); + class_addMethod(subclass, aliasSelector, originalIMP, types); +} + + +// Implementation of the -class method; return the Class that was reported with [realObject class] prior to mocking +- (Class)classForRealObject +{ + // in here "self" is a reference to the real object, not the mock + OCPartialMockObject *mock = OCMGetAssociatedMockForObject(self); + if(mock == nil) + [NSException raise:NSInternalInconsistencyException format:@"No partial mock for object %p", self]; + return [mock mockedClass]; +} + + +- (id)forwardingTargetForSelectorForRealObject:(SEL)sel +{ + // in here "self" is a reference to the real object, not the mock + OCPartialMockObject *mock = OCMGetAssociatedMockForObject(self); + if(mock == nil) + [NSException raise:NSInternalInconsistencyException format:@"No partial mock for object %p", self]; + if([mock handleSelector:sel]) + return self; + + return [self ocmock_replaced_forwardingTargetForSelector:sel]; +} + +// Make the compiler happy in -forwardingTargetForSelectorForRealObject: because it can't find the message… +- (id)ocmock_replaced_forwardingTargetForSelector:(SEL)sel +{ + return nil; +} + + +- (void)forwardInvocationForRealObject:(NSInvocation *)anInvocation +{ + // in here "self" is a reference to the real object, not the mock + OCPartialMockObject *mock = OCMGetAssociatedMockForObject(self); + if(mock == nil) + [NSException raise:NSInternalInconsistencyException format:@"No partial mock for object %p", self]; + + if([mock handleInvocation:anInvocation] == NO) + { + [anInvocation setSelector:OCMAliasForOriginalSelector([anInvocation selector])]; + [anInvocation invoke]; + } +} + + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCProtocolMockObject.h b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCProtocolMockObject.h new file mode 100644 index 0000000..0b3f6b1 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCProtocolMockObject.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2005-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import + +@interface OCProtocolMockObject : OCMockObject +{ + Protocol *mockedProtocol; +} + +- (id)initWithProtocol:(Protocol *)aProtocol; + +@end + diff --git a/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCProtocolMockObject.m b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCProtocolMockObject.m new file mode 100644 index 0000000..55dc7b5 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/OCMock/Source/OCMock/OCProtocolMockObject.m @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005-2016 Erik Doernenburg and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#import +#import "NSMethodSignature+OCMAdditions.h" +#import "OCProtocolMockObject.h" + +@implementation OCProtocolMockObject + +#pragma mark Initialisers, description, accessors, etc. + +- (id)initWithProtocol:(Protocol *)aProtocol +{ + NSParameterAssert(aProtocol != nil); + [super init]; + mockedProtocol = aProtocol; + return self; +} + +- (NSString *)description +{ + const char* name = protocol_getName(mockedProtocol); + return [NSString stringWithFormat:@"OCMockObject(%s)", name]; +} + +#pragma mark Proxy API + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + struct { BOOL isRequired; BOOL isInstance; } opts[4] = { {YES, YES}, {NO, YES}, {YES, NO}, {NO, NO} }; + for(int i = 0; i < 4; i++) + { + struct objc_method_description methodDescription = protocol_getMethodDescription(mockedProtocol, aSelector, opts[i].isRequired, opts[i].isInstance); + if(methodDescription.name != NULL) + return [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + } + return nil; +} + +- (BOOL)conformsToProtocol:(Protocol *)aProtocol +{ + return protocol_conformsToProtocol(mockedProtocol, aProtocol); +} + +- (BOOL)respondsToSelector:(SEL)selector +{ + return ([self methodSignatureForSelector:selector] != nil); +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Pods.xcodeproj/project.pbxproj b/Students/Benny/Les 1 OCMock/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..087a63a --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,1922 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 01F7D55919C59833456188558FE8D7FA /* OCMExpectationRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = A2FD9E3F0AB004599D07FA46089D094B /* OCMExpectationRecorder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0310B1523123778B0E3FB78BE3A14095 /* OCMBlockCaller.h in Headers */ = {isa = PBXBuildFile; fileRef = 85C021FBB437212FDD7ACE16E8C938A6 /* OCMBlockCaller.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 04AE1DC56A0C088489EA27CED5190838 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 479AF0F07D0B0287D6BCD7EC600A5E37 /* Stringers.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 099E42CA64F8B9331551138F9955BF58 /* DeserializeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88BE5ABF5325A3D9C0E56A03A31F1CA /* DeserializeOperators.swift */; }; + 0AEAD2BEB61CCA26BB0798F2E527BF84 /* OCMRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 2051AC723FB26CC4070611F36B8EA188 /* OCMRecorder.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 0B846370B6EA04F7D7909A403DD16317 /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C54D9C80B6B4F8DC4DAA27974B21EFE /* CwlBadInstructionException.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 0D183650A2D88CB6DAD886030A3A2B62 /* OCMBoxedReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = C0341FB69A58995B563731DE709F5AD4 /* OCMBoxedReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 0D4B1951108CF54E1968467D30C351B5 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9769B91E691ADE611F7F6AC681D52F /* MatcherFunc.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 0DA0637490BAF2C83C67E680D59D4B2D /* World+DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = D63F54AEE93CA155C4E1499D441E66D9 /* World+DSL.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0DF2D4E6B55D67E28D8BE9EC5A25F24E /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = F136A722EA31CAC77AB2BB3BE4D28654 /* Async.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 0E32A8C1B69250199C8EC0794CF3A3B6 /* OCMStubRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = A0537C3FE7FB2F62CEDDF7F13B8D0F29 /* OCMStubRecorder.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 10B953E63951E8DB495AA5B5EBDBBABA /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9A22019596EFBBF25C3EF6A600143A4 /* PostNotification.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 10DC5AA88ADF41EEC50B734FE6DD139A /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = D9CB429A7827557A08631629B18A51EA /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 110FEE62D84E1B42BC73A191C2280F80 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4572F7A638016C53B2D3770855145E /* World+DSL.swift */; }; + 116FA1BBD719AFAA5593D71332D2A926 /* OCClassMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = E127D5052F1A017C30FD3662C466C67F /* OCClassMockObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 11EEDB6DB6F03E2AF3FC368AA32274AC /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4462A2F84912074D21DB4E7CA49167FC /* ThrowAssertion.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 123D36BB9CA549C55BBE6FC7D21BAB97 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = 569076F80E248EA1DE57361C916957AA /* NMBStringify.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 126DE3E39B6CB11E17B4D778B3BCD309 /* Service.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896260E35229AA52016418546468F017 /* Service.swift */; }; + 13A1051CA96D84674E588FECAF52DD43 /* OCMExpectationRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 2169474468C959719E0C739FCF027BE6 /* OCMExpectationRecorder.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 13AA024ACA7FE3FAD7E0FFD5AC77370D /* OCMVerifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 87DAAD46F1B7147C89D44E670B574A6E /* OCMVerifier.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 147E00CDCEDB145F0012FA174BA4E545 /* OCObserverMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BB64B08CA6FF3FDAA94F163970A0F77 /* OCObserverMockObject.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 15081C3A4D626D9631A9594847D2E2A6 /* OCMFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DAF2C746A0A017C15BD9577E4637F15 /* OCMFunctions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1583087CE691D66E050A0AE7C07296BD /* OCMNotificationPoster.h in Headers */ = {isa = PBXBuildFile; fileRef = 2748656F8759F1DF93B72762A568C88D /* OCMNotificationPoster.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 159707F50B6FEC09BCC282AEF0DF96D2 /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C542C1EE5B7A348F6DAA30969D04E886 /* NSBundle+CurrentTestBundle.swift */; }; + 15B38D7F47211A8BB83F27F5016E4240 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4237A12880574E77B830212EB4596EBF /* World.swift */; }; + 15FEDB8A315321D48BC7E535429ADB48 /* OCMInvocationStub.h in Headers */ = {isa = PBXBuildFile; fileRef = B127F55EADAC4535E8A9FFCAEFD60744 /* OCMInvocationStub.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1B4C1833AAC1153CDB88D93E2BF303B1 /* World.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA359CDAEEA10BCC7E83B89E2A00E85 /* World.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1BF6E849045B943940185AC089FF7312 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 677FBE720E59F083FEA6C3A79B1F5CE9 /* Filter.swift */; }; + 1C37D984F1BBBC7278E1FB6BDB153892 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A4BFE0C60B656489C6E63522F8CD5C /* CwlCatchBadInstruction.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 1D3C26CA81028CC5F2EA8FB0511C79E3 /* ServiceQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 175DF4BE0B1017B4D5D4CB6081AC4B45 /* ServiceQueue.swift */; }; + 1D53147F49F02FC693C33D8526049C90 /* OCMIndirectReturnValueProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = F1911C129343485A3A9CBCB3433191C3 /* OCMIndirectReturnValueProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1DD2C9A900B7D7B5F3862D15C1A8AD7E /* NSValue+OCMAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 424988859F380BE3FCA69FC5A5300A1D /* NSValue+OCMAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1F707004C05C63F90F0030E8E4902D66 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F5FDBCD14BDCB054BC8F13764534368 /* BeLessThanOrEqual.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 2173F4681D2DDDF63A01A7439EDE1FD4 /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B428B850CA5D63C24F4946A74E78C5B6 /* NMBObjCMatcher.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 24394811C369F117D75337F436C81222 /* OCMock-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5502FB0000811E1CE290E375DA48C225 /* OCMock-dummy.m */; }; + 26860D2C7C5CA85423CCBFB8B415A1B9 /* FaroError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CFF6A991E06C066F8FA8EF520AE8829 /* FaroError.swift */; }; + 288DBE855F794BA1AE8BC47AA413693E /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 440F12D9E2F445F41FCCA0B785A2F836 /* BeginWith.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 28B5E9BDDC2F53432C7D7D244837F1B5 /* OCClassMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D69172D8E3DDB58A086A167DDC4CFFE6 /* OCClassMockObject.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 29E8951140FD80478059735AF70ED501 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08A6C9C6DDF4475FB935D46CFBB7C3FE /* QuickSelectedTestSuiteBuilder.swift */; }; + 2A320686E07FACD8D19C185064FE67E1 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ACB8301A60C48C42EB67A0F23684703 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; + 2D89EDBA82F92ED6D0D0831660745753 /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 619DF9020189CFD375CFD8B33A8AFEB6 /* ExampleHooks.swift */; }; + 2DF80575B9759A9E8004F4F642D0D123 /* ContainElementSatisfying.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF5CA75DFE5280DCCE30B1B962314F73 /* ContainElementSatisfying.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 30F80459D8D536D8B99880EDD353987A /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56EEF5B5C1579A07C7A11F798287D5FF /* BeGreaterThan.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 318F9AE6D9561CFB487071A821B4217D /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56837149D3B326D000FE3F548D98F9E5 /* BeLessThan.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 32AB6828BB98A679D3EBCC16C7BE9566 /* Functional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F015F21170F9DA1A4DA6C5C6F52DF38 /* Functional.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 34E0569B2666F68A70EB676EFDCC4434 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07C0B663DC35B929E7A991EBAC776168 /* CwlCatchException.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 353759005B92EEC29E4B15765C4D3EEB /* OCPartialMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = BA290B4864ABFCA9459B007FA1B6562E /* OCPartialMockObject.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 383B3EF018CDFD095EFEB7D74769144A /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 266DE843BBF26E21E8415D3748732254 /* EndWith.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 38D5085895B3757AF0DCED078EF8B145 /* OCMRealObjectForwarder.h in Headers */ = {isa = PBXBuildFile; fileRef = BF557F810F703A2A207CE481103495AF /* OCMRealObjectForwarder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3CAE0E6185C96CB26F761BD020EE1337 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B3DAA212362983A0234B64FBF292FDB /* Configuration.swift */; }; + 3D1CB7A4AB9B00BC95F06CF858F18BCE /* OCMFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B3BC02D8B8967D44B9CAE0BDABA9979 /* OCMFunctions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 407775EDF27F892E16C3A9D22C6883ED /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 27447EB20550587F4B0328BB526DE709 /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 409A3ECDDC680D0BD343E3F203862E25 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 890F317A22755FCB5B52E5476D38CEEE /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 41B3A99C33F17DE2DD0D81105157CEDB /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44B19049B0308546117F80A8F637C792 /* ExampleMetadata.swift */; }; + 4552366371FE1ACA9600897C31D70E4C /* OCMObserverRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = FD7B955E6DE6F1E00CAFB564C49D3910 /* OCMObserverRecorder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 45E91E6E79D1EEACF0F7A668E3D9A89D /* OCProtocolMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 02AA7937B66BF3A10C30387ED1890620 /* OCProtocolMockObject.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 471FC4CC094184E255A6522E7A70DC99 /* ErrorPrinting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59EA412FBF3C72496F43540928A9643A /* ErrorPrinting.swift */; }; + 4A17E1DB4EA2CCBF04B76F5F8EB417A1 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 47E283B8196008FDB29580D733364660 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B6579FFF0062EEBBABB8336C0871171 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3196F0CFC24ED7C4EE0BFF3062DF4E6C /* Errors.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 4E8250BDB662F542F9294F6941333373 /* OCMPassByRefSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = C5A58AC25DF1C7D8DDB5851AC43E3BB2 /* OCMPassByRefSetter.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 4F02F5DD4EC7C3AFD1EC38E2F55B0C4A /* OCMBlockArgCaller.m in Sources */ = {isa = PBXBuildFile; fileRef = EF02E46AB54FD2B8F9059547A6BC8066 /* OCMBlockArgCaller.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 4F4A7459D96FDABBAB640D1D1B1BB42E /* OCMNotificationPoster.m in Sources */ = {isa = PBXBuildFile; fileRef = 50574C3D7DF684F07948CA1A258AFC94 /* OCMNotificationPoster.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 5037A042D2012439DEC932F10FC51B95 /* NSMethodSignature+OCMAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D8BC502DFDFDA1D3F79A7278155B46C3 /* NSMethodSignature+OCMAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5111CA15767FEC30071EA48EFE057C18 /* Faro-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 449378DE182400BF22C43323CDA70CDC /* Faro-dummy.m */; }; + 51CAB174257235556CE8902084F0E662 /* NSNotificationCenter+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C88B178AD14CC52279BE25D75C2A72 /* NSNotificationCenter+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 522459A2F7DB405AC0CF912A2BBDD096 /* JSONReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23D7D79A61B7C74610B6088FF427AA34 /* JSONReader.swift */; }; + 5362A4223DA7F71617F6928579053CFB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */; }; + 543D9D71DD92175A9CC5F0831CF2A028 /* OCPartialMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = EDE023D2ABB9C849FE7025EDFBE651F9 /* OCPartialMockObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 54471D429F63760B736E52506A0B861B /* OCMInvocationMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8DF6B5676E97E498CFB3893655C882 /* OCMInvocationMatcher.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 56164F20A216AB17E39F748455590953 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */; }; + 5685322E421AB4DA6A91B26C09833B29 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3196E03A7BCE9105FFC25B9CF9D24D70 /* BeIdenticalTo.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 57D22918F6C3F9E290045796B4632947 /* Quick-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5B03D30A3F817B663600B243F47B4D /* Quick-dummy.m */; }; + 58FB50DB554239F854ECBEC3C86F3A92 /* OCMRealObjectForwarder.m in Sources */ = {isa = PBXBuildFile; fileRef = 925685DE04283B4215A8F3B4D0C5F713 /* OCMRealObjectForwarder.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 59578DBAB2520015A65B5B160722A370 /* NSValue+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D460C9A1928BDDC623D597B52A4C553 /* NSValue+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 65335E2F74AE71C270659EC7E8725030 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7659A8D54A36194CF322D3B98EB2FCA7 /* Expression.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 6678BE4D299D36DEDF4ED0DDE129C3B3 /* Quick-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DA44C87AB51E7A2D45482E922336410 /* Quick-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69F9C31FC991A69337CE9B599993D68D /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64BD74BB6D364B8C9BF5A55D5F435D64 /* NimbleEnvironment.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 6B28666A1AFDD1CFBB4036BAFE730947 /* ParameterEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B21942C7D947127C4EC619A10D8C7A6 /* ParameterEnum.swift */; }; + 6B74023612DABC9C1E2B6ABAC537814A /* NSString+C99ExtendedIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C449EDFDDB7185886E70C427C7811C8 /* NSString+C99ExtendedIdentifier.swift */; }; + 6DB51F9889708E3B90223C3F39BAD587 /* Faro-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B6E61CBA24C69FF3E46D82ECA84E06E /* Faro-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6DEAD4CD0FF9467DA3FD3F22816418C6 /* OCMArgAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 98850039C4F804F91DF520C56800F674 /* OCMArgAction.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6F36A431DE56B28FD400D20036A23DE4 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = DF2EE9D65678DA76E5F21EB3E845301B /* NMBExceptionCapture.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 704DA81E48A5263B35189F36C5247A53 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB7180F398749CE8A83A3562CD47A7C /* FailureMessage.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 71213523998EC4038EEF2881118A57A1 /* NSInvocation+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = FD48E0253E7CEB78DAFEC9CECBB49D81 /* NSInvocation+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7272DB71A8C5325A0778F63E6F6C9957 /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EA867E606E14C0872561F83652E84CF /* AssertionDispatcher.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 7276DB3552398200B421D06F207EC0E3 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D12BED901082321E8CFEC598BA2D70E /* NimbleXCTestHandler.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 72C8CC2855787B9DC1A37DDEB5E24155 /* OCMFunctionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A6FB4B10B6FC72106523B7A8B84EFC63 /* OCMFunctionsPrivate.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 748BB746CA429F9C5D510EEF3245ECFD /* Nimble-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DB34B3D8F257A7890CE9F8EA883FF85A /* Nimble-dummy.m */; }; + 74BC62D6FEB722F4976016FD4DCA870B /* OCMObserverRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E9CCC68588CEB5C4FDA0098BFA1B0B9 /* OCMObserverRecorder.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 756FF97F6CD9FE10EE8EF3C0B507B544 /* QuickSpecBase.h in Headers */ = {isa = PBXBuildFile; fileRef = EBF2BAC92509FAAEA0779082C1C322E5 /* QuickSpecBase.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 762C9DEE2C8F18DF9559D188115C91B1 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B932CDAD8906CB1DE98972235602044 /* QCKDSL.m */; }; + 772D5A1B086DCD32B6BFC1D707D20D76 /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF3EA03FE9BD48F53AAA80396506128 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 77C1E9B05B46101709D7A3804D61987A /* URL+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BE0907DCCA28A7E577F744CBE6EC43 /* URL+FileName.swift */; }; + 799D65F10E77B49AB2402931BA0D7506 /* MockSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 488EB785E17F22A933DE2766C460EBB6 /* MockSession.swift */; }; + 7B006E74668E41702B8881E724728DE9 /* OCMBlockCaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C85CA8691A43CDBBA4B7605B6FCE4AD /* OCMBlockCaller.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7BD907A708031D5361E1A97CACF9F24E /* Nimble-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A60AC7A612EF03420A75BF5AB7B64698 /* Nimble-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7D94DE66B8B5E3B4A0B5E53A88C3FAEE /* OCMIndirectReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = A4EBD4A49844BD4CC6B4B699DCAFC134 /* OCMIndirectReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7FE9A99D985CD0179F9420DEFC6099B2 /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D72971A42D77BB86326B203C1457BE /* Closures.swift */; }; + 80D1788131B3D3326041E62364F8C7AA /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76DDA5D300FF3EE51C7BBC48CA21E979 /* BeAKindOf.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 8232C47C42A5943000582E7481019BD3 /* Pods-Objective-CTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F184BCA8F3494CCF89439247DBF87 /* Pods-Objective-CTests-dummy.m */; }; + 82558AE4441757075270A8A260B34EC9 /* OCObserverMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 719A5DB86ADF4CEF7E34D72CB175D36E /* OCObserverMockObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 84388DA969A4D5B21058909917B6DE99 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECCEF1AE64AB2737FCA2A75F0760E89 /* Result.swift */; }; + 84D9CBA354DEF26CEC5A6F9D83014554 /* SerializeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85BF2DAB6137E8AB33AB39E81AC398E7 /* SerializeOperators.swift */; }; + 86B6F55EA68F9A3ED63C65C3375BEBFF /* ServiceConvenienceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ACE2FA7D2EF192CA34044B1AD47ABE1 /* ServiceConvenienceExtension.swift */; }; + 86FF90618135B7C9032BC7075343F236 /* OCMBlockArgCaller.h in Headers */ = {isa = PBXBuildFile; fileRef = 229D5414BB786A871A70534E780D9A16 /* OCMBlockArgCaller.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 874EF0A06B9FC80B877261425BAB4ED2 /* mach_excServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5B0B661BE17B10DD3AB8BF20397B0B /* mach_excServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 88B771FB81DD05BF7E48A0D9271D9EB4 /* CwlCatchBadInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 8385073FF1FC52F9986F8809736A8115 /* CwlCatchBadInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8B7AD0583E8417752FE1B58622C7572A /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 39C2F9228C71CF526F9542DED335C294 /* QuickConfiguration.m */; }; + 8C3C59CF7A92D0794E10B0249129D43C /* FaroSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041F40AB4A337F8D7FD923731741B00F /* FaroSession.swift */; }; + 8D87CFDF007039D68604BC06C34DC309 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D42487135E21EE53A8378138FBB6B14 /* ExampleGroup.swift */; }; + 8EE2E0824E8AD382EC6553104A60430E /* OCMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 74652B094B794A4F1132199C493A63F9 /* OCMockObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 90FD8AF59C660969E39FD42C10991176 /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4B98F25D27824128D54C5C5A19BBE9C /* SuiteHooks.swift */; }; + 915751C97068AF644D3FE4498633DAB1 /* OCMExceptionReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = B9F2278D55DE315CA3067DD2E21434F3 /* OCMExceptionReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 926F67C94121C19A959745138E5B42B6 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B9B78E3720DC751A90BD5C21D05C774 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 92F61FA0ACB1B709FFEBE1D9DC2C68E5 /* OCMPassByRefSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C99905C8DB11FA8B11C51A528FD5CC5 /* OCMPassByRefSetter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 974362D040AC870A5D72E365B21A8CE4 /* OCMExceptionReturnValueProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = DF9CFE075C5D35C4EE1B13EC9679F90A /* OCMExceptionReturnValueProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 99B1107CE4EADFBF179C43FE3487D045 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */; }; + 9A92686CF21CC8ECAB69A3CFB621FA4B /* OCMock-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 302CA5B370C8880A732ECC37A27E3BD1 /* OCMock-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9B00A3D917761F18BD3F36A3C4386721 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 814EDFF45B3ADC2BCB0BBA17372353F9 /* QuickSpec.m */; }; + 9B5E74ACA03C1B450B3AACA8674CC4A0 /* Adaptable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D17A097B714278FFAB252E3FCF22E2 /* Adaptable.swift */; }; + 9CFDCD6DF628E2A14C68C468E3FE437F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */; }; + 9D9155396F48333B854DBE586138EDBF /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9886CF6FFF7821226D662199CD2D435 /* NMBExpectation.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + 9E91CB1A923A3604EE7909397A6558F8 /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA53CE8AF9DD3E17F0C70EFB0FD27405 /* QuickTestSuite.swift */; }; + 9F3C54F28CD7BAC3682DD33BC380F091 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = FB4E3DAA9766B7D4A44B58DCC3D24F84 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A0F475377A398A87070131ADEC7F6C6C /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71C74B4921D91CD6BCC28E9A98B64AF /* DSL.swift */; }; + A1268C3E1B318712F159EF222F19BD8B /* NSNotificationCenter+OCMAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EFDEC734F4BF1E9C076BC02F6765C8A /* NSNotificationCenter+OCMAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A279D4DAE8E16C5D8F9019CDBED14D73 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15E637B1786AA1682A8ACDE06F0C5EA9 /* DSL.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + A39D312940A4B6EDA53103B77E32C93A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AECEA2EDA41473899EE391CA038EDC38 /* XCTest.framework */; }; + A4AF7E8EF9BB26F4CE7FD9EA32D4AD4C /* OCMMacroState.h in Headers */ = {isa = PBXBuildFile; fileRef = 430BEAB384EF23E18AB55404F45B500A /* OCMMacroState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A4CD01540B9FCF8F26D52856704571D7 /* OCMReturnValueProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E635935B36C0E759C0C146D13956EB2 /* OCMReturnValueProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A59AE6011C58D3D2F009DEF7F5AA259B /* OCMInvocationExpectation.m in Sources */ = {isa = PBXBuildFile; fileRef = D54B25F7B345B1640ECA299C5889329F /* OCMInvocationExpectation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + A665BE606F6B28E89B531EDE41657ECE /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB30625660AB607FB8E3575225C29D4 /* Match.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + A87CA098369D61EFC7A05BD61512A3F5 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52DC61C441864F619A3E199E65EE6929 /* BeAnInstanceOf.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + A9571E56544CD912F0DA62E545DB2419 /* OCMReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6627A5066D4FA2A4F3183603ECD72427 /* OCMReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + AA6EAFA71E1A6862AA312D89A601C34F /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA25F5226E62D1B78172E014CFA2DD2 /* AsyncMatcherWrapper.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + ABEE3775B4FD25B3C86EE712BC2502B2 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34764871C1F32D2DF0A7C97BAAA92678 /* BeGreaterThanOrEqualTo.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + AD2B0E5BFF8EAD0EDF0449F8D198277C /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 088BC7AE541E2B5846E908EC38A8043D /* BeEmpty.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + AF7F875677FF3EB4B6ADDB1373B34249 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 701A528296F7DDEE6AF18D6221EA6126 /* BeLogical.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + AF814F353BF9C15BAED3E4067DCC3BF7 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD34968E9AAB6CCEE822821FAF06EA1 /* MatchError.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + B138DBC0F7D2656EE7E413BEA735C71D /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B3C6B8D47B66B14F7FF22821423917 /* DSL+Wait.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + B16340143CE7FF40A32CD8082ED4152D /* CurrentTestCaseTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E9887DA589CE1D767C5432D5EF03AF /* CurrentTestCaseTracker.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B1D59A1BD0FBDF3BA9A5B65ACFC25D56 /* ThrowError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD210F446F274ADDF9BB2CC88723580 /* ThrowError.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + B1D876C441B5F61984E35ABB5210AFE6 /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C06DDE9D47475D20BD34B4CF21FCAA8 /* CwlDarwinDefinitions.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + B200AEB2373802A1B871987A18D08F75 /* OCMConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 74356A33E3762DCFA90AF009639CD2DA /* OCMConstraint.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B33B6DFAA43992C898AF6D4F1C539A8A /* OCMInvocationStub.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B08559C758F7143032F9260EBBB2BD8 /* OCMInvocationStub.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B3E6AA126A971418B57B78A6B4E753E3 /* OCMInvocationExpectation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E099104B165EE8F1C4A492B330574D2 /* OCMInvocationExpectation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B40D8DAB504B721D2BC6A6DDFDD82067 /* OCMConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 04650C15A3E1EEAE92B072F94F1008A2 /* OCMConstraint.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B42B8EFE65F8B07957190A15F590093A /* OCMInvocationMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 131262D643B0B521327E407C92585834 /* OCMInvocationMatcher.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B4E9303A7A16306EE54AC43CB0183D91 /* Call.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9F018CD70EE3E8DB4B9F765AC613579 /* Call.swift */; }; + B612F1F906E3AF8B1FC6B893229E83B6 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BF2DCE604BA5C282E0BE5B85CB00B7F /* AssertionRecorder.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + B66FB06824BBED66619F17DB82CC2A64 /* OCMLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 24BAC2ED093F5B48E100F4EE238CCE9C /* OCMLocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B7AE85F0249D6CE2F37CFFD41E3D17BB /* Serializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B877F4EC6304092C86F89BB5AA7EE76 /* Serializable.swift */; }; + B852DBE3593443215A94EEFD59786402 /* NSObject+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 619BB7A22883B7B2E5A221513014313C /* NSObject+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B8F0C855C23E200720AD907B8E5244FD /* Deserializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4317F0673AE4243F95EB140825A60B7F /* Deserializable.swift */; }; + BD181F7E8C0BB325B051DA9F2FBD71BC /* NSMethodSignature+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 83502779789D0516E709DF9ACCFE9468 /* NSMethodSignature+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + BE8A249B6E2643D0CAABF318BA9291E8 /* QuickSpecBase.m in Sources */ = {isa = PBXBuildFile; fileRef = B48D54793862AA2302F5E16E028E382E /* QuickSpecBase.m */; }; + C08FCDC247B35C971F5AE7E58987E8AC /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = A31C891DE1CAE112530DB2E7E424C86A /* SatisfyAnyOf.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + C39921387DA273A0952A999B0CDC03F9 /* CwlCatchBadInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = 13EC4E317B7B17F803A96AB19F03D67C /* CwlCatchBadInstruction.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + C65A28088F0668711386816290C3880E /* OCMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = C0015224404262544DE7B83E7954AD52 /* OCMockObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + C710B6A7B1A479349273B3AC04CF07C5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */; }; + C813295B8127E0A3518AE9C574ACEF5B /* DeserializeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF49C8C3DD8025331B7F158EB13ABB1 /* DeserializeFunctions.swift */; }; + C8C4B19F966FD8529D426E5FB8F5A0EF /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE43844F164FE3F918256B570F0777EB /* Callsite.swift */; }; + C9132B1E287B7ECA69A90F4766ADE9C2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EB3A4DB318A893542FB6A8242E425A /* DSL.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + C97B9F51427BCD4C63EC7D75AB161833 /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB37ABD2DE8F664796C0EE3907B043B6 /* Contain.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + CC2C1A15C25533A85E0EF848B23F702A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */; }; + CF451EAA94004B370612757B61B46D2D /* OCMArgAction.m in Sources */ = {isa = PBXBuildFile; fileRef = D698EBAA6379D206E4C776A658BFD31B /* OCMArgAction.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + D515ABEFDC8F8F5278A7A8C280468B5C /* JSONAdaptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23341927F939A99D7618E49A339CBFDE /* JSONAdaptor.swift */; }; + D5D4E8223C271A19448FCEAC36A9B441 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = B572EA694ECD0DEE474414124B2D0C04 /* AdapterProtocols.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + D6A1634CFD5243D18DB762116C8CEF8F /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F37A03A2B9DD962C48ABA116B6138A4 /* BeVoid.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + D7408861438442F67469ACE39D1604C1 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86712ACD792328965934C8E4598790C5 /* BeCloseTo.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + D93C5A1929F8FD53F7EF2C3CA16CCC95 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5FCBD308AF6B1756A280ADD0DEF666F /* Expectation.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + D9921CDBA36587248C63AFDD5B3C1981 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3D76125FCC36E6FC71570FD9832BC1C /* Equal.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + D9C7A57A574090442C8631BA856B1599 /* OCMMacroState.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5D821EABCECCD30415450CAC661FB3 /* OCMMacroState.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + DB039F39038342DE5258F386F694A9A0 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C47ADC55EE591D376E5130494D3103 /* SourceLocation.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + DB5066EBB8C95A3F8818628C9CA6794D /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = 9700521F2B4193A044A781A80B9AE998 /* CwlCatchException.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + DC9C69D7524AFEECCDC73D5CF1F4C028 /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2DDC74B6B7A9622CE36D390BCE6A9EC /* HaveCount.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + DD7E9850FD1FD06C3542485F2553DAF3 /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F86F386D72616F0543B86738A2B974D8 /* HooksPhase.swift */; }; + DEF289C7BF4E97D42B06B1EB7CAE0951 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = DD78AC2ECB2F447DEB1BAF68ABB3EE06 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E057BF21900146896798A3ED597BFA8D /* FaroService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9296A5869224FBE565BA60A0A0D6C7 /* FaroService.swift */; }; + E14A5FC189CD75054825E45DA6D9F293 /* OCMBoxedReturnValueProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 611CBF0BB7483B56ACD6A64ADFC894FE /* OCMBoxedReturnValueProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E1554E6ED22E94CAD97E211C7FBA530B /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71290B8EFD4F2112C1B10D1E1456BBB7 /* MatcherProtocols.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + E4070427AD7F08E573CAA22DCEB79FB1 /* OCProtocolMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2AB251AF671293C30BCA11CB42CD39C /* OCProtocolMockObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + E4A87D8BA9BA24EE81DEC41C8BE98F2B /* OCMVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DCCFE49D2AA7D774D2E50D7A5554D38 /* OCMVerifier.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E612B2EB49E835FEECD743A0F53FE2EC /* Pods-Objective-C-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 625F5B8D9A5E5241326DB676D4CA4E98 /* Pods-Objective-C-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E61FEAB563814E928FFF2C1EF239058A /* NSObject+OCMAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 178363EA10143927B2A73BE53D75C5C6 /* NSObject+OCMAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E688AB23EE6C5F3515CFDC297E8BC671 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88FFA5B6104280C84A5334A672FA2209 /* Configuration.swift */; }; + E6F1B20197D630B80285B5F6E5FAE80F /* OCMRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E5DEEB028078566503617AC8EC42FC1 /* OCMRecorder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E9CD7EF9DD6E75404E4264F6F0AC8D26 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA32FFDFF86560AD2CE21BE9A9E5E696 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EB4FF2AC450F3EB0553C41AEFE4CA67E /* MockService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1FCFACE537FA1A2D7A55FDFED06A01 /* MockService.swift */; }; + EC33739AB54F71355C4FD5AAEF92F4B1 /* OCMStubRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CA42E725AA1BC788D14B8E085C8DF37 /* OCMStubRecorder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EEACC5B78AFB71C8594380C005C17A4B /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = 16922A80B5F583450F9CDFE96AB35D50 /* XCTestObservationCenter+Register.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + EF73A2955B4C9154D1D51CF619CD5CBE /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A5BB201BD9BF5C9C87790A837F108F8 /* ErrorUtility.swift */; }; + EF973B571A12BC721BFCD80737EB5C16 /* DateParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 886BFCC81C9DFAD3953DB628C804AF0C /* DateParser.swift */; }; + EFC1318446EB79DC091867000F45D61C /* OCMLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = AA397E648B4C103FB8B6C5386529D697 /* OCMLocation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + F02C2CD0A94965FFA8928B316D5825CB /* OCMArg.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A6042939A32620F014384C86FD5CBE2 /* OCMArg.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F100D41C0564EE46CA47DA9E3540DA70 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F44AAB15A4E7B7605C6769D734E47B /* BeNil.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + F17C28263ABEAA0D453A5C3BA4ED2E6A /* Pods-Objective-C-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 10FB066A127BFFFD865E4B4EEACD5073 /* Pods-Objective-C-dummy.m */; }; + F2ED0A18E020A07A092F957B2C7EF0E2 /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B5CD7F90676965355E5F8A58763CFA /* mach_excServer.c */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + F98852F58D5FDF0191647087678ABE70 /* OCMArg.m in Sources */ = {isa = PBXBuildFile; fileRef = DC9527D93007FDED4F2B30FE9E46F21C /* OCMArg.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + FA1DDDB5F0219950071EABB20F6A2EC8 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F9E3CC6AB1E9D7A424DDF6093BC559 /* Example.swift */; }; + FAACCCDBE0D2785212E37468636AAB0A /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B61EE0ECD44A33AC1241DA949C8BC1C /* AllPass.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; + FAB7A1E7E1414DC657BA79D07135E15B /* OCMock.h in Headers */ = {isa = PBXBuildFile; fileRef = B90D72876497A4309472CC39D0C9CECC /* OCMock.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FBD596B095C58C7A3AA647CAB7802226 /* NSInvocation+OCMAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7EA82F9F7487BF9876330B934F58C2 /* NSInvocation+OCMAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FC4D8B6B0FDE5146C0D44F697F7F55C6 /* Pods-Objective-CTests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D6A1375347C3B187910D2A7D07A5E082 /* Pods-Objective-CTests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FD9373DD3C1910FB513089F4CD39613B /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59A395EF59AF7711A15508D3B5F0C5C0 /* RaisesException.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 41A4F0806CA11282CCDE42486853F25C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC54C98851E54D349520C786701A1845; + remoteInfo = OCMock; + }; + 5585FDAA1F5495AF815BE2A8991FFF74 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 16DB55216A6C01E5C8284AC8D28E99FF; + remoteInfo = Quick; + }; + A9650A9FC71DDF2254F985238463D393 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0921CC2F4398BE9A4F1CEACB30684B56; + remoteInfo = Nimble; + }; + D922E2291C6A5FDC0BDDA2604C5EF505 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5357EF6DAFBD3DB4890F10DBD75929E6; + remoteInfo = Faro; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0062E1BE6CA18731E251D5B78032D276 /* Pods-Objective-C-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Objective-C-frameworks.sh"; sourceTree = ""; }; + 0287B60C452CC527AF49B49EF794D864 /* OCMock.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = OCMock.modulemap; sourceTree = ""; }; + 02AA7937B66BF3A10C30387ED1890620 /* OCProtocolMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCProtocolMockObject.h; path = Source/OCMock/OCProtocolMockObject.h; sourceTree = ""; }; + 041F40AB4A337F8D7FD923731741B00F /* FaroSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FaroSession.swift; path = Sources/FaroSession.swift; sourceTree = ""; }; + 04650C15A3E1EEAE92B072F94F1008A2 /* OCMConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMConstraint.h; path = Source/OCMock/OCMConstraint.h; sourceTree = ""; }; + 05A4BFE0C60B656489C6E63522F8CD5C /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlCatchBadInstruction.swift; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift; sourceTree = ""; }; + 07C0B663DC35B929E7A991EBAC776168 /* CwlCatchException.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlCatchException.swift; path = Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift; sourceTree = ""; }; + 088BC7AE541E2B5846E908EC38A8043D /* BeEmpty.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeEmpty.swift; path = Sources/Nimble/Matchers/BeEmpty.swift; sourceTree = ""; }; + 08A6C9C6DDF4475FB935D46CFBB7C3FE /* QuickSelectedTestSuiteBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = QuickSelectedTestSuiteBuilder.swift; path = Sources/Quick/QuickSelectedTestSuiteBuilder.swift; sourceTree = ""; }; + 0CA42E725AA1BC788D14B8E085C8DF37 /* OCMStubRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMStubRecorder.h; path = Source/OCMock/OCMStubRecorder.h; sourceTree = ""; }; + 10FB066A127BFFFD865E4B4EEACD5073 /* Pods-Objective-C-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Objective-C-dummy.m"; sourceTree = ""; }; + 131262D643B0B521327E407C92585834 /* OCMInvocationMatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMInvocationMatcher.h; path = Source/OCMock/OCMInvocationMatcher.h; sourceTree = ""; }; + 13EC4E317B7B17F803A96AB19F03D67C /* CwlCatchBadInstruction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = CwlCatchBadInstruction.m; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m; sourceTree = ""; }; + 15E637B1786AA1682A8ACDE06F0C5EA9 /* DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DSL.swift; path = Sources/Nimble/DSL.swift; sourceTree = ""; }; + 16048E67F4F5838F45749AE0B084AE85 /* Pods-Objective-C.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Objective-C.debug.xcconfig"; sourceTree = ""; }; + 16922A80B5F583450F9CDFE96AB35D50 /* XCTestObservationCenter+Register.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "XCTestObservationCenter+Register.m"; path = "Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m"; sourceTree = ""; }; + 175DF4BE0B1017B4D5D4CB6081AC4B45 /* ServiceQueue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceQueue.swift; path = Sources/ServiceQueue.swift; sourceTree = ""; }; + 178363EA10143927B2A73BE53D75C5C6 /* NSObject+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+OCMAdditions.h"; path = "Source/OCMock/NSObject+OCMAdditions.h"; sourceTree = ""; }; + 1955D0701621AA1083EB133B11FFA0DA /* Quick.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Quick.xcconfig; sourceTree = ""; }; + 1A5BB201BD9BF5C9C87790A837F108F8 /* ErrorUtility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ErrorUtility.swift; path = Sources/Quick/ErrorUtility.swift; sourceTree = ""; }; + 1BF25C10228C211CE52ACD13EC78C48C /* Pods-Objective-CTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Objective-CTests-acknowledgements.markdown"; sourceTree = ""; }; + 1CFF6A991E06C066F8FA8EF520AE8829 /* FaroError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FaroError.swift; path = Sources/Error/FaroError.swift; sourceTree = ""; }; + 1D12BED901082321E8CFEC598BA2D70E /* NimbleXCTestHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NimbleXCTestHandler.swift; path = Sources/Nimble/Adapters/NimbleXCTestHandler.swift; sourceTree = ""; }; + 1DCCFE49D2AA7D774D2E50D7A5554D38 /* OCMVerifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMVerifier.h; path = Source/OCMock/OCMVerifier.h; sourceTree = ""; }; + 1F4572F7A638016C53B2D3770855145E /* World+DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "World+DSL.swift"; path = "Sources/Quick/DSL/World+DSL.swift"; sourceTree = ""; }; + 1FA359CDAEEA10BCC7E83B89E2A00E85 /* World.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = World.h; path = Sources/QuickObjectiveC/World.h; sourceTree = ""; }; + 2051AC723FB26CC4070611F36B8EA188 /* OCMRecorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMRecorder.m; path = Source/OCMock/OCMRecorder.m; sourceTree = ""; }; + 2169474468C959719E0C739FCF027BE6 /* OCMExpectationRecorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMExpectationRecorder.m; path = Source/OCMock/OCMExpectationRecorder.m; sourceTree = ""; }; + 229D5414BB786A871A70534E780D9A16 /* OCMBlockArgCaller.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMBlockArgCaller.h; path = Source/OCMock/OCMBlockArgCaller.h; sourceTree = ""; }; + 23341927F939A99D7618E49A339CBFDE /* JSONAdaptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = JSONAdaptor.swift; path = Sources/Adaptor/JSONAdaptor.swift; sourceTree = ""; }; + 23D7D79A61B7C74610B6088FF427AA34 /* JSONReader.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = JSONReader.swift; path = Sources/JSONReader.swift; sourceTree = ""; }; + 24BAC2ED093F5B48E100F4EE238CCE9C /* OCMLocation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMLocation.h; path = Source/OCMock/OCMLocation.h; sourceTree = ""; }; + 266DE843BBF26E21E8415D3748732254 /* EndWith.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EndWith.swift; path = Sources/Nimble/Matchers/EndWith.swift; sourceTree = ""; }; + 27447EB20550587F4B0328BB526DE709 /* QuickSpec.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QuickSpec.h; path = Sources/QuickObjectiveC/QuickSpec.h; sourceTree = ""; }; + 2748656F8759F1DF93B72762A568C88D /* OCMNotificationPoster.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMNotificationPoster.h; path = Source/OCMock/OCMNotificationPoster.h; sourceTree = ""; }; + 28AB5DBD0522552D27CE6066AA7F103A /* Pods-Objective-CTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Objective-CTests-acknowledgements.plist"; sourceTree = ""; }; + 292232F1B1C05570F4463F776EED58AE /* Pods-Objective-C-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Objective-C-resources.sh"; sourceTree = ""; }; + 2B6E61CBA24C69FF3E46D82ECA84E06E /* Faro-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Faro-umbrella.h"; sourceTree = ""; }; + 2BB64B08CA6FF3FDAA94F163970A0F77 /* OCObserverMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCObserverMockObject.h; path = Source/OCMock/OCObserverMockObject.h; sourceTree = ""; }; + 2C54D9C80B6B4F8DC4DAA27974B21EFE /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlBadInstructionException.swift; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift; sourceTree = ""; }; + 2C85CA8691A43CDBBA4B7605B6FCE4AD /* OCMBlockCaller.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMBlockCaller.m; path = Source/OCMock/OCMBlockCaller.m; sourceTree = ""; }; + 2CEEFF7743CDB1EA3DFFACB600DB9244 /* Pods-Objective-C.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Objective-C.release.xcconfig"; sourceTree = ""; }; + 2D460C9A1928BDDC623D597B52A4C553 /* NSValue+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSValue+OCMAdditions.m"; path = "Source/OCMock/NSValue+OCMAdditions.m"; sourceTree = ""; }; + 302CA5B370C8880A732ECC37A27E3BD1 /* OCMock-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OCMock-umbrella.h"; sourceTree = ""; }; + 3196E03A7BCE9105FFC25B9CF9D24D70 /* BeIdenticalTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeIdenticalTo.swift; path = Sources/Nimble/Matchers/BeIdenticalTo.swift; sourceTree = ""; }; + 3196F0CFC24ED7C4EE0BFF3062DF4E6C /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = Sources/Nimble/Utils/Errors.swift; sourceTree = ""; }; + 329B01B29C908A610BC407136CF28606 /* OCMock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMock.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 32D17A097B714278FFAB252E3FCF22E2 /* Adaptable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Adaptable.swift; path = Sources/Adaptor/Adaptable.swift; sourceTree = ""; }; + 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 34764871C1F32D2DF0A7C97BAAA92678 /* BeGreaterThanOrEqualTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeGreaterThanOrEqualTo.swift; path = Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift; sourceTree = ""; }; + 38B3CC3B48F33AD5745B7741791EBF1F /* Pods-Objective-C.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Objective-C.modulemap"; sourceTree = ""; }; + 39C2F9228C71CF526F9542DED335C294 /* QuickConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QuickConfiguration.m; path = Sources/QuickObjectiveC/Configuration/QuickConfiguration.m; sourceTree = ""; }; + 3AD34968E9AAB6CCEE822821FAF06EA1 /* MatchError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatchError.swift; path = Sources/Nimble/Matchers/MatchError.swift; sourceTree = ""; }; + 3B57F6B10C1624BF9CACAF60FF6008AF /* Pods_Objective_C.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Objective_C.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3BB7757F5B3ABEF9532ED971B16BE7EB /* Pods-Objective-C-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Objective-C-acknowledgements.plist"; sourceTree = ""; }; + 3E9CCC68588CEB5C4FDA0098BFA1B0B9 /* OCMObserverRecorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMObserverRecorder.m; path = Source/OCMock/OCMObserverRecorder.m; sourceTree = ""; }; + 3F5FDBCD14BDCB054BC8F13764534368 /* BeLessThanOrEqual.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLessThanOrEqual.swift; path = Sources/Nimble/Matchers/BeLessThanOrEqual.swift; sourceTree = ""; }; + 40B48EF63540BB3A0D8EE11FB1A73F62 /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 40E6319955D53643D206E339870036D2 /* Quick.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Quick.modulemap; sourceTree = ""; }; + 4237A12880574E77B830212EB4596EBF /* World.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = World.swift; path = Sources/Quick/World.swift; sourceTree = ""; }; + 424988859F380BE3FCA69FC5A5300A1D /* NSValue+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSValue+OCMAdditions.h"; path = "Source/OCMock/NSValue+OCMAdditions.h"; sourceTree = ""; }; + 430BEAB384EF23E18AB55404F45B500A /* OCMMacroState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMMacroState.h; path = Source/OCMock/OCMMacroState.h; sourceTree = ""; }; + 4317F0673AE4243F95EB140825A60B7F /* Deserializable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Deserializable.swift; path = Sources/Deserialize/Deserializable.swift; sourceTree = ""; }; + 440F12D9E2F445F41FCCA0B785A2F836 /* BeginWith.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeginWith.swift; path = Sources/Nimble/Matchers/BeginWith.swift; sourceTree = ""; }; + 4462A2F84912074D21DB4E7CA49167FC /* ThrowAssertion.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ThrowAssertion.swift; path = Sources/Nimble/Matchers/ThrowAssertion.swift; sourceTree = ""; }; + 449378DE182400BF22C43323CDA70CDC /* Faro-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Faro-dummy.m"; sourceTree = ""; }; + 44B19049B0308546117F80A8F637C792 /* ExampleMetadata.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleMetadata.swift; path = Sources/Quick/ExampleMetadata.swift; sourceTree = ""; }; + 479AF0F07D0B0287D6BCD7EC600A5E37 /* Stringers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Stringers.swift; path = Sources/Nimble/Utils/Stringers.swift; sourceTree = ""; }; + 47E283B8196008FDB29580D733364660 /* DSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DSL.h; path = Sources/NimbleObjectiveC/DSL.h; sourceTree = ""; }; + 488EB785E17F22A933DE2766C460EBB6 /* MockSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MockSession.swift; path = Sources/MockSession.swift; sourceTree = ""; }; + 494F6E32A484C7DD0328F446A182062B /* Nimble-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Nimble-prefix.pch"; sourceTree = ""; }; + 49E9887DA589CE1D767C5432D5EF03AF /* CurrentTestCaseTracker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CurrentTestCaseTracker.h; path = Sources/NimbleObjectiveC/CurrentTestCaseTracker.h; sourceTree = ""; }; + 4B2D0C101D41CD176370670B665B469A /* Pods-Objective-CTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Objective-CTests-frameworks.sh"; sourceTree = ""; }; + 4BB30625660AB607FB8E3575225C29D4 /* Match.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Match.swift; path = Sources/Nimble/Matchers/Match.swift; sourceTree = ""; }; + 4C5B0B661BE17B10DD3AB8BF20397B0B /* mach_excServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mach_excServer.h; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h; sourceTree = ""; }; + 4F015F21170F9DA1A4DA6C5C6F52DF38 /* Functional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Functional.swift; path = Sources/Nimble/Utils/Functional.swift; sourceTree = ""; }; + 50574C3D7DF684F07948CA1A258AFC94 /* OCMNotificationPoster.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMNotificationPoster.m; path = Source/OCMock/OCMNotificationPoster.m; sourceTree = ""; }; + 517CD3179A8CE261D89E642892BD4F7D /* Faro.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Faro.modulemap; sourceTree = ""; }; + 52DC61C441864F619A3E199E65EE6929 /* BeAnInstanceOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeAnInstanceOf.swift; path = Sources/Nimble/Matchers/BeAnInstanceOf.swift; sourceTree = ""; }; + 53C47ADC55EE591D376E5130494D3103 /* SourceLocation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SourceLocation.swift; path = Sources/Nimble/Utils/SourceLocation.swift; sourceTree = ""; }; + 5502FB0000811E1CE290E375DA48C225 /* OCMock-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "OCMock-dummy.m"; sourceTree = ""; }; + 56837149D3B326D000FE3F548D98F9E5 /* BeLessThan.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLessThan.swift; path = Sources/Nimble/Matchers/BeLessThan.swift; sourceTree = ""; }; + 569076F80E248EA1DE57361C916957AA /* NMBStringify.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NMBStringify.m; path = Sources/NimbleObjectiveC/NMBStringify.m; sourceTree = ""; }; + 56EEF5B5C1579A07C7A11F798287D5FF /* BeGreaterThan.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeGreaterThan.swift; path = Sources/Nimble/Matchers/BeGreaterThan.swift; sourceTree = ""; }; + 59A395EF59AF7711A15508D3B5F0C5C0 /* RaisesException.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RaisesException.swift; path = Sources/Nimble/Matchers/RaisesException.swift; sourceTree = ""; }; + 59EA412FBF3C72496F43540928A9643A /* ErrorPrinting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ErrorPrinting.swift; path = Sources/Error/ErrorPrinting.swift; sourceTree = ""; }; + 5B9B78E3720DC751A90BD5C21D05C774 /* NMBStringify.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NMBStringify.h; path = Sources/NimbleObjectiveC/NMBStringify.h; sourceTree = ""; }; + 5C3C3174A1881CC23CDE7F0A082A2553 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5C449EDFDDB7185886E70C427C7811C8 /* NSString+C99ExtendedIdentifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSString+C99ExtendedIdentifier.swift"; path = "Sources/Quick/NSString+C99ExtendedIdentifier.swift"; sourceTree = ""; }; + 5C5F184BCA8F3494CCF89439247DBF87 /* Pods-Objective-CTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Objective-CTests-dummy.m"; sourceTree = ""; }; + 5DAF2C746A0A017C15BD9577E4637F15 /* OCMFunctions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMFunctions.h; path = Source/OCMock/OCMFunctions.h; sourceTree = ""; }; + 5F52F8F231445D2D63341BABC3551852 /* Nimble.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Nimble.xcconfig; sourceTree = ""; }; + 611CBF0BB7483B56ACD6A64ADFC894FE /* OCMBoxedReturnValueProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMBoxedReturnValueProvider.h; path = Source/OCMock/OCMBoxedReturnValueProvider.h; sourceTree = ""; }; + 619BB7A22883B7B2E5A221513014313C /* NSObject+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+OCMAdditions.m"; path = "Source/OCMock/NSObject+OCMAdditions.m"; sourceTree = ""; }; + 619DF9020189CFD375CFD8B33A8AFEB6 /* ExampleHooks.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleHooks.swift; path = Sources/Quick/Hooks/ExampleHooks.swift; sourceTree = ""; }; + 625F5B8D9A5E5241326DB676D4CA4E98 /* Pods-Objective-C-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Objective-C-umbrella.h"; sourceTree = ""; }; + 64BD74BB6D364B8C9BF5A55D5F435D64 /* NimbleEnvironment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NimbleEnvironment.swift; path = Sources/Nimble/Adapters/NimbleEnvironment.swift; sourceTree = ""; }; + 65015122FB42E5A77EE57E47451C0036 /* Faro.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Faro.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 65EB3A4DB318A893542FB6A8242E425A /* DSL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DSL.m; path = Sources/NimbleObjectiveC/DSL.m; sourceTree = ""; }; + 6627A5066D4FA2A4F3183603ECD72427 /* OCMReturnValueProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMReturnValueProvider.m; path = Source/OCMock/OCMReturnValueProvider.m; sourceTree = ""; }; + 677FBE720E59F083FEA6C3A79B1F5CE9 /* Filter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filter.swift; path = Sources/Quick/Filter.swift; sourceTree = ""; }; + 67B5CD7F90676965355E5F8A58763CFA /* mach_excServer.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; name = mach_excServer.c; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c; sourceTree = ""; }; + 6B21942C7D947127C4EC619A10D8C7A6 /* ParameterEnum.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEnum.swift; path = Sources/ParameterEnum.swift; sourceTree = ""; }; + 6BF2DCE604BA5C282E0BE5B85CB00B7F /* AssertionRecorder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssertionRecorder.swift; path = Sources/Nimble/Adapters/AssertionRecorder.swift; sourceTree = ""; }; + 6C06DDE9D47475D20BD34B4CF21FCAA8 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlDarwinDefinitions.swift; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift; sourceTree = ""; }; + 6C99905C8DB11FA8B11C51A528FD5CC5 /* OCMPassByRefSetter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMPassByRefSetter.h; path = Source/OCMock/OCMPassByRefSetter.h; sourceTree = ""; }; + 6CD210F446F274ADDF9BB2CC88723580 /* ThrowError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ThrowError.swift; path = Sources/Nimble/Matchers/ThrowError.swift; sourceTree = ""; }; + 6DA44C87AB51E7A2D45482E922336410 /* Quick-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Quick-umbrella.h"; sourceTree = ""; }; + 6E635935B36C0E759C0C146D13956EB2 /* OCMReturnValueProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMReturnValueProvider.h; path = Source/OCMock/OCMReturnValueProvider.h; sourceTree = ""; }; + 6F37A03A2B9DD962C48ABA116B6138A4 /* BeVoid.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeVoid.swift; path = Sources/Nimble/Matchers/BeVoid.swift; sourceTree = ""; }; + 701A528296F7DDEE6AF18D6221EA6126 /* BeLogical.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLogical.swift; path = Sources/Nimble/Matchers/BeLogical.swift; sourceTree = ""; }; + 71290B8EFD4F2112C1B10D1E1456BBB7 /* MatcherProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatcherProtocols.swift; path = Sources/Nimble/Matchers/MatcherProtocols.swift; sourceTree = ""; }; + 719A5DB86ADF4CEF7E34D72CB175D36E /* OCObserverMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCObserverMockObject.m; path = Source/OCMock/OCObserverMockObject.m; sourceTree = ""; }; + 72F9E3CC6AB1E9D7A424DDF6093BC559 /* Example.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Example.swift; path = Sources/Quick/Example.swift; sourceTree = ""; }; + 74356A33E3762DCFA90AF009639CD2DA /* OCMConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMConstraint.m; path = Source/OCMock/OCMConstraint.m; sourceTree = ""; }; + 74652B094B794A4F1132199C493A63F9 /* OCMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMockObject.h; path = Source/OCMock/OCMockObject.h; sourceTree = ""; }; + 74D72971A42D77BB86326B203C1457BE /* Closures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Closures.swift; path = Sources/Quick/Hooks/Closures.swift; sourceTree = ""; }; + 75F5E38DA4836420522A574969A89E06 /* Pods-Objective-CTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Objective-CTests.modulemap"; sourceTree = ""; }; + 7659A8D54A36194CF322D3B98EB2FCA7 /* Expression.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expression.swift; path = Sources/Nimble/Expression.swift; sourceTree = ""; }; + 76DDA5D300FF3EE51C7BBC48CA21E979 /* BeAKindOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeAKindOf.swift; path = Sources/Nimble/Matchers/BeAKindOf.swift; sourceTree = ""; }; + 7A6042939A32620F014384C86FD5CBE2 /* OCMArg.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMArg.h; path = Source/OCMock/OCMArg.h; sourceTree = ""; }; + 7B3BC02D8B8967D44B9CAE0BDABA9979 /* OCMFunctions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMFunctions.m; path = Source/OCMock/OCMFunctions.m; sourceTree = ""; }; + 7D7CF9F89C4BBECC41DE6F211618FDAD /* OCMock-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OCMock-prefix.pch"; sourceTree = ""; }; + 7EA867E606E14C0872561F83652E84CF /* AssertionDispatcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssertionDispatcher.swift; path = Sources/Nimble/Adapters/AssertionDispatcher.swift; sourceTree = ""; }; + 814EDFF45B3ADC2BCB0BBA17372353F9 /* QuickSpec.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QuickSpec.m; path = Sources/QuickObjectiveC/QuickSpec.m; sourceTree = ""; }; + 83502779789D0516E709DF9ACCFE9468 /* NSMethodSignature+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMethodSignature+OCMAdditions.m"; path = "Source/OCMock/NSMethodSignature+OCMAdditions.m"; sourceTree = ""; }; + 8385073FF1FC52F9986F8809736A8115 /* CwlCatchBadInstruction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CwlCatchBadInstruction.h; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h; sourceTree = ""; }; + 85BF2DAB6137E8AB33AB39E81AC398E7 /* SerializeOperators.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SerializeOperators.swift; path = Sources/Serialize/SerializeOperators.swift; sourceTree = ""; }; + 85C021FBB437212FDD7ACE16E8C938A6 /* OCMBlockCaller.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMBlockCaller.h; path = Source/OCMock/OCMBlockCaller.h; sourceTree = ""; }; + 86712ACD792328965934C8E4598790C5 /* BeCloseTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeCloseTo.swift; path = Sources/Nimble/Matchers/BeCloseTo.swift; sourceTree = ""; }; + 87DAAD46F1B7147C89D44E670B574A6E /* OCMVerifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMVerifier.m; path = Source/OCMock/OCMVerifier.m; sourceTree = ""; }; + 886BFCC81C9DFAD3953DB628C804AF0C /* DateParser.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DateParser.swift; path = Sources/DateParser.swift; sourceTree = ""; }; + 88FFA5B6104280C84A5334A672FA2209 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = Sources/Configuration.swift; sourceTree = ""; }; + 890F317A22755FCB5B52E5476D38CEEE /* Nimble.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Nimble.h; path = Sources/Nimble/Nimble.h; sourceTree = ""; }; + 8912EA8E035414AD25D99ACF380BECF4 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 896260E35229AA52016418546468F017 /* Service.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Service.swift; path = Sources/Service.swift; sourceTree = ""; }; + 8B3DAA212362983A0234B64FBF292FDB /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = Sources/Quick/Configuration/Configuration.swift; sourceTree = ""; }; + 8B877F4EC6304092C86F89BB5AA7EE76 /* Serializable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Serializable.swift; path = Sources/Serialize/Serializable.swift; sourceTree = ""; }; + 8D42487135E21EE53A8378138FBB6B14 /* ExampleGroup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleGroup.swift; path = Sources/Quick/ExampleGroup.swift; sourceTree = ""; }; + 8E5DEEB028078566503617AC8EC42FC1 /* OCMRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMRecorder.h; path = Source/OCMock/OCMRecorder.h; sourceTree = ""; }; + 8E7EA82F9F7487BF9876330B934F58C2 /* NSInvocation+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSInvocation+OCMAdditions.h"; path = "Source/OCMock/NSInvocation+OCMAdditions.h"; sourceTree = ""; }; + 8EFDEC734F4BF1E9C076BC02F6765C8A /* NSNotificationCenter+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSNotificationCenter+OCMAdditions.h"; path = "Source/OCMock/NSNotificationCenter+OCMAdditions.h"; sourceTree = ""; }; + 925685DE04283B4215A8F3B4D0C5F713 /* OCMRealObjectForwarder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMRealObjectForwarder.m; path = Source/OCMock/OCMRealObjectForwarder.m; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9700521F2B4193A044A781A80B9AE998 /* CwlCatchException.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = CwlCatchException.m; path = Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m; sourceTree = ""; }; + 97B3C6B8D47B66B14F7FF22821423917 /* DSL+Wait.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DSL+Wait.swift"; path = "Sources/Nimble/DSL+Wait.swift"; sourceTree = ""; }; + 98850039C4F804F91DF520C56800F674 /* OCMArgAction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMArgAction.h; path = Source/OCMock/OCMArgAction.h; sourceTree = ""; }; + 99B3E4ACD71BF0C25226E2EF483E00D2 /* Nimble.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Nimble.modulemap; sourceTree = ""; }; + 9A1FCFACE537FA1A2D7A55FDFED06A01 /* MockService.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MockService.swift; path = Sources/MockService.swift; sourceTree = ""; }; + 9A8DF6B5676E97E498CFB3893655C882 /* OCMInvocationMatcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMInvocationMatcher.m; path = Source/OCMock/OCMInvocationMatcher.m; sourceTree = ""; }; + 9ACB8301A60C48C42EB67A0F23684703 /* XCTestSuite+QuickTestSuiteBuilder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "XCTestSuite+QuickTestSuiteBuilder.m"; path = "Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m"; sourceTree = ""; }; + 9ACE2FA7D2EF192CA34044B1AD47ABE1 /* ServiceConvenienceExtension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceConvenienceExtension.swift; path = Sources/ServiceConvenienceExtension.swift; sourceTree = ""; }; + 9B08559C758F7143032F9260EBBB2BD8 /* OCMInvocationStub.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMInvocationStub.m; path = Source/OCMock/OCMInvocationStub.m; sourceTree = ""; }; + 9B5D821EABCECCD30415450CAC661FB3 /* OCMMacroState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMMacroState.m; path = Source/OCMock/OCMMacroState.m; sourceTree = ""; }; + 9B61EE0ECD44A33AC1241DA949C8BC1C /* AllPass.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AllPass.swift; path = Sources/Nimble/Matchers/AllPass.swift; sourceTree = ""; }; + 9B932CDAD8906CB1DE98972235602044 /* QCKDSL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QCKDSL.m; path = Sources/QuickObjectiveC/DSL/QCKDSL.m; sourceTree = ""; }; + 9CE599F68154101800B9EF2B199AE852 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9E099104B165EE8F1C4A492B330574D2 /* OCMInvocationExpectation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMInvocationExpectation.h; path = Source/OCMock/OCMInvocationExpectation.h; sourceTree = ""; }; + 9ECCEF1AE64AB2737FCA2A75F0760E89 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Sources/Result.swift; sourceTree = ""; }; + A0537C3FE7FB2F62CEDDF7F13B8D0F29 /* OCMStubRecorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMStubRecorder.m; path = Source/OCMock/OCMStubRecorder.m; sourceTree = ""; }; + A2FD9E3F0AB004599D07FA46089D094B /* OCMExpectationRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMExpectationRecorder.h; path = Source/OCMock/OCMExpectationRecorder.h; sourceTree = ""; }; + A31C891DE1CAE112530DB2E7E424C86A /* SatisfyAnyOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SatisfyAnyOf.swift; path = Sources/Nimble/Matchers/SatisfyAnyOf.swift; sourceTree = ""; }; + A4EBD4A49844BD4CC6B4B699DCAFC134 /* OCMIndirectReturnValueProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMIndirectReturnValueProvider.m; path = Source/OCMock/OCMIndirectReturnValueProvider.m; sourceTree = ""; }; + A53BB1419B785A0FD04D021466A95D63 /* Pods-Objective-CTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Objective-CTests.release.xcconfig"; sourceTree = ""; }; + A60AC7A612EF03420A75BF5AB7B64698 /* Nimble-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Nimble-umbrella.h"; sourceTree = ""; }; + A660BC2F3FE238E4DBF50BAD1BFC9CE3 /* Pods-Objective-CTests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Objective-CTests-resources.sh"; sourceTree = ""; }; + A6FB4B10B6FC72106523B7A8B84EFC63 /* OCMFunctionsPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMFunctionsPrivate.h; path = Source/OCMock/OCMFunctionsPrivate.h; sourceTree = ""; }; + A9E2C82DA706FF783924DEB5E982CA0C /* Pods_Objective_CTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Objective_CTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + AA397E648B4C103FB8B6C5386529D697 /* OCMLocation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMLocation.m; path = Source/OCMock/OCMLocation.m; sourceTree = ""; }; + AAC925078508A0E70D092652F350C58E /* OCMock.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = OCMock.xcconfig; sourceTree = ""; }; + AECEA2EDA41473899EE391CA038EDC38 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + AF046C56A407E6D26F32C9B6368E6FB6 /* Pods-Objective-C-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Objective-C-acknowledgements.markdown"; sourceTree = ""; }; + B127F55EADAC4535E8A9FFCAEFD60744 /* OCMInvocationStub.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMInvocationStub.h; path = Source/OCMock/OCMInvocationStub.h; sourceTree = ""; }; + B1CA4CFFF78F749A082386D8B88B4507 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B3D76125FCC36E6FC71570FD9832BC1C /* Equal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Equal.swift; path = Sources/Nimble/Matchers/Equal.swift; sourceTree = ""; }; + B428B850CA5D63C24F4946A74E78C5B6 /* NMBObjCMatcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NMBObjCMatcher.swift; path = Sources/Nimble/Adapters/NMBObjCMatcher.swift; sourceTree = ""; }; + B48D54793862AA2302F5E16E028E382E /* QuickSpecBase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QuickSpecBase.m; path = Sources/QuickSpecBase/QuickSpecBase.m; sourceTree = ""; }; + B572EA694ECD0DEE474414124B2D0C04 /* AdapterProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdapterProtocols.swift; path = Sources/Nimble/Adapters/AdapterProtocols.swift; sourceTree = ""; }; + B617734E153AB73823D5CE893ECB0426 /* Faro.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Faro.xcconfig; sourceTree = ""; }; + B90D72876497A4309472CC39D0C9CECC /* OCMock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMock.h; path = Source/OCMock/OCMock.h; sourceTree = ""; }; + B9F2278D55DE315CA3067DD2E21434F3 /* OCMExceptionReturnValueProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMExceptionReturnValueProvider.m; path = Source/OCMock/OCMExceptionReturnValueProvider.m; sourceTree = ""; }; + BA290B4864ABFCA9459B007FA1B6562E /* OCPartialMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCPartialMockObject.h; path = Source/OCMock/OCPartialMockObject.h; sourceTree = ""; }; + BB9769B91E691ADE611F7F6AC681D52F /* MatcherFunc.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatcherFunc.swift; path = Sources/Nimble/Matchers/MatcherFunc.swift; sourceTree = ""; }; + BC9296A5869224FBE565BA60A0A0D6C7 /* FaroService.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FaroService.swift; path = Sources/FaroService.swift; sourceTree = ""; }; + BF557F810F703A2A207CE481103495AF /* OCMRealObjectForwarder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMRealObjectForwarder.h; path = Source/OCMock/OCMRealObjectForwarder.h; sourceTree = ""; }; + C0015224404262544DE7B83E7954AD52 /* OCMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMockObject.m; path = Source/OCMock/OCMockObject.m; sourceTree = ""; }; + C0341FB69A58995B563731DE709F5AD4 /* OCMBoxedReturnValueProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMBoxedReturnValueProvider.m; path = Source/OCMock/OCMBoxedReturnValueProvider.m; sourceTree = ""; }; + C2DDC74B6B7A9622CE36D390BCE6A9EC /* HaveCount.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HaveCount.swift; path = Sources/Nimble/Matchers/HaveCount.swift; sourceTree = ""; }; + C542C1EE5B7A348F6DAA30969D04E886 /* NSBundle+CurrentTestBundle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+CurrentTestBundle.swift"; path = "Sources/Quick/NSBundle+CurrentTestBundle.swift"; sourceTree = ""; }; + C5A58AC25DF1C7D8DDB5851AC43E3BB2 /* OCMPassByRefSetter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMPassByRefSetter.m; path = Source/OCMock/OCMPassByRefSetter.m; sourceTree = ""; }; + C5FCBD308AF6B1756A280ADD0DEF666F /* Expectation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expectation.swift; path = Sources/Nimble/Expectation.swift; sourceTree = ""; }; + C71C74B4921D91CD6BCC28E9A98B64AF /* DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DSL.swift; path = Sources/Quick/DSL/DSL.swift; sourceTree = ""; }; + C88BE5ABF5325A3D9C0E56A03A31F1CA /* DeserializeOperators.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeserializeOperators.swift; path = Sources/Deserialize/DeserializeOperators.swift; sourceTree = ""; }; + C9886CF6FFF7821226D662199CD2D435 /* NMBExpectation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NMBExpectation.swift; path = Sources/Nimble/Adapters/NMBExpectation.swift; sourceTree = ""; }; + C9BE0907DCCA28A7E577F744CBE6EC43 /* URL+FileName.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URL+FileName.swift"; path = "Sources/Quick/URL+FileName.swift"; sourceTree = ""; }; + CA1705A49E8A8002453BD92191AAC0E8 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D12432C8F19A8A53C50313F6DFEC46C2 /* Quick-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Quick-prefix.pch"; sourceTree = ""; }; + D170774DC82F46FDAA65C9AC2856B469 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D1F44AAB15A4E7B7605C6769D734E47B /* BeNil.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeNil.swift; path = Sources/Nimble/Matchers/BeNil.swift; sourceTree = ""; }; + D2AB251AF671293C30BCA11CB42CD39C /* OCProtocolMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCProtocolMockObject.m; path = Source/OCMock/OCProtocolMockObject.m; sourceTree = ""; }; + D54B25F7B345B1640ECA299C5889329F /* OCMInvocationExpectation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMInvocationExpectation.m; path = Source/OCMock/OCMInvocationExpectation.m; sourceTree = ""; }; + D63F54AEE93CA155C4E1499D441E66D9 /* World+DSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "World+DSL.h"; path = "Sources/QuickObjectiveC/DSL/World+DSL.h"; sourceTree = ""; }; + D69172D8E3DDB58A086A167DDC4CFFE6 /* OCClassMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCClassMockObject.h; path = Source/OCMock/OCClassMockObject.h; sourceTree = ""; }; + D698EBAA6379D206E4C776A658BFD31B /* OCMArgAction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMArgAction.m; path = Source/OCMock/OCMArgAction.m; sourceTree = ""; }; + D6A1375347C3B187910D2A7D07A5E082 /* Pods-Objective-CTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Objective-CTests-umbrella.h"; sourceTree = ""; }; + D8BC502DFDFDA1D3F79A7278155B46C3 /* NSMethodSignature+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMethodSignature+OCMAdditions.h"; path = "Source/OCMock/NSMethodSignature+OCMAdditions.h"; sourceTree = ""; }; + D9569ED31D7F19786D9EE4502A715AE3 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D9CB429A7827557A08631629B18A51EA /* QCKDSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QCKDSL.h; path = Sources/QuickObjectiveC/DSL/QCKDSL.h; sourceTree = ""; }; + D9F018CD70EE3E8DB4B9F765AC613579 /* Call.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Call.swift; path = Sources/Call.swift; sourceTree = ""; }; + DA53CE8AF9DD3E17F0C70EFB0FD27405 /* QuickTestSuite.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = QuickTestSuite.swift; path = Sources/Quick/QuickTestSuite.swift; sourceTree = ""; }; + DA5B03D30A3F817B663600B243F47B4D /* Quick-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Quick-dummy.m"; sourceTree = ""; }; + DB34B3D8F257A7890CE9F8EA883FF85A /* Nimble-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Nimble-dummy.m"; sourceTree = ""; }; + DC9527D93007FDED4F2B30FE9E46F21C /* OCMArg.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMArg.m; path = Source/OCMock/OCMArg.m; sourceTree = ""; }; + DCF3EA03FE9BD48F53AAA80396506128 /* Quick.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Quick.h; path = Sources/QuickObjectiveC/Quick.h; sourceTree = ""; }; + DD78AC2ECB2F447DEB1BAF68ABB3EE06 /* CwlCatchException.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CwlCatchException.h; path = Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h; sourceTree = ""; }; + DDB7180F398749CE8A83A3562CD47A7C /* FailureMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FailureMessage.swift; path = Sources/Nimble/FailureMessage.swift; sourceTree = ""; }; + DE43844F164FE3F918256B570F0777EB /* Callsite.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Callsite.swift; path = Sources/Quick/Callsite.swift; sourceTree = ""; }; + DF2EE9D65678DA76E5F21EB3E845301B /* NMBExceptionCapture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NMBExceptionCapture.m; path = Sources/NimbleObjectiveC/NMBExceptionCapture.m; sourceTree = ""; }; + DF9CFE075C5D35C4EE1B13EC9679F90A /* OCMExceptionReturnValueProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMExceptionReturnValueProvider.h; path = Source/OCMock/OCMExceptionReturnValueProvider.h; sourceTree = ""; }; + E127D5052F1A017C30FD3662C466C67F /* OCClassMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCClassMockObject.m; path = Source/OCMock/OCClassMockObject.m; sourceTree = ""; }; + E4B98F25D27824128D54C5C5A19BBE9C /* SuiteHooks.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SuiteHooks.swift; path = Sources/Quick/Hooks/SuiteHooks.swift; sourceTree = ""; }; + E9A22019596EFBBF25C3EF6A600143A4 /* PostNotification.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PostNotification.swift; path = Sources/Nimble/Matchers/PostNotification.swift; sourceTree = ""; }; + EAF49C8C3DD8025331B7F158EB13ABB1 /* DeserializeFunctions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeserializeFunctions.swift; path = Sources/Deserialize/DeserializeFunctions.swift; sourceTree = ""; }; + EB37ABD2DE8F664796C0EE3907B043B6 /* Contain.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Contain.swift; path = Sources/Nimble/Matchers/Contain.swift; sourceTree = ""; }; + EBF2BAC92509FAAEA0779082C1C322E5 /* QuickSpecBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QuickSpecBase.h; path = Sources/QuickSpecBase/include/QuickSpecBase.h; sourceTree = ""; }; + EDE023D2ABB9C849FE7025EDFBE651F9 /* OCPartialMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCPartialMockObject.m; path = Source/OCMock/OCPartialMockObject.m; sourceTree = ""; }; + EE3FA4B2CA33BBD6A99D9FF6155E7A3F /* Faro-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Faro-prefix.pch"; sourceTree = ""; }; + EF02E46AB54FD2B8F9059547A6BC8066 /* OCMBlockArgCaller.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMBlockArgCaller.m; path = Source/OCMock/OCMBlockArgCaller.m; sourceTree = ""; }; + EF5CA75DFE5280DCCE30B1B962314F73 /* ContainElementSatisfying.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContainElementSatisfying.swift; path = Sources/Nimble/Matchers/ContainElementSatisfying.swift; sourceTree = ""; }; + F136A722EA31CAC77AB2BB3BE4D28654 /* Async.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Async.swift; path = Sources/Nimble/Utils/Async.swift; sourceTree = ""; }; + F1911C129343485A3A9CBCB3433191C3 /* OCMIndirectReturnValueProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMIndirectReturnValueProvider.h; path = Source/OCMock/OCMIndirectReturnValueProvider.h; sourceTree = ""; }; + F5C88B178AD14CC52279BE25D75C2A72 /* NSNotificationCenter+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSNotificationCenter+OCMAdditions.m"; path = "Source/OCMock/NSNotificationCenter+OCMAdditions.m"; sourceTree = ""; }; + F86F386D72616F0543B86738A2B974D8 /* HooksPhase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HooksPhase.swift; path = Sources/Quick/Hooks/HooksPhase.swift; sourceTree = ""; }; + FA32FFDFF86560AD2CE21BE9A9E5E696 /* NMBExceptionCapture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NMBExceptionCapture.h; path = Sources/NimbleObjectiveC/NMBExceptionCapture.h; sourceTree = ""; }; + FA76FC1B69882F1CF1D2719EC89ABD6F /* Pods-Objective-CTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Objective-CTests.debug.xcconfig"; sourceTree = ""; }; + FB4E3DAA9766B7D4A44B58DCC3D24F84 /* QuickConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QuickConfiguration.h; path = Sources/QuickObjectiveC/Configuration/QuickConfiguration.h; sourceTree = ""; }; + FBA25F5226E62D1B78172E014CFA2DD2 /* AsyncMatcherWrapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AsyncMatcherWrapper.swift; path = Sources/Nimble/Matchers/AsyncMatcherWrapper.swift; sourceTree = ""; }; + FD48E0253E7CEB78DAFEC9CECBB49D81 /* NSInvocation+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSInvocation+OCMAdditions.m"; path = "Source/OCMock/NSInvocation+OCMAdditions.m"; sourceTree = ""; }; + FD7B955E6DE6F1E00CAFB564C49D3910 /* OCMObserverRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMObserverRecorder.h; path = Source/OCMock/OCMObserverRecorder.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 37F4BB7AF5C3CD484ECFE696DE6E0B96 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9CFDCD6DF628E2A14C68C468E3FE437F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7D29925DDA06F94E7C818CA2403C1B0B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CC2C1A15C25533A85E0EF848B23F702A /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 86B474E76B80DCB721C6FF063561ACD0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5362A4223DA7F71617F6928579053CFB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A0673853CCFEF089C0BF4D09E710CC4F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C710B6A7B1A479349273B3AC04CF07C5 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C29091602A1A8C14808F5C8AD7CC9DD9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 56164F20A216AB17E39F748455590953 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FE5E7B87C12F692A60CE1465BD209155 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 99B1107CE4EADFBF179C43FE3487D045 /* Foundation.framework in Frameworks */, + A39D312940A4B6EDA53103B77E32C93A /* XCTest.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0CB5FCD428EC580F68D63BD23ADB94F5 /* OCMock */ = { + isa = PBXGroup; + children = ( + 8E7EA82F9F7487BF9876330B934F58C2 /* NSInvocation+OCMAdditions.h */, + FD48E0253E7CEB78DAFEC9CECBB49D81 /* NSInvocation+OCMAdditions.m */, + D8BC502DFDFDA1D3F79A7278155B46C3 /* NSMethodSignature+OCMAdditions.h */, + 83502779789D0516E709DF9ACCFE9468 /* NSMethodSignature+OCMAdditions.m */, + 8EFDEC734F4BF1E9C076BC02F6765C8A /* NSNotificationCenter+OCMAdditions.h */, + F5C88B178AD14CC52279BE25D75C2A72 /* NSNotificationCenter+OCMAdditions.m */, + 178363EA10143927B2A73BE53D75C5C6 /* NSObject+OCMAdditions.h */, + 619BB7A22883B7B2E5A221513014313C /* NSObject+OCMAdditions.m */, + 424988859F380BE3FCA69FC5A5300A1D /* NSValue+OCMAdditions.h */, + 2D460C9A1928BDDC623D597B52A4C553 /* NSValue+OCMAdditions.m */, + D69172D8E3DDB58A086A167DDC4CFFE6 /* OCClassMockObject.h */, + E127D5052F1A017C30FD3662C466C67F /* OCClassMockObject.m */, + 7A6042939A32620F014384C86FD5CBE2 /* OCMArg.h */, + DC9527D93007FDED4F2B30FE9E46F21C /* OCMArg.m */, + 98850039C4F804F91DF520C56800F674 /* OCMArgAction.h */, + D698EBAA6379D206E4C776A658BFD31B /* OCMArgAction.m */, + 229D5414BB786A871A70534E780D9A16 /* OCMBlockArgCaller.h */, + EF02E46AB54FD2B8F9059547A6BC8066 /* OCMBlockArgCaller.m */, + 85C021FBB437212FDD7ACE16E8C938A6 /* OCMBlockCaller.h */, + 2C85CA8691A43CDBBA4B7605B6FCE4AD /* OCMBlockCaller.m */, + 611CBF0BB7483B56ACD6A64ADFC894FE /* OCMBoxedReturnValueProvider.h */, + C0341FB69A58995B563731DE709F5AD4 /* OCMBoxedReturnValueProvider.m */, + 04650C15A3E1EEAE92B072F94F1008A2 /* OCMConstraint.h */, + 74356A33E3762DCFA90AF009639CD2DA /* OCMConstraint.m */, + DF9CFE075C5D35C4EE1B13EC9679F90A /* OCMExceptionReturnValueProvider.h */, + B9F2278D55DE315CA3067DD2E21434F3 /* OCMExceptionReturnValueProvider.m */, + A2FD9E3F0AB004599D07FA46089D094B /* OCMExpectationRecorder.h */, + 2169474468C959719E0C739FCF027BE6 /* OCMExpectationRecorder.m */, + 5DAF2C746A0A017C15BD9577E4637F15 /* OCMFunctions.h */, + 7B3BC02D8B8967D44B9CAE0BDABA9979 /* OCMFunctions.m */, + A6FB4B10B6FC72106523B7A8B84EFC63 /* OCMFunctionsPrivate.h */, + F1911C129343485A3A9CBCB3433191C3 /* OCMIndirectReturnValueProvider.h */, + A4EBD4A49844BD4CC6B4B699DCAFC134 /* OCMIndirectReturnValueProvider.m */, + 9E099104B165EE8F1C4A492B330574D2 /* OCMInvocationExpectation.h */, + D54B25F7B345B1640ECA299C5889329F /* OCMInvocationExpectation.m */, + 131262D643B0B521327E407C92585834 /* OCMInvocationMatcher.h */, + 9A8DF6B5676E97E498CFB3893655C882 /* OCMInvocationMatcher.m */, + B127F55EADAC4535E8A9FFCAEFD60744 /* OCMInvocationStub.h */, + 9B08559C758F7143032F9260EBBB2BD8 /* OCMInvocationStub.m */, + 24BAC2ED093F5B48E100F4EE238CCE9C /* OCMLocation.h */, + AA397E648B4C103FB8B6C5386529D697 /* OCMLocation.m */, + 430BEAB384EF23E18AB55404F45B500A /* OCMMacroState.h */, + 9B5D821EABCECCD30415450CAC661FB3 /* OCMMacroState.m */, + 2748656F8759F1DF93B72762A568C88D /* OCMNotificationPoster.h */, + 50574C3D7DF684F07948CA1A258AFC94 /* OCMNotificationPoster.m */, + FD7B955E6DE6F1E00CAFB564C49D3910 /* OCMObserverRecorder.h */, + 3E9CCC68588CEB5C4FDA0098BFA1B0B9 /* OCMObserverRecorder.m */, + B90D72876497A4309472CC39D0C9CECC /* OCMock.h */, + 74652B094B794A4F1132199C493A63F9 /* OCMockObject.h */, + C0015224404262544DE7B83E7954AD52 /* OCMockObject.m */, + 6C99905C8DB11FA8B11C51A528FD5CC5 /* OCMPassByRefSetter.h */, + C5A58AC25DF1C7D8DDB5851AC43E3BB2 /* OCMPassByRefSetter.m */, + BF557F810F703A2A207CE481103495AF /* OCMRealObjectForwarder.h */, + 925685DE04283B4215A8F3B4D0C5F713 /* OCMRealObjectForwarder.m */, + 8E5DEEB028078566503617AC8EC42FC1 /* OCMRecorder.h */, + 2051AC723FB26CC4070611F36B8EA188 /* OCMRecorder.m */, + 6E635935B36C0E759C0C146D13956EB2 /* OCMReturnValueProvider.h */, + 6627A5066D4FA2A4F3183603ECD72427 /* OCMReturnValueProvider.m */, + 0CA42E725AA1BC788D14B8E085C8DF37 /* OCMStubRecorder.h */, + A0537C3FE7FB2F62CEDDF7F13B8D0F29 /* OCMStubRecorder.m */, + 1DCCFE49D2AA7D774D2E50D7A5554D38 /* OCMVerifier.h */, + 87DAAD46F1B7147C89D44E670B574A6E /* OCMVerifier.m */, + 2BB64B08CA6FF3FDAA94F163970A0F77 /* OCObserverMockObject.h */, + 719A5DB86ADF4CEF7E34D72CB175D36E /* OCObserverMockObject.m */, + BA290B4864ABFCA9459B007FA1B6562E /* OCPartialMockObject.h */, + EDE023D2ABB9C849FE7025EDFBE651F9 /* OCPartialMockObject.m */, + 02AA7937B66BF3A10C30387ED1890620 /* OCProtocolMockObject.h */, + D2AB251AF671293C30BCA11CB42CD39C /* OCProtocolMockObject.m */, + 374A90D3F775DA33BBE7A370B3D58E2C /* Support Files */, + ); + path = OCMock; + sourceTree = ""; + }; + 14552130F547495B9F4C406003B890FB /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 8771BD09CEA58E68C1B37C7D5759FB7F /* Pods-Objective-C */, + D22A7B283E79013EC4B0450C5AC57312 /* Pods-Objective-CTests */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 374A90D3F775DA33BBE7A370B3D58E2C /* Support Files */ = { + isa = PBXGroup; + children = ( + D170774DC82F46FDAA65C9AC2856B469 /* Info.plist */, + 0287B60C452CC527AF49B49EF794D864 /* OCMock.modulemap */, + AAC925078508A0E70D092652F350C58E /* OCMock.xcconfig */, + 5502FB0000811E1CE290E375DA48C225 /* OCMock-dummy.m */, + 7D7CF9F89C4BBECC41DE6F211618FDAD /* OCMock-prefix.pch */, + 302CA5B370C8880A732ECC37A27E3BD1 /* OCMock-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/OCMock"; + sourceTree = ""; + }; + 433CD3331B6C3787F473C941B61FC68F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9D9CFF97A2D41D7CB20A427D5386C7A6 /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4414FE16CF211BCEFB0584199959D8AF /* Support Files */ = { + isa = PBXGroup; + children = ( + 517CD3179A8CE261D89E642892BD4F7D /* Faro.modulemap */, + B617734E153AB73823D5CE893ECB0426 /* Faro.xcconfig */, + 449378DE182400BF22C43323CDA70CDC /* Faro-dummy.m */, + EE3FA4B2CA33BBD6A99D9FF6155E7A3F /* Faro-prefix.pch */, + 2B6E61CBA24C69FF3E46D82ECA84E06E /* Faro-umbrella.h */, + 5C3C3174A1881CC23CDE7F0A082A2553 /* Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/Faro"; + sourceTree = ""; + }; + 4F77F594C717A7EEBAF7ED32A6119BD3 /* Support Files */ = { + isa = PBXGroup; + children = ( + 9CE599F68154101800B9EF2B199AE852 /* Info.plist */, + 99B3E4ACD71BF0C25226E2EF483E00D2 /* Nimble.modulemap */, + 5F52F8F231445D2D63341BABC3551852 /* Nimble.xcconfig */, + DB34B3D8F257A7890CE9F8EA883FF85A /* Nimble-dummy.m */, + 494F6E32A484C7DD0328F446A182062B /* Nimble-prefix.pch */, + A60AC7A612EF03420A75BF5AB7B64698 /* Nimble-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Nimble"; + sourceTree = ""; + }; + 6937DDF96409F9C333F97BAEBF2C144D /* Faro */ = { + isa = PBXGroup; + children = ( + 32D17A097B714278FFAB252E3FCF22E2 /* Adaptable.swift */, + D9F018CD70EE3E8DB4B9F765AC613579 /* Call.swift */, + 88FFA5B6104280C84A5334A672FA2209 /* Configuration.swift */, + 886BFCC81C9DFAD3953DB628C804AF0C /* DateParser.swift */, + 4317F0673AE4243F95EB140825A60B7F /* Deserializable.swift */, + EAF49C8C3DD8025331B7F158EB13ABB1 /* DeserializeFunctions.swift */, + C88BE5ABF5325A3D9C0E56A03A31F1CA /* DeserializeOperators.swift */, + 59EA412FBF3C72496F43540928A9643A /* ErrorPrinting.swift */, + 1CFF6A991E06C066F8FA8EF520AE8829 /* FaroError.swift */, + BC9296A5869224FBE565BA60A0A0D6C7 /* FaroService.swift */, + 041F40AB4A337F8D7FD923731741B00F /* FaroSession.swift */, + 23341927F939A99D7618E49A339CBFDE /* JSONAdaptor.swift */, + 23D7D79A61B7C74610B6088FF427AA34 /* JSONReader.swift */, + 9A1FCFACE537FA1A2D7A55FDFED06A01 /* MockService.swift */, + 488EB785E17F22A933DE2766C460EBB6 /* MockSession.swift */, + 6B21942C7D947127C4EC619A10D8C7A6 /* ParameterEnum.swift */, + 9ECCEF1AE64AB2737FCA2A75F0760E89 /* Result.swift */, + 8B877F4EC6304092C86F89BB5AA7EE76 /* Serializable.swift */, + 85BF2DAB6137E8AB33AB39E81AC398E7 /* SerializeOperators.swift */, + 896260E35229AA52016418546468F017 /* Service.swift */, + 9ACE2FA7D2EF192CA34044B1AD47ABE1 /* ServiceConvenienceExtension.swift */, + 175DF4BE0B1017B4D5D4CB6081AC4B45 /* ServiceQueue.swift */, + 4414FE16CF211BCEFB0584199959D8AF /* Support Files */, + ); + path = Faro; + sourceTree = ""; + }; + 7C1D4F0C43BFC31D897D98C4B71C265D /* Products */ = { + isa = PBXGroup; + children = ( + 65015122FB42E5A77EE57E47451C0036 /* Faro.framework */, + D9569ED31D7F19786D9EE4502A715AE3 /* Nimble.framework */, + 329B01B29C908A610BC407136CF28606 /* OCMock.framework */, + 3B57F6B10C1624BF9CACAF60FF6008AF /* Pods_Objective_C.framework */, + A9E2C82DA706FF783924DEB5E982CA0C /* Pods_Objective_CTests.framework */, + 40B48EF63540BB3A0D8EE11FB1A73F62 /* Quick.framework */, + ); + name = Products; + sourceTree = ""; + }; + 7DB346D0F39D3F0E887471402A8071AB = { + isa = PBXGroup; + children = ( + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, + FB26CDF132743299BCBCF575FC06E910 /* Pods */, + 7C1D4F0C43BFC31D897D98C4B71C265D /* Products */, + 14552130F547495B9F4C406003B890FB /* Targets Support Files */, + ); + sourceTree = ""; + }; + 854E4D87FE965F897D930CC383EB79FB /* Support Files */ = { + isa = PBXGroup; + children = ( + CA1705A49E8A8002453BD92191AAC0E8 /* Info.plist */, + 40E6319955D53643D206E339870036D2 /* Quick.modulemap */, + 1955D0701621AA1083EB133B11FFA0DA /* Quick.xcconfig */, + DA5B03D30A3F817B663600B243F47B4D /* Quick-dummy.m */, + D12432C8F19A8A53C50313F6DFEC46C2 /* Quick-prefix.pch */, + 6DA44C87AB51E7A2D45482E922336410 /* Quick-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Quick"; + sourceTree = ""; + }; + 8771BD09CEA58E68C1B37C7D5759FB7F /* Pods-Objective-C */ = { + isa = PBXGroup; + children = ( + 8912EA8E035414AD25D99ACF380BECF4 /* Info.plist */, + 38B3CC3B48F33AD5745B7741791EBF1F /* Pods-Objective-C.modulemap */, + AF046C56A407E6D26F32C9B6368E6FB6 /* Pods-Objective-C-acknowledgements.markdown */, + 3BB7757F5B3ABEF9532ED971B16BE7EB /* Pods-Objective-C-acknowledgements.plist */, + 10FB066A127BFFFD865E4B4EEACD5073 /* Pods-Objective-C-dummy.m */, + 0062E1BE6CA18731E251D5B78032D276 /* Pods-Objective-C-frameworks.sh */, + 292232F1B1C05570F4463F776EED58AE /* Pods-Objective-C-resources.sh */, + 625F5B8D9A5E5241326DB676D4CA4E98 /* Pods-Objective-C-umbrella.h */, + 16048E67F4F5838F45749AE0B084AE85 /* Pods-Objective-C.debug.xcconfig */, + 2CEEFF7743CDB1EA3DFFACB600DB9244 /* Pods-Objective-C.release.xcconfig */, + ); + name = "Pods-Objective-C"; + path = "Target Support Files/Pods-Objective-C"; + sourceTree = ""; + }; + 9D9CFF97A2D41D7CB20A427D5386C7A6 /* iOS */ = { + isa = PBXGroup; + children = ( + 32DF21EF8268E32D359CD23F2CF3EFE3 /* Foundation.framework */, + AECEA2EDA41473899EE391CA038EDC38 /* XCTest.framework */, + ); + name = iOS; + sourceTree = ""; + }; + C4754FA59C20577190B62372F64ADADF /* Nimble */ = { + isa = PBXGroup; + children = ( + B572EA694ECD0DEE474414124B2D0C04 /* AdapterProtocols.swift */, + 9B61EE0ECD44A33AC1241DA949C8BC1C /* AllPass.swift */, + 7EA867E606E14C0872561F83652E84CF /* AssertionDispatcher.swift */, + 6BF2DCE604BA5C282E0BE5B85CB00B7F /* AssertionRecorder.swift */, + F136A722EA31CAC77AB2BB3BE4D28654 /* Async.swift */, + FBA25F5226E62D1B78172E014CFA2DD2 /* AsyncMatcherWrapper.swift */, + 76DDA5D300FF3EE51C7BBC48CA21E979 /* BeAKindOf.swift */, + 52DC61C441864F619A3E199E65EE6929 /* BeAnInstanceOf.swift */, + 86712ACD792328965934C8E4598790C5 /* BeCloseTo.swift */, + 088BC7AE541E2B5846E908EC38A8043D /* BeEmpty.swift */, + 440F12D9E2F445F41FCCA0B785A2F836 /* BeginWith.swift */, + 56EEF5B5C1579A07C7A11F798287D5FF /* BeGreaterThan.swift */, + 34764871C1F32D2DF0A7C97BAAA92678 /* BeGreaterThanOrEqualTo.swift */, + 3196E03A7BCE9105FFC25B9CF9D24D70 /* BeIdenticalTo.swift */, + 56837149D3B326D000FE3F548D98F9E5 /* BeLessThan.swift */, + 3F5FDBCD14BDCB054BC8F13764534368 /* BeLessThanOrEqual.swift */, + 701A528296F7DDEE6AF18D6221EA6126 /* BeLogical.swift */, + D1F44AAB15A4E7B7605C6769D734E47B /* BeNil.swift */, + 6F37A03A2B9DD962C48ABA116B6138A4 /* BeVoid.swift */, + EB37ABD2DE8F664796C0EE3907B043B6 /* Contain.swift */, + EF5CA75DFE5280DCCE30B1B962314F73 /* ContainElementSatisfying.swift */, + 49E9887DA589CE1D767C5432D5EF03AF /* CurrentTestCaseTracker.h */, + 2C54D9C80B6B4F8DC4DAA27974B21EFE /* CwlBadInstructionException.swift */, + 8385073FF1FC52F9986F8809736A8115 /* CwlCatchBadInstruction.h */, + 13EC4E317B7B17F803A96AB19F03D67C /* CwlCatchBadInstruction.m */, + 05A4BFE0C60B656489C6E63522F8CD5C /* CwlCatchBadInstruction.swift */, + DD78AC2ECB2F447DEB1BAF68ABB3EE06 /* CwlCatchException.h */, + 9700521F2B4193A044A781A80B9AE998 /* CwlCatchException.m */, + 07C0B663DC35B929E7A991EBAC776168 /* CwlCatchException.swift */, + 6C06DDE9D47475D20BD34B4CF21FCAA8 /* CwlDarwinDefinitions.swift */, + 47E283B8196008FDB29580D733364660 /* DSL.h */, + 65EB3A4DB318A893542FB6A8242E425A /* DSL.m */, + 15E637B1786AA1682A8ACDE06F0C5EA9 /* DSL.swift */, + 97B3C6B8D47B66B14F7FF22821423917 /* DSL+Wait.swift */, + 266DE843BBF26E21E8415D3748732254 /* EndWith.swift */, + B3D76125FCC36E6FC71570FD9832BC1C /* Equal.swift */, + 3196F0CFC24ED7C4EE0BFF3062DF4E6C /* Errors.swift */, + C5FCBD308AF6B1756A280ADD0DEF666F /* Expectation.swift */, + 7659A8D54A36194CF322D3B98EB2FCA7 /* Expression.swift */, + DDB7180F398749CE8A83A3562CD47A7C /* FailureMessage.swift */, + 4F015F21170F9DA1A4DA6C5C6F52DF38 /* Functional.swift */, + C2DDC74B6B7A9622CE36D390BCE6A9EC /* HaveCount.swift */, + 67B5CD7F90676965355E5F8A58763CFA /* mach_excServer.c */, + 4C5B0B661BE17B10DD3AB8BF20397B0B /* mach_excServer.h */, + 4BB30625660AB607FB8E3575225C29D4 /* Match.swift */, + BB9769B91E691ADE611F7F6AC681D52F /* MatcherFunc.swift */, + 71290B8EFD4F2112C1B10D1E1456BBB7 /* MatcherProtocols.swift */, + 3AD34968E9AAB6CCEE822821FAF06EA1 /* MatchError.swift */, + 890F317A22755FCB5B52E5476D38CEEE /* Nimble.h */, + 64BD74BB6D364B8C9BF5A55D5F435D64 /* NimbleEnvironment.swift */, + 1D12BED901082321E8CFEC598BA2D70E /* NimbleXCTestHandler.swift */, + FA32FFDFF86560AD2CE21BE9A9E5E696 /* NMBExceptionCapture.h */, + DF2EE9D65678DA76E5F21EB3E845301B /* NMBExceptionCapture.m */, + C9886CF6FFF7821226D662199CD2D435 /* NMBExpectation.swift */, + B428B850CA5D63C24F4946A74E78C5B6 /* NMBObjCMatcher.swift */, + 5B9B78E3720DC751A90BD5C21D05C774 /* NMBStringify.h */, + 569076F80E248EA1DE57361C916957AA /* NMBStringify.m */, + E9A22019596EFBBF25C3EF6A600143A4 /* PostNotification.swift */, + 59A395EF59AF7711A15508D3B5F0C5C0 /* RaisesException.swift */, + A31C891DE1CAE112530DB2E7E424C86A /* SatisfyAnyOf.swift */, + 53C47ADC55EE591D376E5130494D3103 /* SourceLocation.swift */, + 479AF0F07D0B0287D6BCD7EC600A5E37 /* Stringers.swift */, + 4462A2F84912074D21DB4E7CA49167FC /* ThrowAssertion.swift */, + 6CD210F446F274ADDF9BB2CC88723580 /* ThrowError.swift */, + 16922A80B5F583450F9CDFE96AB35D50 /* XCTestObservationCenter+Register.m */, + 4F77F594C717A7EEBAF7ED32A6119BD3 /* Support Files */, + ); + path = Nimble; + sourceTree = ""; + }; + D15C23C32957BAD50D0930798353CB5A /* Quick */ = { + isa = PBXGroup; + children = ( + DE43844F164FE3F918256B570F0777EB /* Callsite.swift */, + 74D72971A42D77BB86326B203C1457BE /* Closures.swift */, + 8B3DAA212362983A0234B64FBF292FDB /* Configuration.swift */, + C71C74B4921D91CD6BCC28E9A98B64AF /* DSL.swift */, + 1A5BB201BD9BF5C9C87790A837F108F8 /* ErrorUtility.swift */, + 72F9E3CC6AB1E9D7A424DDF6093BC559 /* Example.swift */, + 8D42487135E21EE53A8378138FBB6B14 /* ExampleGroup.swift */, + 619DF9020189CFD375CFD8B33A8AFEB6 /* ExampleHooks.swift */, + 44B19049B0308546117F80A8F637C792 /* ExampleMetadata.swift */, + 677FBE720E59F083FEA6C3A79B1F5CE9 /* Filter.swift */, + F86F386D72616F0543B86738A2B974D8 /* HooksPhase.swift */, + C542C1EE5B7A348F6DAA30969D04E886 /* NSBundle+CurrentTestBundle.swift */, + 5C449EDFDDB7185886E70C427C7811C8 /* NSString+C99ExtendedIdentifier.swift */, + D9CB429A7827557A08631629B18A51EA /* QCKDSL.h */, + 9B932CDAD8906CB1DE98972235602044 /* QCKDSL.m */, + DCF3EA03FE9BD48F53AAA80396506128 /* Quick.h */, + FB4E3DAA9766B7D4A44B58DCC3D24F84 /* QuickConfiguration.h */, + 39C2F9228C71CF526F9542DED335C294 /* QuickConfiguration.m */, + 08A6C9C6DDF4475FB935D46CFBB7C3FE /* QuickSelectedTestSuiteBuilder.swift */, + 27447EB20550587F4B0328BB526DE709 /* QuickSpec.h */, + 814EDFF45B3ADC2BCB0BBA17372353F9 /* QuickSpec.m */, + EBF2BAC92509FAAEA0779082C1C322E5 /* QuickSpecBase.h */, + B48D54793862AA2302F5E16E028E382E /* QuickSpecBase.m */, + DA53CE8AF9DD3E17F0C70EFB0FD27405 /* QuickTestSuite.swift */, + E4B98F25D27824128D54C5C5A19BBE9C /* SuiteHooks.swift */, + C9BE0907DCCA28A7E577F744CBE6EC43 /* URL+FileName.swift */, + 1FA359CDAEEA10BCC7E83B89E2A00E85 /* World.h */, + 4237A12880574E77B830212EB4596EBF /* World.swift */, + D63F54AEE93CA155C4E1499D441E66D9 /* World+DSL.h */, + 1F4572F7A638016C53B2D3770855145E /* World+DSL.swift */, + 9ACB8301A60C48C42EB67A0F23684703 /* XCTestSuite+QuickTestSuiteBuilder.m */, + 854E4D87FE965F897D930CC383EB79FB /* Support Files */, + ); + path = Quick; + sourceTree = ""; + }; + D22A7B283E79013EC4B0450C5AC57312 /* Pods-Objective-CTests */ = { + isa = PBXGroup; + children = ( + B1CA4CFFF78F749A082386D8B88B4507 /* Info.plist */, + 75F5E38DA4836420522A574969A89E06 /* Pods-Objective-CTests.modulemap */, + 1BF25C10228C211CE52ACD13EC78C48C /* Pods-Objective-CTests-acknowledgements.markdown */, + 28AB5DBD0522552D27CE6066AA7F103A /* Pods-Objective-CTests-acknowledgements.plist */, + 5C5F184BCA8F3494CCF89439247DBF87 /* Pods-Objective-CTests-dummy.m */, + 4B2D0C101D41CD176370670B665B469A /* Pods-Objective-CTests-frameworks.sh */, + A660BC2F3FE238E4DBF50BAD1BFC9CE3 /* Pods-Objective-CTests-resources.sh */, + D6A1375347C3B187910D2A7D07A5E082 /* Pods-Objective-CTests-umbrella.h */, + FA76FC1B69882F1CF1D2719EC89ABD6F /* Pods-Objective-CTests.debug.xcconfig */, + A53BB1419B785A0FD04D021466A95D63 /* Pods-Objective-CTests.release.xcconfig */, + ); + name = "Pods-Objective-CTests"; + path = "Target Support Files/Pods-Objective-CTests"; + sourceTree = ""; + }; + FB26CDF132743299BCBCF575FC06E910 /* Pods */ = { + isa = PBXGroup; + children = ( + 6937DDF96409F9C333F97BAEBF2C144D /* Faro */, + C4754FA59C20577190B62372F64ADADF /* Nimble */, + 0CB5FCD428EC580F68D63BD23ADB94F5 /* OCMock */, + D15C23C32957BAD50D0930798353CB5A /* Quick */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 17E0259EB1A2833A5CB9941C33695845 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6DB51F9889708E3B90223C3F39BAD587 /* Faro-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6715D50B9530063A587A479ADF8A97C0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B16340143CE7FF40A32CD8082ED4152D /* CurrentTestCaseTracker.h in Headers */, + 88B771FB81DD05BF7E48A0D9271D9EB4 /* CwlCatchBadInstruction.h in Headers */, + DEF289C7BF4E97D42B06B1EB7CAE0951 /* CwlCatchException.h in Headers */, + 4A17E1DB4EA2CCBF04B76F5F8EB417A1 /* DSL.h in Headers */, + 874EF0A06B9FC80B877261425BAB4ED2 /* mach_excServer.h in Headers */, + 7BD907A708031D5361E1A97CACF9F24E /* Nimble-umbrella.h in Headers */, + 409A3ECDDC680D0BD343E3F203862E25 /* Nimble.h in Headers */, + E9CD7EF9DD6E75404E4264F6F0AC8D26 /* NMBExceptionCapture.h in Headers */, + 926F67C94121C19A959745138E5B42B6 /* NMBStringify.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 808E9C27E7118677651A7526B0945512 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + FBD596B095C58C7A3AA647CAB7802226 /* NSInvocation+OCMAdditions.h in Headers */, + 5037A042D2012439DEC932F10FC51B95 /* NSMethodSignature+OCMAdditions.h in Headers */, + A1268C3E1B318712F159EF222F19BD8B /* NSNotificationCenter+OCMAdditions.h in Headers */, + E61FEAB563814E928FFF2C1EF239058A /* NSObject+OCMAdditions.h in Headers */, + 1DD2C9A900B7D7B5F3862D15C1A8AD7E /* NSValue+OCMAdditions.h in Headers */, + 28B5E9BDDC2F53432C7D7D244837F1B5 /* OCClassMockObject.h in Headers */, + F02C2CD0A94965FFA8928B316D5825CB /* OCMArg.h in Headers */, + 6DEAD4CD0FF9467DA3FD3F22816418C6 /* OCMArgAction.h in Headers */, + 86FF90618135B7C9032BC7075343F236 /* OCMBlockArgCaller.h in Headers */, + 0310B1523123778B0E3FB78BE3A14095 /* OCMBlockCaller.h in Headers */, + E14A5FC189CD75054825E45DA6D9F293 /* OCMBoxedReturnValueProvider.h in Headers */, + B40D8DAB504B721D2BC6A6DDFDD82067 /* OCMConstraint.h in Headers */, + 974362D040AC870A5D72E365B21A8CE4 /* OCMExceptionReturnValueProvider.h in Headers */, + 01F7D55919C59833456188558FE8D7FA /* OCMExpectationRecorder.h in Headers */, + 15081C3A4D626D9631A9594847D2E2A6 /* OCMFunctions.h in Headers */, + 72C8CC2855787B9DC1A37DDEB5E24155 /* OCMFunctionsPrivate.h in Headers */, + 1D53147F49F02FC693C33D8526049C90 /* OCMIndirectReturnValueProvider.h in Headers */, + B3E6AA126A971418B57B78A6B4E753E3 /* OCMInvocationExpectation.h in Headers */, + B42B8EFE65F8B07957190A15F590093A /* OCMInvocationMatcher.h in Headers */, + 15FEDB8A315321D48BC7E535429ADB48 /* OCMInvocationStub.h in Headers */, + B66FB06824BBED66619F17DB82CC2A64 /* OCMLocation.h in Headers */, + A4AF7E8EF9BB26F4CE7FD9EA32D4AD4C /* OCMMacroState.h in Headers */, + 1583087CE691D66E050A0AE7C07296BD /* OCMNotificationPoster.h in Headers */, + 4552366371FE1ACA9600897C31D70E4C /* OCMObserverRecorder.h in Headers */, + 9A92686CF21CC8ECAB69A3CFB621FA4B /* OCMock-umbrella.h in Headers */, + FAB7A1E7E1414DC657BA79D07135E15B /* OCMock.h in Headers */, + 8EE2E0824E8AD382EC6553104A60430E /* OCMockObject.h in Headers */, + 92F61FA0ACB1B709FFEBE1D9DC2C68E5 /* OCMPassByRefSetter.h in Headers */, + 38D5085895B3757AF0DCED078EF8B145 /* OCMRealObjectForwarder.h in Headers */, + E6F1B20197D630B80285B5F6E5FAE80F /* OCMRecorder.h in Headers */, + A4CD01540B9FCF8F26D52856704571D7 /* OCMReturnValueProvider.h in Headers */, + EC33739AB54F71355C4FD5AAEF92F4B1 /* OCMStubRecorder.h in Headers */, + E4A87D8BA9BA24EE81DEC41C8BE98F2B /* OCMVerifier.h in Headers */, + 147E00CDCEDB145F0012FA174BA4E545 /* OCObserverMockObject.h in Headers */, + 353759005B92EEC29E4B15765C4D3EEB /* OCPartialMockObject.h in Headers */, + 45E91E6E79D1EEACF0F7A668E3D9A89D /* OCProtocolMockObject.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ACF1E77F934F5ACD595D5283844DD184 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E612B2EB49E835FEECD743A0F53FE2EC /* Pods-Objective-C-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C9406922555C50826D642B27B5496062 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 10DC5AA88ADF41EEC50B734FE6DD139A /* QCKDSL.h in Headers */, + 6678BE4D299D36DEDF4ED0DDE129C3B3 /* Quick-umbrella.h in Headers */, + 772D5A1B086DCD32B6BFC1D707D20D76 /* Quick.h in Headers */, + 9F3C54F28CD7BAC3682DD33BC380F091 /* QuickConfiguration.h in Headers */, + 407775EDF27F892E16C3A9D22C6883ED /* QuickSpec.h in Headers */, + 756FF97F6CD9FE10EE8EF3C0B507B544 /* QuickSpecBase.h in Headers */, + 0DA0637490BAF2C83C67E680D59D4B2D /* World+DSL.h in Headers */, + 1B4C1833AAC1153CDB88D93E2BF303B1 /* World.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FAC824708FAA408C8363671161E3C721 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + FC4D8B6B0FDE5146C0D44F697F7F55C6 /* Pods-Objective-CTests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0921CC2F4398BE9A4F1CEACB30684B56 /* Nimble */ = { + isa = PBXNativeTarget; + buildConfigurationList = 761C67FF258DB3BE6B2D4612FA9938E8 /* Build configuration list for PBXNativeTarget "Nimble" */; + buildPhases = ( + 41E146CA370726574B1C3087CF111D13 /* Sources */, + A0673853CCFEF089C0BF4D09E710CC4F /* Frameworks */, + 6715D50B9530063A587A479ADF8A97C0 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Nimble; + productName = Nimble; + productReference = D9569ED31D7F19786D9EE4502A715AE3 /* Nimble.framework */; + productType = "com.apple.product-type.framework"; + }; + 16DB55216A6C01E5C8284AC8D28E99FF /* Quick */ = { + isa = PBXNativeTarget; + buildConfigurationList = 256B3DB637CDCE30CF65C0A757D4A39B /* Build configuration list for PBXNativeTarget "Quick" */; + buildPhases = ( + D8BFB325D2600FE8C94882E8A7E69FF7 /* Sources */, + FE5E7B87C12F692A60CE1465BD209155 /* Frameworks */, + C9406922555C50826D642B27B5496062 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Quick; + productName = Quick; + productReference = 40B48EF63540BB3A0D8EE11FB1A73F62 /* Quick.framework */; + productType = "com.apple.product-type.framework"; + }; + 5357EF6DAFBD3DB4890F10DBD75929E6 /* Faro */ = { + isa = PBXNativeTarget; + buildConfigurationList = 51BC2981928AC437CA514D1D4A17DC11 /* Build configuration list for PBXNativeTarget "Faro" */; + buildPhases = ( + E0467D365F196829432E7673F83599EC /* Sources */, + C29091602A1A8C14808F5C8AD7CC9DD9 /* Frameworks */, + 17E0259EB1A2833A5CB9941C33695845 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Faro; + productName = Faro; + productReference = 65015122FB42E5A77EE57E47451C0036 /* Faro.framework */; + productType = "com.apple.product-type.framework"; + }; + 7F5863A1B11B64357F8965BBB12D3A8A /* Pods-Objective-C */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7C4C40C3D8082F462A288F5A3751DB35 /* Build configuration list for PBXNativeTarget "Pods-Objective-C" */; + buildPhases = ( + 813F355909042E2946DD3E94BC11199C /* Sources */, + 86B474E76B80DCB721C6FF063561ACD0 /* Frameworks */, + ACF1E77F934F5ACD595D5283844DD184 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + 3C2639D67D16D9C5C5E7EA0423E6A754 /* PBXTargetDependency */, + ); + name = "Pods-Objective-C"; + productName = "Pods-Objective-C"; + productReference = 3B57F6B10C1624BF9CACAF60FF6008AF /* Pods_Objective_C.framework */; + productType = "com.apple.product-type.framework"; + }; + DC54C98851E54D349520C786701A1845 /* OCMock */ = { + isa = PBXNativeTarget; + buildConfigurationList = AE8BA48E64C0BE4DC719C4BAE69F06A8 /* Build configuration list for PBXNativeTarget "OCMock" */; + buildPhases = ( + BE952139340A1F69DCCDE76D81E60234 /* Sources */, + 7D29925DDA06F94E7C818CA2403C1B0B /* Frameworks */, + 808E9C27E7118677651A7526B0945512 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OCMock; + productName = OCMock; + productReference = 329B01B29C908A610BC407136CF28606 /* OCMock.framework */; + productType = "com.apple.product-type.framework"; + }; + F81EE532567F417A0B3A6F1B6F81E17E /* Pods-Objective-CTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 508EAE8162277958C8C86E678F43A16D /* Build configuration list for PBXNativeTarget "Pods-Objective-CTests" */; + buildPhases = ( + 8A25304453A4CB2105F8B0FDFDDC7F26 /* Sources */, + 37F4BB7AF5C3CD484ECFE696DE6E0B96 /* Frameworks */, + FAC824708FAA408C8363671161E3C721 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + FBDA57D3EF95EEF541C31C133CDC85F9 /* PBXTargetDependency */, + 6A37931EBFBF872C57384C1E299A5FB1 /* PBXTargetDependency */, + 50399049888800FE5907D257AC35F1B5 /* PBXTargetDependency */, + ); + name = "Pods-Objective-CTests"; + productName = "Pods-Objective-CTests"; + productReference = A9E2C82DA706FF783924DEB5E982CA0C /* Pods_Objective_CTests.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0700; + }; + buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7DB346D0F39D3F0E887471402A8071AB; + productRefGroup = 7C1D4F0C43BFC31D897D98C4B71C265D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5357EF6DAFBD3DB4890F10DBD75929E6 /* Faro */, + 0921CC2F4398BE9A4F1CEACB30684B56 /* Nimble */, + DC54C98851E54D349520C786701A1845 /* OCMock */, + 7F5863A1B11B64357F8965BBB12D3A8A /* Pods-Objective-C */, + F81EE532567F417A0B3A6F1B6F81E17E /* Pods-Objective-CTests */, + 16DB55216A6C01E5C8284AC8D28E99FF /* Quick */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 41E146CA370726574B1C3087CF111D13 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5D4E8223C271A19448FCEAC36A9B441 /* AdapterProtocols.swift in Sources */, + FAACCCDBE0D2785212E37468636AAB0A /* AllPass.swift in Sources */, + 7272DB71A8C5325A0778F63E6F6C9957 /* AssertionDispatcher.swift in Sources */, + B612F1F906E3AF8B1FC6B893229E83B6 /* AssertionRecorder.swift in Sources */, + 0DF2D4E6B55D67E28D8BE9EC5A25F24E /* Async.swift in Sources */, + AA6EAFA71E1A6862AA312D89A601C34F /* AsyncMatcherWrapper.swift in Sources */, + 80D1788131B3D3326041E62364F8C7AA /* BeAKindOf.swift in Sources */, + A87CA098369D61EFC7A05BD61512A3F5 /* BeAnInstanceOf.swift in Sources */, + D7408861438442F67469ACE39D1604C1 /* BeCloseTo.swift in Sources */, + AD2B0E5BFF8EAD0EDF0449F8D198277C /* BeEmpty.swift in Sources */, + 288DBE855F794BA1AE8BC47AA413693E /* BeginWith.swift in Sources */, + 30F80459D8D536D8B99880EDD353987A /* BeGreaterThan.swift in Sources */, + ABEE3775B4FD25B3C86EE712BC2502B2 /* BeGreaterThanOrEqualTo.swift in Sources */, + 5685322E421AB4DA6A91B26C09833B29 /* BeIdenticalTo.swift in Sources */, + 318F9AE6D9561CFB487071A821B4217D /* BeLessThan.swift in Sources */, + 1F707004C05C63F90F0030E8E4902D66 /* BeLessThanOrEqual.swift in Sources */, + AF7F875677FF3EB4B6ADDB1373B34249 /* BeLogical.swift in Sources */, + F100D41C0564EE46CA47DA9E3540DA70 /* BeNil.swift in Sources */, + D6A1634CFD5243D18DB762116C8CEF8F /* BeVoid.swift in Sources */, + C97B9F51427BCD4C63EC7D75AB161833 /* Contain.swift in Sources */, + 2DF80575B9759A9E8004F4F642D0D123 /* ContainElementSatisfying.swift in Sources */, + 0B846370B6EA04F7D7909A403DD16317 /* CwlBadInstructionException.swift in Sources */, + C39921387DA273A0952A999B0CDC03F9 /* CwlCatchBadInstruction.m in Sources */, + 1C37D984F1BBBC7278E1FB6BDB153892 /* CwlCatchBadInstruction.swift in Sources */, + DB5066EBB8C95A3F8818628C9CA6794D /* CwlCatchException.m in Sources */, + 34E0569B2666F68A70EB676EFDCC4434 /* CwlCatchException.swift in Sources */, + B1D876C441B5F61984E35ABB5210AFE6 /* CwlDarwinDefinitions.swift in Sources */, + B138DBC0F7D2656EE7E413BEA735C71D /* DSL+Wait.swift in Sources */, + C9132B1E287B7ECA69A90F4766ADE9C2 /* DSL.m in Sources */, + A279D4DAE8E16C5D8F9019CDBED14D73 /* DSL.swift in Sources */, + 383B3EF018CDFD095EFEB7D74769144A /* EndWith.swift in Sources */, + D9921CDBA36587248C63AFDD5B3C1981 /* Equal.swift in Sources */, + 4B6579FFF0062EEBBABB8336C0871171 /* Errors.swift in Sources */, + D93C5A1929F8FD53F7EF2C3CA16CCC95 /* Expectation.swift in Sources */, + 65335E2F74AE71C270659EC7E8725030 /* Expression.swift in Sources */, + 704DA81E48A5263B35189F36C5247A53 /* FailureMessage.swift in Sources */, + 32AB6828BB98A679D3EBCC16C7BE9566 /* Functional.swift in Sources */, + DC9C69D7524AFEECCDC73D5CF1F4C028 /* HaveCount.swift in Sources */, + F2ED0A18E020A07A092F957B2C7EF0E2 /* mach_excServer.c in Sources */, + A665BE606F6B28E89B531EDE41657ECE /* Match.swift in Sources */, + 0D4B1951108CF54E1968467D30C351B5 /* MatcherFunc.swift in Sources */, + E1554E6ED22E94CAD97E211C7FBA530B /* MatcherProtocols.swift in Sources */, + AF814F353BF9C15BAED3E4067DCC3BF7 /* MatchError.swift in Sources */, + 748BB746CA429F9C5D510EEF3245ECFD /* Nimble-dummy.m in Sources */, + 69F9C31FC991A69337CE9B599993D68D /* NimbleEnvironment.swift in Sources */, + 7276DB3552398200B421D06F207EC0E3 /* NimbleXCTestHandler.swift in Sources */, + 6F36A431DE56B28FD400D20036A23DE4 /* NMBExceptionCapture.m in Sources */, + 9D9155396F48333B854DBE586138EDBF /* NMBExpectation.swift in Sources */, + 2173F4681D2DDDF63A01A7439EDE1FD4 /* NMBObjCMatcher.swift in Sources */, + 123D36BB9CA549C55BBE6FC7D21BAB97 /* NMBStringify.m in Sources */, + 10B953E63951E8DB495AA5B5EBDBBABA /* PostNotification.swift in Sources */, + FD9373DD3C1910FB513089F4CD39613B /* RaisesException.swift in Sources */, + C08FCDC247B35C971F5AE7E58987E8AC /* SatisfyAnyOf.swift in Sources */, + DB039F39038342DE5258F386F694A9A0 /* SourceLocation.swift in Sources */, + 04AE1DC56A0C088489EA27CED5190838 /* Stringers.swift in Sources */, + 11EEDB6DB6F03E2AF3FC368AA32274AC /* ThrowAssertion.swift in Sources */, + B1D59A1BD0FBDF3BA9A5B65ACFC25D56 /* ThrowError.swift in Sources */, + EEACC5B78AFB71C8594380C005C17A4B /* XCTestObservationCenter+Register.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 813F355909042E2946DD3E94BC11199C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F17C28263ABEAA0D453A5C3BA4ED2E6A /* Pods-Objective-C-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8A25304453A4CB2105F8B0FDFDDC7F26 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8232C47C42A5943000582E7481019BD3 /* Pods-Objective-CTests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BE952139340A1F69DCCDE76D81E60234 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 71213523998EC4038EEF2881118A57A1 /* NSInvocation+OCMAdditions.m in Sources */, + BD181F7E8C0BB325B051DA9F2FBD71BC /* NSMethodSignature+OCMAdditions.m in Sources */, + 51CAB174257235556CE8902084F0E662 /* NSNotificationCenter+OCMAdditions.m in Sources */, + B852DBE3593443215A94EEFD59786402 /* NSObject+OCMAdditions.m in Sources */, + 59578DBAB2520015A65B5B160722A370 /* NSValue+OCMAdditions.m in Sources */, + 116FA1BBD719AFAA5593D71332D2A926 /* OCClassMockObject.m in Sources */, + F98852F58D5FDF0191647087678ABE70 /* OCMArg.m in Sources */, + CF451EAA94004B370612757B61B46D2D /* OCMArgAction.m in Sources */, + 4F02F5DD4EC7C3AFD1EC38E2F55B0C4A /* OCMBlockArgCaller.m in Sources */, + 7B006E74668E41702B8881E724728DE9 /* OCMBlockCaller.m in Sources */, + 0D183650A2D88CB6DAD886030A3A2B62 /* OCMBoxedReturnValueProvider.m in Sources */, + B200AEB2373802A1B871987A18D08F75 /* OCMConstraint.m in Sources */, + 915751C97068AF644D3FE4498633DAB1 /* OCMExceptionReturnValueProvider.m in Sources */, + 13A1051CA96D84674E588FECAF52DD43 /* OCMExpectationRecorder.m in Sources */, + 3D1CB7A4AB9B00BC95F06CF858F18BCE /* OCMFunctions.m in Sources */, + 7D94DE66B8B5E3B4A0B5E53A88C3FAEE /* OCMIndirectReturnValueProvider.m in Sources */, + A59AE6011C58D3D2F009DEF7F5AA259B /* OCMInvocationExpectation.m in Sources */, + 54471D429F63760B736E52506A0B861B /* OCMInvocationMatcher.m in Sources */, + B33B6DFAA43992C898AF6D4F1C539A8A /* OCMInvocationStub.m in Sources */, + EFC1318446EB79DC091867000F45D61C /* OCMLocation.m in Sources */, + D9C7A57A574090442C8631BA856B1599 /* OCMMacroState.m in Sources */, + 4F4A7459D96FDABBAB640D1D1B1BB42E /* OCMNotificationPoster.m in Sources */, + 74BC62D6FEB722F4976016FD4DCA870B /* OCMObserverRecorder.m in Sources */, + 24394811C369F117D75337F436C81222 /* OCMock-dummy.m in Sources */, + C65A28088F0668711386816290C3880E /* OCMockObject.m in Sources */, + 4E8250BDB662F542F9294F6941333373 /* OCMPassByRefSetter.m in Sources */, + 58FB50DB554239F854ECBEC3C86F3A92 /* OCMRealObjectForwarder.m in Sources */, + 0AEAD2BEB61CCA26BB0798F2E527BF84 /* OCMRecorder.m in Sources */, + A9571E56544CD912F0DA62E545DB2419 /* OCMReturnValueProvider.m in Sources */, + 0E32A8C1B69250199C8EC0794CF3A3B6 /* OCMStubRecorder.m in Sources */, + 13AA024ACA7FE3FAD7E0FFD5AC77370D /* OCMVerifier.m in Sources */, + 82558AE4441757075270A8A260B34EC9 /* OCObserverMockObject.m in Sources */, + 543D9D71DD92175A9CC5F0831CF2A028 /* OCPartialMockObject.m in Sources */, + E4070427AD7F08E573CAA22DCEB79FB1 /* OCProtocolMockObject.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D8BFB325D2600FE8C94882E8A7E69FF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C8C4B19F966FD8529D426E5FB8F5A0EF /* Callsite.swift in Sources */, + 7FE9A99D985CD0179F9420DEFC6099B2 /* Closures.swift in Sources */, + 3CAE0E6185C96CB26F761BD020EE1337 /* Configuration.swift in Sources */, + A0F475377A398A87070131ADEC7F6C6C /* DSL.swift in Sources */, + EF73A2955B4C9154D1D51CF619CD5CBE /* ErrorUtility.swift in Sources */, + FA1DDDB5F0219950071EABB20F6A2EC8 /* Example.swift in Sources */, + 8D87CFDF007039D68604BC06C34DC309 /* ExampleGroup.swift in Sources */, + 2D89EDBA82F92ED6D0D0831660745753 /* ExampleHooks.swift in Sources */, + 41B3A99C33F17DE2DD0D81105157CEDB /* ExampleMetadata.swift in Sources */, + 1BF6E849045B943940185AC089FF7312 /* Filter.swift in Sources */, + DD7E9850FD1FD06C3542485F2553DAF3 /* HooksPhase.swift in Sources */, + 159707F50B6FEC09BCC282AEF0DF96D2 /* NSBundle+CurrentTestBundle.swift in Sources */, + 6B74023612DABC9C1E2B6ABAC537814A /* NSString+C99ExtendedIdentifier.swift in Sources */, + 762C9DEE2C8F18DF9559D188115C91B1 /* QCKDSL.m in Sources */, + 57D22918F6C3F9E290045796B4632947 /* Quick-dummy.m in Sources */, + 8B7AD0583E8417752FE1B58622C7572A /* QuickConfiguration.m in Sources */, + 29E8951140FD80478059735AF70ED501 /* QuickSelectedTestSuiteBuilder.swift in Sources */, + 9B00A3D917761F18BD3F36A3C4386721 /* QuickSpec.m in Sources */, + BE8A249B6E2643D0CAABF318BA9291E8 /* QuickSpecBase.m in Sources */, + 9E91CB1A923A3604EE7909397A6558F8 /* QuickTestSuite.swift in Sources */, + 90FD8AF59C660969E39FD42C10991176 /* SuiteHooks.swift in Sources */, + 77C1E9B05B46101709D7A3804D61987A /* URL+FileName.swift in Sources */, + 110FEE62D84E1B42BC73A191C2280F80 /* World+DSL.swift in Sources */, + 15B38D7F47211A8BB83F27F5016E4240 /* World.swift in Sources */, + 2A320686E07FACD8D19C185064FE67E1 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E0467D365F196829432E7673F83599EC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9B5E74ACA03C1B450B3AACA8674CC4A0 /* Adaptable.swift in Sources */, + B4E9303A7A16306EE54AC43CB0183D91 /* Call.swift in Sources */, + E688AB23EE6C5F3515CFDC297E8BC671 /* Configuration.swift in Sources */, + EF973B571A12BC721BFCD80737EB5C16 /* DateParser.swift in Sources */, + B8F0C855C23E200720AD907B8E5244FD /* Deserializable.swift in Sources */, + C813295B8127E0A3518AE9C574ACEF5B /* DeserializeFunctions.swift in Sources */, + 099E42CA64F8B9331551138F9955BF58 /* DeserializeOperators.swift in Sources */, + 471FC4CC094184E255A6522E7A70DC99 /* ErrorPrinting.swift in Sources */, + 5111CA15767FEC30071EA48EFE057C18 /* Faro-dummy.m in Sources */, + 26860D2C7C5CA85423CCBFB8B415A1B9 /* FaroError.swift in Sources */, + E057BF21900146896798A3ED597BFA8D /* FaroService.swift in Sources */, + 8C3C59CF7A92D0794E10B0249129D43C /* FaroSession.swift in Sources */, + D515ABEFDC8F8F5278A7A8C280468B5C /* JSONAdaptor.swift in Sources */, + 522459A2F7DB405AC0CF912A2BBDD096 /* JSONReader.swift in Sources */, + EB4FF2AC450F3EB0553C41AEFE4CA67E /* MockService.swift in Sources */, + 799D65F10E77B49AB2402931BA0D7506 /* MockSession.swift in Sources */, + 6B28666A1AFDD1CFBB4036BAFE730947 /* ParameterEnum.swift in Sources */, + 84388DA969A4D5B21058909917B6DE99 /* Result.swift in Sources */, + B7AE85F0249D6CE2F37CFFD41E3D17BB /* Serializable.swift in Sources */, + 84D9CBA354DEF26CEC5A6F9D83014554 /* SerializeOperators.swift in Sources */, + 126DE3E39B6CB11E17B4D778B3BCD309 /* Service.swift in Sources */, + 86B6F55EA68F9A3ED63C65C3375BEBFF /* ServiceConvenienceExtension.swift in Sources */, + 1D3C26CA81028CC5F2EA8FB0511C79E3 /* ServiceQueue.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 3C2639D67D16D9C5C5E7EA0423E6A754 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Faro; + target = 5357EF6DAFBD3DB4890F10DBD75929E6 /* Faro */; + targetProxy = D922E2291C6A5FDC0BDDA2604C5EF505 /* PBXContainerItemProxy */; + }; + 50399049888800FE5907D257AC35F1B5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Quick; + target = 16DB55216A6C01E5C8284AC8D28E99FF /* Quick */; + targetProxy = 5585FDAA1F5495AF815BE2A8991FFF74 /* PBXContainerItemProxy */; + }; + 6A37931EBFBF872C57384C1E299A5FB1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = OCMock; + target = DC54C98851E54D349520C786701A1845 /* OCMock */; + targetProxy = 41A4F0806CA11282CCDE42486853F25C /* PBXContainerItemProxy */; + }; + FBDA57D3EF95EEF541C31C133CDC85F9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Nimble; + target = 0921CC2F4398BE9A4F1CEACB30684B56 /* Nimble */; + targetProxy = A9650A9FC71DDF2254F985238463D393 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 014146C0C5567965569864E91D361A65 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AAC925078508A0E70D092652F350C58E /* OCMock.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/OCMock/OCMock-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OCMock/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OCMock/OCMock.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = OCMock; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 0E0AD4FF6AA5FBB0FBA354417A2A1C68 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5F52F8F231445D2D63341BABC3551852 /* Nimble.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/Nimble/Nimble-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Nimble/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Nimble/Nimble.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = Nimble; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 12914D756594D15C6F2CA12FE5F89F1B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + ONLY_ACTIVE_ARCH = YES; + PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 353F04AF586D433964C82B7737CCC295 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AAC925078508A0E70D092652F350C58E /* OCMock.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/OCMock/OCMock-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/OCMock/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/OCMock/OCMock.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = OCMock; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 6443D647999465AA6EE3E30DBE1E01BA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CEEFF7743CDB1EA3DFFACB600DB9244 /* Pods-Objective-C.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = "Target Support Files/Pods-Objective-C/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Objective-C/Pods-Objective-C.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_Objective_C; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 655B76266B5A2CE366BC052D0249AE20 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 16048E67F4F5838F45749AE0B084AE85 /* Pods-Objective-C.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = "Target Support Files/Pods-Objective-C/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Objective-C/Pods-Objective-C.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_Objective_C; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 82B4F92BB43A2152D49349C13D7A1214 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B617734E153AB73823D5CE893ECB0426 /* Faro.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/Faro/Faro-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Faro/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Faro/Faro.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = Faro; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 855021AD34F1DF49DBD0041DB94803BE /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A53BB1419B785A0FD04D021466A95D63 /* Pods-Objective-CTests.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = "Target Support Files/Pods-Objective-CTests/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_Objective_CTests; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 96CEA245DA8C817E8D60299BA2C785B2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FA76FC1B69882F1CF1D2719EC89ABD6F /* Pods-Objective-CTests.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = "Target Support Files/Pods-Objective-CTests/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_Objective_CTests; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + A18080D500212DBA2ED5E37392C84210 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5F52F8F231445D2D63341BABC3551852 /* Nimble.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/Nimble/Nimble-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Nimble/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Nimble/Nimble.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = Nimble; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B59F17EE45DB6EA9806B55A92862B903 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1955D0701621AA1083EB133B11FFA0DA /* Quick.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/Quick/Quick-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Quick/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Quick/Quick.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = Quick; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + BA815552D5724AB6DE81E38E407FFA2B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B617734E153AB73823D5CE893ECB0426 /* Faro.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/Faro/Faro-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Faro/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Faro/Faro.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = Faro; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + E72E7977875C2D251FC62736BBDDC389 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + FC51E3D6296DA3629B17E0AD315E79A1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1955D0701621AA1083EB133B11FFA0DA /* Quick.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/Quick/Quick-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Quick/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Quick/Quick.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = Quick; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 256B3DB637CDCE30CF65C0A757D4A39B /* Build configuration list for PBXNativeTarget "Quick" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FC51E3D6296DA3629B17E0AD315E79A1 /* Debug */, + B59F17EE45DB6EA9806B55A92862B903 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 12914D756594D15C6F2CA12FE5F89F1B /* Debug */, + E72E7977875C2D251FC62736BBDDC389 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 508EAE8162277958C8C86E678F43A16D /* Build configuration list for PBXNativeTarget "Pods-Objective-CTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96CEA245DA8C817E8D60299BA2C785B2 /* Debug */, + 855021AD34F1DF49DBD0041DB94803BE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 51BC2981928AC437CA514D1D4A17DC11 /* Build configuration list for PBXNativeTarget "Faro" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 82B4F92BB43A2152D49349C13D7A1214 /* Debug */, + BA815552D5724AB6DE81E38E407FFA2B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 761C67FF258DB3BE6B2D4612FA9938E8 /* Build configuration list for PBXNativeTarget "Nimble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A18080D500212DBA2ED5E37392C84210 /* Debug */, + 0E0AD4FF6AA5FBB0FBA354417A2A1C68 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7C4C40C3D8082F462A288F5A3751DB35 /* Build configuration list for PBXNativeTarget "Pods-Objective-C" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 655B76266B5A2CE366BC052D0249AE20 /* Debug */, + 6443D647999465AA6EE3E30DBE1E01BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AE8BA48E64C0BE4DC719C4BAE69F06A8 /* Build configuration list for PBXNativeTarget "OCMock" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 353F04AF586D433964C82B7737CCC295 /* Debug */, + 014146C0C5567965569864E91D361A65 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/LICENSE b/Students/Benny/Les 1 OCMock/Pods/Quick/LICENSE new file mode 100644 index 0000000..e900165 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014, Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/README.md b/Students/Benny/Les 1 OCMock/Pods/Quick/README.md new file mode 100644 index 0000000..e6dc0ad --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/README.md @@ -0,0 +1,88 @@ +![](http://f.cl.ly/items/0r1E192C1R0b2g2Q3h2w/QuickLogo_Color.png) + +[![Build Status](https://travis-ci.org/Quick/Quick.svg?branch=master)](https://travis-ci.org/Quick/Quick) +[![CocoaPods](https://img.shields.io/cocoapods/v/Quick.svg)](https://cocoapods.org/pods/Quick) +[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Platforms](https://img.shields.io/cocoapods/p/Quick.svg)](https://cocoapods.org/pods/Quick) + +Quick is a behavior-driven development framework for Swift and Objective-C. +Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo). + +![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/QuickSpec%20screenshot.png) + +```swift +// Swift + +import Quick +import Nimble + +class TableOfContentsSpec: QuickSpec { + override func spec() { + describe("the 'Documentation' directory") { + it("has everything you need to get started") { + let sections = Directory("Documentation").sections + expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups")) + expect(sections).to(contain("Installing Quick")) + } + + context("if it doesn't have what you're looking for") { + it("needs to be updated") { + let you = You(awesome: true) + expect{you.submittedAnIssue}.toEventually(beTruthy()) + } + } + } + } +} +``` +#### Nimble +Quick comes together with [Nimble](https://github.com/Quick/Nimble) — a matcher framework for your tests. You can learn why `XCTAssert()` statements make your expectations unclear and how to fix that using Nimble assertions [here](./Documentation/en-us/NimbleAssertions.md). + +## Swift Version + +Certain versions of Quick and Nimble only support certain versions of Swift. Depending on which version of Swift your project uses, you should use specific versions of Quick and Nimble. Use the table below to determine which versions of Quick and Nimble are compatible with your project. + +|Swift version |Quick version |Nimble version | +|:--------------------|:---------------|:--------------| +|Swift 3 |v1.0.0 or later |v5.0.0 or later| +|Swift 2.2 / Swift 2.3|v0.9.3 |v4.1.0 | + +## Documentation + +All documentation can be found in the [Documentation folder](./Documentation), including [detailed installation instructions](./Documentation/en-us/InstallingQuick.md) for CocoaPods, Carthage, Git submodules, and more. For example, you can install Quick and [Nimble](https://github.com/Quick/Nimble) using CocoaPods by adding the following to your Podfile: + +```rb +# Podfile + +use_frameworks! + +target "MyApp" do + # Normal libraries + + abstract_target 'Tests' do + inherit! :search_paths + target "MyAppTests" + target "MyAppUITests" + + pod 'Quick' + pod 'Nimble' + end +end +``` + +## Projects using Quick + +Over ten-thousand apps use either Quick and Nimble however, as they are not included in the app binary, neither appear in “Top Used Libraries” blog posts. Therefore, it would be greatly appreciated to remind contributors that their efforts are valued by compiling a list of organizations and projects that use them. + +Does your organization or project use Quick and Nimble? If yes, [please add your project to the list](https://github.com/Quick/Quick/wiki/Projects-using-Quick). + +## Who uses Quick + +Similar to projects using Quick, it would be nice to hear why people use Quick and Nimble. Are there features you love? Are there features that are just okay? Are there some features we have that no one uses? + +Have something positive to say about Quick (or Nimble)? If yes, [provide a testimonial here](https://github.com/Quick/Quick/wiki/Who-uses-Quick). + + +## License + +Apache 2.0 license. See the [`LICENSE`](LICENSE) file for details. diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Callsite.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Callsite.swift new file mode 100644 index 0000000..bb5cc0c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Callsite.swift @@ -0,0 +1,32 @@ +import Foundation + +/** + An object encapsulating the file and line number at which + a particular example is defined. +*/ +final public class Callsite: NSObject { + /** + The absolute path of the file in which an example is defined. + */ + public let file: String + + /** + The line number on which an example is defined. + */ + public let line: UInt + + internal init(file: String, line: UInt) { + self.file = file + self.line = line + } +} + +extension Callsite { + /** + Returns a boolean indicating whether two Callsite objects are equal. + If two callsites are in the same file and on the same line, they must be equal. + */ + @nonobjc public static func == (lhs: Callsite, rhs: Callsite) -> Bool { + return lhs.file == rhs.file && lhs.line == rhs.line + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Configuration/Configuration.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Configuration/Configuration.swift new file mode 100644 index 0000000..583651b --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Configuration/Configuration.swift @@ -0,0 +1,161 @@ +import Foundation + +/** + A closure that temporarily exposes a Configuration object within + the scope of the closure. +*/ +public typealias QuickConfigurer = (_ configuration: Configuration) -> Void + +/** + A closure that, given metadata about an example, returns a boolean value + indicating whether that example should be run. +*/ +public typealias ExampleFilter = (_ example: Example) -> Bool + +/** + A configuration encapsulates various options you can use + to configure Quick's behavior. +*/ +final public class Configuration: NSObject { + internal let exampleHooks = ExampleHooks() + internal let suiteHooks = SuiteHooks() + internal var exclusionFilters: [ExampleFilter] = [ { example in + if let pending = example.filterFlags[Filter.pending] { + return pending + } else { + return false + } + }] + internal var inclusionFilters: [ExampleFilter] = [ { example in + if let focused = example.filterFlags[Filter.focused] { + return focused + } else { + return false + } + }] + + /** + Run all examples if none match the configured filters. True by default. + */ + public var runAllWhenEverythingFiltered = true + + /** + Registers an inclusion filter. + + All examples are filtered using all inclusion filters. + The remaining examples are run. If no examples remain, all examples are run. + + - parameter filter: A filter that, given an example, returns a value indicating + whether that example should be included in the examples + that are run. + */ + public func include(_ filter: @escaping ExampleFilter) { + inclusionFilters.append(filter) + } + + /** + Registers an exclusion filter. + + All examples that remain after being filtered by the inclusion filters are + then filtered via all exclusion filters. + + - parameter filter: A filter that, given an example, returns a value indicating + whether that example should be excluded from the examples + that are run. + */ + public func exclude(_ filter: @escaping ExampleFilter) { + exclusionFilters.append(filter) + } + + /** + Identical to Quick.Configuration.beforeEach, except the closure is + provided with metadata on the example that the closure is being run + prior to. + */ +#if _runtime(_ObjC) + @objc(beforeEachWithMetadata:) + public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + exampleHooks.appendBefore(closure) + } +#else + public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + exampleHooks.appendBefore(closure) + } +#endif + + /** + Like Quick.DSL.beforeEach, this configures Quick to execute the + given closure before each example that is run. The closure + passed to this method is executed before each example Quick runs, + globally across the test suite. You may call this method multiple + times across mulitple +[QuickConfigure configure:] methods in order + to define several closures to run before each example. + + Note that, since Quick makes no guarantee as to the order in which + +[QuickConfiguration configure:] methods are evaluated, there is no + guarantee as to the order in which beforeEach closures are evaluated + either. Mulitple beforeEach defined on a single configuration, however, + will be executed in the order they're defined. + + - parameter closure: The closure to be executed before each example + in the test suite. + */ + public func beforeEach(_ closure: @escaping BeforeExampleClosure) { + exampleHooks.appendBefore(closure) + } + + /** + Identical to Quick.Configuration.afterEach, except the closure + is provided with metadata on the example that the closure is being + run after. + */ +#if _runtime(_ObjC) + @objc(afterEachWithMetadata:) + public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + exampleHooks.appendAfter(closure) + } +#else + public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + exampleHooks.appendAfter(closure) + } +#endif + + /** + Like Quick.DSL.afterEach, this configures Quick to execute the + given closure after each example that is run. The closure + passed to this method is executed after each example Quick runs, + globally across the test suite. You may call this method multiple + times across mulitple +[QuickConfigure configure:] methods in order + to define several closures to run after each example. + + Note that, since Quick makes no guarantee as to the order in which + +[QuickConfiguration configure:] methods are evaluated, there is no + guarantee as to the order in which afterEach closures are evaluated + either. Mulitple afterEach defined on a single configuration, however, + will be executed in the order they're defined. + + - parameter closure: The closure to be executed before each example + in the test suite. + */ + public func afterEach(_ closure: @escaping AfterExampleClosure) { + exampleHooks.appendAfter(closure) + } + + /** + Like Quick.DSL.beforeSuite, this configures Quick to execute + the given closure prior to any and all examples that are run. + The two methods are functionally equivalent. + */ + public func beforeSuite(_ closure: @escaping BeforeSuiteClosure) { + suiteHooks.appendBefore(closure) + } + + /** + Like Quick.DSL.afterSuite, this configures Quick to execute + the given closure after all examples have been run. + The two methods are functionally equivalent. + */ + public func afterSuite(_ closure: @escaping AfterSuiteClosure) { + suiteHooks.appendAfter(closure) + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/DSL/DSL.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/DSL/DSL.swift new file mode 100644 index 0000000..3da2c42 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/DSL/DSL.swift @@ -0,0 +1,241 @@ +/** + Defines a closure to be run prior to any examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before the first example is run, this closure + will not be executed. + + - parameter closure: The closure to be run prior to any examples in the test suite. +*/ +public func beforeSuite(_ closure: @escaping BeforeSuiteClosure) { + World.sharedWorld.beforeSuite(closure) +} + +/** + Defines a closure to be run after all of the examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before all examples are run, this closure + will not be executed. + + - parameter closure: The closure to be run after all of the examples in the test suite. +*/ +public func afterSuite(_ closure: @escaping AfterSuiteClosure) { + World.sharedWorld.afterSuite(closure) +} + +/** + Defines a group of shared examples. These examples can be re-used in several locations + by using the `itBehavesLike` function. + + - parameter name: The name of the shared example group. This must be unique across all shared example + groups defined in a test suite. + - parameter closure: A closure containing the examples. This behaves just like an example group defined + using `describe` or `context`--the closure may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). +*/ +public func sharedExamples(_ name: String, closure: @escaping () -> Void) { + World.sharedWorld.sharedExamples(name) { _ in closure() } +} + +/** + Defines a group of shared examples. These examples can be re-used in several locations + by using the `itBehavesLike` function. + + - parameter name: The name of the shared example group. This must be unique across all shared example + groups defined in a test suite. + - parameter closure: A closure containing the examples. This behaves just like an example group defined + using `describe` or `context`--the closure may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + + The closure takes a SharedExampleContext as an argument. This context is a function + that can be executed to retrieve parameters passed in via an `itBehavesLike` function. +*/ +public func sharedExamples(_ name: String, closure: @escaping SharedExampleClosure) { + World.sharedWorld.sharedExamples(name, closure: closure) +} + +/** + Defines an example group. Example groups are logical groupings of examples. + Example groups can share setup and teardown code. + + - parameter description: An arbitrary string describing the example group. + - parameter closure: A closure that can contain other examples. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. +*/ +public func describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.describe(description, flags: flags, closure: closure) +} + +/** + Defines an example group. Equivalent to `describe`. +*/ +public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.context(description, flags: flags, closure: closure) +} + +/** + Defines a closure to be run prior to each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of beforeEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + - parameter closure: The closure to be run prior to each example. +*/ +public func beforeEach(_ closure: @escaping BeforeExampleClosure) { + World.sharedWorld.beforeEach(closure) +} + +/** + Identical to Quick.DSL.beforeEach, except the closure is provided with + metadata on the example that the closure is being run prior to. +*/ +public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) { + World.sharedWorld.beforeEach(closure: closure) +} + +/** + Defines a closure to be run after each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of afterEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + - parameter closure: The closure to be run after each example. +*/ +public func afterEach(_ closure: @escaping AfterExampleClosure) { + World.sharedWorld.afterEach(closure) +} + +/** + Identical to Quick.DSL.afterEach, except the closure is provided with + metadata on the example that the closure is being run after. +*/ +public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) { + World.sharedWorld.afterEach(closure: closure) +} + +/** + Defines an example. Examples use assertions to demonstrate how code should + behave. These are like "tests" in XCTest. + + - parameter description: An arbitrary string describing what the example is meant to specify. + - parameter closure: A closure that can contain assertions. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the example. A sensible default is provided. + - parameter line: The line containing the example. A sensible default is provided. +*/ +public func it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.it(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Inserts the examples defined using a `sharedExamples` function into the current example group. + The shared examples are executed at this location, as if they were written out manually. + + - parameter name: The name of the shared examples group to be executed. This must be identical to the + name of a shared examples group defined using `sharedExamples`. If there are no shared + examples that match the name given, an exception is thrown and the test suite will crash. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. +*/ +public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) { + itBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] }) +} + +/** + Inserts the examples defined using a `sharedExamples` function into the current example group. + The shared examples are executed at this location, as if they were written out manually. + This function also passes those shared examples a context that can be evaluated to give the shared + examples extra information on the subject of the example. + + - parameter name: The name of the shared examples group to be executed. This must be identical to the + name of a shared examples group defined using `sharedExamples`. If there are no shared + examples that match the name given, an exception is thrown and the test suite will crash. + - parameter sharedExampleContext: A closure that, when evaluated, returns key-value pairs that provide the + shared examples with extra information on the subject of the example. + - parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups. + Empty by default. + - parameter file: The absolute path to the file containing the current example group. A sensible default is provided. + - parameter line: The line containing the current example group. A sensible default is provided. +*/ +public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) { + World.sharedWorld.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) +} + +/** + Defines an example or example group that should not be executed. Use `pending` to temporarily disable + examples or groups that should not be run yet. + + - parameter description: An arbitrary string describing the example or example group. + - parameter closure: A closure that will not be evaluated. +*/ +public func pending(_ description: String, closure: () -> Void) { + World.sharedWorld.pending(description, closure: closure) +} + +/** + Use this to quickly mark a `describe` closure as pending. + This disables all examples within the closure. +*/ +public func xdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + World.sharedWorld.xdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly mark a `context` closure as pending. + This disables all examples within the closure. +*/ +public func xcontext(_ description: String, flags: FilterFlags, closure: () -> Void) { + xdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly mark an `it` closure as pending. + This disables the example and ensures the code within the closure is never run. +*/ +public func xit(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.xit(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Use this to quickly focus a `describe` closure, focusing the examples in the closure. + If any examples in the test suite are focused, only those examples are executed. + This trumps any explicitly focused or unfocused examples within the closure--they are all treated as focused. +*/ +public func fdescribe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + World.sharedWorld.fdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly focus a `context` closure. Equivalent to `fdescribe`. +*/ +public func fcontext(_ description: String, flags: FilterFlags = [:], closure: () -> Void) { + fdescribe(description, flags: flags, closure: closure) +} + +/** + Use this to quickly focus an `it` closure, focusing the example. + If any examples in the test suite are focused, only those examples are executed. +*/ +public func fit(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) { + World.sharedWorld.fit(description, flags: flags, file: file, line: line, closure: closure) +} + +/** + Use this to quickly focus an `itBehavesLike` closure. +*/ +public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) { + fitBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] }) +} + +/** + Use this to quickly focus an `itBehavesLike` closure. +*/ +public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) { + World.sharedWorld.fitBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/DSL/World+DSL.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/DSL/World+DSL.swift new file mode 100644 index 0000000..127ca54 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/DSL/World+DSL.swift @@ -0,0 +1,175 @@ +import Foundation + +/** + Adds methods to World to support top-level DSL functions (Swift) and + macros (Objective-C). These functions map directly to the DSL that test + writers use in their specs. +*/ +extension World { + internal func beforeSuite(_ closure: @escaping BeforeSuiteClosure) { + suiteHooks.appendBefore(closure) + } + + internal func afterSuite(_ closure: @escaping AfterSuiteClosure) { + suiteHooks.appendAfter(closure) + } + + internal func sharedExamples(_ name: String, closure: @escaping SharedExampleClosure) { + registerSharedExample(name, closure: closure) + } + + internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) { + guard currentExampleMetadata == nil else { + raiseError("'describe' cannot be used inside '\(currentPhase)', 'describe' may only be used inside 'context' or 'describe'. ") + } + guard currentExampleGroup != nil else { + raiseError("Error: example group was not created by its parent QuickSpec spec. Check that describe() or context() was used in QuickSpec.spec() and not a more general context (i.e. an XCTestCase test)") + } + let group = ExampleGroup(description: description, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group, closure: closure) + } + + internal func context(_ description: String, flags: FilterFlags, closure: () -> Void) { + guard currentExampleMetadata == nil else { + raiseError("'context' cannot be used inside '\(currentPhase)', 'context' may only be used inside 'context' or 'describe'. ") + } + self.describe(description, flags: flags, closure: closure) + } + + internal func fdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.describe(description, flags: focusedFlags, closure: closure) + } + + internal func xdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.describe(description, flags: pendingFlags, closure: closure) + } + + internal func beforeEach(_ closure: @escaping BeforeExampleClosure) { + guard currentExampleMetadata == nil else { + raiseError("'beforeEach' cannot be used inside '\(currentPhase)', 'beforeEach' may only be used inside 'context' or 'describe'. ") + } + currentExampleGroup.hooks.appendBefore(closure) + } + +#if _runtime(_ObjC) + @objc(beforeEachWithMetadata:) + internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendBefore(closure) + } +#else + internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendBefore(closure) + } +#endif + + internal func afterEach(_ closure: @escaping AfterExampleClosure) { + guard currentExampleMetadata == nil else { + raiseError("'afterEach' cannot be used inside '\(currentPhase)', 'afterEach' may only be used inside 'context' or 'describe'. ") + } + currentExampleGroup.hooks.appendAfter(closure) + } + +#if _runtime(_ObjC) + @objc(afterEachWithMetadata:) + internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendAfter(closure) + } +#else + internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) { + currentExampleGroup.hooks.appendAfter(closure) + } +#endif + + internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + if beforesCurrentlyExecuting { + raiseError("'it' cannot be used inside 'beforeEach', 'it' may only be used inside 'context' or 'describe'. ") + } + if aftersCurrentlyExecuting { + raiseError("'it' cannot be used inside 'afterEach', 'it' may only be used inside 'context' or 'describe'. ") + } + guard currentExampleMetadata == nil else { + raiseError("'it' cannot be used inside 'it', 'it' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let example = Example(description: description, callsite: callsite, flags: flags, closure: closure) + currentExampleGroup.appendExample(example) + } + + internal func fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.it(description, flags: focusedFlags, file: file, line: line, closure: closure) + } + + internal func xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + var pendingFlags = flags + pendingFlags[Filter.pending] = true + self.it(description, flags: pendingFlags, file: file, line: line, closure: closure) + } + + internal func itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + guard currentExampleMetadata == nil else { + raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ") + } + let callsite = Callsite(file: file, line: line) + let closure = World.sharedWorld.sharedExample(name) + + let group = ExampleGroup(description: name, flags: flags) + currentExampleGroup.appendExampleGroup(group) + performWithCurrentExampleGroup(group) { + closure(sharedExampleContext) + } + + group.walkDownExamples { (example: Example) in + example.isSharedExample = true + example.callsite = callsite + } + } + + internal func fitBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + var focusedFlags = flags + focusedFlags[Filter.focused] = true + self.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: focusedFlags, file: file, line: line) + } + +#if _runtime(_ObjC) + @objc(itWithDescription:flags:file:line:closure:) + private func objc_it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + it(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(fitWithDescription:flags:file:line:closure:) + private func objc_fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + fit(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(xitWithDescription:flags:file:line:closure:) + private func objc_xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) { + xit(description, flags: flags, file: file, line: line, closure: closure) + } + + @objc(itBehavesLikeSharedExampleNamed:sharedExampleContext:flags:file:line:) + private func objc_itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) { + itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line) + } +#endif + + internal func pending(_ description: String, closure: () -> Void) { + print("Pending: \(description)") + } + + private var currentPhase: String { + if beforesCurrentlyExecuting { + return "beforeEach" + } else if aftersCurrentlyExecuting { + return "afterEach" + } + + return "it" + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ErrorUtility.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ErrorUtility.swift new file mode 100644 index 0000000..8405a81 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ErrorUtility.swift @@ -0,0 +1,10 @@ +import Foundation + +internal func raiseError(_ message: String) -> Never { +#if _runtime(_ObjC) + NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise() +#endif + + // This won't be reached when ObjC is available and the exception above is raisd + fatalError(message) +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Example.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Example.swift new file mode 100644 index 0000000..56b3303 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Example.swift @@ -0,0 +1,113 @@ +import Foundation + +private var numberOfExamplesRun = 0 + +/** + Examples, defined with the `it` function, use assertions to + demonstrate how code should behave. These are like "tests" in XCTest. +*/ +final public class Example: NSObject { + /** + A boolean indicating whether the example is a shared example; + i.e.: whether it is an example defined with `itBehavesLike`. + */ + public var isSharedExample = false + + /** + The site at which the example is defined. + This must be set correctly in order for Xcode to highlight + the correct line in red when reporting a failure. + */ + public var callsite: Callsite + + weak internal var group: ExampleGroup? + + private let internalDescription: String + private let closure: () -> Void + private let flags: FilterFlags + + internal init(description: String, callsite: Callsite, flags: FilterFlags, closure: @escaping () -> Void) { + self.internalDescription = description + self.closure = closure + self.callsite = callsite + self.flags = flags + } + + public override var description: String { + return internalDescription + } + + /** + The example name. A name is a concatenation of the name of + the example group the example belongs to, followed by the + description of the example itself. + + The example name is used to generate a test method selector + to be displayed in Xcode's test navigator. + */ + public var name: String { + guard let groupName = group?.name else { return description } + return "\(groupName), \(description)" + } + + /** + Executes the example closure, as well as all before and after + closures defined in the its surrounding example groups. + */ + public func run() { + let world = World.sharedWorld + + if numberOfExamplesRun == 0 { + world.suiteHooks.executeBefores() + } + + let exampleMetadata = ExampleMetadata(example: self, exampleIndex: numberOfExamplesRun) + world.currentExampleMetadata = exampleMetadata + + world.exampleHooks.executeBefores(exampleMetadata) + group!.phase = .beforesExecuting + for before in group!.befores { + before(exampleMetadata) + } + group!.phase = .beforesFinished + + closure() + + group!.phase = .aftersExecuting + for after in group!.afters { + after(exampleMetadata) + } + group!.phase = .aftersFinished + world.exampleHooks.executeAfters(exampleMetadata) + + numberOfExamplesRun += 1 + + if !world.isRunningAdditionalSuites && numberOfExamplesRun >= world.includedExampleCount { + world.suiteHooks.executeAfters() + } + } + + /** + Evaluates the filter flags set on this example and on the example groups + this example belongs to. Flags set on the example are trumped by flags on + the example group it belongs to. Flags on inner example groups are trumped + by flags on outer example groups. + */ + internal var filterFlags: FilterFlags { + var aggregateFlags = flags + for (key, value) in group!.filterFlags { + aggregateFlags[key] = value + } + return aggregateFlags + } +} + +extension Example { + /** + Returns a boolean indicating whether two Example objects are equal. + If two examples are defined at the exact same callsite, they must be equal. + */ + @nonobjc public static func == (lhs: Example, rhs: Example) -> Bool { + return lhs.callsite == rhs.callsite + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ExampleGroup.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ExampleGroup.swift new file mode 100644 index 0000000..ca38356 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ExampleGroup.swift @@ -0,0 +1,103 @@ +import Foundation + +/** + Example groups are logical groupings of examples, defined with + the `describe` and `context` functions. Example groups can share + setup and teardown code. +*/ +final public class ExampleGroup: NSObject { + weak internal var parent: ExampleGroup? + internal let hooks = ExampleHooks() + + internal var phase: HooksPhase = .nothingExecuted + + private let internalDescription: String + private let flags: FilterFlags + private let isInternalRootExampleGroup: Bool + private var childGroups = [ExampleGroup]() + private var childExamples = [Example]() + + internal init(description: String, flags: FilterFlags, isInternalRootExampleGroup: Bool = false) { + self.internalDescription = description + self.flags = flags + self.isInternalRootExampleGroup = isInternalRootExampleGroup + } + + public override var description: String { + return internalDescription + } + + /** + Returns a list of examples that belong to this example group, + or to any of its descendant example groups. + */ + public var examples: [Example] { + var examples = childExamples + for group in childGroups { + examples.append(contentsOf: group.examples) + } + return examples + } + + internal var name: String? { + if let parent = parent { + guard let name = parent.name else { return description } + return "\(name), \(description)" + } else { + return isInternalRootExampleGroup ? nil : description + } + } + + internal var filterFlags: FilterFlags { + var aggregateFlags = flags + walkUp { group in + for (key, value) in group.flags { + aggregateFlags[key] = value + } + } + return aggregateFlags + } + + internal var befores: [BeforeExampleWithMetadataClosure] { + var closures = Array(hooks.befores.reversed()) + walkUp { group in + closures.append(contentsOf: Array(group.hooks.befores.reversed())) + } + return Array(closures.reversed()) + } + + internal var afters: [AfterExampleWithMetadataClosure] { + var closures = hooks.afters + walkUp { group in + closures.append(contentsOf: group.hooks.afters) + } + return closures + } + + internal func walkDownExamples(_ callback: (_ example: Example) -> Void) { + for example in childExamples { + callback(example) + } + for group in childGroups { + group.walkDownExamples(callback) + } + } + + internal func appendExampleGroup(_ group: ExampleGroup) { + group.parent = self + childGroups.append(group) + } + + internal func appendExample(_ example: Example) { + example.group = self + childExamples.append(example) + } + + private func walkUp(_ callback: (_ group: ExampleGroup) -> Void) { + var group = self + while let parent = group.parent { + callback(parent) + group = parent + } + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ExampleMetadata.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ExampleMetadata.swift new file mode 100644 index 0000000..e7510f7 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/ExampleMetadata.swift @@ -0,0 +1,24 @@ +import Foundation + +/** + A class that encapsulates information about an example, + including the index at which the example was executed, as + well as the example itself. +*/ +final public class ExampleMetadata: NSObject { + /** + The example for which this metadata was collected. + */ + public let example: Example + + /** + The index at which this example was executed in the + test suite. + */ + public let exampleIndex: Int + + internal init(example: Example, exampleIndex: Int) { + self.example = example + self.exampleIndex = exampleIndex + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Filter.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Filter.swift new file mode 100644 index 0000000..d452efe --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Filter.swift @@ -0,0 +1,31 @@ +import Foundation + +/** + A mapping of string keys to booleans that can be used to + filter examples or example groups. For example, a "focused" + example would have the flags [Focused: true]. +*/ +public typealias FilterFlags = [String: Bool] + +/** + A namespace for filter flag keys, defined primarily to make the + keys available in Objective-C. +*/ +final public class Filter: NSObject { + /** + Example and example groups with [Focused: true] are included in test runs, + excluding all other examples without this flag. Use this to only run one or + two tests that you're currently focusing on. + */ + public class var focused: String { + return "focused" + } + + /** + Example and example groups with [Pending: true] are excluded from test runs. + Use this to temporarily suspend examples that you know do not pass yet. + */ + public class var pending: String { + return "pending" + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/Closures.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/Closures.swift new file mode 100644 index 0000000..9c7d310 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/Closures.swift @@ -0,0 +1,35 @@ +// MARK: Example Hooks + +/** + A closure executed before an example is run. +*/ +public typealias BeforeExampleClosure = () -> Void + +/** + A closure executed before an example is run. The closure is given example metadata, + which contains information about the example that is about to be run. +*/ +public typealias BeforeExampleWithMetadataClosure = (_ exampleMetadata: ExampleMetadata) -> Void + +/** + A closure executed after an example is run. +*/ +public typealias AfterExampleClosure = BeforeExampleClosure + +/** + A closure executed after an example is run. The closure is given example metadata, + which contains information about the example that has just finished running. +*/ +public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure + +// MARK: Suite Hooks + +/** + A closure executed before any examples are run. +*/ +public typealias BeforeSuiteClosure = () -> Void + +/** + A closure executed after all examples have finished running. +*/ +public typealias AfterSuiteClosure = BeforeSuiteClosure diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift new file mode 100644 index 0000000..449cbfc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift @@ -0,0 +1,42 @@ +/** + A container for closures to be executed before and after each example. +*/ +final internal class ExampleHooks { + internal var befores: [BeforeExampleWithMetadataClosure] = [] + internal var afters: [AfterExampleWithMetadataClosure] = [] + internal var phase: HooksPhase = .nothingExecuted + + internal func appendBefore(_ closure: @escaping BeforeExampleWithMetadataClosure) { + befores.append(closure) + } + + internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { + befores.append { (_: ExampleMetadata) in closure() } + } + + internal func appendAfter(_ closure: @escaping AfterExampleWithMetadataClosure) { + afters.append(closure) + } + + internal func appendAfter(_ closure: @escaping AfterExampleClosure) { + afters.append { (_: ExampleMetadata) in closure() } + } + + internal func executeBefores(_ exampleMetadata: ExampleMetadata) { + phase = .beforesExecuting + for before in befores { + before(exampleMetadata) + } + + phase = .beforesFinished + } + + internal func executeAfters(_ exampleMetadata: ExampleMetadata) { + phase = .aftersExecuting + for after in afters { + after(exampleMetadata) + } + + phase = .aftersFinished + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift new file mode 100644 index 0000000..2440158 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift @@ -0,0 +1,11 @@ +/** + A description of the execution cycle of the current example with + respect to the hooks of that example. + */ +internal enum HooksPhase { + case nothingExecuted + case beforesExecuting + case beforesFinished + case aftersExecuting + case aftersFinished +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift new file mode 100644 index 0000000..b39292b --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift @@ -0,0 +1,32 @@ +/** + A container for closures to be executed before and after all examples. +*/ +final internal class SuiteHooks { + internal var befores: [BeforeSuiteClosure] = [] + internal var afters: [AfterSuiteClosure] = [] + internal var phase: HooksPhase = .nothingExecuted + + internal func appendBefore(_ closure: @escaping BeforeSuiteClosure) { + befores.append(closure) + } + + internal func appendAfter(_ closure: @escaping AfterSuiteClosure) { + afters.append(closure) + } + + internal func executeBefores() { + phase = .beforesExecuting + for before in befores { + before() + } + phase = .beforesFinished + } + + internal func executeAfters() { + phase = .aftersExecuting + for after in afters { + after() + } + phase = .aftersFinished + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift new file mode 100644 index 0000000..994dd72 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift @@ -0,0 +1,25 @@ +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) + +import Foundation + +extension Bundle { + + /** + Locates the first bundle with a '.xctest' file extension. + */ + internal static var currentTestBundle: Bundle? { + return allBundles.first { $0.bundlePath.hasSuffix(".xctest") } + } + + /** + Return the module name of the bundle. + Uses the bundle filename and transform it to match Xcode's transformation. + Module name has to be a valid "C99 extended identifier". + */ + internal var moduleName: String { + let fileName = bundleURL.fileName as NSString + return fileName.c99ExtendedIdentifier + } +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift new file mode 100644 index 0000000..4514863 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift @@ -0,0 +1,33 @@ +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) +import Foundation + +public extension NSString { + + private static var invalidCharacters: CharacterSet = { + var invalidCharacters = CharacterSet() + + let invalidCharacterSets: [CharacterSet] = [ + .whitespacesAndNewlines, + .illegalCharacters, + .controlCharacters, + .punctuationCharacters, + .nonBaseCharacters, + .symbols, + ] + + for invalidSet in invalidCharacterSets { + invalidCharacters.formUnion(invalidSet) + } + + return invalidCharacters + }() + + @objc(qck_c99ExtendedIdentifier) + var c99ExtendedIdentifier: String { + let validComponents = components(separatedBy: NSString.invalidCharacters) + let result = validComponents.joined(separator: "_") + + return result.isEmpty ? "_" : result + } +} +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift new file mode 100644 index 0000000..d49e859 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift @@ -0,0 +1,74 @@ +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) +import Foundation + +/** + Responsible for building a "Selected tests" suite. This corresponds to a single + spec, and all its examples. + */ +internal class QuickSelectedTestSuiteBuilder: QuickTestSuiteBuilder { + + /** + The test spec class to run. + */ + let testCaseClass: AnyClass! + + /** + For Objective-C classes, returns the class name. For Swift classes without, + an explicit Objective-C name, returns a module-namespaced class name + (e.g., "FooTests.FooSpec"). + */ + var testSuiteClassName: String { + return NSStringFromClass(testCaseClass) + } + + /** + Given a test case name: + + FooSpec/testFoo + + Optionally constructs a test suite builder for the named test case class + in the running test bundle. + + If no test bundle can be found, or the test case class can't be found, + initialization fails and returns `nil`. + */ + init?(forTestCaseWithName name: String) { + guard let testCaseClass = testCaseClassForTestCaseWithName(name) else { + self.testCaseClass = nil + return nil + } + + self.testCaseClass = testCaseClass + } + + /** + Returns a `QuickTestSuite` that runs the associated test case class. + */ + func buildTestSuite() -> QuickTestSuite { + return QuickTestSuite(forTestCaseClass: testCaseClass) + } + +} + +/** + Searches `Bundle.allBundles()` for an xctest bundle, then looks up the named + test case class in that bundle. + + Returns `nil` if a bundle or test case class cannot be found. + */ +private func testCaseClassForTestCaseWithName(_ name: String) -> AnyClass? { + func extractClassName(_ name: String) -> String? { + return name.components(separatedBy: "/").first + } + + guard let className = extractClassName(name) else { return nil } + guard let bundle = Bundle.currentTestBundle else { return nil } + + if let testCaseClass = bundle.classNamed(className) { return testCaseClass } + + let moduleName = bundle.moduleName + + return NSClassFromString("\(moduleName).\(className)") +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/QuickTestSuite.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/QuickTestSuite.swift new file mode 100644 index 0000000..0cb5187 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/QuickTestSuite.swift @@ -0,0 +1,52 @@ +#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) + +import XCTest + +/** + This protocol defines the role of an object that builds test suites. + */ +internal protocol QuickTestSuiteBuilder { + + /** + Construct a `QuickTestSuite` instance with the appropriate test cases added as tests. + + Subsequent calls to this method should return equivalent test suites. + */ + func buildTestSuite() -> QuickTestSuite + +} + +/** + A base class for a class cluster of Quick test suites, that should correctly + build dynamic test suites for XCTest to execute. + */ +public class QuickTestSuite: XCTestSuite { + + private static var builtTestSuites: Set = Set() + + /** + Construct a test suite for a specific, selected subset of test cases (rather + than the default, which as all test cases). + + If this method is called multiple times for the same test case class, e.g.. + + FooSpec/testFoo + FooSpec/testBar + + It is expected that the first call should return a valid test suite, and + all subsequent calls should return `nil`. + */ + public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? { + guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil } + + if builtTestSuites.contains(builder.testSuiteClassName) { + return nil + } else { + builtTestSuites.insert(builder.testSuiteClassName) + return builder.buildTestSuite() + } + } + +} + +#endif diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/URL+FileName.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/URL+FileName.swift new file mode 100644 index 0000000..23c4781 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/URL+FileName.swift @@ -0,0 +1,12 @@ +import Foundation + +extension URL { + + /** + Returns the path file name without file extension. + */ + var fileName: String { + return self.deletingPathExtension().lastPathComponent + } + +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/World.swift b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/World.swift new file mode 100644 index 0000000..fb5ec25 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/Quick/World.swift @@ -0,0 +1,233 @@ +import Foundation + +/** + A closure that, when evaluated, returns a dictionary of key-value + pairs that can be accessed from within a group of shared examples. +*/ +public typealias SharedExampleContext = () -> [String: Any] + +/** + A closure that is used to define a group of shared examples. This + closure may contain any number of example and example groups. +*/ +public typealias SharedExampleClosure = (@escaping SharedExampleContext) -> Void + +/** + A collection of state Quick builds up in order to work its magic. + World is primarily responsible for maintaining a mapping of QuickSpec + classes to root example groups for those classes. + + It also maintains a mapping of shared example names to shared + example closures. + + You may configure how Quick behaves by calling the -[World configure:] + method from within an overridden +[QuickConfiguration configure:] method. +*/ +final internal class World: NSObject { + /** + The example group that is currently being run. + The DSL requires that this group is correctly set in order to build a + correct hierarchy of example groups and their examples. + */ + internal var currentExampleGroup: ExampleGroup! + + /** + The example metadata of the test that is currently being run. + This is useful for using the Quick test metadata (like its name) at + runtime. + */ + + internal var currentExampleMetadata: ExampleMetadata? + + /** + A flag that indicates whether additional test suites are being run + within this test suite. This is only true within the context of Quick + functional tests. + */ +#if _runtime(_ObjC) + // Convention of generating Objective-C selector has been changed on Swift 3 + @objc(isRunningAdditionalSuites) + internal var isRunningAdditionalSuites = false +#else + internal var isRunningAdditionalSuites = false +#endif + + private var specs: [String: ExampleGroup] = [:] + private var sharedExamples: [String: SharedExampleClosure] = [:] + private let configuration = Configuration() + + internal private(set) var isConfigurationFinalized = false + + internal var exampleHooks: ExampleHooks {return configuration.exampleHooks } + internal var suiteHooks: SuiteHooks { return configuration.suiteHooks } + + // MARK: Singleton Constructor + + private override init() {} + static let sharedWorld = World() + + // MARK: Public Interface + + /** + Exposes the World's Configuration object within the scope of the closure + so that it may be configured. This method must not be called outside of + an overridden +[QuickConfiguration configure:] method. + + - parameter closure: A closure that takes a Configuration object that can + be mutated to change Quick's behavior. + */ + internal func configure(_ closure: QuickConfigurer) { + assert(!isConfigurationFinalized, + "Quick cannot be configured outside of a +[QuickConfiguration configure:] method. You should not call -[World configure:] directly. Instead, subclass QuickConfiguration and override the +[QuickConfiguration configure:] method.") + closure(configuration) + } + + /** + Finalizes the World's configuration. + Any subsequent calls to World.configure() will raise. + */ + internal func finalizeConfiguration() { + isConfigurationFinalized = true + } + + /** + Returns an internally constructed root example group for the given + QuickSpec class. + + A root example group with the description "root example group" is lazily + initialized for each QuickSpec class. This root example group wraps the + top level of a -[QuickSpec spec] method--it's thanks to this group that + users can define beforeEach and it closures at the top level, like so: + + override func spec() { + // These belong to the root example group + beforeEach {} + it("is at the top level") {} + } + + - parameter cls: The QuickSpec class for which to retrieve the root example group. + - returns: The root example group for the class. + */ + internal func rootExampleGroupForSpecClass(_ cls: AnyClass) -> ExampleGroup { + let name = String(describing: cls) + + if let group = specs[name] { + return group + } else { + let group = ExampleGroup( + description: "root example group", + flags: [:], + isInternalRootExampleGroup: true + ) + specs[name] = group + return group + } + } + + /** + Returns all examples that should be run for a given spec class. + There are two filtering passes that occur when determining which examples should be run. + That is, these examples are the ones that are included by inclusion filters, and are + not excluded by exclusion filters. + + - parameter specClass: The QuickSpec subclass for which examples are to be returned. + - returns: A list of examples to be run as test invocations. + */ + internal func examples(_ specClass: AnyClass) -> [Example] { + // 1. Grab all included examples. + let included = includedExamples + // 2. Grab the intersection of (a) examples for this spec, and (b) included examples. + let spec = rootExampleGroupForSpecClass(specClass).examples.filter { included.contains($0) } + // 3. Remove all excluded examples. + return spec.filter { example in + !self.configuration.exclusionFilters.reduce(false) { $0 || $1(example) } + } + } + +#if _runtime(_ObjC) + @objc(examplesForSpecClass:) + private func objc_examples(_ specClass: AnyClass) -> [Example] { + return examples(specClass) + } +#endif + + // MARK: Internal + + internal func registerSharedExample(_ name: String, closure: @escaping SharedExampleClosure) { + raiseIfSharedExampleAlreadyRegistered(name) + sharedExamples[name] = closure + } + + internal func sharedExample(_ name: String) -> SharedExampleClosure { + raiseIfSharedExampleNotRegistered(name) + return sharedExamples[name]! + } + + internal var includedExampleCount: Int { + return includedExamples.count + } + + internal var beforesCurrentlyExecuting: Bool { + let suiteBeforesExecuting = suiteHooks.phase == .beforesExecuting + let exampleBeforesExecuting = exampleHooks.phase == .beforesExecuting + var groupBeforesExecuting = false + if let runningExampleGroup = currentExampleMetadata?.example.group { + groupBeforesExecuting = runningExampleGroup.phase == .beforesExecuting + } + + return suiteBeforesExecuting || exampleBeforesExecuting || groupBeforesExecuting + } + + internal var aftersCurrentlyExecuting: Bool { + let suiteAftersExecuting = suiteHooks.phase == .aftersExecuting + let exampleAftersExecuting = exampleHooks.phase == .aftersExecuting + var groupAftersExecuting = false + if let runningExampleGroup = currentExampleMetadata?.example.group { + groupAftersExecuting = runningExampleGroup.phase == .aftersExecuting + } + + return suiteAftersExecuting || exampleAftersExecuting || groupAftersExecuting + } + + internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) { + let previousExampleGroup = currentExampleGroup + currentExampleGroup = group + + closure() + + currentExampleGroup = previousExampleGroup + } + + private var allExamples: [Example] { + var all: [Example] = [] + for (_, group) in specs { + group.walkDownExamples { all.append($0) } + } + return all + } + + private var includedExamples: [Example] { + let all = allExamples + let included = all.filter { example in + return self.configuration.inclusionFilters.reduce(false) { $0 || $1(example) } + } + + if included.isEmpty && configuration.runAllWhenEverythingFiltered { + return all + } else { + return included + } + } + + private func raiseIfSharedExampleAlreadyRegistered(_ name: String) { + if sharedExamples[name] != nil { + raiseError("A shared example named '\(name)' has already been registered.") + } + } + + private func raiseIfSharedExampleNotRegistered(_ name: String) { + if sharedExamples[name] == nil { + raiseError("No shared example named '\(name)' has been registered. Registered shared examples: '\(Array(sharedExamples.keys))'") + } + } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h new file mode 100644 index 0000000..5646199 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h @@ -0,0 +1,30 @@ +#import + +@class Configuration; + +/** + Subclass QuickConfiguration and override the +[QuickConfiguration configure:] + method in order to configure how Quick behaves when running specs, or to define + shared examples that are used across spec files. + */ +@interface QuickConfiguration : NSObject + +/** + This method is executed on each subclass of this class before Quick runs + any examples. You may override this method on as many subclasses as you like, but + there is no guarantee as to the order in which these methods are executed. + + You can override this method in order to: + + 1. Configure how Quick behaves, by modifying properties on the Configuration object. + Setting the same properties in several methods has undefined behavior. + + 2. Define shared examples using `sharedExamples`. + + @param configuration A mutable object that is used to configure how Quick behaves on + a framework level. For details on all the options, see the + documentation in Configuration.swift. + */ ++ (void)configure:(Configuration *)configuration; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m new file mode 100644 index 0000000..937b818 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m @@ -0,0 +1,83 @@ +#import "QuickConfiguration.h" +#import "World.h" +#import + +typedef void (^QCKClassEnumerationBlock)(Class klass); + +/** + Finds all direct subclasses of the given class and passes them to the block provided. + The classes are iterated over in the order that objc_getClassList returns them. + + @param klass The base class to find subclasses of. + @param block A block that takes a Class. This block will be executed once for each subclass of klass. + */ +void qck_enumerateSubclasses(Class klass, QCKClassEnumerationBlock block) { + Class *classes = NULL; + int classesCount = objc_getClassList(NULL, 0); + + if (classesCount > 0) { + classes = (Class *)calloc(sizeof(Class), classesCount); + classesCount = objc_getClassList(classes, classesCount); + + Class subclass, superclass; + for(int i = 0; i < classesCount; i++) { + subclass = classes[i]; + superclass = class_getSuperclass(subclass); + if (superclass == klass && block) { + block(subclass); + } + } + + free(classes); + } +} + +@implementation QuickConfiguration + +#pragma mark - Object Lifecycle + +/** + QuickConfiguration is not meant to be instantiated; it merely provides a hook + for users to configure how Quick behaves. Raise an exception if an instance of + QuickConfiguration is created. + */ +- (instancetype)init { + NSString *className = NSStringFromClass([self class]); + NSString *selectorName = NSStringFromSelector(@selector(configure:)); + [NSException raise:NSInternalInconsistencyException + format:@"%@ is not meant to be instantiated; " + @"subclass %@ and override %@ to configure Quick.", + className, className, selectorName]; + return nil; +} + +#pragma mark - NSObject Overrides + +/** + Hook into when QuickConfiguration is initialized in the runtime in order to + call +[QuickConfiguration configure:] on each of its subclasses. + */ ++ (void)initialize { + // Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses. + if ([self class] == [QuickConfiguration class]) { + + // Only enumerate over subclasses once, even if +[QuickConfiguration initialize] + // were to be called several times. This is necessary because +[QuickSpec initialize] + // manually calls +[QuickConfiguration initialize]. + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + qck_enumerateSubclasses([QuickConfiguration class], ^(__unsafe_unretained Class klass) { + [[World sharedWorld] configure:^(Configuration *configuration) { + [klass configure:configuration]; + }]; + }); + [[World sharedWorld] finalizeConfiguration]; + }); + } +} + +#pragma mark - Public Interface + ++ (void)configure:(Configuration *)configuration { } + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h new file mode 100644 index 0000000..c5f3152 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h @@ -0,0 +1,234 @@ +#import + +@class ExampleMetadata; + +/** + Provides a hook for Quick to be configured before any examples are run. + Within this scope, override the +[QuickConfiguration configure:] method + to set properties on a configuration object to customize Quick behavior. + For details, see the documentation for Configuraiton.swift. + + @param name The name of the configuration class. Like any Objective-C + class name, this must be unique to the current runtime + environment. + */ +#define QuickConfigurationBegin(name) \ + @interface name : QuickConfiguration; @end \ + @implementation name \ + + +/** + Marks the end of a Quick configuration. + Make sure you put this after `QuickConfigurationBegin`. + */ +#define QuickConfigurationEnd \ + @end \ + + +/** + Defines a new QuickSpec. Define examples and example groups within the space + between this and `QuickSpecEnd`. + + @param name The name of the spec class. Like any Objective-C class name, this + must be unique to the current runtime environment. + */ +#define QuickSpecBegin(name) \ + @interface name : QuickSpec; @end \ + @implementation name \ + - (void)spec { \ + + +/** + Marks the end of a QuickSpec. Make sure you put this after `QuickSpecBegin`. + */ +#define QuickSpecEnd \ + } \ + @end \ + +typedef NSDictionary *(^QCKDSLSharedExampleContext)(void); +typedef void (^QCKDSLSharedExampleBlock)(QCKDSLSharedExampleContext); +typedef void (^QCKDSLEmptyBlock)(void); +typedef void (^QCKDSLExampleMetadataBlock)(ExampleMetadata *exampleMetadata); + +#define QUICK_EXPORT FOUNDATION_EXPORT + +QUICK_EXPORT void qck_beforeSuite(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_afterSuite(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure); +QUICK_EXPORT void qck_describe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_context(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_beforeEach(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure); +QUICK_EXPORT void qck_afterEach(QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure); +QUICK_EXPORT void qck_pending(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure); +QUICK_EXPORT void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure); + +#ifndef QUICK_DISABLE_SHORT_SYNTAX +/** + Defines a closure to be run prior to any examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before the first example is run, this closure + will not be executed. + + @param closure The closure to be run prior to any examples in the test suite. + */ +static inline void beforeSuite(QCKDSLEmptyBlock closure) { + qck_beforeSuite(closure); +} + + +/** + Defines a closure to be run after all of the examples in the test suite. + You may define an unlimited number of these closures, but there is no + guarantee as to the order in which they're run. + + If the test suite crashes before all examples are run, this closure + will not be executed. + + @param closure The closure to be run after all of the examples in the test suite. + */ +static inline void afterSuite(QCKDSLEmptyBlock closure) { + qck_afterSuite(closure); +} + +/** + Defines a group of shared examples. These examples can be re-used in several locations + by using the `itBehavesLike` function. + + @param name The name of the shared example group. This must be unique across all shared example + groups defined in a test suite. + @param closure A closure containing the examples. This behaves just like an example group defined + using `describe` or `context`--the closure may contain any number of `beforeEach` + and `afterEach` closures, as well as any number of examples (defined using `it`). + */ +static inline void sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { + qck_sharedExamples(name, closure); +} + +/** + Defines an example group. Example groups are logical groupings of examples. + Example groups can share setup and teardown code. + + @param description An arbitrary string describing the example group. + @param closure A closure that can contain other examples. + */ +static inline void describe(NSString *description, QCKDSLEmptyBlock closure) { + qck_describe(description, closure); +} + +/** + Defines an example group. Equivalent to `describe`. + */ +static inline void context(NSString *description, QCKDSLEmptyBlock closure) { + qck_context(description, closure); +} + +/** + Defines a closure to be run prior to each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of beforeEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + @param closure The closure to be run prior to each example. + */ +static inline void beforeEach(QCKDSLEmptyBlock closure) { + qck_beforeEach(closure); +} + +/** + Identical to QCKDSL.beforeEach, except the closure is provided with + metadata on the example that the closure is being run prior to. + */ +static inline void beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + qck_beforeEachWithMetadata(closure); +} + +/** + Defines a closure to be run after each example in the current example + group. This closure is not run for pending or otherwise disabled examples. + An example group may contain an unlimited number of afterEach. They'll be + run in the order they're defined, but you shouldn't rely on that behavior. + + @param closure The closure to be run after each example. + */ +static inline void afterEach(QCKDSLEmptyBlock closure) { + qck_afterEach(closure); +} + +/** + Identical to QCKDSL.afterEach, except the closure is provided with + metadata on the example that the closure is being run after. + */ +static inline void afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + qck_afterEachWithMetadata(closure); +} + +/** + Defines an example or example group that should not be executed. Use `pending` to temporarily disable + examples or groups that should not be run yet. + + @param description An arbitrary string describing the example or example group. + @param closure A closure that will not be evaluated. + */ +static inline void pending(NSString *description, QCKDSLEmptyBlock closure) { + qck_pending(description, closure); +} + +/** + Use this to quickly mark a `describe` block as pending. + This disables all examples within the block. + */ +static inline void xdescribe(NSString *description, QCKDSLEmptyBlock closure) { + qck_xdescribe(description, closure); +} + +/** + Use this to quickly mark a `context` block as pending. + This disables all examples within the block. + */ +static inline void xcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_xcontext(description, closure); +} + +/** + Use this to quickly focus a `describe` block, focusing the examples in the block. + If any examples in the test suite are focused, only those examples are executed. + This trumps any explicitly focused or unfocused examples within the block--they are all treated as focused. + */ +static inline void fdescribe(NSString *description, QCKDSLEmptyBlock closure) { + qck_fdescribe(description, closure); +} + +/** + Use this to quickly focus a `context` block. Equivalent to `fdescribe`. + */ +static inline void fcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_fcontext(description, closure); +} + +#define it qck_it +#define xit qck_xit +#define fit qck_fit +#define itBehavesLike qck_itBehavesLike +#define xitBehavesLike qck_xitBehavesLike +#define fitBehavesLike qck_fitBehavesLike +#endif + +#define qck_it qck_it_builder(@{}, @(__FILE__), __LINE__) +#define qck_xit qck_it_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__) +#define qck_fit qck_it_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__) +#define qck_itBehavesLike qck_itBehavesLike_builder(@{}, @(__FILE__), __LINE__) +#define qck_xitBehavesLike qck_itBehavesLike_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__) +#define qck_fitBehavesLike qck_itBehavesLike_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__) + +typedef void (^QCKItBlock)(NSString *description, QCKDSLEmptyBlock closure); +typedef void (^QCKItBehavesLikeBlock)(NSString *description, QCKDSLSharedExampleContext context); + +QUICK_EXPORT QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line); +QUICK_EXPORT QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line); diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m new file mode 100644 index 0000000..10e8a3d --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m @@ -0,0 +1,79 @@ +#import "QCKDSL.h" +#import "World.h" +#import "World+DSL.h" + +void qck_beforeSuite(QCKDSLEmptyBlock closure) { + [[World sharedWorld] beforeSuite:closure]; +} + +void qck_afterSuite(QCKDSLEmptyBlock closure) { + [[World sharedWorld] afterSuite:closure]; +} + +void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { + [[World sharedWorld] sharedExamples:name closure:closure]; +} + +void qck_describe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] describe:description flags:@{} closure:closure]; +} + +void qck_context(NSString *description, QCKDSLEmptyBlock closure) { + qck_describe(description, closure); +} + +void qck_beforeEach(QCKDSLEmptyBlock closure) { + [[World sharedWorld] beforeEach:closure]; +} + +void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + [[World sharedWorld] beforeEachWithMetadata:closure]; +} + +void qck_afterEach(QCKDSLEmptyBlock closure) { + [[World sharedWorld] afterEach:closure]; +} + +void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) { + [[World sharedWorld] afterEachWithMetadata:closure]; +} + +QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line) { + return ^(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] itWithDescription:description + flags:flags + file:file + line:line + closure:closure]; + }; +} + +QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line) { + return ^(NSString *name, QCKDSLSharedExampleContext context) { + [[World sharedWorld] itBehavesLikeSharedExampleNamed:name + sharedExampleContext:context + flags:flags + file:file + line:line]; + }; +} + +void qck_pending(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] pending:description closure:closure]; +} + +void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] xdescribe:description flags:@{} closure:closure]; +} + +void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_xdescribe(description, closure); +} + +void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure) { + [[World sharedWorld] fdescribe:description flags:@{} closure:closure]; +} + +void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure) { + qck_fdescribe(description, closure); +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h new file mode 100644 index 0000000..a3b8524 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h @@ -0,0 +1,20 @@ +#import + +@interface World (SWIFT_EXTENSION(Quick)) +- (void)beforeSuite:(void (^ __nonnull)(void))closure; +- (void)afterSuite:(void (^ __nonnull)(void))closure; +- (void)sharedExamples:(NSString * __nonnull)name closure:(void (^ __nonnull)(NSDictionary * __nonnull (^ __nonnull)(void)))closure; +- (void)describe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)context:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)fdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)xdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure; +- (void)beforeEach:(void (^ __nonnull)(void))closure; +- (void)beforeEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure; +- (void)afterEach:(void (^ __nonnull)(void))closure; +- (void)afterEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure; +- (void)itWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure; +- (void)fitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure; +- (void)xitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure; +- (void)itBehavesLikeSharedExampleNamed:(NSString * __nonnull)name sharedExampleContext:(NSDictionary * __nonnull (^ __nonnull)(void))sharedExampleContext flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line; +- (void)pending:(NSString * __nonnull)description closure:(void (^ __nonnull)(void))closure; +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Quick.h b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Quick.h new file mode 100644 index 0000000..87dad10 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/Quick.h @@ -0,0 +1,11 @@ +#import + +//! Project version number for Quick. +FOUNDATION_EXPORT double QuickVersionNumber; + +//! Project version string for Quick. +FOUNDATION_EXPORT const unsigned char QuickVersionString[]; + +#import "QuickSpec.h" +#import "QCKDSL.h" +#import "QuickConfiguration.h" diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.h b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.h new file mode 100644 index 0000000..105a97e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.h @@ -0,0 +1,50 @@ +#import + +/** + QuickSpec is a base class all specs written in Quick inherit from. + They need to inherit from QuickSpec, a subclass of XCTestCase, in + order to be discovered by the XCTest framework. + + XCTest automatically compiles a list of XCTestCase subclasses included + in the test target. It iterates over each class in that list, and creates + a new instance of that class for each test method. It then creates an + "invocation" to execute that test method. The invocation is an instance of + NSInvocation, which represents a single message send in Objective-C. + The invocation is set on the XCTestCase instance, and the test is run. + + Most of the code in QuickSpec is dedicated to hooking into XCTest events. + First, when the spec is first loaded and before it is sent any messages, + the +[NSObject initialize] method is called. QuickSpec overrides this method + to call +[QuickSpec spec]. This builds the example group stacks and + registers them with Quick.World, a global register of examples. + + Then, XCTest queries QuickSpec for a list of test methods. Normally, XCTest + automatically finds all methods whose selectors begin with the string "test". + However, QuickSpec overrides this default behavior by implementing the + +[XCTestCase testInvocations] method. This method iterates over each example + registered in Quick.World, defines a new method for that example, and + returns an invocation to call that method to XCTest. Those invocations are + the tests that are run by XCTest. Their selector names are displayed in + the Xcode test navigation bar. + */ +@interface QuickSpec : XCTestCase + +/** + Override this method in your spec to define a set of example groups + and examples. + + @code + override func spec() { + describe("winter") { + it("is coming") { + // ... + } + } + } + @endcode + + See DSL.swift for more information on what syntax is available. + */ +- (void)spec; + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.m b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.m new file mode 100644 index 0000000..4891679 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.m @@ -0,0 +1,141 @@ +#import "QuickSpec.h" +#import "QuickConfiguration.h" +#import "World.h" +#import + +static QuickSpec *currentSpec = nil; + +@interface QuickSpec () +@property (nonatomic, strong) Example *example; +@end + +@implementation QuickSpec + +#pragma mark - XCTestCase Overrides + +/** + The runtime sends initialize to each class in a program just before the class, or any class + that inherits from it, is sent its first message from within the program. QuickSpec hooks into + this event to compile the example groups for this spec subclass. + + If an exception occurs when compiling the examples, report it to the user. Chances are they + included an expectation outside of a "it", "describe", or "context" block. + */ ++ (void)initialize { + [QuickConfiguration initialize]; + + World *world = [World sharedWorld]; + [world performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{ + QuickSpec *spec = [self new]; + + @try { + [spec spec]; + } + @catch (NSException *exception) { + [NSException raise:NSInternalInconsistencyException + format:@"An exception occurred when building Quick's example groups.\n" + @"Some possible reasons this might happen include:\n\n" + @"- An 'expect(...).to' expectation was evaluated outside of " + @"an 'it', 'context', or 'describe' block\n" + @"- 'sharedExamples' was called twice with the same name\n" + @"- 'itBehavesLike' was called with a name that is not registered as a shared example\n\n" + @"Here's the original exception: '%@', reason: '%@', userInfo: '%@'", + exception.name, exception.reason, exception.userInfo]; + } + [self testInvocations]; + }]; +} + +/** + Invocations for each test method in the test case. QuickSpec overrides this method to define a + new method for each example defined in +[QuickSpec spec]. + + @return An array of invocations that execute the newly defined example methods. + */ ++ (NSArray *)testInvocations { + NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]]; + NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]]; + + NSMutableSet *selectorNames = [NSMutableSet set]; + + for (Example *example in examples) { + SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames]; + + NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.selector = selector; + + [invocations addObject:invocation]; + } + + return invocations; +} + +#pragma mark - Public Interface + +- (void)spec { } + +#pragma mark - Internal Methods + +/** + QuickSpec uses this method to dynamically define a new instance method for the + given example. The instance method runs the example, catching any exceptions. + The exceptions are then reported as test failures. + + In order to report the correct file and line number, examples must raise exceptions + containing following keys in their userInfo: + + - "SenTestFilenameKey": A String representing the file name + - "SenTestLineNumberKey": An Int representing the line number + + These keys used to be used by SenTestingKit, and are still used by some testing tools + in the wild. See: https://github.com/Quick/Quick/pull/41 + + @return The selector of the newly defined instance method. + */ ++ (SEL)addInstanceMethodForExample:(Example *)example classSelectorNames:(NSMutableSet *)selectorNames { + IMP implementation = imp_implementationWithBlock(^(QuickSpec *self){ + self.example = example; + currentSpec = self; + [example run]; + }); + + const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(void), @encode(id), @encode(SEL)] UTF8String]; + + NSString *originalName = example.name.qck_c99ExtendedIdentifier; + NSString *selectorName = originalName; + NSUInteger i = 2; + + while ([selectorNames containsObject:selectorName]) { + selectorName = [NSString stringWithFormat:@"%@_%tu", originalName, i++]; + } + + [selectorNames addObject:selectorName]; + + SEL selector = NSSelectorFromString(selectorName); + class_addMethod(self, selector, implementation, types); + + return selector; +} + +/** + This method is used to record failures, whether they represent example + expectations that were not met, or exceptions raised during test setup + and teardown. By default, the failure will be reported as an + XCTest failure, and the example will be highlighted in Xcode. + */ +- (void)recordFailureWithDescription:(NSString *)description + inFile:(NSString *)filePath + atLine:(NSUInteger)lineNumber + expected:(BOOL)expected { + if (self.example.isSharedExample) { + filePath = self.example.callsite.file; + lineNumber = self.example.callsite.line; + } + [currentSpec.testRun recordFailureWithDescription:description + inFile:filePath + atLine:lineNumber + expected:expected]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/World.h b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/World.h new file mode 100644 index 0000000..e638cf6 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/World.h @@ -0,0 +1,18 @@ +#import + +@class ExampleGroup; +@class ExampleMetadata; + +SWIFT_CLASS("_TtC5Quick5World") +@interface World + +@property (nonatomic) ExampleGroup * __nullable currentExampleGroup; +@property (nonatomic) ExampleMetadata * __nullable currentExampleMetadata; +@property (nonatomic) BOOL isRunningAdditionalSuites; ++ (World * __nonnull)sharedWorld; +- (void)configure:(void (^ __nonnull)(Configuration * __nonnull))closure; +- (void)finalizeConfiguration; +- (ExampleGroup * __nonnull)rootExampleGroupForSpecClass:(Class __nonnull)cls; +- (NSArray * __nonnull)examplesForSpecClass:(Class __nonnull)specClass; +- (void)performWithCurrentExampleGroup:(ExampleGroup * __nonnull)group closure:(void (^ __nonnull)(void))closure; +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m new file mode 100644 index 0000000..e49939e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m @@ -0,0 +1,40 @@ +#import +#import +#import + +@interface XCTestSuite (QuickTestSuiteBuilder) +@end + +@implementation XCTestSuite (QuickTestSuiteBuilder) + +/** + In order to ensure we can correctly build dynamic test suites, we need to + replace some of the default test suite constructors. + */ ++ (void)load { + Method testCaseWithName = class_getClassMethod(self, @selector(testSuiteForTestCaseWithName:)); + Method hooked_testCaseWithName = class_getClassMethod(self, @selector(qck_hooked_testSuiteForTestCaseWithName:)); + method_exchangeImplementations(testCaseWithName, hooked_testCaseWithName); +} + +/** + The `+testSuiteForTestCaseWithName:` method is called when a specific test case + class is run from the Xcode test navigator. If the built test suite is `nil`, + Xcode will not run any tests for that test case. + + Given if the following test case class is run from the Xcode test navigator: + + FooSpec + testFoo + testBar + + XCTest will invoke this once per test case, with test case names following this format: + + FooSpec/testFoo + FooSpec/testBar + */ ++ (nullable instancetype)qck_hooked_testSuiteForTestCaseWithName:(nonnull NSString *)name { + return [QuickTestSuite selectedTestSuiteForTestCaseWithName:name]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickSpecBase/QuickSpecBase.m b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickSpecBase/QuickSpecBase.m new file mode 100644 index 0000000..10b6f7e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickSpecBase/QuickSpecBase.m @@ -0,0 +1,55 @@ +#import "QuickSpecBase.h" + +#pragma mark - _QuickSelectorWrapper + +@interface _QuickSelectorWrapper () +@property(nonatomic, assign) SEL selector; +@end + +@implementation _QuickSelectorWrapper + +- (instancetype)initWithSelector:(SEL)selector { + self = [super init]; + _selector = selector; + return self; +} + +@end + + +#pragma mark - _QuickSpecBase + +@implementation _QuickSpecBase + +- (instancetype)init { + self = [super initWithInvocation: nil]; + return self; +} + +/** + Invocations for each test method in the test case. QuickSpec overrides this method to define a + new method for each example defined in +[QuickSpec spec]. + + @return An array of invocations that execute the newly defined example methods. + */ ++ (NSArray *)testInvocations { + NSArray<_QuickSelectorWrapper *> *wrappers = [self _qck_testMethodSelectors]; + NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:wrappers.count]; + + for (_QuickSelectorWrapper *wrapper in wrappers) { + SEL selector = wrapper.selector; + NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + invocation.selector = selector; + + [invocations addObject:invocation]; + } + + return invocations; +} + ++ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors { + return @[]; +} + +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h new file mode 100644 index 0000000..69e96cc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h @@ -0,0 +1,11 @@ +@import Foundation; +@import XCTest; + +@interface _QuickSelectorWrapper : NSObject +- (instancetype)initWithSelector:(SEL)selector; +@end + +@interface _QuickSpecBase : XCTestCase ++ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors; +- (instancetype)init NS_DESIGNATED_INITIALIZER; +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-dummy.m b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-dummy.m new file mode 100644 index 0000000..dffbaf1 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Faro : NSObject +@end +@implementation PodsDummy_Faro +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-prefix.pch b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-umbrella.h b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-umbrella.h new file mode 100644 index 0000000..cfbbd8e --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double FaroVersionNumber; +FOUNDATION_EXPORT const unsigned char FaroVersionString[]; + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro.modulemap b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro.modulemap new file mode 100644 index 0000000..812602f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro.modulemap @@ -0,0 +1,6 @@ +framework module Faro { + umbrella header "Faro-umbrella.h" + + export * + module * { export * } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro.xcconfig new file mode 100644 index 0000000..fd0f028 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Faro.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Faro +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Faro +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Info.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Info.plist new file mode 100644 index 0000000..e366a71 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Faro/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.9 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Info.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Info.plist new file mode 100644 index 0000000..5f6d93f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.0.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-dummy.m b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-dummy.m new file mode 100644 index 0000000..e8177ab --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Nimble : NSObject +@end +@implementation PodsDummy_Nimble +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-prefix.pch b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-umbrella.h b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-umbrella.h new file mode 100644 index 0000000..4b43df9 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble-umbrella.h @@ -0,0 +1,23 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "CwlCatchException.h" +#import "CwlCatchBadInstruction.h" +#import "mach_excServer.h" +#import "Nimble.h" +#import "DSL.h" +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble.modulemap b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble.modulemap new file mode 100644 index 0000000..6f77009 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble.modulemap @@ -0,0 +1,6 @@ +framework module Nimble { + umbrella header "Nimble-umbrella.h" + + export * + module * { export * } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble.xcconfig new file mode 100644 index 0000000..12698c0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Nimble/Nimble.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Nimble +ENABLE_BITCODE = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = -weak-lswiftXCTest -weak_framework "XCTest" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Nimble +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/Info.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/Info.plist new file mode 100644 index 0000000..ebdce25 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.4.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-dummy.m b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-dummy.m new file mode 100644 index 0000000..7e5d150 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_OCMock : NSObject +@end +@implementation PodsDummy_OCMock +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-prefix.pch b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-umbrella.h b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-umbrella.h new file mode 100644 index 0000000..b7e152f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock-umbrella.h @@ -0,0 +1,26 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "OCMock.h" +#import "OCMockObject.h" +#import "OCMArg.h" +#import "OCMConstraint.h" +#import "OCMLocation.h" +#import "OCMMacroState.h" +#import "OCMRecorder.h" +#import "OCMStubRecorder.h" +#import "NSNotificationCenter+OCMAdditions.h" +#import "OCMFunctions.h" + +FOUNDATION_EXPORT double OCMockVersionNumber; +FOUNDATION_EXPORT const unsigned char OCMockVersionString[]; + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock.modulemap b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock.modulemap new file mode 100644 index 0000000..8fe04ae --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock.modulemap @@ -0,0 +1,6 @@ +framework module OCMock { + umbrella header "OCMock-umbrella.h" + + export * + module * { export * } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock.xcconfig new file mode 100644 index 0000000..a9f16c4 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/OCMock/OCMock.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/OCMock +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/OCMock +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Info.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-acknowledgements.markdown b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-acknowledgements.markdown new file mode 100644 index 0000000..acc06ff --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-acknowledgements.markdown @@ -0,0 +1,26 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## Faro + +Copyright (c) 2016 iCapps + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-acknowledgements.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-acknowledgements.plist new file mode 100644 index 0000000..a41879d --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-acknowledgements.plist @@ -0,0 +1,58 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2016 iCapps <development@icapps.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + Faro + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-dummy.m b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-dummy.m new file mode 100644 index 0000000..9f318a7 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_Objective_C : NSObject +@end +@implementation PodsDummy_Pods_Objective_C +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-frameworks.sh b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-frameworks.sh new file mode 100755 index 0000000..1e75d3f --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-frameworks.sh @@ -0,0 +1,99 @@ +#!/bin/sh +set -e + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # use filter instead of exclude so missing patterns dont' throw errors + echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current file + archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" + stripped="" + for arch in $archs; do + if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "$BUILT_PRODUCTS_DIR/Faro/Faro.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "$BUILT_PRODUCTS_DIR/Faro/Faro.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-resources.sh b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-resources.sh new file mode 100755 index 0000000..4602c68 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-resources.sh @@ -0,0 +1,99 @@ +#!/bin/sh +set -e + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +case "${TARGETED_DEVICE_FAMILY}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-umbrella.h b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-umbrella.h new file mode 100644 index 0000000..3755c34 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_Objective_CVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_Objective_CVersionString[]; + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.debug.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.debug.xcconfig new file mode 100644 index 0000000..9153c77 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.debug.xcconfig @@ -0,0 +1,10 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Faro" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Faro/Faro.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "Faro" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.modulemap b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.modulemap new file mode 100644 index 0000000..60fb3df --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.modulemap @@ -0,0 +1,6 @@ +framework module Pods_Objective_C { + umbrella header "Pods-Objective-C-umbrella.h" + + export * + module * { export * } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.release.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.release.xcconfig new file mode 100644 index 0000000..9153c77 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-C/Pods-Objective-C.release.xcconfig @@ -0,0 +1,10 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Faro" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Faro/Faro.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "Faro" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Info.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-acknowledgements.markdown b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-acknowledgements.markdown new file mode 100644 index 0000000..0d6c5fc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-acknowledgements.markdown @@ -0,0 +1,594 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## Nimble + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## OCMock + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + +## Quick + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014, Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-acknowledgements.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-acknowledgements.plist new file mode 100644 index 0000000..33e0f42 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-acknowledgements.plist @@ -0,0 +1,638 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache 2.0 + Title + Nimble + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + License + Apache 2.0 + Title + OCMock + Type + PSGroupSpecifier + + + FooterText + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014, Quick Team + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache 2.0 + Title + Quick + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-dummy.m b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-dummy.m new file mode 100644 index 0000000..f4dee0b --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_Objective_CTests : NSObject +@end +@implementation PodsDummy_Pods_Objective_CTests +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-frameworks.sh b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-frameworks.sh new file mode 100755 index 0000000..e7825dc --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-frameworks.sh @@ -0,0 +1,103 @@ +#!/bin/sh +set -e + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # use filter instead of exclude so missing patterns dont' throw errors + echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current file + archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" + stripped="" + for arch in $archs; do + if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "$BUILT_PRODUCTS_DIR/Nimble/Nimble.framework" + install_framework "$BUILT_PRODUCTS_DIR/OCMock/OCMock.framework" + install_framework "$BUILT_PRODUCTS_DIR/Quick/Quick.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "$BUILT_PRODUCTS_DIR/Nimble/Nimble.framework" + install_framework "$BUILT_PRODUCTS_DIR/OCMock/OCMock.framework" + install_framework "$BUILT_PRODUCTS_DIR/Quick/Quick.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-resources.sh b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-resources.sh new file mode 100755 index 0000000..4602c68 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-resources.sh @@ -0,0 +1,99 @@ +#!/bin/sh +set -e + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +case "${TARGETED_DEVICE_FAMILY}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-umbrella.h b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-umbrella.h new file mode 100644 index 0000000..6880fe0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_Objective_CTestsVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_Objective_CTestsVersionString[]; + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.debug.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.debug.xcconfig new file mode 100644 index 0000000..4593b25 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.debug.xcconfig @@ -0,0 +1,10 @@ +EMBEDDED_CONTENT_CONTAINS_SWIFT = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "$PODS_CONFIGURATION_BUILD_DIR/Nimble" "$PODS_CONFIGURATION_BUILD_DIR/OCMock" "$PODS_CONFIGURATION_BUILD_DIR/Quick" "$PODS_CONFIGURATION_BUILD_DIR/Faro" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Nimble/Nimble.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/OCMock/OCMock.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Quick/Quick.framework/Headers" $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Faro/Faro.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "Nimble" -framework "OCMock" -framework "Quick" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.modulemap b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.modulemap new file mode 100644 index 0000000..5b06a7c --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.modulemap @@ -0,0 +1,6 @@ +framework module Pods_Objective_CTests { + umbrella header "Pods-Objective-CTests-umbrella.h" + + export * + module * { export * } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.release.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.release.xcconfig new file mode 100644 index 0000000..4593b25 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Pods-Objective-CTests/Pods-Objective-CTests.release.xcconfig @@ -0,0 +1,10 @@ +EMBEDDED_CONTENT_CONTAINS_SWIFT = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "$PODS_CONFIGURATION_BUILD_DIR/Nimble" "$PODS_CONFIGURATION_BUILD_DIR/OCMock" "$PODS_CONFIGURATION_BUILD_DIR/Quick" "$PODS_CONFIGURATION_BUILD_DIR/Faro" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Nimble/Nimble.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/OCMock/OCMock.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Quick/Quick.framework/Headers" $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Faro/Faro.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "Nimble" -framework "OCMock" -framework "Quick" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Info.plist b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Info.plist new file mode 100644 index 0000000..21a30b4 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-dummy.m b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-dummy.m new file mode 100644 index 0000000..54d7dc0 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Quick : NSObject +@end +@implementation PodsDummy_Quick +@end diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-prefix.pch b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-umbrella.h b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-umbrella.h new file mode 100644 index 0000000..1de6bf3 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick-umbrella.h @@ -0,0 +1,20 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "QuickConfiguration.h" +#import "QCKDSL.h" +#import "Quick.h" +#import "QuickSpec.h" + +FOUNDATION_EXPORT double QuickVersionNumber; +FOUNDATION_EXPORT const unsigned char QuickVersionString[]; + diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick.modulemap b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick.modulemap new file mode 100644 index 0000000..1d12b21 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick.modulemap @@ -0,0 +1,6 @@ +framework module Quick { + umbrella header "Quick-umbrella.h" + + export * + module * { export * } +} diff --git a/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick.xcconfig b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick.xcconfig new file mode 100644 index 0000000..66c8d21 --- /dev/null +++ b/Students/Benny/Les 1 OCMock/Pods/Target Support Files/Quick/Quick.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Quick +ENABLE_BITCODE = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = -framework "XCTest" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = $BUILD_DIR +PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Quick +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Students/Benny/Objective-C VS Swift.md b/Students/Benny/Objective-C VS Swift.md new file mode 100644 index 0000000..1d537fc --- /dev/null +++ b/Students/Benny/Objective-C VS Swift.md @@ -0,0 +1,131 @@ +# Objective-C vs Swift differences +--- + +This document contains a brief overview for the following differences between Objective-C and Swift: + +* Classes +* Variables +* Functions +* Debugging +* Imports + +## Classes + +### Objective-C: + +Objective-C abstracts a class's interface from it's implementation. This means that classes only provide essential information from the interface (.h file) while hiding details in the implementation file (.m file) + +* Interface (.h file): + + + ```Objective-C + @interface Car: NSObject { + // Add Protected instance variables here (not recommended) + } + // Add properties and methods here + ``` + +* Implementation (.m file): + + ```Objective-C + @implementation Car { + // Define functions, properties, etc. + } + ``` + +* Initializing + + We allocate and initialize classes in an object of the class to access it's data members defined in the Interface. + + ```Objective-C + Car car = [[Car alloc]init]; // Create car object of type Car + ``` + +### Swift: + +In Swift, there is no need to create interfaces or implementation files. It allows us to create a class as a single file while the external interface will be created by default once the class is initialized. + +* Class (.swift file): + + ```Swift + class Car { + + } + ``` + +## Variables + +All variables in Objective-C have to be typed, as opposed to Swift where they can be implicitly defined. + +**Objective-C** + +```Objective-C +NSString *aString = @"Some text" +``` + +**Swift** + +```Swift +var aString = "Some text" +``` + +## Functions + +**Objective-C** +```Objective-C +- (int)addX:(int)x toY:(int)y { // (return type)methodName:(parameter1 type)(parameter1 name) ... + int sum = x + y; + return sum; +} +``` + +**Swift** +```Swift +func add(_ x:Int, to y: Int) -> Int { + let sum = x + y + return sum +} +``` + +## Debugging + +In Objective-C we need format specifiers to print out our code. These format specifiers include: + + * %@ (Objective-C Object) + * %d (int) + * %f (float, double) + * ... + +These are no longer necessary in Swift + +**Objective-C:** +```Objective-C +NSLog(@"%@", aString) // prints: "Some text" +``` + +**Swift** +```Swift +print(aString) // prints: "Some text" +``` + +## Imports + +In Objective-C, the traditional way of accessing files is by #import the header of the desired file. + +```Objective-C +#import "Foo.h" // A file you own and is in your project +#import // A file inside a framework/module +``` + +Swift does not import Headers, but modules. + +```Swift +import UIKit +``` + +It is also possible to import a module in Objective-C when the imported framework is a module. + +```Objective-C +// If this framework is a module you can write +@import UIKit +``` diff --git a/Students/Benny/README.md b/Students/Benny/README.md index d7fbe2e..52de0f4 100644 --- a/Students/Benny/README.md +++ b/Students/Benny/README.md @@ -1,3 +1,11 @@ # Benny -Put instructions and finished products here. +### Quick links to lessons and notes + +* [OCMock+Faro](1.%20OCMock+Faro/Lesson%201%20-%20Objective-C%20Foundation%20via%20Mocks.md) + +* [Object-Oriented C](2.%20Object%20Oriented%20C/Lesson%202:%20How%20Apple%20teaches%20Objective-C.md) + +* [Protocols & Bridging](3.%20Protocols%20and%20bridging/Lesson%203:%20Protocols%20and%20Bridging.md) + +* [Mapping, sort, reduce, ...](4.%20Mapping%2C%20sort%2C%20reduce/Lesson%204:%20Mapping%2C%20filtering%2C%20reduce%2C%20sort….md) diff --git a/Teacher/Objective-C/PostService.swift b/Teacher/Objective-C/PostService.swift index 978ace6..8d89b58 100644 --- a/Teacher/Objective-C/PostService.swift +++ b/Teacher/Objective-C/PostService.swift @@ -11,10 +11,10 @@ import Faro class PostService: BridgeFaroService { func post(_ id: Int, post: @escaping (Post) -> Void, fail: @escaping (String) -> Void) { - let _ = fetchPosts(BridgeCall("posts/\(id)"), post: post, fail: fail) + let _ = fetchPost(BridgeCall("posts/\(id)"), post: post, fail: fail) } - func fetchPosts(_ call: BridgeCall, post: @escaping (Post) -> Void, fail: @escaping (String) -> Void) -> URLSessionDataTask? { + func fetchPost(_ call: BridgeCall, post: @escaping (Post) -> Void, fail: @escaping (String) -> Void) -> URLSessionDataTask? { return service.perform(call.call) { (result: Result) in switch result { case .model(let model):