Sharing on Facebook, Twitter and Google+
[FIXED] Font of navbar. [FIXED] A few compile fixes. [IMPROVED] Made properties nonatomic. [ADDED] Support for facebook, twitter and google+ sharing.
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
||||
[submodule "External/FontReplacer"]
|
||||
path = External/FontReplacer
|
||||
url = git://github.com/0xced/FontReplacer.git
|
||||
[submodule "External/facebook-ios-sdk"]
|
||||
path = External/facebook-ios-sdk
|
||||
url = https://github.com/facebook/facebook-ios-sdk
|
||||
|
2
External/Pearl
vendored
@ -1 +1 @@
|
||||
Subproject commit d295f7d413fb2afa9fcdf70079969fd78ac8fb70
|
||||
Subproject commit 19a7054441049ea1519fe0bb72bc52d4542964cc
|
1
External/facebook-ios-sdk
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 682535050207c771706823cbf0fc31a206b12956
|
3
External/google-plus-ios-sdk/Changelog
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
2012-06-25 -- v1.0.0
|
||||
- Google+ sign-in button, share plugin, and Google+ history integration library
|
||||
with sample app.
|
25
External/google-plus-ios-sdk/OpenSource/GTL/GTLBase64.h
vendored
Normal file
@ -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 <Foundation/Foundation.h>
|
||||
|
||||
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);
|
139
External/google-plus-ios-sdk/OpenSource/GTL/GTLBase64.m
vendored
Normal file
@ -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];
|
||||
|
||||
uint8_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]] = 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;
|
||||
|
||||
NSUInteger inputLength = 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: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++] = (table[i0] << 2) | (table[i1] >> 4);
|
||||
if (outputPoint < outputLength) {
|
||||
output[outputPoint++] = ((table[i1] & 0xF) << 4) | (table[i2] >> 2);
|
||||
}
|
||||
if (outputPoint < outputLength) {
|
||||
output[outputPoint++] = ((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);
|
||||
}
|
49
External/google-plus-ios-sdk/OpenSource/GTL/GTLBatchQuery.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/* 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
|
||||
//
|
||||
|
||||
#import "GTLQuery.h"
|
||||
|
||||
@interface GTLBatchQuery : NSObject <GTLQueryProtocol> {
|
||||
@private
|
||||
NSMutableArray *queries_;
|
||||
NSMutableDictionary *requestIDMap_;
|
||||
BOOL skipAuthorization_;
|
||||
NSDictionary *additionalHTTPHeaders_;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
+ (id)batchQuery;
|
||||
+ (id)batchQueryWithQueries:(NSArray *)array;
|
||||
|
||||
- (void)addQuery:(GTLQuery *)query;
|
||||
|
||||
- (GTLQuery *)queryForRequestID:(NSString *)requestID;
|
||||
|
||||
@end
|
133
External/google-plus-ios-sdk/OpenSource/GTL/GTLBatchQuery.m
vendored
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLBatchQuery.m
|
||||
//
|
||||
|
||||
#import "GTLBatchQuery.h"
|
||||
|
||||
@implementation GTLBatchQuery
|
||||
|
||||
@synthesize shouldSkipAuthorization = skipAuthorization_,
|
||||
additionalHTTPHeaders = additionalHTTPHeaders_;
|
||||
|
||||
+ (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];
|
||||
[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
|
58
External/google-plus-ios-sdk/OpenSource/GTL/GTLBatchResult.h
vendored
Normal file
@ -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 <GTLBatchItemCreationProtocol> {
|
||||
@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
|
92
External/google-plus-ios-sdk/OpenSource/GTL/GTLBatchResult.m
vendored
Normal file
@ -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
|
56
External/google-plus-ios-sdk/OpenSource/GTL/GTLDateTime.h
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/* 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
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "GTLDefines.h"
|
||||
|
||||
@interface GTLDateTime : NSObject <NSCopying> {
|
||||
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
|
||||
}
|
||||
|
||||
// Note: nil can be passed for time zone arguments when the time zone is not
|
||||
// known.
|
||||
|
||||
+ (GTLDateTime *)dateTimeWithRFC3339String:(NSString *)str;
|
||||
+ (GTLDateTime *)dateTimeWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz;
|
||||
|
||||
- (void)setFromDate:(NSDate *)date timeZone:(NSTimeZone *)tz;
|
||||
- (void)setFromRFC3339String:(NSString *)str;
|
||||
|
||||
@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, retain) NSTimeZone *timeZone;
|
||||
@property (nonatomic, copy) NSDateComponents *dateComponents;
|
||||
@property (nonatomic, assign) NSInteger milliseconds; // This is only for the fraction of a second 0-999
|
||||
|
||||
@property (nonatomic, assign) BOOL hasTime;
|
||||
@property (nonatomic, assign) NSInteger offsetSeconds;
|
||||
@property (nonatomic, assign, getter=isUniversalTime) BOOL universalTime;
|
||||
|
||||
- (void)setTimeZone:(NSTimeZone *)timeZone withOffsetSeconds:(NSInteger)val;
|
||||
|
||||
@end
|
422
External/google-plus-ios-sdk/OpenSource/GTL/GTLDateTime.m
vendored
Normal file
@ -0,0 +1,422 @@
|
||||
/* 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"
|
||||
|
||||
|
||||
@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_;
|
||||
|
||||
+ (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;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[dateComponents_ release];
|
||||
[timeZone_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
|
||||
GTLDateTime *newObj = [[GTLDateTime alloc] init];
|
||||
|
||||
newObj.universalTime = self.isUniversalTime;
|
||||
[newObj setTimeZone:self.timeZone withOffsetSeconds:self.offsetSeconds];
|
||||
newObj.dateComponents = self.dateComponents;
|
||||
newObj.milliseconds = self.milliseconds;
|
||||
|
||||
return newObj;
|
||||
}
|
||||
|
||||
// until NSDateComponent implements isEqual, we'll use this
|
||||
- (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]
|
||||
&& [dc1 week] == [dc2 week]
|
||||
&& [dc1 weekday] == [dc2 weekday]
|
||||
&& [dc1 weekdayOrdinal] == [dc2 weekdayOrdinal];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(GTLDateTime *)other {
|
||||
|
||||
if (self == other) return YES;
|
||||
if (![other isKindOfClass:[GTLDateTime class]]) return NO;
|
||||
|
||||
BOOL areDateComponentsEqual = [self doesDateComponents:self.dateComponents
|
||||
equalDateComponents:other.dateComponents];
|
||||
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 != NSUndefinedDateComponent) {
|
||||
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 = NSUndefinedDateComponent;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTimeZone:(NSTimeZone *)timeZone withOffsetSeconds:(NSInteger)val {
|
||||
[timeZone_ release];
|
||||
timeZone_ = [timeZone retain];
|
||||
|
||||
offsetSeconds_ = val;
|
||||
}
|
||||
|
||||
- (NSCalendar *)calendar {
|
||||
NSCalendar *cal = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
|
||||
NSTimeZone *tz = self.timeZone;
|
||||
if (tz) {
|
||||
[cal setTimeZone:tz];
|
||||
}
|
||||
return cal;
|
||||
}
|
||||
|
||||
- (NSDate *)date {
|
||||
NSCalendar *cal = self.calendar;
|
||||
NSDateComponents *dateComponents = self.dateComponents;
|
||||
NSTimeInterval extraMillisecondsAsSeconds = 0.0;
|
||||
|
||||
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 setTimeZone:gmt];
|
||||
} else {
|
||||
// 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 == NSUndefinedDateComponent) {
|
||||
// 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 = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
|
||||
if (tz) {
|
||||
[cal setTimeZone:tz];
|
||||
}
|
||||
|
||||
NSUInteger const kComponentBits = (NSYearCalendarUnit | NSMonthCalendarUnit
|
||||
| NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit
|
||||
| NSSecondCalendarUnit);
|
||||
|
||||
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 = NSUndefinedDateComponent;
|
||||
|
||||
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 = NSUndefinedDateComponent;
|
||||
NSInteger month = NSUndefinedDateComponent;
|
||||
NSInteger day = NSUndefinedDateComponent;
|
||||
NSInteger hour = NSUndefinedDateComponent;
|
||||
NSInteger minute = NSUndefinedDateComponent;
|
||||
NSInteger sec = NSUndefinedDateComponent;
|
||||
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];
|
||||
|
||||
NSCharacterSet* dashSet = [NSCharacterSet characterSetWithCharactersInString:@"-"];
|
||||
NSCharacterSet* tSet = [NSCharacterSet characterSetWithCharactersInString:@"Tt "];
|
||||
NSCharacterSet* colonSet = [NSCharacterSet characterSetWithCharactersInString:@":"];
|
||||
NSCharacterSet* plusMinusZSet = [NSCharacterSet characterSetWithCharactersInString:@"+-zZ"];
|
||||
|
||||
// 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:dashSet intoString:NULL] &&
|
||||
[scanner scanInteger:&month] &&
|
||||
[scanner scanCharactersFromSet:dashSet intoString:NULL] &&
|
||||
[scanner scanInteger:&day] &&
|
||||
// Thh:mm:ss
|
||||
[scanner scanCharactersFromSet:tSet intoString:NULL] &&
|
||||
[scanner scanInteger:&hour] &&
|
||||
[scanner scanCharactersFromSet:colonSet intoString:NULL] &&
|
||||
[scanner scanInteger:&minute] &&
|
||||
[scanner scanCharactersFromSet:colonSet 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:plusMinusZSet intoString:&sign] &&
|
||||
[scanner scanInteger:&offsetHour] &&
|
||||
[scanner scanCharactersFromSet:colonSet 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 = NSUndefinedDateComponent;
|
||||
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 = NSUndefinedDateComponent;
|
||||
} else {
|
||||
totalOffset *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.offsetSeconds = totalOffset;
|
||||
}
|
||||
|
||||
- (BOOL)hasTime {
|
||||
NSDateComponents *dateComponents = self.dateComponents;
|
||||
|
||||
BOOL hasTime = ([dateComponents hour] != NSUndefinedDateComponent
|
||||
&& [dateComponents minute] != NSUndefinedDateComponent);
|
||||
|
||||
return hasTime;
|
||||
}
|
||||
|
||||
- (void)setHasTime:(BOOL)shouldHaveTime {
|
||||
|
||||
// we'll set time values to zero or NSUndefinedDateComponent as appropriate
|
||||
BOOL hadTime = self.hasTime;
|
||||
|
||||
if (shouldHaveTime && !hadTime) {
|
||||
[dateComponents_ setHour:0];
|
||||
[dateComponents_ setMinute:0];
|
||||
[dateComponents_ setSecond:0];
|
||||
milliseconds_ = 0;
|
||||
offsetSeconds_ = NSUndefinedDateComponent;
|
||||
isUniversalTime_ = NO;
|
||||
|
||||
} else if (hadTime && !shouldHaveTime) {
|
||||
[dateComponents_ setHour:NSUndefinedDateComponent];
|
||||
[dateComponents_ setMinute:NSUndefinedDateComponent];
|
||||
[dateComponents_ setSecond:NSUndefinedDateComponent];
|
||||
milliseconds_ = 0;
|
||||
offsetSeconds_ = NSUndefinedDateComponent;
|
||||
isUniversalTime_ = NO;
|
||||
self.timeZone = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
128
External/google-plus-ios-sdk/OpenSource/GTL/GTLDefines.h
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
/* 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 <TargetConditionals.h>
|
||||
#import <AvailabilityMacros.h>
|
||||
|
||||
//
|
||||
// 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
|
45
External/google-plus-ios-sdk/OpenSource/GTL/GTLErrorObject.h
vendored
Normal file
@ -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
|
78
External/google-plus-ios-sdk/OpenSource/GTL/GTLErrorObject.m
vendored
Normal file
@ -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
|
||||
|
||||
|
35
External/google-plus-ios-sdk/OpenSource/GTL/GTLFramework.h
vendored
Normal file
@ -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 <Foundation/Foundation.h>
|
||||
|
||||
#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
|
40
External/google-plus-ios-sdk/OpenSource/GTL/GTLFramework.m
vendored
Normal file
@ -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;
|
||||
}
|
41
External/google-plus-ios-sdk/OpenSource/GTL/GTLJSONParser.h
vendored
Normal file
@ -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 <Foundation/Foundation.h>
|
||||
|
||||
#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
|
150
External/google-plus-ios-sdk/OpenSource/GTL/GTLJSONParser.m
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
/* 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 {
|
||||
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
|
180
External/google-plus-ios-sdk/OpenSource/GTL/GTLObject.h
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
/* 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
|
||||
//
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GTLDefines.h"
|
||||
#import "GTLUtilities.h"
|
||||
#import "GTLDateTime.h"
|
||||
|
||||
#undef _EXTERN
|
||||
#undef _INITIALIZE_AS
|
||||
#ifdef GTLOBJECT_DEFINE_GLOBALS
|
||||
#define _EXTERN
|
||||
#define _INITIALIZE_AS(x) =x
|
||||
#else
|
||||
#define _EXTERN extern
|
||||
#define _INITIALIZE_AS(x)
|
||||
#endif
|
||||
|
||||
@protocol GTLCollectionProtocol
|
||||
@optional
|
||||
@property (retain) NSArray *items;
|
||||
@end
|
||||
|
||||
@protocol GTLBatchItemCreationProtocol
|
||||
- (void)createItemsWithClassMap:(NSDictionary *)batchClassMap;
|
||||
@end
|
||||
|
||||
@interface GTLObject : NSObject <NSCopying> {
|
||||
|
||||
@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;
|
||||
- (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;
|
||||
- (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.
|
||||
- (void)setProperty:(id)obj forKey:(NSString *)key; // pass nil obj to remove property
|
||||
- (id)propertyForKey:(NSString *)key;
|
||||
|
||||
// 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 and the
|
||||
// itemAtIndex: convenience method.
|
||||
//
|
||||
// Subclasses must implement the items method dynamically.
|
||||
@interface GTLCollectionObject : GTLObject <GTLCollectionProtocol, NSFastEnumeration>
|
||||
|
||||
// itemAtIndex: returns nil when the index exceeds the bounds of the items array
|
||||
- (id)itemAtIndex:(NSUInteger)idx;
|
||||
|
||||
@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, 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
|
691
External/google-plus-ios-sdk/OpenSource/GTL/GTLObject.m
vendored
Normal file
@ -0,0 +1,691 @@
|
||||
/* 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
|
||||
//
|
||||
|
||||
#define GTLOBJECT_DEFINE_GLOBALS 1
|
||||
|
||||
#include <objc/runtime.h>
|
||||
|
||||
#import "GTLObject.h"
|
||||
#import "GTLRuntimeCommon.h"
|
||||
#import "GTLJSONParser.h"
|
||||
|
||||
static NSString *const kUserDataPropertyKey = @"_userData";
|
||||
|
||||
@interface GTLObject () <GTLRuntimeCommon>
|
||||
+ (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 ([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)[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 = [GTLUtilities newStaticDictionary];
|
||||
}
|
||||
|
||||
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]]) {
|
||||
// no actual result, such as the response from a delete
|
||||
return nil;
|
||||
}
|
||||
|
||||
GTL_ASSERT([json count] != 0, @"Creating object from empty json");
|
||||
if ([json count] == 0) 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 <GTLBatchItemCreationProtocol> batch =
|
||||
(id <GTLBatchItemCreationProtocol>) 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 = [GTLUtilities newStaticDictionary];
|
||||
}
|
||||
if (gArrayPropertyToClassMapCache == nil) {
|
||||
gArrayPropertyToClassMapCache = [GTLUtilities newStaticDictionary];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary *)propertyToJSONKeyMapForClass:(Class<GTLRuntimeCommon>)aClass {
|
||||
NSDictionary *resultMap =
|
||||
[GTLUtilities mergedClassDictionaryForSelector:@selector(propertyToJSONKeyMap)
|
||||
startClass:aClass
|
||||
ancestorClass:[GTLObject class]
|
||||
cache:gJSONKeyMapCache];
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)arrayPropertyToClassMapForClass:(Class<GTLRuntimeCommon>)aClass {
|
||||
NSDictionary *resultMap =
|
||||
[GTLUtilities mergedClassDictionaryForSelector:@selector(arrayPropertyToClassMap)
|
||||
startClass:aClass
|
||||
ancestorClass:[GTLObject class]
|
||||
cache:gArrayPropertyToClassMapCache];
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
#pragma mark Runtime Support
|
||||
|
||||
+ (Class<GTLRuntimeCommon>)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.
|
||||
|
||||
- (id)itemAtIndex:(NSUInteger)idx {
|
||||
NSArray *items = [self performSelector:@selector(items)];
|
||||
if (idx < [items count]) {
|
||||
return [items objectAtIndex:idx];
|
||||
}
|
||||
return 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
|
36
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlus.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlus.h
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
|
||||
#import "GTLPlusConstants.h"
|
||||
|
||||
#import "GTLPlusItemScope.h"
|
||||
#import "GTLPlusMoment.h"
|
||||
#import "GTLPlusPerson.h"
|
||||
|
||||
#import "GTLQueryPlus.h"
|
||||
#import "GTLServicePlus.h"
|
46
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusConstants.h
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusConstants.h
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if GTL_BUILT_AS_FRAMEWORK
|
||||
#import "GTL/GTLDefines.h"
|
||||
#else
|
||||
#import "GTLDefines.h"
|
||||
#endif
|
||||
|
||||
// Authorization scope
|
||||
// Know who you are on Google
|
||||
GTL_EXTERN NSString * const kGTLAuthScopePlusMe; // "https://www.googleapis.com/auth/plus.me"
|
||||
// View and manage user activity information in Google+
|
||||
GTL_EXTERN NSString * const kGTLAuthScopePlusMomentsWrite; // "https://www.googleapis.com/auth/plus.moments.write"
|
||||
// View your email address
|
||||
GTL_EXTERN NSString * const kGTLAuthScopePlusUserinfoEmail; // "https://www.googleapis.com/auth/userinfo.email"
|
||||
|
||||
// Collection
|
||||
GTL_EXTERN NSString * const kGTLPlusCollectionVault; // "vault"
|
37
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusConstants.m
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusConstants.m
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
|
||||
#import "GTLPlusConstants.h"
|
||||
|
||||
// Authorization scope
|
||||
NSString * const kGTLAuthScopePlusMe = @"https://www.googleapis.com/auth/plus.me";
|
||||
NSString * const kGTLAuthScopePlusMomentsWrite = @"https://www.googleapis.com/auth/plus.moments.write";
|
||||
NSString * const kGTLAuthScopePlusUserinfoEmail = @"https://www.googleapis.com/auth/userinfo.email";
|
||||
|
||||
// Collection
|
||||
NSString * const kGTLPlusCollectionVault = @"vault";
|
225
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusItemScope.h
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusItemScope.h
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLPlusItemScope (0 custom class methods, 55 custom properties)
|
||||
|
||||
#if GTL_BUILT_AS_FRAMEWORK
|
||||
#import "GTL/GTLObject.h"
|
||||
#else
|
||||
#import "GTLObject.h"
|
||||
#endif
|
||||
|
||||
@class GTLPlusItemScope;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusItemScope
|
||||
//
|
||||
|
||||
@interface GTLPlusItemScope : GTLObject
|
||||
|
||||
// The subject matter of the content.
|
||||
@property (retain) GTLPlusItemScope *about;
|
||||
|
||||
// An additional name for a Person, can be used for a middle name.
|
||||
@property (retain) NSArray *additionalName; // of NSString
|
||||
|
||||
// Postal address.
|
||||
@property (retain) GTLPlusItemScope *address;
|
||||
|
||||
// Address country.
|
||||
@property (copy) NSString *addressCountry;
|
||||
|
||||
// Address locality.
|
||||
@property (copy) NSString *addressLocality;
|
||||
|
||||
// Address region.
|
||||
@property (copy) NSString *addressRegion;
|
||||
|
||||
// The encoding.
|
||||
@property (retain) NSArray *associatedMedia; // of GTLPlusItemScope
|
||||
|
||||
// Number of attendees.
|
||||
@property (retain) NSNumber *attendeeCount; // intValue
|
||||
|
||||
// A person attending the event.
|
||||
@property (retain) NSArray *attendees; // of GTLPlusItemScope
|
||||
|
||||
// From http://schema.org/MusicRecording, the audio file.
|
||||
@property (retain) GTLPlusItemScope *audio;
|
||||
|
||||
// The person who created this scope.
|
||||
@property (retain) NSArray *author; // of GTLPlusItemScope
|
||||
|
||||
// Best possible rating value.
|
||||
@property (copy) NSString *bestRating;
|
||||
|
||||
// Date of birth.
|
||||
@property (copy) NSString *birthDate;
|
||||
|
||||
// From http://schema.org/MusicRecording, the artist that performed this
|
||||
// recording.
|
||||
@property (retain) GTLPlusItemScope *byArtist;
|
||||
|
||||
// The caption for this object.
|
||||
@property (copy) NSString *caption;
|
||||
|
||||
// File size in (mega/kilo) bytes.
|
||||
@property (copy) NSString *contentSize;
|
||||
|
||||
// Actual bytes of the media object, for example the image file or video file.
|
||||
@property (copy) NSString *contentUrl;
|
||||
|
||||
// The list of contributors for this scope.
|
||||
@property (retain) NSArray *contributor; // of GTLPlusItemScope
|
||||
|
||||
// The date this scope was created.
|
||||
@property (copy) NSString *dateCreated;
|
||||
|
||||
// The date this scope was last modified.
|
||||
@property (copy) NSString *dateModified;
|
||||
|
||||
// The initial date this scope was published.
|
||||
@property (copy) NSString *datePublished;
|
||||
|
||||
// The string describing the content of this scope.
|
||||
// Remapped to 'descriptionProperty' to avoid NSObject's 'description'.
|
||||
@property (copy) NSString *descriptionProperty;
|
||||
|
||||
// The duration of the item (movie, audio recording, event, etc.) in ISO 8601
|
||||
// date format.
|
||||
@property (copy) NSString *duration;
|
||||
|
||||
// A URL pointing to a player for a specific video. In general, this is the
|
||||
// information in the src element of an embed tag and should not be the same as
|
||||
// the content of the loc tag.
|
||||
@property (copy) NSString *embedUrl;
|
||||
|
||||
// The end date and time of the event (in ISO 8601 date format).
|
||||
@property (copy) NSString *endDate;
|
||||
|
||||
// Family name. In the U.S., the last name of an Person. This can be used along
|
||||
// with givenName instead of the Name property.
|
||||
@property (copy) NSString *familyName;
|
||||
|
||||
// Gender of the person.
|
||||
@property (copy) NSString *gender;
|
||||
|
||||
// Geo coordinates.
|
||||
@property (retain) GTLPlusItemScope *geo;
|
||||
|
||||
// Given name. In the U.S., the first name of a Person. This can be used along
|
||||
// with familyName instead of the Name property.
|
||||
@property (copy) NSString *givenName;
|
||||
|
||||
// The height of the media object.
|
||||
@property (copy) NSString *height;
|
||||
|
||||
// The id for this item scope.
|
||||
// identifier property maps to 'id' in JSON (to avoid Objective C's 'id').
|
||||
@property (copy) NSString *identifier;
|
||||
|
||||
// A url to the image for this scope.
|
||||
@property (copy) NSString *image;
|
||||
|
||||
// From http://schema.org/MusicRecording, which album a song is in.
|
||||
@property (retain) GTLPlusItemScope *inAlbum;
|
||||
|
||||
// Identifies this resource as an itemScope.
|
||||
@property (copy) NSString *kind;
|
||||
|
||||
// Latitude.
|
||||
@property (retain) NSNumber *latitude; // doubleValue
|
||||
|
||||
// The location of the event or organization.
|
||||
@property (retain) GTLPlusItemScope *location;
|
||||
|
||||
// Longitude.
|
||||
@property (retain) NSNumber *longitude; // doubleValue
|
||||
|
||||
// The name of this scope.
|
||||
@property (copy) NSString *name;
|
||||
|
||||
// Property of http://schema.org/TVEpisode indicating which series the episode
|
||||
// belongs to.
|
||||
@property (retain) GTLPlusItemScope *partOfTVSeries;
|
||||
|
||||
// The main performer or performers of the event—for example, a presenter,
|
||||
// musician, or actor.
|
||||
@property (retain) NSArray *performers; // of GTLPlusItemScope
|
||||
|
||||
// Player type required—for example, Flash or Silverlight.
|
||||
@property (copy) NSString *playerType;
|
||||
|
||||
// Postal code.
|
||||
@property (copy) NSString *postalCode;
|
||||
|
||||
// Post office box number.
|
||||
@property (copy) NSString *postOfficeBoxNumber;
|
||||
|
||||
// Rating value.
|
||||
@property (copy) NSString *ratingValue;
|
||||
|
||||
// Review rating.
|
||||
@property (retain) NSArray *reviewRating; // of GTLPlusItemScope
|
||||
|
||||
// The start date and time of the event (in ISO 8601 date format).
|
||||
@property (copy) NSString *startDate;
|
||||
|
||||
// Street address.
|
||||
@property (copy) NSString *streetAddress;
|
||||
|
||||
// Comment text, review text, etc.
|
||||
@property (copy) NSString *text;
|
||||
|
||||
// Thumbnail image for an image or video.
|
||||
@property (retain) GTLPlusItemScope *thumbnail;
|
||||
|
||||
// A url to a thumbnail image for this scope.
|
||||
@property (copy) NSString *thumbnailUrl;
|
||||
|
||||
// The exchange traded instrument associated with a Corporation object. The
|
||||
// tickerSymbol is expressed as an exchange and an instrument name separated by
|
||||
// a space character. For the exchange component of the tickerSymbol attribute,
|
||||
// we reccommend using the controlled vocaulary of Market Identifier Codes (MIC)
|
||||
// specified in ISO15022.
|
||||
@property (copy) NSString *tickerSymbol;
|
||||
|
||||
// The item type.
|
||||
@property (copy) NSString *type;
|
||||
|
||||
// A url for this scope.
|
||||
@property (copy) NSString *url;
|
||||
|
||||
// The width of the media object.
|
||||
@property (copy) NSString *width;
|
||||
|
||||
// Worst possible rating value.
|
||||
@property (copy) NSString *worstRating;
|
||||
|
||||
@end
|
78
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusItemScope.m
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusItemScope.m
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLPlusItemScope (0 custom class methods, 55 custom properties)
|
||||
|
||||
#import "GTLPlusItemScope.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusItemScope
|
||||
//
|
||||
|
||||
@implementation GTLPlusItemScope
|
||||
@dynamic about, additionalName, address, addressCountry, addressLocality,
|
||||
addressRegion, associatedMedia, attendeeCount, attendees, audio,
|
||||
author, bestRating, birthDate, byArtist, caption, contentSize,
|
||||
contentUrl, contributor, dateCreated, dateModified, datePublished,
|
||||
descriptionProperty, duration, embedUrl, endDate, familyName, gender,
|
||||
geo, givenName, height, identifier, image, inAlbum, kind, latitude,
|
||||
location, longitude, name, partOfTVSeries, performers, playerType,
|
||||
postalCode, postOfficeBoxNumber, ratingValue, reviewRating, startDate,
|
||||
streetAddress, text, thumbnail, thumbnailUrl, tickerSymbol, type, url,
|
||||
width, worstRating;
|
||||
|
||||
+ (NSDictionary *)propertyToJSONKeyMap {
|
||||
NSDictionary *map =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"associated_media", @"associatedMedia",
|
||||
@"description", @"descriptionProperty",
|
||||
@"id", @"identifier",
|
||||
nil];
|
||||
return map;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)arrayPropertyToClassMap {
|
||||
NSDictionary *map =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSString class], @"additionalName",
|
||||
[GTLPlusItemScope class], @"associated_media",
|
||||
[GTLPlusItemScope class], @"attendees",
|
||||
[GTLPlusItemScope class], @"author",
|
||||
[GTLPlusItemScope class], @"contributor",
|
||||
[GTLPlusItemScope class], @"performers",
|
||||
[GTLPlusItemScope class], @"reviewRating",
|
||||
nil];
|
||||
return map;
|
||||
}
|
||||
|
||||
+ (void)load {
|
||||
[self registerObjectClassForKind:@"plus#itemScope"];
|
||||
}
|
||||
|
||||
@end
|
79
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusMoment.h
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusMoment.h
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLPlusMoment (0 custom class methods, 6 custom properties)
|
||||
// GTLPlusMomentVerb (0 custom class methods, 1 custom properties)
|
||||
|
||||
#if GTL_BUILT_AS_FRAMEWORK
|
||||
#import "GTL/GTLObject.h"
|
||||
#else
|
||||
#import "GTLObject.h"
|
||||
#endif
|
||||
|
||||
@class GTLPlusItemScope;
|
||||
@class GTLPlusMomentVerb;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusMoment
|
||||
//
|
||||
|
||||
@interface GTLPlusMoment : GTLObject
|
||||
|
||||
// Identifies this resource as a moment.
|
||||
@property (copy) NSString *kind;
|
||||
|
||||
// The object generated by performing the action on the item
|
||||
@property (retain) GTLPlusItemScope *result;
|
||||
|
||||
// Timestamp of the action (when it occured) in RFC3339 format.
|
||||
@property (retain) GTLDateTime *startDate;
|
||||
|
||||
// The object on which the action was performed
|
||||
@property (retain) GTLPlusItemScope *target;
|
||||
|
||||
// The schema.org activity type
|
||||
@property (copy) NSString *type;
|
||||
|
||||
// The action the user performed
|
||||
@property (retain) GTLPlusMomentVerb *verb;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusMomentVerb
|
||||
//
|
||||
|
||||
@interface GTLPlusMomentVerb : GTLObject
|
||||
|
||||
// Url name of the verb
|
||||
@property (copy) NSString *url;
|
||||
|
||||
@end
|
58
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusMoment.m
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusMoment.m
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLPlusMoment (0 custom class methods, 6 custom properties)
|
||||
// GTLPlusMomentVerb (0 custom class methods, 1 custom properties)
|
||||
|
||||
#import "GTLPlusMoment.h"
|
||||
|
||||
#import "GTLPlusItemScope.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusMoment
|
||||
//
|
||||
|
||||
@implementation GTLPlusMoment
|
||||
@dynamic kind, result, startDate, target, type, verb;
|
||||
|
||||
+ (void)load {
|
||||
[self registerObjectClassForKind:@"plus#moment"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusMomentVerb
|
||||
//
|
||||
|
||||
@implementation GTLPlusMomentVerb
|
||||
@dynamic url;
|
||||
@end
|
285
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusPerson.h
vendored
Normal file
@ -0,0 +1,285 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusPerson.h
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLPlusPerson (0 custom class methods, 21 custom properties)
|
||||
// GTLPlusPersonEmailsItem (0 custom class methods, 3 custom properties)
|
||||
// GTLPlusPersonImage (0 custom class methods, 1 custom properties)
|
||||
// GTLPlusPersonName (0 custom class methods, 6 custom properties)
|
||||
// GTLPlusPersonOrganizationsItem (0 custom class methods, 9 custom properties)
|
||||
// GTLPlusPersonPlacesLivedItem (0 custom class methods, 2 custom properties)
|
||||
// GTLPlusPersonUrlsItem (0 custom class methods, 3 custom properties)
|
||||
|
||||
#if GTL_BUILT_AS_FRAMEWORK
|
||||
#import "GTL/GTLObject.h"
|
||||
#else
|
||||
#import "GTLObject.h"
|
||||
#endif
|
||||
|
||||
@class GTLPlusPersonEmailsItem;
|
||||
@class GTLPlusPersonImage;
|
||||
@class GTLPlusPersonName;
|
||||
@class GTLPlusPersonOrganizationsItem;
|
||||
@class GTLPlusPersonPlacesLivedItem;
|
||||
@class GTLPlusPersonUrlsItem;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPerson
|
||||
//
|
||||
|
||||
@interface GTLPlusPerson : GTLObject
|
||||
|
||||
// A short biography for this person.
|
||||
@property (copy) NSString *aboutMe;
|
||||
|
||||
// The person's date of birth, represented as YYYY-MM-DD.
|
||||
@property (copy) NSString *birthday;
|
||||
|
||||
// The current location for this person.
|
||||
@property (copy) NSString *currentLocation;
|
||||
|
||||
// The name of this person, suitable for display.
|
||||
@property (copy) NSString *displayName;
|
||||
|
||||
// A list of email addresses for this person.
|
||||
@property (retain) NSArray *emails; // of GTLPlusPersonEmailsItem
|
||||
|
||||
// ETag of this response for caching purposes.
|
||||
@property (copy) NSString *ETag;
|
||||
|
||||
// The person's gender. Possible values are:
|
||||
// - "male" - Male gender.
|
||||
// - "female" - Female gender.
|
||||
// - "other" - Other.
|
||||
@property (copy) NSString *gender;
|
||||
|
||||
// If "true", indicates that the person has installed the app that is making the
|
||||
// request and has chosen to expose this install state to the caller. A value of
|
||||
// "false" indicates that the install state cannot be determined (it is either
|
||||
// not installed or the person has chosen to keep this information private).
|
||||
@property (retain) NSNumber *hasApp; // boolValue
|
||||
|
||||
// The ID of this person.
|
||||
// identifier property maps to 'id' in JSON (to avoid Objective C's 'id').
|
||||
@property (copy) NSString *identifier;
|
||||
|
||||
// The representation of the person's profile photo.
|
||||
@property (retain) GTLPlusPersonImage *image;
|
||||
|
||||
// Identifies this resource as a person. Value: "plus#person".
|
||||
@property (copy) NSString *kind;
|
||||
|
||||
// The languages spoken by this person.
|
||||
@property (retain) NSArray *languagesSpoken; // of NSString
|
||||
|
||||
// An object representation of the individual components of a person's name.
|
||||
@property (retain) GTLPlusPersonName *name;
|
||||
|
||||
// The nickname of this person.
|
||||
@property (copy) NSString *nickname;
|
||||
|
||||
// Type of person within Google+. Possible values are:
|
||||
// - "person" - represents an actual person.
|
||||
// - "page" - represents a page.
|
||||
@property (copy) NSString *objectType;
|
||||
|
||||
// A list of current or past organizations with which this person is associated.
|
||||
@property (retain) NSArray *organizations; // of GTLPlusPersonOrganizationsItem
|
||||
|
||||
// A list of places where this person has lived.
|
||||
@property (retain) NSArray *placesLived; // of GTLPlusPersonPlacesLivedItem
|
||||
|
||||
// The person's relationship status. Possible values are:
|
||||
// - "single" - Person is single.
|
||||
// - "in_a_relationship" - Person is in a relationship.
|
||||
// - "engaged" - Person is engaged.
|
||||
// - "married" - Person is married.
|
||||
// - "its_complicated" - The relationship is complicated.
|
||||
// - "open_relationship" - Person is in an open relationship.
|
||||
// - "widowed" - Person is widowed.
|
||||
// - "in_domestic_partnership" - Person is in a domestic partnership.
|
||||
// - "in_civil_union" - Person is in a civil union.
|
||||
@property (copy) NSString *relationshipStatus;
|
||||
|
||||
// The brief description (tagline) of this person.
|
||||
@property (copy) NSString *tagline;
|
||||
|
||||
// The URL of this person's profile.
|
||||
@property (copy) NSString *url;
|
||||
|
||||
// A list of URLs for this person.
|
||||
@property (retain) NSArray *urls; // of GTLPlusPersonUrlsItem
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonEmailsItem
|
||||
//
|
||||
|
||||
@interface GTLPlusPersonEmailsItem : GTLObject
|
||||
|
||||
// If "true", indicates this email address is the person's primary one.
|
||||
@property (retain) NSNumber *primary; // boolValue
|
||||
|
||||
// The type of address. Possible values are:
|
||||
// - "home" - Home email address.
|
||||
// - "work" - Work email address.
|
||||
// - "other" - Other.
|
||||
@property (copy) NSString *type;
|
||||
|
||||
// The email address.
|
||||
@property (copy) NSString *value;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonImage
|
||||
//
|
||||
|
||||
@interface GTLPlusPersonImage : GTLObject
|
||||
|
||||
// The URL of the person's profile photo. To re-size the image and crop it to a
|
||||
// square, append the query string ?sz=x, where x is the dimension in pixels of
|
||||
// each side.
|
||||
@property (copy) NSString *url;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonName
|
||||
//
|
||||
|
||||
@interface GTLPlusPersonName : GTLObject
|
||||
|
||||
// The family name (last name) of this person.
|
||||
@property (copy) NSString *familyName;
|
||||
|
||||
// The full name of this person, including middle names, suffixes, etc.
|
||||
@property (copy) NSString *formatted;
|
||||
|
||||
// The given name (first name) of this person.
|
||||
@property (copy) NSString *givenName;
|
||||
|
||||
// The honorific prefixes (such as "Dr." or "Mrs.") for this person.
|
||||
@property (copy) NSString *honorificPrefix;
|
||||
|
||||
// The honorific suffixes (such as "Jr.") for this person.
|
||||
@property (copy) NSString *honorificSuffix;
|
||||
|
||||
// The middle name of this person.
|
||||
@property (copy) NSString *middleName;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonOrganizationsItem
|
||||
//
|
||||
|
||||
@interface GTLPlusPersonOrganizationsItem : GTLObject
|
||||
|
||||
// The department within the organization.
|
||||
@property (copy) NSString *department;
|
||||
|
||||
// A short description of the person's role in this organization.
|
||||
// Remapped to 'descriptionProperty' to avoid NSObject's 'description'.
|
||||
@property (copy) NSString *descriptionProperty;
|
||||
|
||||
// The date the person left this organization.
|
||||
@property (copy) NSString *endDate;
|
||||
|
||||
// The location of this organization.
|
||||
@property (copy) NSString *location;
|
||||
|
||||
// The name of the organization.
|
||||
@property (copy) NSString *name;
|
||||
|
||||
// If "true", indicates this organization is the person's primary one (typically
|
||||
// interpreted as current one).
|
||||
@property (retain) NSNumber *primary; // boolValue
|
||||
|
||||
// The date the person joined this organization.
|
||||
@property (copy) NSString *startDate;
|
||||
|
||||
// The person's job title or role within the organization.
|
||||
@property (copy) NSString *title;
|
||||
|
||||
// The type of organization. Possible values are:
|
||||
// - "work" - Work.
|
||||
// - "school" - School.
|
||||
@property (copy) NSString *type;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonPlacesLivedItem
|
||||
//
|
||||
|
||||
@interface GTLPlusPersonPlacesLivedItem : GTLObject
|
||||
|
||||
// If "true", this place of residence is this person's primary residence.
|
||||
@property (retain) NSNumber *primary; // boolValue
|
||||
|
||||
// A place where this person has lived. For example: "Seattle, WA", "Near
|
||||
// Toronto".
|
||||
@property (copy) NSString *value;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonUrlsItem
|
||||
//
|
||||
|
||||
@interface GTLPlusPersonUrlsItem : GTLObject
|
||||
|
||||
// If "true", this URL is the person's primary URL.
|
||||
@property (retain) NSNumber *primary; // boolValue
|
||||
|
||||
// The type of URL. Possible values are:
|
||||
// - "home" - URL for home.
|
||||
// - "work" - URL for work.
|
||||
// - "blog" - URL for blog.
|
||||
// - "profile" - URL for profile.
|
||||
// - "other" - Other.
|
||||
@property (copy) NSString *type;
|
||||
|
||||
// The URL value.
|
||||
@property (copy) NSString *value;
|
||||
|
||||
@end
|
145
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLPlusPerson.m
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLPlusPerson.m
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLPlusPerson (0 custom class methods, 21 custom properties)
|
||||
// GTLPlusPersonEmailsItem (0 custom class methods, 3 custom properties)
|
||||
// GTLPlusPersonImage (0 custom class methods, 1 custom properties)
|
||||
// GTLPlusPersonName (0 custom class methods, 6 custom properties)
|
||||
// GTLPlusPersonOrganizationsItem (0 custom class methods, 9 custom properties)
|
||||
// GTLPlusPersonPlacesLivedItem (0 custom class methods, 2 custom properties)
|
||||
// GTLPlusPersonUrlsItem (0 custom class methods, 3 custom properties)
|
||||
|
||||
#import "GTLPlusPerson.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPerson
|
||||
//
|
||||
|
||||
@implementation GTLPlusPerson
|
||||
@dynamic aboutMe, birthday, currentLocation, displayName, emails, ETag, gender,
|
||||
hasApp, identifier, image, kind, languagesSpoken, name, nickname,
|
||||
objectType, organizations, placesLived, relationshipStatus, tagline,
|
||||
url, urls;
|
||||
|
||||
+ (NSDictionary *)propertyToJSONKeyMap {
|
||||
NSDictionary *map =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"etag", @"ETag",
|
||||
@"id", @"identifier",
|
||||
nil];
|
||||
return map;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)arrayPropertyToClassMap {
|
||||
NSDictionary *map =
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[GTLPlusPersonEmailsItem class], @"emails",
|
||||
[NSString class], @"languagesSpoken",
|
||||
[GTLPlusPersonOrganizationsItem class], @"organizations",
|
||||
[GTLPlusPersonPlacesLivedItem class], @"placesLived",
|
||||
[GTLPlusPersonUrlsItem class], @"urls",
|
||||
nil];
|
||||
return map;
|
||||
}
|
||||
|
||||
+ (void)load {
|
||||
[self registerObjectClassForKind:@"plus#person"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonEmailsItem
|
||||
//
|
||||
|
||||
@implementation GTLPlusPersonEmailsItem
|
||||
@dynamic primary, type, value;
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonImage
|
||||
//
|
||||
|
||||
@implementation GTLPlusPersonImage
|
||||
@dynamic url;
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonName
|
||||
//
|
||||
|
||||
@implementation GTLPlusPersonName
|
||||
@dynamic familyName, formatted, givenName, honorificPrefix, honorificSuffix,
|
||||
middleName;
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonOrganizationsItem
|
||||
//
|
||||
|
||||
@implementation GTLPlusPersonOrganizationsItem
|
||||
@dynamic department, descriptionProperty, endDate, location, name, primary,
|
||||
startDate, title, type;
|
||||
|
||||
+ (NSDictionary *)propertyToJSONKeyMap {
|
||||
NSDictionary *map =
|
||||
[NSDictionary dictionaryWithObject:@"description"
|
||||
forKey:@"descriptionProperty"];
|
||||
return map;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonPlacesLivedItem
|
||||
//
|
||||
|
||||
@implementation GTLPlusPersonPlacesLivedItem
|
||||
@dynamic primary, value;
|
||||
@end
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// GTLPlusPersonUrlsItem
|
||||
//
|
||||
|
||||
@implementation GTLPlusPersonUrlsItem
|
||||
@dynamic primary, type, value;
|
||||
@end
|
90
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLQueryPlus.h
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLQueryPlus.h
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLQueryPlus (2 custom class methods, 4 custom properties)
|
||||
|
||||
#if GTL_BUILT_AS_FRAMEWORK
|
||||
#import "GTL/GTLQuery.h"
|
||||
#else
|
||||
#import "GTLQuery.h"
|
||||
#endif
|
||||
|
||||
@class GTLPlusMoment;
|
||||
|
||||
@interface GTLQueryPlus : 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 (copy) NSString *collection;
|
||||
@property (assign) BOOL debug;
|
||||
@property (copy) NSString *userId;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark "moments" methods
|
||||
// These create a GTLQueryPlus object.
|
||||
|
||||
// Method: plus.moments.insert
|
||||
// Record a user activity (e.g Bill watched a video on Youtube)
|
||||
// Required:
|
||||
// userId: The ID of the user to get activities for. The special value "me"
|
||||
// can be used to indicate the authenticated user.
|
||||
// collection: The collection to which to write moments.
|
||||
// kGTLPlusCollectionVault: The default collection for writing new moments.
|
||||
// Optional:
|
||||
// debug: Return the moment as written. Should be used only for debugging.
|
||||
// Authorization scope(s):
|
||||
// kGTLAuthScopePlusMomentsWrite
|
||||
// Fetches a GTLPlusMoment.
|
||||
+ (id)queryForMomentsInsertWithObject:(GTLPlusMoment *)object
|
||||
userId:(NSString *)userId
|
||||
collection:(NSString *)collection;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark "people" methods
|
||||
// These create a GTLQueryPlus object.
|
||||
|
||||
// Method: plus.people.get
|
||||
// Get a person's profile.
|
||||
// Required:
|
||||
// userId: The ID of the person to get the profile for. The special value "me"
|
||||
// can be used to indicate the authenticated user.
|
||||
// Authorization scope(s):
|
||||
// kGTLAuthScopePlusMe
|
||||
// kGTLAuthScopePlusUserinfoEmail
|
||||
// Fetches a GTLPlusPerson.
|
||||
+ (id)queryForPeopleGetWithUserId:(NSString *)userId;
|
||||
|
||||
@end
|
72
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLQueryPlus.m
vendored
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLQueryPlus.m
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLQueryPlus (2 custom class methods, 4 custom properties)
|
||||
|
||||
#import "GTLQueryPlus.h"
|
||||
|
||||
#import "GTLPlusMoment.h"
|
||||
#import "GTLPlusPerson.h"
|
||||
|
||||
@implementation GTLQueryPlus
|
||||
|
||||
@dynamic collection, debug, fields, userId;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark "moments" methods
|
||||
// These create a GTLQueryPlus object.
|
||||
|
||||
+ (id)queryForMomentsInsertWithObject:(GTLPlusMoment *)object
|
||||
userId:(NSString *)userId
|
||||
collection:(NSString *)collection {
|
||||
if (object == nil) {
|
||||
GTL_DEBUG_ASSERT(object != nil, @"%@ got a nil object", NSStringFromSelector(_cmd));
|
||||
return nil;
|
||||
}
|
||||
NSString *methodName = @"plus.moments.insert";
|
||||
GTLQueryPlus *query = [self queryWithMethodName:methodName];
|
||||
query.bodyObject = object;
|
||||
query.userId = userId;
|
||||
query.collection = collection;
|
||||
query.expectedObjectClass = [GTLPlusMoment class];
|
||||
return query;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark "people" methods
|
||||
// These create a GTLQueryPlus object.
|
||||
|
||||
+ (id)queryForPeopleGetWithUserId:(NSString *)userId {
|
||||
NSString *methodName = @"plus.people.get";
|
||||
GTLQueryPlus *query = [self queryWithMethodName:methodName];
|
||||
query.userId = userId;
|
||||
query.expectedObjectClass = [GTLPlusPerson class];
|
||||
return query;
|
||||
}
|
||||
|
||||
@end
|
61
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLServicePlus.h
vendored
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLServicePlus.h
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLServicePlus (0 custom class methods, 0 custom properties)
|
||||
|
||||
#if GTL_BUILT_AS_FRAMEWORK
|
||||
#import "GTL/GTLService.h"
|
||||
#else
|
||||
#import "GTLService.h"
|
||||
#endif
|
||||
|
||||
@interface GTLServicePlus : GTLService
|
||||
|
||||
// No new methods
|
||||
|
||||
// Clients should create a standard query with any of the class methods in
|
||||
// GTLQueryPlus.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
|
63
External/google-plus-ios-sdk/OpenSource/GTL/GTLPlus/GTLServicePlus.m
vendored
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLServicePlus.m
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// NOTE: This file is generated from Google APIs Discovery Service.
|
||||
// Service:
|
||||
// Google+ API (plus/v1moments)
|
||||
// Description:
|
||||
// The Google+ API enables developers to build on top of the Google+ platform.
|
||||
// Documentation:
|
||||
// http://developers.google.com/+/api/
|
||||
// Classes:
|
||||
// GTLServicePlus (0 custom class methods, 0 custom properties)
|
||||
|
||||
#import "GTLPlus.h"
|
||||
|
||||
@implementation GTLServicePlus
|
||||
|
||||
#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:
|
||||
[GTLQueryPlus class],
|
||||
[GTLPlusItemScope class],
|
||||
[GTLPlusMoment class],
|
||||
[GTLPlusPerson class],
|
||||
nil];
|
||||
return classes;
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// Version from discovery.
|
||||
self.apiVersion = @"v1moments";
|
||||
|
||||
// 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"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
132
External/google-plus-ios-sdk/OpenSource/GTL/GTLQuery.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/* 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
|
||||
//
|
||||
|
||||
#import "GTLObject.h"
|
||||
#import "GTLUploadParameters.h"
|
||||
|
||||
@protocol GTLQueryProtocol <NSObject, NSCopying>
|
||||
- (BOOL)isBatchQuery;
|
||||
- (BOOL)shouldSkipAuthorization;
|
||||
- (void)executionDidStop;
|
||||
- (NSDictionary *)additionalHTTPHeaders;
|
||||
- (GTLUploadParameters *)uploadParameters;
|
||||
@end
|
||||
|
||||
@protocol GTLQueryCollectionProtocol
|
||||
@optional
|
||||
@property (retain) NSString *pageToken;
|
||||
@property (retain) NSNumber *startIndex;
|
||||
@end
|
||||
|
||||
@class GTLServiceTicket;
|
||||
|
||||
@interface GTLQuery : NSObject <GTLQueryProtocol> {
|
||||
@private
|
||||
NSString *methodName_;
|
||||
NSMutableDictionary *json_;
|
||||
GTLObject *bodyObject_;
|
||||
NSMutableDictionary *childCache_;
|
||||
NSString *requestID_;
|
||||
GTLUploadParameters *uploadParameters_;
|
||||
NSDictionary *urlQueryParameters_;
|
||||
NSDictionary *additionalHTTPHeaders_;
|
||||
Class expectedObjectClass_;
|
||||
BOOL skipAuthorization_;
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
void (^completionBlock_)(GTLServiceTicket *ticket, id object, NSError *error);
|
||||
#elif !__LP64__
|
||||
// Placeholders: for 32-bit builds, keep the size of the object's ivar section
|
||||
// the same with and without blocks
|
||||
id completionPlaceholder_;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
// 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);
|
||||
#endif
|
||||
|
||||
// methodName is the RPC method name to use.
|
||||
+ (id)queryWithMethodName:(NSString *)methodName;
|
||||
|
||||
// methodName is the RPC method name to use.
|
||||
- (id)initWithMethodName:(NSString *)method;
|
||||
|
||||
// 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;
|
||||
|
||||
// Auto-generated request IDs
|
||||
+ (NSString *)nextRequestID;
|
||||
|
||||
// Methods for subclasses to override.
|
||||
+ (NSDictionary *)parameterNameMap;
|
||||
+ (NSDictionary *)arrayPropertyToClassMap;
|
||||
@end
|
267
External/google-plus-ios-sdk/OpenSource/GTL/GTLQuery.m
vendored
Normal file
@ -0,0 +1,267 @@
|
||||
/* 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 <objc/runtime.h>
|
||||
|
||||
#import "GTLQuery.h"
|
||||
#import "GTLRuntimeCommon.h"
|
||||
#import "GTLUtilities.h"
|
||||
|
||||
@interface GTLQuery () <GTLRuntimeCommon>
|
||||
@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_;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
@synthesize completionBlock = completionBlock_;
|
||||
#endif
|
||||
|
||||
+ (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];
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
[completionBlock_ release];
|
||||
#endif
|
||||
|
||||
[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;
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
query.completionBlock = self.completionBlock;
|
||||
#endif
|
||||
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 {
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
self.completionBlock = nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (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 *gParameterNameMapCache = nil;
|
||||
static NSMutableDictionary *gArrayPropertyToClassMapCache = nil;
|
||||
|
||||
+ (void)initialize {
|
||||
// note that initialize is guaranteed by the runtime to be called in a
|
||||
// thread-safe manner
|
||||
if (gParameterNameMapCache == nil) {
|
||||
gParameterNameMapCache = [GTLUtilities newStaticDictionary];
|
||||
}
|
||||
if (gArrayPropertyToClassMapCache == nil) {
|
||||
gArrayPropertyToClassMapCache = [GTLUtilities newStaticDictionary];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary *)propertyToJSONKeyMapForClass:(Class<GTLRuntimeCommon>)aClass {
|
||||
NSDictionary *resultMap =
|
||||
[GTLUtilities mergedClassDictionaryForSelector:@selector(parameterNameMap)
|
||||
startClass:aClass
|
||||
ancestorClass:[GTLQuery class]
|
||||
cache:gParameterNameMapCache];
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)arrayPropertyToClassMapForClass:(Class<GTLRuntimeCommon>)aClass {
|
||||
NSDictionary *resultMap =
|
||||
[GTLUtilities mergedClassDictionaryForSelector:@selector(arrayPropertyToClassMap)
|
||||
startClass:aClass
|
||||
ancestorClass:[GTLQuery class]
|
||||
cache:gArrayPropertyToClassMapCache];
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
#pragma mark Runtime Support
|
||||
|
||||
- (NSDictionary *)surrogates {
|
||||
// Stub method just needed for RumtimeCommon, query doesn't use surrogates.
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (Class<GTLRuntimeCommon>)ancestorClass {
|
||||
return [GTLQuery class];
|
||||
}
|
||||
|
||||
+ (BOOL)resolveInstanceMethod:(SEL)sel {
|
||||
BOOL resolved = [GTLRuntimeCommon resolveInstanceMethod:sel onClass:self];
|
||||
if (resolved)
|
||||
return YES;
|
||||
|
||||
return [super resolveInstanceMethod:sel];
|
||||
}
|
||||
|
||||
@end
|
57
External/google-plus-ios-sdk/OpenSource/GTL/GTLRuntimeCommon.h
vendored
Normal file
@ -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 <Foundation/Foundation.h>
|
||||
|
||||
#import "GTLDefines.h"
|
||||
|
||||
// This protocol and support class are an internal implementation detail so
|
||||
// GTLObject and GTLQuery can share some code.
|
||||
|
||||
@protocol GTLRuntimeCommon <NSObject>
|
||||
@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<GTLRuntimeCommon>)aClass;
|
||||
// Array item types
|
||||
+ (NSDictionary *)arrayPropertyToClassMapForClass:(Class<GTLRuntimeCommon>)aClass;
|
||||
// The parent class for dynamic support
|
||||
+ (Class<GTLRuntimeCommon>)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
|
1135
External/google-plus-ios-sdk/OpenSource/GTL/GTLRuntimeCommon.m
vendored
Normal file
592
External/google-plus-ios-sdk/OpenSource/GTL/GTLService.h
vendored
Normal file
@ -0,0 +1,592 @@
|
||||
/* 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
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GTLDefines.h"
|
||||
#import "GTMHTTPFetcherService.h"
|
||||
#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"
|
||||
|
||||
#undef _EXTERN
|
||||
#undef _INITIALIZE_AS
|
||||
#ifdef GTLSERVICE_DEFINE_GLOBALS
|
||||
#define _EXTERN
|
||||
#define _INITIALIZE_AS(x) =x
|
||||
#else
|
||||
#define _EXTERN extern
|
||||
#define _INITIALIZE_AS(x)
|
||||
#endif
|
||||
|
||||
// Error domains
|
||||
_EXTERN NSString* const kGTLServiceErrorDomain _INITIALIZE_AS(@"com.google.GTLServiceDomain");
|
||||
enum {
|
||||
kGTLErrorQueryResultMissing = -3000,
|
||||
kGTLErrorWaitTimedOut = -3001
|
||||
};
|
||||
|
||||
_EXTERN NSString* const kGTLJSONRPCErrorDomain _INITIALIZE_AS(@"com.google.GTLJSONRPCErrorDomain");
|
||||
|
||||
// We'll consistently store the server error string in the userInfo under
|
||||
// this key
|
||||
_EXTERN NSString* const kGTLServerErrorStringKey _INITIALIZE_AS(@"error");
|
||||
|
||||
_EXTERN Class const kGTLUseRegisteredClass _INITIALIZE_AS(nil);
|
||||
|
||||
_EXTERN NSUInteger const kGTLStandardUploadChunkSize _INITIALIZE_AS(NSUIntegerMax);
|
||||
|
||||
// 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 _INITIALIZE_AS(@"GTLStructuredError");
|
||||
|
||||
// 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 _INITIALIZE_AS(@"*");
|
||||
|
||||
// Notifications when parsing of a fetcher feed or entry begins or ends
|
||||
_EXTERN NSString* const kGTLServiceTicketParsingStartedNotification _INITIALIZE_AS(@"kGTLServiceTicketParsingStartedNotification");
|
||||
_EXTERN NSString* const kGTLServiceTicketParsingStoppedNotification _INITIALIZE_AS(@"kGTLServiceTicketParsingStoppedNotification");
|
||||
|
||||
@class GTLServiceTicket;
|
||||
|
||||
// Block types used for fetch callbacks
|
||||
//
|
||||
// These typedefs are not used in the header file method declarations
|
||||
// since it's more useful when code sense expansions show the argument
|
||||
// types rather than the typedefs
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
typedef void (^GTLServiceCompletionHandler)(GTLServiceTicket *ticket, id object, NSError *error);
|
||||
|
||||
typedef void (^GTLServiceUploadProgressBlock)(GTLServiceTicket *ticket, unsigned long long numberOfBytesRead, unsigned long long dataLength);
|
||||
#else
|
||||
typedef void *GTLServiceCompletionHandler;
|
||||
|
||||
typedef void *GTLServiceUploadProgressBlock;
|
||||
#endif // NS_BLOCKS_AVAILABLE
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//
|
||||
// Service base class
|
||||
//
|
||||
|
||||
@interface GTLService : NSObject {
|
||||
@private
|
||||
NSOperationQueue *parseQueue_;
|
||||
NSString *userAgent_;
|
||||
GTMHTTPFetcherService *fetcherService_;
|
||||
NSString *userAgentAddition_;
|
||||
|
||||
NSMutableDictionary *serviceProperties_; // initial values for properties in future tickets
|
||||
|
||||
NSDictionary *surrogates_; // initial value for surrogates in future tickets
|
||||
|
||||
SEL uploadProgressSelector_; // optional
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
BOOL (^retryBlock_)(GTLServiceTicket *, BOOL, NSError *);
|
||||
void (^uploadProgressBlock_)(GTLServiceTicket *ticket,
|
||||
unsigned long long numberOfBytesRead,
|
||||
unsigned long long dataLength);
|
||||
#elif !__LP64__
|
||||
// Placeholders: for 32-bit builds, keep the size of the object's ivar section
|
||||
// the same with and without blocks
|
||||
id retryPlaceholder_;
|
||||
id uploadProgressPlaceholder_;
|
||||
#endif
|
||||
|
||||
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_;
|
||||
|
||||
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
|
||||
|
||||
- (GTLServiceTicket *)executeQuery:(id<GTLQueryProtocol>)query
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
- (GTLServiceTicket *)executeQuery:(id<GTLQueryProtocol>)query
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
#endif
|
||||
|
||||
// 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 <GTMFetcherAuthorizationProtocol> 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 GTMHTTPFetcher retry
|
||||
// selector, this selector's first argument is a ticket, not a fetcher.
|
||||
|
||||
@property (nonatomic, assign) SEL retrySelector;
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
@property (copy) BOOL (^retryBlock)(GTLServiceTicket *ticket, BOOL suggestedWillRetry, NSError *error);
|
||||
#endif
|
||||
|
||||
@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;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName
|
||||
insertingObject:(GTLObject *)bodyObject
|
||||
objectClass:(Class)objectClass
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName
|
||||
parameters:(NSDictionary *)parameters
|
||||
insertingObject:(GTLObject *)bodyObject
|
||||
objectClass:(Class)objectClass
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName
|
||||
parameters:(NSDictionary *)parameters
|
||||
objectClass:(Class)objectClass
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName
|
||||
insertingObject:(GTLObject *)bodyObject
|
||||
objectClass:(Class)objectClass
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectWithMethodNamed:(NSString *)methodName
|
||||
parameters:(NSDictionary *)parameters
|
||||
insertingObject:(GTLObject *)bodyObject
|
||||
objectClass:(Class)objectClass
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
#endif
|
||||
|
||||
#pragma mark REST Fetch Methods
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)objectURL
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)objectURL
|
||||
objectClass:(Class)objectClass
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
- (GTLServiceTicket *)fetchPublicObjectWithURL:(NSURL *)objectURL
|
||||
objectClass:(Class)objectClass
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectByInsertingObject:(GTLObject *)bodyToPut
|
||||
forURL:(NSURL *)destinationURL
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectByUpdatingObject:(GTLObject *)bodyToPut
|
||||
forURL:(NSURL *)destinationURL
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
- (GTLServiceTicket *)deleteResourceURL:(NSURL *)destinationURL
|
||||
ETag:(NSString *)etagOrNil
|
||||
delegate:(id)delegate
|
||||
didFinishSelector:(SEL)finishedSelector;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
- (GTLServiceTicket *)fetchObjectWithURL:(NSURL *)objectURL
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectByInsertingObject:(GTLObject *)bodyToPut
|
||||
forURL:(NSURL *)destinationURL
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
|
||||
- (GTLServiceTicket *)fetchObjectByUpdatingObject:(GTLObject *)bodyToPut
|
||||
forURL:(NSURL *)destinationURL
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
|
||||
- (GTLServiceTicket *)deleteResourceURL:(NSURL *)destinationURL
|
||||
ETag:(NSString *)etagOrNil
|
||||
completionHandler:(void (^)(GTLServiceTicket *ticket, id object, NSError *error))handler;
|
||||
#endif
|
||||
|
||||
#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; // pass nil obj to remove property
|
||||
- (id)servicePropertyForKey:(NSString *)key;
|
||||
|
||||
@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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// The queue used for parsing JSON responses (previously this property
|
||||
// was called operationQueue)
|
||||
@property (nonatomic, retain) NSOperationQueue *parseQueue;
|
||||
|
||||
// The fetcher service object issues the GTMHTTPFetcher instances
|
||||
// for this API service
|
||||
@property (nonatomic, retain) GTMHTTPFetcherService *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.
|
||||
@property (nonatomic, assign) NSInteger cookieStorageMethod;
|
||||
|
||||
// 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;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
@property (copy) void (^uploadProgressBlock)(GTLServiceTicket *ticket, unsigned long long numberOfBytesRead, unsigned long long dataLength);
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//
|
||||
// Ticket base class
|
||||
//
|
||||
@interface GTLServiceTicket : NSObject {
|
||||
GTLService *service_;
|
||||
|
||||
NSMutableDictionary *ticketProperties_;
|
||||
NSDictionary *surrogates_;
|
||||
|
||||
GTMHTTPFetcher *objectFetcher_;
|
||||
SEL uploadProgressSelector_;
|
||||
BOOL shouldFetchNextPages_;
|
||||
BOOL isRetryEnabled_;
|
||||
SEL retrySelector_;
|
||||
NSTimeInterval maxRetryInterval_;
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
BOOL (^retryBlock_)(GTLServiceTicket *, BOOL, NSError *);
|
||||
void (^uploadProgressBlock_)(GTLServiceTicket *ticket,
|
||||
unsigned long long numberOfBytesRead,
|
||||
unsigned long long dataLength);
|
||||
#elif !__LP64__
|
||||
// Placeholders: for 32-bit builds, keep the size of the object's ivar section
|
||||
// the same with and without blocks
|
||||
id retryPlaceholder_;
|
||||
id uploadProgressPlaceholder_;
|
||||
#endif
|
||||
|
||||
GTLObject *postedObject_;
|
||||
GTLObject *fetchedObject_;
|
||||
id<GTLQueryProtocol> executingQuery_;
|
||||
id<GTLQueryProtocol> 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) GTMHTTPFetcher *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; // 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<GTLQueryProtocol> executingQuery; // Query currently being fetched by this ticket
|
||||
@property (nonatomic, retain) id<GTLQueryProtocol> originalQuery; // Query used to create this ticket
|
||||
- (GTLQuery *)queryForRequestID:(NSString *)requestID; // 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;
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
@property (copy) BOOL (^retryBlock)(GTLServiceTicket *ticket, BOOL suggestedWillRetry, NSError *error);
|
||||
#endif
|
||||
@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
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
@property (copy) void (^uploadProgressBlock)(GTLServiceTicket *ticket, unsigned long long numberOfBytesRead, unsigned long long dataLength);
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// Category to provide opaque access to tickets stored in fetcher properties
|
||||
@interface GTMHTTPFetcher (GTLServiceTicketAdditions)
|
||||
- (id)ticket;
|
||||
@end
|
||||
|
2387
External/google-plus-ios-sdk/OpenSource/GTL/GTLService.m
vendored
Normal file
58
External/google-plus-ios-sdk/OpenSource/GTL/GTLTargetNamespace.h
vendored
Normal file
@ -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
|
57
External/google-plus-ios-sdk/OpenSource/GTL/GTLUploadParameters.h
vendored
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
//
|
||||
// GTLUploadParameters.h
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "GTLDefines.h"
|
||||
|
||||
@interface GTLUploadParameters : NSObject <NSCopying> {
|
||||
@private
|
||||
NSString *MIMEType_;
|
||||
NSData *data_;
|
||||
NSFileHandle *fileHandle_;
|
||||
NSURL *uploadLocationURL_;
|
||||
NSString *slug_;
|
||||
BOOL shouldSendUploadOnly_;
|
||||
}
|
||||
|
||||
// Uploading requires MIME type and one of
|
||||
// - data to be uploaded
|
||||
// - file handle for uploading
|
||||
@property (copy) NSString *MIMEType;
|
||||
@property (retain) NSData *data;
|
||||
@property (retain) NSFileHandle *fileHandle;
|
||||
|
||||
// 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;
|
||||
|
||||
+ (GTLUploadParameters *)uploadParametersWithData:(NSData *)data
|
||||
MIMEType:(NSString *)mimeType;
|
||||
|
||||
+ (GTLUploadParameters *)uploadParametersWithFileHandle:(NSFileHandle *)fileHandle
|
||||
MIMEType:(NSString *)mimeType;
|
||||
|
||||
@end
|
107
External/google-plus-ios-sdk/OpenSource/GTL/GTLUploadParameters.m
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/* 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 <objc/runtime.h>
|
||||
|
||||
#import "GTLUploadParameters.h"
|
||||
|
||||
@implementation GTLUploadParameters
|
||||
|
||||
@synthesize MIMEType = MIMEType_,
|
||||
data = data_,
|
||||
fileHandle = fileHandle_,
|
||||
uploadLocationURL = uploadLocationURL_,
|
||||
slug = slug_,
|
||||
shouldSendUploadOnly = shouldSendUploadOnly_;
|
||||
|
||||
+ (GTLUploadParameters *)uploadParametersWithData:(NSData *)data
|
||||
MIMEType:(NSString *)mimeType {
|
||||
GTLUploadParameters *params = [[[GTLUploadParameters alloc] init] autorelease];
|
||||
params.data = data;
|
||||
params.MIMEType = mimeType;
|
||||
return params;
|
||||
}
|
||||
|
||||
+ (GTLUploadParameters *)uploadParametersWithFileHandle:(NSFileHandle *)fileHandle
|
||||
MIMEType:(NSString *)mimeType {
|
||||
GTLUploadParameters *params = [[[GTLUploadParameters alloc] init] autorelease];
|
||||
params.fileHandle = fileHandle;
|
||||
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.uploadLocationURL = self.uploadLocationURL;
|
||||
newParams.slug = self.slug;
|
||||
newParams.shouldSendUploadOnly = self.shouldSendUploadOnly;
|
||||
return newParams;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[MIMEType_ release];
|
||||
[data_ release];
|
||||
[fileHandle_ 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 (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
|
105
External/google-plus-ios-sdk/OpenSource/GTL/GTLUtilities.h
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/* 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 <Foundation/Foundation.h>
|
||||
|
||||
#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;
|
||||
|
||||
// Allocate a global dictionary
|
||||
+ (NSMutableDictionary *)newStaticDictionary;
|
||||
|
||||
// Walk up the class tree merging dictionaries and return the result.
|
||||
+ (NSDictionary *)mergedClassDictionaryForSelector:(SEL)selector
|
||||
startClass:(Class)startClass
|
||||
ancestorClass:(Class)ancestorClass
|
||||
cache:(NSMutableDictionary *)cache;
|
||||
|
||||
//
|
||||
// MIME Types
|
||||
//
|
||||
|
||||
// Utility routine to convert a file path to the file's MIME type using
|
||||
// Mac OS X's UTI database
|
||||
#if !GTL_FOUNDATION_ONLY
|
||||
+ (NSString *)MIMETypeForFileAtPath:(NSString *)path
|
||||
defaultMIMEType:(NSString *)defaultType;
|
||||
#endif
|
||||
|
||||
@end
|
376
External/google-plus-ios-sdk/OpenSource/GTL/GTLUtilities.m
vendored
Normal file
@ -0,0 +1,376 @@
|
||||
/* 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 <objc/runtime.h>
|
||||
|
||||
@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 = 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
|
||||
|
||||
+ (NSMutableDictionary *)newStaticDictionary {
|
||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||
|
||||
// make the dictionary ineligible for garbage collection
|
||||
#if !GTL_IPHONE
|
||||
[[NSGarbageCollector defaultCollector] disableCollectorForPointer:dict];
|
||||
#endif
|
||||
return dict;
|
||||
}
|
||||
|
||||
+ (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<NSCopying>)startClass];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark MIME Types
|
||||
|
||||
// Utility routine to convert a file path to the file's MIME type using
|
||||
// Mac OS X's UTI database
|
||||
#if !GTL_FOUNDATION_ONLY
|
||||
+ (NSString *)MIMETypeForFileAtPath:(NSString *)path
|
||||
defaultMIMEType:(NSString *)defaultType {
|
||||
NSString *result = defaultType;
|
||||
|
||||
// Convert the path to an FSRef
|
||||
FSRef fileFSRef;
|
||||
Boolean isDirectory;
|
||||
OSStatus err = FSPathMakeRef((UInt8 *) [path fileSystemRepresentation],
|
||||
&fileFSRef, &isDirectory);
|
||||
if (err == noErr) {
|
||||
// Get the UTI (content type) for the FSRef
|
||||
CFStringRef fileUTI;
|
||||
err = LSCopyItemAttribute(&fileFSRef, kLSRolesAll, kLSItemContentType,
|
||||
(CFTypeRef *)&fileUTI);
|
||||
if (err == noErr) {
|
||||
// Get the MIME type for the UTI
|
||||
CFStringRef mimeTypeTag;
|
||||
mimeTypeTag = UTTypeCopyPreferredTagWithClass(fileUTI,
|
||||
kUTTagClassMIMEType);
|
||||
if (mimeTypeTag) {
|
||||
// Convert the CFStringRef to an autoreleased NSString
|
||||
result = [(id)CFMakeCollectable(mimeTypeTag) autorelease];
|
||||
}
|
||||
CFRelease(fileUTI);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
@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 ([num isKindOfClass:[NSString class]]) {
|
||||
NSDecimalNumber *reallyNum;
|
||||
// Force the parse to use '.' as the number seperator.
|
||||
static NSLocale *usLocale = nil;
|
||||
@synchronized([GTLUtilities class]) {
|
||||
if (usLocale == nil) {
|
||||
usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
|
||||
}
|
||||
reallyNum = [NSDecimalNumber decimalNumberWithString:(NSString*)num
|
||||
locale:(id)usLocale];
|
||||
}
|
||||
if (reallyNum != nil) {
|
||||
num = reallyNum;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
439
External/google-plus-ios-sdk/OpenSource/GTMDefines.h
vendored
Normal file
@ -0,0 +1,439 @@
|
||||
//
|
||||
// GTMDefines.h
|
||||
//
|
||||
// Copyright 2008 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 <AvailabilityMacros.h>
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#include <Availability.h>
|
||||
#endif // TARGET_OS_IPHONE
|
||||
|
||||
// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs
|
||||
#ifndef MAC_OS_X_VERSION_10_5
|
||||
#define MAC_OS_X_VERSION_10_5 1050
|
||||
#endif
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
#define MAC_OS_X_VERSION_10_6 1060
|
||||
#endif
|
||||
#ifndef MAC_OS_X_VERSION_10_7
|
||||
#define MAC_OS_X_VERSION_10_7 1070
|
||||
#endif
|
||||
|
||||
// Not all __IPHONE_X macros defined in past SDKs
|
||||
#ifndef __IPHONE_3_0
|
||||
#define __IPHONE_3_0 30000
|
||||
#endif
|
||||
#ifndef __IPHONE_3_1
|
||||
#define __IPHONE_3_1 30100
|
||||
#endif
|
||||
#ifndef __IPHONE_3_2
|
||||
#define __IPHONE_3_2 30200
|
||||
#endif
|
||||
#ifndef __IPHONE_4_0
|
||||
#define __IPHONE_4_0 40000
|
||||
#endif
|
||||
#ifndef __IPHONE_4_3
|
||||
#define __IPHONE_4_3 40300
|
||||
#endif
|
||||
#ifndef __IPHONE_5_0
|
||||
#define __IPHONE_5_0 50000
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CPP symbols that can be overridden in a prefix to control how the toolbox
|
||||
// is compiled.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
|
||||
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
|
||||
// when a validation fails. If you implement your own validators, you may want
|
||||
// to control their internals using the same macros for consistency.
|
||||
#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
|
||||
#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
|
||||
#endif
|
||||
|
||||
// Give ourselves a consistent way to do inlines. Apple's macros even use
|
||||
// a few different actual definitions, so we're based off of the foundation
|
||||
// one.
|
||||
#if !defined(GTM_INLINE)
|
||||
#if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__)
|
||||
#define GTM_INLINE static __inline__ __attribute__((always_inline))
|
||||
#else
|
||||
#define GTM_INLINE static __inline__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Give ourselves a consistent way of doing externs that links up nicely
|
||||
// when mixing objc and objc++
|
||||
#if !defined (GTM_EXTERN)
|
||||
#if defined __cplusplus
|
||||
#define GTM_EXTERN extern "C"
|
||||
#define GTM_EXTERN_C_BEGIN extern "C" {
|
||||
#define GTM_EXTERN_C_END }
|
||||
#else
|
||||
#define GTM_EXTERN extern
|
||||
#define GTM_EXTERN_C_BEGIN
|
||||
#define GTM_EXTERN_C_END
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Give ourselves a consistent way of exporting things if we have visibility
|
||||
// set to hidden.
|
||||
#if !defined (GTM_EXPORT)
|
||||
#define GTM_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
// Give ourselves a consistent way of declaring something as unused. This
|
||||
// doesn't use __unused because that is only supported in gcc 4.2 and greater.
|
||||
#if !defined (GTM_UNUSED)
|
||||
#define GTM_UNUSED(x) ((void)(x))
|
||||
#endif
|
||||
|
||||
// _GTMDevLog & _GTMDevAssert
|
||||
//
|
||||
// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
|
||||
// developer level errors. This implementation simply macros to NSLog/NSAssert.
|
||||
// It is not intended to be a general logging/reporting system.
|
||||
//
|
||||
// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
|
||||
// for a little more background on the usage of these macros.
|
||||
//
|
||||
// _GTMDevLog log some error/problem in debug builds
|
||||
// _GTMDevAssert assert if conditon isn't met w/in a method/function
|
||||
// in all builds.
|
||||
//
|
||||
// To replace this system, just provide different macro definitions in your
|
||||
// prefix header. Remember, any implementation you provide *must* be thread
|
||||
// safe since this could be called by anything in what ever situtation it has
|
||||
// been placed in.
|
||||
//
|
||||
|
||||
// We only define the simple macros if nothing else has defined this.
|
||||
#ifndef _GTMDevLog
|
||||
|
||||
#ifdef DEBUG
|
||||
#define _GTMDevLog(...) NSLog(__VA_ARGS__)
|
||||
#else
|
||||
#define _GTMDevLog(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif // _GTMDevLog
|
||||
|
||||
#ifndef _GTMDevAssert
|
||||
// we directly invoke the NSAssert handler so we can pass on the varargs
|
||||
// (NSAssert doesn't have a macro we can use that takes varargs)
|
||||
#if !defined(NS_BLOCK_ASSERTIONS)
|
||||
#define _GTMDevAssert(condition, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
[[NSAssertionHandler currentHandler] \
|
||||
handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
|
||||
file:[NSString stringWithUTF8String:__FILE__] \
|
||||
lineNumber:__LINE__ \
|
||||
description:__VA_ARGS__]; \
|
||||
} \
|
||||
} while(0)
|
||||
#else // !defined(NS_BLOCK_ASSERTIONS)
|
||||
#define _GTMDevAssert(condition, ...) do { } while (0)
|
||||
#endif // !defined(NS_BLOCK_ASSERTIONS)
|
||||
|
||||
#endif // _GTMDevAssert
|
||||
|
||||
// _GTMCompileAssert
|
||||
// _GTMCompileAssert is an assert that is meant to fire at compile time if you
|
||||
// want to check things at compile instead of runtime. For example if you
|
||||
// want to check that a wchar is 4 bytes instead of 2 you would use
|
||||
// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
|
||||
// Note that the second "arg" is not in quotes, and must be a valid processor
|
||||
// symbol in it's own right (no spaces, punctuation etc).
|
||||
|
||||
// Wrapping this in an #ifndef allows external groups to define their own
|
||||
// compile time assert scheme.
|
||||
#ifndef _GTMCompileAssert
|
||||
// We got this technique from here:
|
||||
// http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
|
||||
|
||||
#define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
|
||||
#define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
|
||||
#define _GTMCompileAssert(test, msg) \
|
||||
typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
|
||||
#endif // _GTMCompileAssert
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CPP symbols defined based on the project settings so the GTM code has
|
||||
// simple things to test against w/o scattering the knowledge of project
|
||||
// setting through all the code.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Provide a single constant CPP symbol that all of GTM uses for ifdefing
|
||||
// iPhone code.
|
||||
#if TARGET_OS_IPHONE // iPhone SDK
|
||||
// For iPhone specific stuff
|
||||
#define GTM_IPHONE_SDK 1
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
#define GTM_IPHONE_SIMULATOR 1
|
||||
#else
|
||||
#define GTM_IPHONE_DEVICE 1
|
||||
#endif // TARGET_IPHONE_SIMULATOR
|
||||
// By default, GTM has provided it's own unittesting support, define this
|
||||
// to use the support provided by Xcode, especially for the Xcode4 support
|
||||
// for unittesting.
|
||||
#ifndef GTM_IPHONE_USE_SENTEST
|
||||
#define GTM_IPHONE_USE_SENTEST 0
|
||||
#endif
|
||||
#else
|
||||
// For MacOS specific stuff
|
||||
#define GTM_MACOS_SDK 1
|
||||
#endif
|
||||
|
||||
// Some of our own availability macros
|
||||
#if GTM_MACOS_SDK
|
||||
#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
|
||||
#define GTM_AVAILABLE_ONLY_ON_MACOS
|
||||
#else
|
||||
#define GTM_AVAILABLE_ONLY_ON_IPHONE
|
||||
#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
// Provide a symbol to include/exclude extra code for GC support. (This mainly
|
||||
// just controls the inclusion of finalize methods).
|
||||
#ifndef GTM_SUPPORT_GC
|
||||
#if GTM_IPHONE_SDK
|
||||
// iPhone never needs GC
|
||||
#define GTM_SUPPORT_GC 0
|
||||
#else
|
||||
// We can't find a symbol to tell if GC is supported/required, so best we
|
||||
// do on Mac targets is include it if we're on 10.5 or later.
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
#define GTM_SUPPORT_GC 0
|
||||
#else
|
||||
#define GTM_SUPPORT_GC 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// To simplify support for 64bit (and Leopard in general), we provide the type
|
||||
// defines for non Leopard SDKs
|
||||
#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
|
||||
// NSInteger/NSUInteger and Max/Mins
|
||||
#ifndef NSINTEGER_DEFINED
|
||||
#if __LP64__ || NS_BUILD_32_LIKE_64
|
||||
typedef long NSInteger;
|
||||
typedef unsigned long NSUInteger;
|
||||
#else
|
||||
typedef int NSInteger;
|
||||
typedef unsigned int NSUInteger;
|
||||
#endif
|
||||
#define NSIntegerMax LONG_MAX
|
||||
#define NSIntegerMin LONG_MIN
|
||||
#define NSUIntegerMax ULONG_MAX
|
||||
#define NSINTEGER_DEFINED 1
|
||||
#endif // NSINTEGER_DEFINED
|
||||
// CGFloat
|
||||
#ifndef CGFLOAT_DEFINED
|
||||
#if defined(__LP64__) && __LP64__
|
||||
// This really is an untested path (64bit on Tiger?)
|
||||
typedef double CGFloat;
|
||||
#define CGFLOAT_MIN DBL_MIN
|
||||
#define CGFLOAT_MAX DBL_MAX
|
||||
#define CGFLOAT_IS_DOUBLE 1
|
||||
#else /* !defined(__LP64__) || !__LP64__ */
|
||||
typedef float CGFloat;
|
||||
#define CGFLOAT_MIN FLT_MIN
|
||||
#define CGFLOAT_MAX FLT_MAX
|
||||
#define CGFLOAT_IS_DOUBLE 0
|
||||
#endif /* !defined(__LP64__) || !__LP64__ */
|
||||
#define CGFLOAT_DEFINED 1
|
||||
#endif // CGFLOAT_DEFINED
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
|
||||
// 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_RETAINED
|
||||
#if __has_feature(attribute_ns_returns_retained)
|
||||
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
||||
#else
|
||||
#define NS_RETURNS_RETAINED
|
||||
#endif
|
||||
#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 CF_RETURNS_RETAINED
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#else
|
||||
#define CF_RETURNS_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CF_RETURNS_NOT_RETAINED
|
||||
#if __has_feature(attribute_cf_returns_not_retained)
|
||||
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
|
||||
#else
|
||||
#define CF_RETURNS_NOT_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NS_CONSUMED
|
||||
#if __has_feature(attribute_ns_consumed)
|
||||
#define NS_CONSUMED __attribute__((ns_consumed))
|
||||
#else
|
||||
#define NS_CONSUMED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CF_CONSUMED
|
||||
#if __has_feature(attribute_cf_consumed)
|
||||
#define CF_CONSUMED __attribute__((cf_consumed))
|
||||
#else
|
||||
#define CF_CONSUMED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NS_CONSUMES_SELF
|
||||
#if __has_feature(attribute_ns_consumes_self)
|
||||
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
|
||||
#else
|
||||
#define NS_CONSUMES_SELF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Defined on 10.6 and above.
|
||||
#ifndef NS_FORMAT_ARGUMENT
|
||||
#define NS_FORMAT_ARGUMENT(A)
|
||||
#endif
|
||||
|
||||
// Defined on 10.6 and above.
|
||||
#ifndef NS_FORMAT_FUNCTION
|
||||
#define NS_FORMAT_FUNCTION(F,A)
|
||||
#endif
|
||||
|
||||
// Defined on 10.6 and above.
|
||||
#ifndef CF_FORMAT_ARGUMENT
|
||||
#define CF_FORMAT_ARGUMENT(A)
|
||||
#endif
|
||||
|
||||
// Defined on 10.6 and above.
|
||||
#ifndef CF_FORMAT_FUNCTION
|
||||
#define CF_FORMAT_FUNCTION(F,A)
|
||||
#endif
|
||||
|
||||
#ifndef GTM_NONNULL
|
||||
#define GTM_NONNULL(x) __attribute__((nonnull(x)))
|
||||
#endif
|
||||
|
||||
// Invalidates the initializer from which it's called.
|
||||
#ifndef GTMInvalidateInitializer
|
||||
#if __has_feature(objc_arc)
|
||||
#define GTMInvalidateInitializer() \
|
||||
do { \
|
||||
_GTMDevAssert(NO, @"Invalid initializer."); \
|
||||
return nil; \
|
||||
} while (0)
|
||||
#else
|
||||
#define GTMInvalidateInitializer() \
|
||||
do { \
|
||||
[self release]; \
|
||||
_GTMDevAssert(NO, @"Invalid initializer."); \
|
||||
return nil; \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
// Declared here so that it can easily be used for logging tracking if
|
||||
// necessary. See GTMUnitTestDevLog.h for details.
|
||||
@class NSString;
|
||||
GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2);
|
||||
|
||||
// Macro to allow you to create NSStrings out of other macros.
|
||||
// #define FOO foo
|
||||
// NSString *fooString = GTM_NSSTRINGIFY(FOO);
|
||||
#if !defined (GTM_NSSTRINGIFY)
|
||||
#define GTM_NSSTRINGIFY_INNER(x) @#x
|
||||
#define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
|
||||
#endif
|
||||
|
||||
// Macro to allow fast enumeration when building for 10.5 or later, and
|
||||
// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration
|
||||
// does keys, so pick the right thing, nothing is done on the FastEnumeration
|
||||
// side to be sure you're getting what you wanted.
|
||||
#ifndef GTM_FOREACH_OBJECT
|
||||
#if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
|
||||
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
|
||||
for (element in enumeration)
|
||||
#define GTM_FOREACH_OBJECT(element, collection) \
|
||||
for (element in collection)
|
||||
#define GTM_FOREACH_KEY(element, collection) \
|
||||
for (element in collection)
|
||||
#else
|
||||
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
|
||||
for (NSEnumerator *_ ## element ## _enum = enumeration; \
|
||||
(element = [_ ## element ## _enum nextObject]) != nil; )
|
||||
#define GTM_FOREACH_OBJECT(element, collection) \
|
||||
GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
|
||||
#define GTM_FOREACH_KEY(element, collection) \
|
||||
GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
|
||||
// To simplify support for both Leopard and Snow Leopard we declare
|
||||
// the Snow Leopard protocols that we need here.
|
||||
#if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
|
||||
#define GTM_10_6_PROTOCOLS_DEFINED 1
|
||||
@protocol NSConnectionDelegate
|
||||
@end
|
||||
@protocol NSAnimationDelegate
|
||||
@end
|
||||
@protocol NSImageDelegate
|
||||
@end
|
||||
@protocol NSTabViewDelegate
|
||||
@end
|
||||
#endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
|
||||
|
||||
// GTM_SEL_STRING is for specifying selector (usually property) names to KVC
|
||||
// or KVO methods.
|
||||
// In debug it will generate warnings for undeclared selectors if
|
||||
// -Wunknown-selector is turned on.
|
||||
// In release it will have no runtime overhead.
|
||||
#ifndef GTM_SEL_STRING
|
||||
#ifdef DEBUG
|
||||
#define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName))
|
||||
#else
|
||||
#define GTM_SEL_STRING(selName) @#selName
|
||||
#endif // DEBUG
|
||||
#endif // GTM_SEL_STRING
|
||||
|
||||
#endif // __OBJC__
|
72
External/google-plus-ios-sdk/OpenSource/GTMGarbageCollection.h
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// GTMGarbageCollection.h
|
||||
//
|
||||
// Copyright 2007-2008 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "GTMDefines.h"
|
||||
|
||||
// This allows us to easily move our code from GC to non GC.
|
||||
// They are no-ops unless we are require Leopard or above.
|
||||
// See
|
||||
// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/index.html
|
||||
// and
|
||||
// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html#//apple_ref/doc/uid/TP40006687-SW1
|
||||
// for details.
|
||||
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) && !GTM_IPHONE_SDK
|
||||
// General use would be to call this through GTMCFAutorelease
|
||||
// but there may be a reason the you want to make something collectable
|
||||
// but not autoreleased, especially in pure GC code where you don't
|
||||
// want to bother with the nop autorelease. Done as a define instead of an
|
||||
// inline so that tools like Clang's scan-build don't report code as leaking.
|
||||
#define GTMNSMakeCollectable(cf) ((id)NSMakeCollectable(cf))
|
||||
|
||||
// GTMNSMakeUncollectable is for global maps, etc. that we don't
|
||||
// want released ever. You should still retain these in non-gc code.
|
||||
GTM_INLINE void GTMNSMakeUncollectable(id object) {
|
||||
[[NSGarbageCollector defaultCollector] disableCollectorForPointer:object];
|
||||
}
|
||||
|
||||
// Hopefully no code really needs this, but GTMIsGarbageCollectionEnabled is
|
||||
// a common way to check at runtime if GC is on.
|
||||
// There are some places where GC doesn't work w/ things w/in Apple's
|
||||
// frameworks, so this is here so GTM unittests and detect it, and not run
|
||||
// individual tests to work around bugs in Apple's frameworks.
|
||||
GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
|
||||
return ([NSGarbageCollector defaultCollector] != nil);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define GTMNSMakeCollectable(cf) ((id)(cf))
|
||||
|
||||
GTM_INLINE void GTMNSMakeUncollectable(id object) {
|
||||
}
|
||||
|
||||
GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// GTMCFAutorelease makes a CF object collectable in GC mode, or adds it
|
||||
// to the autorelease pool in non-GC mode. Either way it is taken care
|
||||
// of. Done as a define instead of an inline so that tools like Clang's
|
||||
// scan-build don't report code as leaking.
|
||||
#define GTMCFAutorelease(cf) ([GTMNSMakeCollectable(cf) autorelease])
|
||||
|
187
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetchHistory.h
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
/* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "GTMHTTPFetcher.h"
|
||||
|
||||
#undef _EXTERN
|
||||
#undef _INITIALIZE_AS
|
||||
#ifdef GTMHTTPFETCHHISTORY_DEFINE_GLOBALS
|
||||
#define _EXTERN
|
||||
#define _INITIALIZE_AS(x) =x
|
||||
#else
|
||||
#if defined(__cplusplus)
|
||||
#define _EXTERN extern "C"
|
||||
#else
|
||||
#define _EXTERN extern
|
||||
#endif
|
||||
#define _INITIALIZE_AS(x)
|
||||
#endif
|
||||
|
||||
|
||||
// default data cache size for when we're caching responses to handle "not
|
||||
// modified" errors for the client
|
||||
#if GTM_IPHONE
|
||||
// iPhone: up to 1MB memory
|
||||
_EXTERN const NSUInteger kGTMDefaultETaggedDataCacheMemoryCapacity _INITIALIZE_AS(1*1024*1024);
|
||||
#else
|
||||
// Mac OS X: up to 15MB memory
|
||||
_EXTERN const NSUInteger kGTMDefaultETaggedDataCacheMemoryCapacity _INITIALIZE_AS(15*1024*1024);
|
||||
#endif
|
||||
|
||||
// forward declarations
|
||||
@class GTMURLCache;
|
||||
@class GTMCookieStorage;
|
||||
|
||||
@interface GTMHTTPFetchHistory : NSObject <GTMHTTPFetchHistoryProtocol> {
|
||||
@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 <GTMCookieStorageProtocol> {
|
||||
@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
|
590
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetchHistory.m
vendored
Normal file
@ -0,0 +1,590 @@
|
||||
/* 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
|
||||
//
|
||||
|
||||
#define GTMHTTPFETCHHISTORY_DEFINE_GLOBALS 1
|
||||
|
||||
#import "GTMHTTPFetchHistory.h"
|
||||
|
||||
const NSTimeInterval kCachedURLReservationInterval = 60.0; // 1 minute
|
||||
static NSString* const kGTMIfNoneMatchHeader = @"If-None-Match";
|
||||
static NSString* const kGTMETagHeader = @"Etag";
|
||||
|
||||
@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 = [cookies_ count] - 1; idx >= 0; idx--) {
|
||||
|
||||
NSHTTPCookie *storedCookie = [cookies_ objectAtIndex:idx];
|
||||
|
||||
NSDate *expiresDate = [storedCookie expiresDate];
|
||||
if (expiresDate && [expiresDate timeIntervalSinceNow] < 0) {
|
||||
[cookies_ removeObjectAtIndex: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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
[etaggedDataCache_ removeCachedResponseForRequest:request];
|
||||
}
|
||||
|
||||
- (void)clearETaggedDataCache {
|
||||
[etaggedDataCache_ removeAllCachedResponses];
|
||||
}
|
||||
|
||||
- (void)clearHistory {
|
||||
[self clearETaggedDataCache];
|
||||
[cookieStorage_ removeAllCookies];
|
||||
}
|
||||
|
||||
- (void)removeAllCookies {
|
||||
[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
|
704
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetcher.h
vendored
Normal file
@ -0,0 +1,704 @@
|
||||
/* 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 <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>
|
||||
//
|
||||
//
|
||||
// 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 <Foundation/Foundation.h>
|
||||
|
||||
#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
|
||||
|
||||
#undef _EXTERN
|
||||
#undef _INITIALIZE_AS
|
||||
#ifdef GTMHTTPFETCHER_DEFINE_GLOBALS
|
||||
#define _EXTERN
|
||||
#define _INITIALIZE_AS(x) =x
|
||||
#else
|
||||
#if defined(__cplusplus)
|
||||
#define _EXTERN extern "C"
|
||||
#else
|
||||
#define _EXTERN extern
|
||||
#endif
|
||||
#define _INITIALIZE_AS(x)
|
||||
#endif
|
||||
|
||||
// notifications
|
||||
//
|
||||
// fetch started and stopped, and fetch retry delay started and stopped
|
||||
_EXTERN NSString* const kGTMHTTPFetcherStartedNotification _INITIALIZE_AS(@"kGTMHTTPFetcherStartedNotification");
|
||||
_EXTERN NSString* const kGTMHTTPFetcherStoppedNotification _INITIALIZE_AS(@"kGTMHTTPFetcherStoppedNotification");
|
||||
_EXTERN NSString* const kGTMHTTPFetcherRetryDelayStartedNotification _INITIALIZE_AS(@"kGTMHTTPFetcherRetryDelayStartedNotification");
|
||||
_EXTERN NSString* const kGTMHTTPFetcherRetryDelayStoppedNotification _INITIALIZE_AS(@"kGTMHTTPFetcherRetryDelayStoppedNotification");
|
||||
|
||||
// callback constants
|
||||
_EXTERN NSString* const kGTMHTTPFetcherErrorDomain _INITIALIZE_AS(@"com.google.GTMHTTPFetcher");
|
||||
_EXTERN NSString* const kGTMHTTPFetcherStatusDomain _INITIALIZE_AS(@"com.google.HTTPStatus");
|
||||
_EXTERN NSString* const kGTMHTTPFetcherErrorChallengeKey _INITIALIZE_AS(@"challenge");
|
||||
_EXTERN NSString* const kGTMHTTPFetcherStatusDataKey _INITIALIZE_AS(@"data"); // data returned with a kGTMHTTPFetcherStatusDomain error
|
||||
|
||||
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"
|
||||
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. If no bundle ID
|
||||
// is available, the process name preceded by "proc_" is used.
|
||||
NSString *GTMApplicationIdentifier(NSBundle *bundle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@class GTMHTTPFetcher;
|
||||
|
||||
@protocol GTMCookieStorageProtocol <NSObject>
|
||||
// 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 <NSObject>
|
||||
// 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 <GTMCookieStorageProtocol>)cookieStorage;
|
||||
- (void)updateFetchHistoryWithRequest:(NSURLRequest *)request
|
||||
response:(NSURLResponse *)response
|
||||
downloadedData:(NSData *)downloadedData;
|
||||
- (void)removeCachedDataForRequest:(NSURLRequest *)request;
|
||||
@end
|
||||
|
||||
@protocol GTMHTTPFetcherServiceProtocol <NSObject>
|
||||
// This protocol allows us to call into the service without requiring
|
||||
// GTMHTTPFetcherService sources in this project
|
||||
- (BOOL)fetcherShouldBeginFetching:(GTMHTTPFetcher *)fetcher;
|
||||
- (void)fetcherDidStop:(GTMHTTPFetcher *)fetcher;
|
||||
|
||||
- (GTMHTTPFetcher *)fetcherWithRequest:(NSURLRequest *)request;
|
||||
- (BOOL)isDelayingFetcher:(GTMHTTPFetcher *)fetcher;
|
||||
@end
|
||||
|
||||
@protocol GTMFetcherAuthorizationProtocol <NSObject>
|
||||
@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;
|
||||
|
||||
- (BOOL)isAuthorizingRequest:(NSURLRequest *)request;
|
||||
|
||||
- (BOOL)isAuthorizedRequest:(NSURLRequest *)request;
|
||||
|
||||
- (NSString *)userEmail;
|
||||
|
||||
@optional
|
||||
@property (assign) id <GTMHTTPFetcherServiceProtocol> fetcherService; // WEAK
|
||||
|
||||
- (BOOL)primeForRefresh;
|
||||
@end
|
||||
|
||||
// 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_;
|
||||
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, for 10.5 and later
|
||||
id <GTMHTTPFetchHistoryProtocol> fetchHistory_; // if supplied by the caller, used for Last-Modified-Since checks and cookies
|
||||
NSInteger cookieStorageMethod_; // constant from above
|
||||
id <GTMCookieStorageProtocol> cookieStorage_;
|
||||
|
||||
id <GTMFetcherAuthorizationProtocol> authorizer_;
|
||||
|
||||
// the service object that created and monitors this fetcher, if any
|
||||
id <GTMHTTPFetcherServiceProtocol> 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_;
|
||||
BOOL hasAttemptedAuthRefresh_;
|
||||
|
||||
NSString *comment_; // comment for log
|
||||
NSString *log_;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// 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 <GTMCookieStorageProtocol>)staticCookieStorage;
|
||||
|
||||
// Object to add authorization to the request, if needed
|
||||
@property (retain) id <GTMFetcherAuthorizationProtocol> authorizer;
|
||||
|
||||
// The service object that created and monitors this fetcher, if any
|
||||
@property (retain) id <GTMHTTPFetcherServiceProtocol> 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
|
||||
@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 <GTMHTTPFetchHistoryProtocol> 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:(id)format, ...;
|
||||
|
||||
// Log of request and response, if logging is enabled
|
||||
@property (copy) NSString *log;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
1741
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetcher.m
vendored
Normal file
85
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetcherLogging.h
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/* 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;
|
||||
@end
|
||||
|
||||
#endif
|
1042
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetcherLogging.m
vendored
Normal file
118
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetcherService.h
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
/* 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<GTMHTTPFetcherServiceProtocol> {
|
||||
@private
|
||||
NSMutableDictionary *delayedHosts_;
|
||||
NSMutableDictionary *runningHosts_;
|
||||
NSUInteger maxRunningFetchersPerHost_;
|
||||
|
||||
GTMHTTPFetchHistory *fetchHistory_;
|
||||
NSArray *runLoopModes_;
|
||||
NSString *userAgent_;
|
||||
NSTimeInterval timeout_;
|
||||
NSURLCredential *credential_; // username & password
|
||||
NSURLCredential *proxyCredential_; // credential supplied to proxy servers
|
||||
NSInteger cookieStorageMethod_;
|
||||
|
||||
BOOL shouldFetchInBackground_;
|
||||
|
||||
id <GTMFetcherAuthorizationProtocol> 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;
|
||||
|
||||
- (void)stopAllFetchers;
|
||||
|
||||
// Properties to be applied to each fetcher;
|
||||
// see GTMHTTPFetcher.h for descriptions
|
||||
@property (copy) NSString *userAgent;
|
||||
@property (assign) NSTimeInterval timeout;
|
||||
@property (retain) NSArray *runLoopModes;
|
||||
@property (retain) NSURLCredential *credential;
|
||||
@property (retain) NSURLCredential *proxyCredential;
|
||||
@property (assign) BOOL shouldFetchInBackground;
|
||||
|
||||
// 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 <GTMFetcherAuthorizationProtocol> 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
|
441
External/google-plus-ios-sdk/OpenSource/GTMHTTPFetcherService.m
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
/* 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_,
|
||||
runLoopModes = runLoopModes_,
|
||||
credential = credential_,
|
||||
proxyCredential = proxyCredential_,
|
||||
cookieStorageMethod = cookieStorageMethod_,
|
||||
shouldFetchInBackground = shouldFetchInBackground_,
|
||||
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];
|
||||
[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.runLoopModes = self.runLoopModes;
|
||||
fetcher.cookieStorageMethod = self.cookieStorageMethod;
|
||||
fetcher.credential = self.credential;
|
||||
fetcher.proxyCredential = self.proxyCredential;
|
||||
fetcher.shouldFetchInBackground = self.shouldFetchInBackground;
|
||||
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 {
|
||||
BOOL isDelayed;
|
||||
@synchronized(self) {
|
||||
NSString *host = [[[fetcher mutableRequest] URL] host];
|
||||
NSArray *delayedForHost = [delayedHosts_ objectForKey:host];
|
||||
NSUInteger idx = [delayedForHost indexOfObjectIdenticalTo:fetcher];
|
||||
isDelayed = (delayedForHost != nil) && (idx != NSNotFound);
|
||||
}
|
||||
return isDelayed;
|
||||
}
|
||||
|
||||
- (BOOL)fetcherShouldBeginFetching:(GTMHTTPFetcher *)fetcher {
|
||||
// Entry point from the fetcher
|
||||
@synchronized(self) {
|
||||
NSString *host = [[[fetcher mutableRequest] URL] host];
|
||||
|
||||
if ([host length] == 0) {
|
||||
#if DEBUG
|
||||
NSAssert1(0, @"%@ 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)startFetcherOnCurrentThread:(GTMHTTPFetcher *)fetcher {
|
||||
[fetcher beginFetchMayDelay:NO
|
||||
mayAuthorize:YES];
|
||||
}
|
||||
|
||||
- (void)startFetcher:(GTMHTTPFetcher *)fetcher {
|
||||
NSThread *thread = [fetcher thread];
|
||||
if ([thread isEqual:[NSThread currentThread]]) {
|
||||
// Same thread
|
||||
[self startFetcherOnCurrentThread:fetcher];
|
||||
} else {
|
||||
// Different thread
|
||||
[self performSelector:@selector(startFetcherOnCurrentThread:)
|
||||
onThread:thread
|
||||
withObject:fetcher
|
||||
waitUntilDone:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopFetcherOnCurrentThread:(GTMHTTPFetcher *)fetcher {
|
||||
[fetcher stopFetching];
|
||||
}
|
||||
|
||||
- (void)stopFetcher:(GTMHTTPFetcher *)fetcher {
|
||||
NSThread *thread = [fetcher thread];
|
||||
if ([thread isEqual:[NSThread currentThread]]) {
|
||||
// Same thread
|
||||
[self stopFetcherOnCurrentThread:fetcher];
|
||||
} else {
|
||||
// Different thread
|
||||
[self performSelector:@selector(stopFetcherOnCurrentThread:)
|
||||
onThread:thread
|
||||
withObject:fetcher
|
||||
waitUntilDone:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (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;
|
||||
}
|
||||
}
|
||||
|
||||
[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 {
|
||||
NSUInteger running = [self numberOfRunningFetchers];
|
||||
NSUInteger delayed = [self numberOfDelayedFetchers];
|
||||
return running + delayed;
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfRunningFetchers {
|
||||
NSUInteger sum = 0;
|
||||
for (NSString *host in runningHosts_) {
|
||||
NSArray *fetchers = [runningHosts_ objectForKey:host];
|
||||
sum += [fetchers count];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfDelayedFetchers {
|
||||
NSUInteger sum = 0;
|
||||
for (NSString *host in delayedHosts_) {
|
||||
NSArray *fetchers = [delayedHosts_ objectForKey:host];
|
||||
sum += [fetchers count];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
- (void)stopAllFetchers {
|
||||
// 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];
|
||||
|
||||
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
|
||||
NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:0.001];
|
||||
[[NSRunLoop currentRunLoop] runUntilDate:stopDate];
|
||||
}
|
||||
}
|
||||
|
||||
#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 <GTMFetcherAuthorizationProtocol>)authorizer {
|
||||
return authorizer_;
|
||||
}
|
||||
|
||||
- (void)setAuthorizer:(id <GTMFetcherAuthorizationProtocol>)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:)]) {
|
||||
[authorizer_ setFetcherService:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (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)]) {
|
||||
GTMHTTPFetcherService *authFS = [authorizer_ fetcherService];
|
||||
if (authFS == self) {
|
||||
[authorizer_ setFetcherService:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
504
External/google-plus-ios-sdk/OpenSource/GTMLogger.h
vendored
Normal file
@ -0,0 +1,504 @@
|
||||
//
|
||||
// GTMLogger.h
|
||||
//
|
||||
// Copyright 2007-2008 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.
|
||||
//
|
||||
|
||||
// Key Abstractions
|
||||
// ----------------
|
||||
//
|
||||
// This file declares multiple classes and protocols that are used by the
|
||||
// GTMLogger logging system. The 4 main abstractions used in this file are the
|
||||
// following:
|
||||
//
|
||||
// * logger (GTMLogger) - The main logging class that users interact with. It
|
||||
// has methods for logging at different levels and uses a log writer, a log
|
||||
// formatter, and a log filter to get the job done.
|
||||
//
|
||||
// * log writer (GTMLogWriter) - Writes a given string to some log file, where
|
||||
// a "log file" can be a physical file on disk, a POST over HTTP to some URL,
|
||||
// or even some in-memory structure (e.g., a ring buffer).
|
||||
//
|
||||
// * log formatter (GTMLogFormatter) - Given a format string and arguments as
|
||||
// a va_list, returns a single formatted NSString. A "formatted string" could
|
||||
// be a string with the date prepended, a string with values in a CSV format,
|
||||
// or even a string of XML.
|
||||
//
|
||||
// * log filter (GTMLogFilter) - Given a formatted log message as an NSString
|
||||
// and the level at which the message is to be logged, this class will decide
|
||||
// whether the given message should be logged or not. This is a flexible way
|
||||
// to filter out messages logged at a certain level, messages that contain
|
||||
// certain text, or filter nothing out at all. This gives the caller the
|
||||
// flexibility to dynamically enable debug logging in Release builds.
|
||||
//
|
||||
// This file also declares some classes to handle the common log writer, log
|
||||
// formatter, and log filter cases. Callers can also create their own writers,
|
||||
// formatters, and filters and they can even build them on top of the ones
|
||||
// declared here. Keep in mind that your custom writer/formatter/filter may be
|
||||
// called from multiple threads, so it must be thread-safe.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "GTMDefines.h"
|
||||
|
||||
// Predeclaration of used protocols that are declared later in this file.
|
||||
@protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter;
|
||||
|
||||
// GTMLogger
|
||||
//
|
||||
// GTMLogger is the primary user-facing class for an object-oriented logging
|
||||
// system. It is built on the concept of log formatters (GTMLogFormatter), log
|
||||
// writers (GTMLogWriter), and log filters (GTMLogFilter). When a message is
|
||||
// sent to a GTMLogger to log a message, the message is formatted using the log
|
||||
// formatter, then the log filter is consulted to see if the message should be
|
||||
// logged, and if so, the message is sent to the log writer to be written out.
|
||||
//
|
||||
// GTMLogger is intended to be a flexible and thread-safe logging solution. Its
|
||||
// flexibility comes from the fact that GTMLogger instances can be customized
|
||||
// with user defined formatters, filters, and writers. And these writers,
|
||||
// filters, and formatters can be combined, stacked, and customized in arbitrary
|
||||
// ways to suit the needs at hand. For example, multiple writers can be used at
|
||||
// the same time, and a GTMLogger instance can even be used as another
|
||||
// GTMLogger's writer. This allows for arbitrarily deep logging trees.
|
||||
//
|
||||
// A standard GTMLogger uses a writer that sends messages to standard out, a
|
||||
// formatter that smacks a timestamp and a few other bits of interesting
|
||||
// information on the message, and a filter that filters out debug messages from
|
||||
// release builds. Using the standard log settings, a log message will look like
|
||||
// the following:
|
||||
//
|
||||
// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo=<Foo: 0x123>
|
||||
//
|
||||
// The output contains the date and time of the log message, the name of the
|
||||
// process followed by its process ID/thread ID, the log level at which the
|
||||
// message was logged (in the previous example the level was 1:
|
||||
// kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in
|
||||
// this case, the log message was @"foo=%@", foo).
|
||||
//
|
||||
// Multiple instances of GTMLogger can be created, each configured their own
|
||||
// way. Though GTMLogger is not a singleton (in the GoF sense), it does provide
|
||||
// access to a shared (i.e., globally accessible) GTMLogger instance. This makes
|
||||
// it convenient for all code in a process to use the same GTMLogger instance.
|
||||
// The shared GTMLogger instance can also be configured in an arbitrary, and
|
||||
// these configuration changes will affect all code that logs through the shared
|
||||
// instance.
|
||||
|
||||
//
|
||||
// Log Levels
|
||||
// ----------
|
||||
// GTMLogger has 3 different log levels: Debug, Info, and Error. GTMLogger
|
||||
// doesn't take any special action based on the log level; it simply forwards
|
||||
// this information on to formatters, filters, and writers, each of which may
|
||||
// optionally take action based on the level. Since log level filtering is
|
||||
// performed at runtime, log messages are typically not filtered out at compile
|
||||
// time. The exception to this rule is that calls to the GTMLoggerDebug() macro
|
||||
// *ARE* filtered out of non-DEBUG builds. This is to be backwards compatible
|
||||
// with behavior that many developers are currently used to. Note that this
|
||||
// means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but
|
||||
// [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out.
|
||||
//
|
||||
// Standard loggers are created with the GTMLogLevelFilter log filter, which
|
||||
// filters out certain log messages based on log level, and some other settings.
|
||||
//
|
||||
// In addition to the -logDebug:, -logInfo:, and -logError: methods defined on
|
||||
// GTMLogger itself, there are also C macros that make usage of the shared
|
||||
// GTMLogger instance very convenient. These macros are:
|
||||
//
|
||||
// GTMLoggerDebug(...)
|
||||
// GTMLoggerInfo(...)
|
||||
// GTMLoggerError(...)
|
||||
//
|
||||
// Again, a notable feature of these macros is that GTMLogDebug() calls *will be
|
||||
// compiled out of non-DEBUG builds*.
|
||||
//
|
||||
// Standard Loggers
|
||||
// ----------------
|
||||
// GTMLogger has the concept of "standard loggers". A standard logger is simply
|
||||
// a logger that is pre-configured with some standard/common writer, formatter,
|
||||
// and filter combination. Standard loggers are created using the creation
|
||||
// methods beginning with "standard". The alternative to a standard logger is a
|
||||
// regular logger, which will send messages to stdout, with no special
|
||||
// formatting, and no filtering.
|
||||
//
|
||||
// How do I use GTMLogger?
|
||||
// ----------------------
|
||||
// The typical way you will want to use GTMLogger is to simply use the
|
||||
// GTMLogger*() macros for logging from code. That way we can easily make
|
||||
// changes to the GTMLogger class and simply update the macros accordingly. Only
|
||||
// your application startup code (perhaps, somewhere in main()) should use the
|
||||
// GTMLogger class directly in order to configure the shared logger, which all
|
||||
// of the code using the macros will be using. Again, this is just the typical
|
||||
// situation.
|
||||
//
|
||||
// To be complete, there are cases where you may want to use GTMLogger directly,
|
||||
// or even create separate GTMLogger instances for some reason. That's fine,
|
||||
// too.
|
||||
//
|
||||
// Examples
|
||||
// --------
|
||||
// The following show some common GTMLogger use cases.
|
||||
//
|
||||
// 1. You want to log something as simply as possible. Also, this call will only
|
||||
// appear in debug builds. In non-DEBUG builds it will be completely removed.
|
||||
//
|
||||
// GTMLoggerDebug(@"foo = %@", foo);
|
||||
//
|
||||
// 2. The previous example is similar to the following. The major difference is
|
||||
// that the previous call (example 1) will be compiled out of Release builds
|
||||
// but this statement will not be compiled out.
|
||||
//
|
||||
// [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo];
|
||||
//
|
||||
// 3. Send all logging output from the shared logger to a file. We do this by
|
||||
// creating an NSFileHandle for writing associated with a file, and setting
|
||||
// that file handle as the logger's writer.
|
||||
//
|
||||
// NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log"
|
||||
// create:YES];
|
||||
// [[GTMLogger sharedLogger] setWriter:f];
|
||||
// GTMLoggerError(@"hi"); // This will be sent to /tmp/f.log
|
||||
//
|
||||
// 4. Create a new GTMLogger that will log to a file. This example differs from
|
||||
// the previous one because here we create a new GTMLogger that is different
|
||||
// from the shared logger.
|
||||
//
|
||||
// GTMLogger *logger = [GTMLogger standardLoggerWithPath:@"/tmp/temp.log"];
|
||||
// [logger logInfo:@"hi temp log file"];
|
||||
//
|
||||
// 5. Create a logger that writes to stdout and does NOT do any formatting to
|
||||
// the log message. This might be useful, for example, when writing a help
|
||||
// screen for a command-line tool to standard output.
|
||||
//
|
||||
// GTMLogger *logger = [GTMLogger logger];
|
||||
// [logger logInfo:@"%@ version 0.1 usage", progName];
|
||||
//
|
||||
// 6. Send log output to stdout AND to a log file. The trick here is that
|
||||
// NSArrays function as composite log writers, which means when an array is
|
||||
// set as the log writer, it forwards all logging messages to all of its
|
||||
// contained GTMLogWriters.
|
||||
//
|
||||
// // Create array of GTMLogWriters
|
||||
// NSArray *writers = [NSArray arrayWithObjects:
|
||||
// [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES],
|
||||
// [NSFileHandle fileHandleWithStandardOutput], nil];
|
||||
//
|
||||
// GTMLogger *logger = [GTMLogger standardLogger];
|
||||
// [logger setWriter:writers];
|
||||
// [logger logInfo:@"hi"]; // Output goes to stdout and /tmp/f.log
|
||||
//
|
||||
// For futher details on log writers, formatters, and filters, see the
|
||||
// documentation below.
|
||||
//
|
||||
// NOTE: GTMLogger is application level logging. By default it does nothing
|
||||
// with _GTMDevLog/_GTMDevAssert (see GTMDefines.h). An application can choose
|
||||
// to bridge _GTMDevLog/_GTMDevAssert to GTMLogger by providing macro
|
||||
// definitions in its prefix header (see GTMDefines.h for how one would do
|
||||
// that).
|
||||
//
|
||||
@interface GTMLogger : NSObject {
|
||||
@private
|
||||
id<GTMLogWriter> writer_;
|
||||
id<GTMLogFormatter> formatter_;
|
||||
id<GTMLogFilter> filter_;
|
||||
}
|
||||
|
||||
//
|
||||
// Accessors for the shared logger instance
|
||||
//
|
||||
|
||||
// Returns a shared/global standard GTMLogger instance. Callers should typically
|
||||
// use this method to get a GTMLogger instance, unless they explicitly want
|
||||
// their own instance to configure for their own needs. This is the only method
|
||||
// that returns a shared instance; all the rest return new GTMLogger instances.
|
||||
+ (id)sharedLogger;
|
||||
|
||||
// Sets the shared logger instance to |logger|. Future calls to +sharedLogger
|
||||
// will return |logger| instead.
|
||||
+ (void)setSharedLogger:(GTMLogger *)logger;
|
||||
|
||||
//
|
||||
// Creation methods
|
||||
//
|
||||
|
||||
// Returns a new autoreleased GTMLogger instance that will log to stdout, using
|
||||
// the GTMLogStandardFormatter, and the GTMLogLevelFilter filter.
|
||||
+ (id)standardLogger;
|
||||
|
||||
// Same as +standardLogger, but logs to stderr.
|
||||
+ (id)standardLoggerWithStderr;
|
||||
|
||||
// Same as +standardLogger but levels >= kGTMLoggerLevelError are routed to
|
||||
// stderr, everything else goes to stdout.
|
||||
+ (id)standardLoggerWithStdoutAndStderr;
|
||||
|
||||
// Returns a new standard GTMLogger instance with a log writer that will
|
||||
// write to the file at |path|, and will use the GTMLogStandardFormatter and
|
||||
// GTMLogLevelFilter classes. If |path| does not exist, it will be created.
|
||||
+ (id)standardLoggerWithPath:(NSString *)path;
|
||||
|
||||
// Returns an autoreleased GTMLogger instance that will use the specified
|
||||
// |writer|, |formatter|, and |filter|.
|
||||
+ (id)loggerWithWriter:(id<GTMLogWriter>)writer
|
||||
formatter:(id<GTMLogFormatter>)formatter
|
||||
filter:(id<GTMLogFilter>)filter;
|
||||
|
||||
// Returns an autoreleased GTMLogger instance that logs to stdout, with the
|
||||
// basic formatter, and no filter. The returned logger differs from the logger
|
||||
// returned by +standardLogger because this one does not do any filtering and
|
||||
// does not do any special log formatting; this is the difference between a
|
||||
// "regular" logger and a "standard" logger.
|
||||
+ (id)logger;
|
||||
|
||||
// Designated initializer. This method returns a GTMLogger initialized with the
|
||||
// specified |writer|, |formatter|, and |filter|. See the setter methods below
|
||||
// for what values will be used if nil is passed for a parameter.
|
||||
- (id)initWithWriter:(id<GTMLogWriter>)writer
|
||||
formatter:(id<GTMLogFormatter>)formatter
|
||||
filter:(id<GTMLogFilter>)filter;
|
||||
|
||||
//
|
||||
// Logging methods
|
||||
//
|
||||
|
||||
// Logs a message at the debug level (kGTMLoggerLevelDebug).
|
||||
- (void)logDebug:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
|
||||
// Logs a message at the info level (kGTMLoggerLevelInfo).
|
||||
- (void)logInfo:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
|
||||
// Logs a message at the error level (kGTMLoggerLevelError).
|
||||
- (void)logError:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
|
||||
// Logs a message at the assert level (kGTMLoggerLevelAssert).
|
||||
- (void)logAssert:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
|
||||
|
||||
|
||||
//
|
||||
// Accessors
|
||||
//
|
||||
|
||||
// Accessor methods for the log writer. If the log writer is set to nil,
|
||||
// [NSFileHandle fileHandleWithStandardOutput] is used.
|
||||
- (id<GTMLogWriter>)writer;
|
||||
- (void)setWriter:(id<GTMLogWriter>)writer;
|
||||
|
||||
// Accessor methods for the log formatter. If the log formatter is set to nil,
|
||||
// GTMLogBasicFormatter is used. This formatter will format log messages in a
|
||||
// plain printf style.
|
||||
- (id<GTMLogFormatter>)formatter;
|
||||
- (void)setFormatter:(id<GTMLogFormatter>)formatter;
|
||||
|
||||
// Accessor methods for the log filter. If the log filter is set to nil,
|
||||
// GTMLogNoFilter is used, which allows all log messages through.
|
||||
- (id<GTMLogFilter>)filter;
|
||||
- (void)setFilter:(id<GTMLogFilter>)filter;
|
||||
|
||||
@end // GTMLogger
|
||||
|
||||
|
||||
// Helper functions that are used by the convenience GTMLogger*() macros that
|
||||
// enable the logging of function names.
|
||||
@interface GTMLogger (GTMLoggerMacroHelpers)
|
||||
- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ...
|
||||
NS_FORMAT_FUNCTION(2, 3);
|
||||
- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ...
|
||||
NS_FORMAT_FUNCTION(2, 3);
|
||||
- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ...
|
||||
NS_FORMAT_FUNCTION(2, 3);
|
||||
- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ...
|
||||
NS_FORMAT_FUNCTION(2, 3);
|
||||
@end // GTMLoggerMacroHelpers
|
||||
|
||||
|
||||
// The convenience macros are only defined if they haven't already been defined.
|
||||
#ifndef GTMLoggerInfo
|
||||
|
||||
// Convenience macros that log to the shared GTMLogger instance. These macros
|
||||
// are how users should typically log to GTMLogger. Notice that GTMLoggerDebug()
|
||||
// calls will be compiled out of non-Debug builds.
|
||||
#define GTMLoggerDebug(...) \
|
||||
[[GTMLogger sharedLogger] logFuncDebug:__func__ msg:__VA_ARGS__]
|
||||
#define GTMLoggerInfo(...) \
|
||||
[[GTMLogger sharedLogger] logFuncInfo:__func__ msg:__VA_ARGS__]
|
||||
#define GTMLoggerError(...) \
|
||||
[[GTMLogger sharedLogger] logFuncError:__func__ msg:__VA_ARGS__]
|
||||
#define GTMLoggerAssert(...) \
|
||||
[[GTMLogger sharedLogger] logFuncAssert:__func__ msg:__VA_ARGS__]
|
||||
|
||||
// If we're not in a debug build, remove the GTMLoggerDebug statements. This
|
||||
// makes calls to GTMLoggerDebug "compile out" of Release builds
|
||||
#ifndef DEBUG
|
||||
#undef GTMLoggerDebug
|
||||
#define GTMLoggerDebug(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif // !defined(GTMLoggerInfo)
|
||||
|
||||
// Log levels.
|
||||
typedef enum {
|
||||
kGTMLoggerLevelUnknown,
|
||||
kGTMLoggerLevelDebug,
|
||||
kGTMLoggerLevelInfo,
|
||||
kGTMLoggerLevelError,
|
||||
kGTMLoggerLevelAssert,
|
||||
} GTMLoggerLevel;
|
||||
|
||||
|
||||
//
|
||||
// Log Writers
|
||||
//
|
||||
|
||||
// Protocol to be implemented by a GTMLogWriter instance.
|
||||
@protocol GTMLogWriter <NSObject>
|
||||
// Writes the given log message to where the log writer is configured to write.
|
||||
- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level;
|
||||
@end // GTMLogWriter
|
||||
|
||||
|
||||
// Simple category on NSFileHandle that makes NSFileHandles valid log writers.
|
||||
// This is convenient because something like, say, +fileHandleWithStandardError
|
||||
// now becomes a valid log writer. Log messages are written to the file handle
|
||||
// with a newline appended.
|
||||
@interface NSFileHandle (GTMFileHandleLogWriter) <GTMLogWriter>
|
||||
// Opens the file at |path| in append mode, and creates the file with |mode|
|
||||
// if it didn't previously exist.
|
||||
+ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode;
|
||||
@end // NSFileHandle
|
||||
|
||||
|
||||
// This category makes NSArray a GTMLogWriter that can be composed of other
|
||||
// GTMLogWriters. This is the classic Composite GoF design pattern. When the
|
||||
// GTMLogWriter -logMessage:level: message is sent to the array, the array
|
||||
// forwards the message to all of its elements that implement the GTMLogWriter
|
||||
// protocol.
|
||||
//
|
||||
// This is useful in situations where you would like to send log output to
|
||||
// multiple log writers at the same time. Simply create an NSArray of the log
|
||||
// writers you wish to use, then set the array as the "writer" for your
|
||||
// GTMLogger instance.
|
||||
@interface NSArray (GTMArrayCompositeLogWriter) <GTMLogWriter>
|
||||
@end // GTMArrayCompositeLogWriter
|
||||
|
||||
|
||||
// This category adapts the GTMLogger interface so that it can be used as a log
|
||||
// writer; it's an "adapter" in the GoF Adapter pattern sense.
|
||||
//
|
||||
// This is useful when you want to configure a logger to log to a specific
|
||||
// writer with a specific formatter and/or filter. But you want to also compose
|
||||
// that with a different log writer that may have its own formatter and/or
|
||||
// filter.
|
||||
@interface GTMLogger (GTMLoggerLogWriter) <GTMLogWriter>
|
||||
@end // GTMLoggerLogWriter
|
||||
|
||||
|
||||
//
|
||||
// Log Formatters
|
||||
//
|
||||
|
||||
// Protocol to be implemented by a GTMLogFormatter instance.
|
||||
@protocol GTMLogFormatter <NSObject>
|
||||
// Returns a formatted string using the format specified in |fmt| and the va
|
||||
// args specified in |args|.
|
||||
- (NSString *)stringForFunc:(NSString *)func
|
||||
withFormat:(NSString *)fmt
|
||||
valist:(va_list)args
|
||||
level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0);
|
||||
@end // GTMLogFormatter
|
||||
|
||||
|
||||
// A basic log formatter that formats a string the same way that NSLog (or
|
||||
// printf) would. It does not do anything fancy, nor does it add any data of its
|
||||
// own.
|
||||
@interface GTMLogBasicFormatter : NSObject <GTMLogFormatter>
|
||||
|
||||
// Helper method for prettying C99 __func__ and GCC __PRETTY_FUNCTION__
|
||||
- (NSString *)prettyNameForFunc:(NSString *)func;
|
||||
|
||||
@end // GTMLogBasicFormatter
|
||||
|
||||
|
||||
// A log formatter that formats the log string like the basic formatter, but
|
||||
// also prepends a timestamp and some basic process info to the message, as
|
||||
// shown in the following sample output.
|
||||
// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] log mesage here
|
||||
@interface GTMLogStandardFormatter : GTMLogBasicFormatter {
|
||||
@private
|
||||
NSDateFormatter *dateFormatter_; // yyyy-MM-dd HH:mm:ss.SSS
|
||||
NSString *pname_;
|
||||
pid_t pid_;
|
||||
}
|
||||
@end // GTMLogStandardFormatter
|
||||
|
||||
|
||||
//
|
||||
// Log Filters
|
||||
//
|
||||
|
||||
// Protocol to be imlemented by a GTMLogFilter instance.
|
||||
@protocol GTMLogFilter <NSObject>
|
||||
// Returns YES if |msg| at |level| should be filtered out; NO otherwise.
|
||||
- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level;
|
||||
@end // GTMLogFilter
|
||||
|
||||
|
||||
// A log filter that filters messages at the kGTMLoggerLevelDebug level out of
|
||||
// non-debug builds. Messages at the kGTMLoggerLevelInfo level are also filtered
|
||||
// out of non-debug builds unless GTMVerboseLogging is set in the environment or
|
||||
// the processes's defaults. Messages at the kGTMLoggerLevelError level are
|
||||
// never filtered.
|
||||
@interface GTMLogLevelFilter : NSObject <GTMLogFilter>
|
||||
@end // GTMLogLevelFilter
|
||||
|
||||
// A simple log filter that does NOT filter anything out;
|
||||
// -filterAllowsMessage:level will always return YES. This can be a convenient
|
||||
// way to enable debug-level logging in release builds (if you so desire).
|
||||
@interface GTMLogNoFilter : NSObject <GTMLogFilter>
|
||||
@end // GTMLogNoFilter
|
||||
|
||||
|
||||
// Base class for custom level filters. Not for direct use, use the minimum
|
||||
// or maximum level subclasses below.
|
||||
@interface GTMLogAllowedLevelFilter : NSObject <GTMLogFilter> {
|
||||
@private
|
||||
NSIndexSet *allowedLevels_;
|
||||
}
|
||||
@end
|
||||
|
||||
// A log filter that allows you to set a minimum log level. Messages below this
|
||||
// level will be filtered.
|
||||
@interface GTMLogMininumLevelFilter : GTMLogAllowedLevelFilter
|
||||
|
||||
// Designated initializer, logs at levels < |level| will be filtered.
|
||||
- (id)initWithMinimumLevel:(GTMLoggerLevel)level;
|
||||
|
||||
@end
|
||||
|
||||
// A log filter that allows you to set a maximum log level. Messages whose level
|
||||
// exceeds this level will be filtered. This is really only useful if you have
|
||||
// a composite GTMLogger that is sending the other messages elsewhere.
|
||||
@interface GTMLogMaximumLevelFilter : GTMLogAllowedLevelFilter
|
||||
|
||||
// Designated initializer, logs at levels > |level| will be filtered.
|
||||
- (id)initWithMaximumLevel:(GTMLoggerLevel)level;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// For subclasses only
|
||||
@interface GTMLogger (PrivateMethods)
|
||||
|
||||
- (void)logInternalFunc:(const char *)func
|
||||
format:(NSString *)fmt
|
||||
valist:(va_list)args
|
||||
level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0);
|
||||
|
||||
@end
|
||||
|
598
External/google-plus-ios-sdk/OpenSource/GTMLogger.m
vendored
Normal file
@ -0,0 +1,598 @@
|
||||
//
|
||||
// GTMLogger.m
|
||||
//
|
||||
// Copyright 2007-2008 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 "GTMLogger.h"
|
||||
#import "GTMGarbageCollection.h"
|
||||
#import <fcntl.h>
|
||||
#import <unistd.h>
|
||||
#import <stdlib.h>
|
||||
#import <pthread.h>
|
||||
|
||||
|
||||
// Reference to the shared GTMLogger instance. This is not a singleton, it's
|
||||
// just an easy reference to one shared instance.
|
||||
static GTMLogger *gSharedLogger = nil;
|
||||
|
||||
|
||||
@implementation GTMLogger
|
||||
|
||||
// Returns a pointer to the shared logger instance. If none exists, a standard
|
||||
// logger is created and returned.
|
||||
+ (id)sharedLogger {
|
||||
@synchronized(self) {
|
||||
if (gSharedLogger == nil) {
|
||||
gSharedLogger = [[self standardLogger] retain];
|
||||
}
|
||||
}
|
||||
return [[gSharedLogger retain] autorelease];
|
||||
}
|
||||
|
||||
+ (void)setSharedLogger:(GTMLogger *)logger {
|
||||
@synchronized(self) {
|
||||
[gSharedLogger autorelease];
|
||||
gSharedLogger = [logger retain];
|
||||
}
|
||||
}
|
||||
|
||||
+ (id)standardLogger {
|
||||
// Don't trust NSFileHandle not to throw
|
||||
@try {
|
||||
id<GTMLogWriter> writer = [NSFileHandle fileHandleWithStandardOutput];
|
||||
id<GTMLogFormatter> fr = [[[GTMLogStandardFormatter alloc] init]
|
||||
autorelease];
|
||||
id<GTMLogFilter> filter = [[[GTMLogLevelFilter alloc] init] autorelease];
|
||||
return [[[self alloc] initWithWriter:writer
|
||||
formatter:fr
|
||||
filter:filter] autorelease];
|
||||
}
|
||||
@catch (id e) {
|
||||
// Ignored
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id)standardLoggerWithStderr {
|
||||
// Don't trust NSFileHandle not to throw
|
||||
@try {
|
||||
id me = [self standardLogger];
|
||||
[me setWriter:[NSFileHandle fileHandleWithStandardError]];
|
||||
return me;
|
||||
}
|
||||
@catch (id e) {
|
||||
// Ignored
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id)standardLoggerWithStdoutAndStderr {
|
||||
// We're going to take advantage of the GTMLogger to GTMLogWriter adaptor
|
||||
// and create a composite logger that an outer "standard" logger can use
|
||||
// as a writer. Our inner loggers should apply no formatting since the main
|
||||
// logger does that and we want the caller to be able to change formatters
|
||||
// or add writers without knowing the inner structure of our composite.
|
||||
|
||||
// Don't trust NSFileHandle not to throw
|
||||
@try {
|
||||
GTMLogBasicFormatter *formatter = [[[GTMLogBasicFormatter alloc] init]
|
||||
autorelease];
|
||||
GTMLogger *stdoutLogger =
|
||||
[self loggerWithWriter:[NSFileHandle fileHandleWithStandardOutput]
|
||||
formatter:formatter
|
||||
filter:[[[GTMLogMaximumLevelFilter alloc]
|
||||
initWithMaximumLevel:kGTMLoggerLevelInfo]
|
||||
autorelease]];
|
||||
GTMLogger *stderrLogger =
|
||||
[self loggerWithWriter:[NSFileHandle fileHandleWithStandardError]
|
||||
formatter:formatter
|
||||
filter:[[[GTMLogMininumLevelFilter alloc]
|
||||
initWithMinimumLevel:kGTMLoggerLevelError]
|
||||
autorelease]];
|
||||
GTMLogger *compositeWriter =
|
||||
[self loggerWithWriter:[NSArray arrayWithObjects:
|
||||
stdoutLogger, stderrLogger, nil]
|
||||
formatter:formatter
|
||||
filter:[[[GTMLogNoFilter alloc] init] autorelease]];
|
||||
GTMLogger *outerLogger = [self standardLogger];
|
||||
[outerLogger setWriter:compositeWriter];
|
||||
return outerLogger;
|
||||
}
|
||||
@catch (id e) {
|
||||
// Ignored
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id)standardLoggerWithPath:(NSString *)path {
|
||||
@try {
|
||||
NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644];
|
||||
if (fh == nil) return nil;
|
||||
id me = [self standardLogger];
|
||||
[me setWriter:fh];
|
||||
return me;
|
||||
}
|
||||
@catch (id e) {
|
||||
// Ignored
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id)loggerWithWriter:(id<GTMLogWriter>)writer
|
||||
formatter:(id<GTMLogFormatter>)formatter
|
||||
filter:(id<GTMLogFilter>)filter {
|
||||
return [[[self alloc] initWithWriter:writer
|
||||
formatter:formatter
|
||||
filter:filter] autorelease];
|
||||
}
|
||||
|
||||
+ (id)logger {
|
||||
return [[[self alloc] init] autorelease];
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
return [self initWithWriter:nil formatter:nil filter:nil];
|
||||
}
|
||||
|
||||
- (id)initWithWriter:(id<GTMLogWriter>)writer
|
||||
formatter:(id<GTMLogFormatter>)formatter
|
||||
filter:(id<GTMLogFilter>)filter {
|
||||
if ((self = [super init])) {
|
||||
[self setWriter:writer];
|
||||
[self setFormatter:formatter];
|
||||
[self setFilter:filter];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// Unlikely, but |writer_| may be an NSFileHandle, which can throw
|
||||
@try {
|
||||
[formatter_ release];
|
||||
[filter_ release];
|
||||
[writer_ release];
|
||||
}
|
||||
@catch (id e) {
|
||||
// Ignored
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id<GTMLogWriter>)writer {
|
||||
return [[writer_ retain] autorelease];
|
||||
}
|
||||
|
||||
- (void)setWriter:(id<GTMLogWriter>)writer {
|
||||
@synchronized(self) {
|
||||
[writer_ autorelease];
|
||||
writer_ = nil;
|
||||
if (writer == nil) {
|
||||
// Try to use stdout, but don't trust NSFileHandle
|
||||
@try {
|
||||
writer_ = [[NSFileHandle fileHandleWithStandardOutput] retain];
|
||||
}
|
||||
@catch (id e) {
|
||||
// Leave |writer_| nil
|
||||
}
|
||||
} else {
|
||||
writer_ = [writer retain];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id<GTMLogFormatter>)formatter {
|
||||
return [[formatter_ retain] autorelease];
|
||||
}
|
||||
|
||||
- (void)setFormatter:(id<GTMLogFormatter>)formatter {
|
||||
@synchronized(self) {
|
||||
[formatter_ autorelease];
|
||||
formatter_ = nil;
|
||||
if (formatter == nil) {
|
||||
@try {
|
||||
formatter_ = [[GTMLogBasicFormatter alloc] init];
|
||||
}
|
||||
@catch (id e) {
|
||||
// Leave |formatter_| nil
|
||||
}
|
||||
} else {
|
||||
formatter_ = [formatter retain];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id<GTMLogFilter>)filter {
|
||||
return [[filter_ retain] autorelease];
|
||||
}
|
||||
|
||||
- (void)setFilter:(id<GTMLogFilter>)filter {
|
||||
@synchronized(self) {
|
||||
[filter_ autorelease];
|
||||
filter_ = nil;
|
||||
if (filter == nil) {
|
||||
@try {
|
||||
filter_ = [[GTMLogNoFilter alloc] init];
|
||||
}
|
||||
@catch (id e) {
|
||||
// Leave |filter_| nil
|
||||
}
|
||||
} else {
|
||||
filter_ = [filter retain];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logDebug:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelDebug];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
- (void)logInfo:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelInfo];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
- (void)logError:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelError];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
- (void)logAssert:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelAssert];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@end // GTMLogger
|
||||
|
||||
|
||||
@implementation GTMLogger (GTMLoggerMacroHelpers)
|
||||
|
||||
- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelDebug];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelInfo];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelError];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
[self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelAssert];
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@end // GTMLoggerMacroHelpers
|
||||
|
||||
|
||||
@implementation GTMLogger (PrivateMethods)
|
||||
|
||||
- (void)logInternalFunc:(const char *)func
|
||||
format:(NSString *)fmt
|
||||
valist:(va_list)args
|
||||
level:(GTMLoggerLevel)level {
|
||||
// Primary point where logging happens, logging should never throw, catch
|
||||
// everything.
|
||||
@try {
|
||||
NSString *fname = func ? [NSString stringWithUTF8String:func] : nil;
|
||||
NSString *msg = [formatter_ stringForFunc:fname
|
||||
withFormat:fmt
|
||||
valist:args
|
||||
level:level];
|
||||
if (msg && [filter_ filterAllowsMessage:msg level:level])
|
||||
[writer_ logMessage:msg level:level];
|
||||
}
|
||||
@catch (id e) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
|
||||
@end // PrivateMethods
|
||||
|
||||
|
||||
@implementation NSFileHandle (GTMFileHandleLogWriter)
|
||||
|
||||
+ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode {
|
||||
int fd = -1;
|
||||
if (path) {
|
||||
int flags = O_WRONLY | O_APPEND | O_CREAT;
|
||||
fd = open([path fileSystemRepresentation], flags, mode);
|
||||
}
|
||||
if (fd == -1) return nil;
|
||||
return [[[self alloc] initWithFileDescriptor:fd
|
||||
closeOnDealloc:YES] autorelease];
|
||||
}
|
||||
|
||||
- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
|
||||
@synchronized(self) {
|
||||
// Closed pipes should not generate exceptions in our caller. Catch here
|
||||
// as well [GTMLogger logInternalFunc:...] so that an exception in this
|
||||
// writer does not prevent other writers from having a chance.
|
||||
@try {
|
||||
NSString *line = [NSString stringWithFormat:@"%@\n", msg];
|
||||
[self writeData:[line dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
@catch (id e) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end // GTMFileHandleLogWriter
|
||||
|
||||
|
||||
@implementation NSArray (GTMArrayCompositeLogWriter)
|
||||
|
||||
- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
|
||||
@synchronized(self) {
|
||||
id<GTMLogWriter> child = nil;
|
||||
GTM_FOREACH_OBJECT(child, self) {
|
||||
if ([child conformsToProtocol:@protocol(GTMLogWriter)])
|
||||
[child logMessage:msg level:level];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end // GTMArrayCompositeLogWriter
|
||||
|
||||
|
||||
@implementation GTMLogger (GTMLoggerLogWriter)
|
||||
|
||||
- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
|
||||
switch (level) {
|
||||
case kGTMLoggerLevelDebug:
|
||||
[self logDebug:@"%@", msg];
|
||||
break;
|
||||
case kGTMLoggerLevelInfo:
|
||||
[self logInfo:@"%@", msg];
|
||||
break;
|
||||
case kGTMLoggerLevelError:
|
||||
[self logError:@"%@", msg];
|
||||
break;
|
||||
case kGTMLoggerLevelAssert:
|
||||
[self logAssert:@"%@", msg];
|
||||
break;
|
||||
default:
|
||||
// Ignore the message.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@end // GTMLoggerLogWriter
|
||||
|
||||
|
||||
@implementation GTMLogBasicFormatter
|
||||
|
||||
- (NSString *)prettyNameForFunc:(NSString *)func {
|
||||
NSString *name = [func stringByTrimmingCharactersInSet:
|
||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
NSString *function = @"(unknown)";
|
||||
if ([name length]) {
|
||||
if (// Objective C __func__ and __PRETTY_FUNCTION__
|
||||
[name hasPrefix:@"-["] || [name hasPrefix:@"+["] ||
|
||||
// C++ __PRETTY_FUNCTION__ and other preadorned formats
|
||||
[name hasSuffix:@")"]) {
|
||||
function = name;
|
||||
} else {
|
||||
// Assume C99 __func__
|
||||
function = [NSString stringWithFormat:@"%@()", name];
|
||||
}
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
- (NSString *)stringForFunc:(NSString *)func
|
||||
withFormat:(NSString *)fmt
|
||||
valist:(va_list)args
|
||||
level:(GTMLoggerLevel)level {
|
||||
// Performance note: We may want to do a quick check here to see if |fmt|
|
||||
// contains a '%', and if not, simply return 'fmt'.
|
||||
if (!(fmt && args)) return nil;
|
||||
return [[[NSString alloc] initWithFormat:fmt arguments:args] autorelease];
|
||||
}
|
||||
|
||||
@end // GTMLogBasicFormatter
|
||||
|
||||
|
||||
@implementation GTMLogStandardFormatter
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init])) {
|
||||
dateFormatter_ = [[NSDateFormatter alloc] init];
|
||||
[dateFormatter_ setFormatterBehavior:NSDateFormatterBehavior10_4];
|
||||
[dateFormatter_ setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];
|
||||
pname_ = [[[NSProcessInfo processInfo] processName] copy];
|
||||
pid_ = [[NSProcessInfo processInfo] processIdentifier];
|
||||
if (!(dateFormatter_ && pname_)) {
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[dateFormatter_ release];
|
||||
[pname_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *)stringForFunc:(NSString *)func
|
||||
withFormat:(NSString *)fmt
|
||||
valist:(va_list)args
|
||||
level:(GTMLoggerLevel)level {
|
||||
NSString *tstamp = nil;
|
||||
@synchronized (dateFormatter_) {
|
||||
tstamp = [dateFormatter_ stringFromDate:[NSDate date]];
|
||||
}
|
||||
return [NSString stringWithFormat:@"%@ %@[%d/%p] [lvl=%d] %@ %@",
|
||||
tstamp, pname_, pid_, pthread_self(),
|
||||
level, [self prettyNameForFunc:func],
|
||||
// |super| has guard for nil |fmt| and |args|
|
||||
[super stringForFunc:func withFormat:fmt valist:args level:level]];
|
||||
}
|
||||
|
||||
@end // GTMLogStandardFormatter
|
||||
|
||||
|
||||
@implementation GTMLogLevelFilter
|
||||
|
||||
// Check the environment and the user preferences for the GTMVerboseLogging key
|
||||
// to see if verbose logging has been enabled. The environment variable will
|
||||
// override the defaults setting, so check the environment first.
|
||||
// COV_NF_START
|
||||
static BOOL IsVerboseLoggingEnabled(void) {
|
||||
static NSString *const kVerboseLoggingKey = @"GTMVerboseLogging";
|
||||
NSString *value = [[[NSProcessInfo processInfo] environment]
|
||||
objectForKey:kVerboseLoggingKey];
|
||||
if (value) {
|
||||
// Emulate [NSString boolValue] for pre-10.5
|
||||
value = [value stringByTrimmingCharactersInSet:
|
||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if ([[value uppercaseString] hasPrefix:@"Y"] ||
|
||||
[[value uppercaseString] hasPrefix:@"T"] ||
|
||||
[value intValue]) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:kVerboseLoggingKey];
|
||||
}
|
||||
// COV_NF_END
|
||||
|
||||
// In DEBUG builds, log everything. If we're not in a debug build we'll assume
|
||||
// that we're in a Release build.
|
||||
- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
|
||||
#if DEBUG
|
||||
return YES;
|
||||
#endif
|
||||
|
||||
BOOL allow = YES;
|
||||
|
||||
switch (level) {
|
||||
case kGTMLoggerLevelDebug:
|
||||
allow = NO;
|
||||
break;
|
||||
case kGTMLoggerLevelInfo:
|
||||
allow = IsVerboseLoggingEnabled();
|
||||
break;
|
||||
case kGTMLoggerLevelError:
|
||||
allow = YES;
|
||||
break;
|
||||
case kGTMLoggerLevelAssert:
|
||||
allow = YES;
|
||||
break;
|
||||
default:
|
||||
allow = YES;
|
||||
break;
|
||||
}
|
||||
|
||||
return allow;
|
||||
}
|
||||
|
||||
@end // GTMLogLevelFilter
|
||||
|
||||
|
||||
@implementation GTMLogNoFilter
|
||||
|
||||
- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
|
||||
return YES; // Allow everything through
|
||||
}
|
||||
|
||||
@end // GTMLogNoFilter
|
||||
|
||||
|
||||
@implementation GTMLogAllowedLevelFilter
|
||||
|
||||
// Private designated initializer
|
||||
- (id)initWithAllowedLevels:(NSIndexSet *)levels {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
allowedLevels_ = [levels retain];
|
||||
// Cap min/max level
|
||||
if (!allowedLevels_ ||
|
||||
// NSIndexSet is unsigned so only check the high bound, but need to
|
||||
// check both first and last index because NSIndexSet appears to allow
|
||||
// wraparound.
|
||||
([allowedLevels_ firstIndex] > kGTMLoggerLevelAssert) ||
|
||||
([allowedLevels_ lastIndex] > kGTMLoggerLevelAssert)) {
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
// Allow all levels in default init
|
||||
return [self initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
|
||||
NSMakeRange(kGTMLoggerLevelUnknown,
|
||||
(kGTMLoggerLevelAssert - kGTMLoggerLevelUnknown + 1))]];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[allowedLevels_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
|
||||
return [allowedLevels_ containsIndex:level];
|
||||
}
|
||||
|
||||
@end // GTMLogAllowedLevelFilter
|
||||
|
||||
|
||||
@implementation GTMLogMininumLevelFilter
|
||||
|
||||
- (id)initWithMinimumLevel:(GTMLoggerLevel)level {
|
||||
return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
|
||||
NSMakeRange(level,
|
||||
(kGTMLoggerLevelAssert - level + 1))]];
|
||||
}
|
||||
|
||||
@end // GTMLogMininumLevelFilter
|
||||
|
||||
|
||||
@implementation GTMLogMaximumLevelFilter
|
||||
|
||||
- (id)initWithMaximumLevel:(GTMLoggerLevel)level {
|
||||
return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
|
||||
NSMakeRange(kGTMLoggerLevelUnknown, level + 1)]];
|
||||
}
|
||||
|
||||
@end // GTMLogMaximumLevelFilter
|
88
External/google-plus-ios-sdk/OpenSource/GTMMethodCheck.h
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// GTMMethodCheck.h
|
||||
//
|
||||
// Copyright 2006-2008 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 <Foundation/Foundation.h>
|
||||
#import <stdio.h>
|
||||
#import <sysexits.h>
|
||||
|
||||
/// A macro for enforcing debug time checks to make sure all required methods are linked in
|
||||
//
|
||||
// When using categories, it can be very easy to forget to include the
|
||||
// implementation of a category.
|
||||
// Let's say you had a class foo that depended on method bar of class baz, and
|
||||
// method bar was implemented as a member of a category.
|
||||
// You could add the following code:
|
||||
// @implementation foo
|
||||
// GTM_METHOD_CHECK(baz, bar)
|
||||
// @end
|
||||
// and the code would check to make sure baz was implemented just before main
|
||||
// was called. This works for both dynamic libraries, and executables.
|
||||
//
|
||||
// Classes (or one of their superclasses) being checked must conform to the
|
||||
// NSObject protocol. We will check this, and spit out a warning if a class does
|
||||
// not conform to NSObject.
|
||||
//
|
||||
// This is not compiled into release builds.
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// If you get an error for GTMMethodCheckMethodChecker not being defined,
|
||||
// you need to link in GTMMethodCheck.m. We keep it hidden so that we can have
|
||||
// it living in several separate images without conflict.
|
||||
// Functions with the ((constructor)) attribute are called after all +loads
|
||||
// have been called. See "Initializing Objective-C Classes" in
|
||||
// http://developer.apple.com/documentation/DeveloperTools/Conceptual/DynamicLibraries/Articles/DynamicLibraryDesignGuidelines.html#//apple_ref/doc/uid/TP40002013-DontLinkElementID_20
|
||||
|
||||
__attribute__ ((constructor, visibility("hidden"))) void GTMMethodCheckMethodChecker(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
// This is the "magic".
|
||||
// A) we need a multi layer define here so that the stupid preprocessor
|
||||
// expands __LINE__ out the way we want it. We need LINE so that each of
|
||||
// out GTM_METHOD_CHECKs generates a unique class method for the class.
|
||||
#define GTM_METHOD_CHECK(class, method) GTM_METHOD_CHECK_INNER(class, method, __LINE__)
|
||||
#define GTM_METHOD_CHECK_INNER(class, method, line) GTM_METHOD_CHECK_INNER_INNER(class, method, line)
|
||||
|
||||
// B) Create up a class method called xxGMethodCheckMethod+class+line that the
|
||||
// GTMMethodCheckMethodChecker function can look for and call. We
|
||||
// look for GTMMethodCheckMethodChecker to enforce linkage of
|
||||
// GTMMethodCheck.m.
|
||||
#define GTM_METHOD_CHECK_INNER_INNER(class, method, line) \
|
||||
+ (void)xxGTMMethodCheckMethod ## class ## line { \
|
||||
void (*addr)() = GTMMethodCheckMethodChecker; \
|
||||
if (addr && ![class instancesRespondToSelector:@selector(method)] \
|
||||
&& ![class respondsToSelector:@selector(method)]) { \
|
||||
fprintf(stderr, "%s:%d: error: We need method '%s' to be linked in for class '%s'\n", \
|
||||
__FILE__, line, #method, #class); \
|
||||
exit(EX_SOFTWARE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else // !DEBUG
|
||||
|
||||
// Do nothing in release.
|
||||
#define GTM_METHOD_CHECK(class, method)
|
||||
|
||||
#endif // DEBUG
|
161
External/google-plus-ios-sdk/OpenSource/GTMMethodCheck.m
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
//
|
||||
// GTMMethodCheck.m
|
||||
//
|
||||
// Copyright 2006-2008 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.
|
||||
//
|
||||
|
||||
// Don't want any of this in release builds
|
||||
#ifdef DEBUG
|
||||
#import "GTMDefines.h"
|
||||
#import "GTMMethodCheck.h"
|
||||
#import "GTMObjC2Runtime.h"
|
||||
#import <dlfcn.h>
|
||||
|
||||
// Checks to see if the cls passed in (or one of it's superclasses) conforms
|
||||
// to NSObject protocol. Inheriting from NSObject is the easiest way to do this
|
||||
// but not all classes (i.e. NSProxy) inherit from NSObject. Also, some classes
|
||||
// inherit from Object instead of NSObject which is fine, and we'll count as
|
||||
// conforming to NSObject for our needs.
|
||||
static BOOL ConformsToNSObjectProtocol(Class cls) {
|
||||
// If we get nil, obviously doesn't conform.
|
||||
if (!cls) return NO;
|
||||
const char *className = class_getName(cls);
|
||||
if (!className) return NO;
|
||||
|
||||
// We're going to assume that all Apple classes will work
|
||||
// (and aren't being checked)
|
||||
// Note to apple: why doesn't obj-c have real namespaces instead of two
|
||||
// letter hacks? If you name your own classes starting with NS this won't
|
||||
// work for you.
|
||||
// Some classes (like _NSZombie) start with _NS.
|
||||
// On Leopard we have to look for CFObject as well.
|
||||
// On iPhone we check Object as well
|
||||
if ((strncmp(className, "NS", 2) == 0)
|
||||
|| (strncmp(className, "_NS", 3) == 0)
|
||||
|| (strncmp(className, "__NS", 4) == 0)
|
||||
|| (strcmp(className, "CFObject") == 0)
|
||||
|| (strcmp(className, "__IncompleteProtocol") == 0)
|
||||
#if GTM_IPHONE_SDK
|
||||
|| (strcmp(className, "Object") == 0)
|
||||
#endif
|
||||
) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// iPhone SDK does not define the |Object| class, so we instead test for the
|
||||
// |NSObject| class.
|
||||
#if GTM_IPHONE_SDK
|
||||
// Iterate through all the protocols |cls| supports looking for NSObject.
|
||||
if (cls == [NSObject class]
|
||||
|| class_conformsToProtocol(cls, @protocol(NSObject))) {
|
||||
return YES;
|
||||
}
|
||||
#else
|
||||
// Iterate through all the protocols |cls| supports looking for NSObject.
|
||||
if (cls == [Object class]
|
||||
|| class_conformsToProtocol(cls, @protocol(NSObject))) {
|
||||
return YES;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Recursively check the superclasses.
|
||||
return ConformsToNSObjectProtocol(class_getSuperclass(cls));
|
||||
}
|
||||
|
||||
void GTMMethodCheckMethodChecker(void) {
|
||||
// Run through all the classes looking for class methods that are
|
||||
// prefixed with xxGMMethodCheckMethod. If it finds one, it calls it.
|
||||
// See GTMMethodCheck.h to see what it does.
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
int numClasses = 0;
|
||||
int newNumClasses = objc_getClassList(NULL, 0);
|
||||
int i;
|
||||
Class *classes = NULL;
|
||||
while (numClasses < newNumClasses) {
|
||||
numClasses = newNumClasses;
|
||||
classes = realloc(classes, sizeof(Class) * numClasses);
|
||||
_GTMDevAssert(classes, @"Unable to allocate memory for classes");
|
||||
newNumClasses = objc_getClassList(classes, numClasses);
|
||||
}
|
||||
for (i = 0; i < numClasses && classes; ++i) {
|
||||
Class cls = classes[i];
|
||||
|
||||
// Since we are directly calling objc_msgSend, we need to conform to
|
||||
// @protocol(NSObject), or else we will tumble into a _objc_msgForward
|
||||
// recursive loop when we try and call a function by name.
|
||||
if (!ConformsToNSObjectProtocol(cls)) {
|
||||
// COV_NF_START
|
||||
_GTMDevLog(@"GTMMethodCheckMethodChecker: Class %s does not conform to "
|
||||
"@protocol(NSObject), so won't be checked",
|
||||
class_getName(cls));
|
||||
continue;
|
||||
// COV_NF_END
|
||||
}
|
||||
// Since we are looking for a class method (+xxGMMethodCheckMethod...)
|
||||
// we need to query the isa pointer to see what methods it support, but
|
||||
// send the method (if it's supported) to the class itself.
|
||||
unsigned int count;
|
||||
Class metaClass = objc_getMetaClass(class_getName(cls));
|
||||
Method *methods = class_copyMethodList(metaClass, &count);
|
||||
unsigned int j;
|
||||
for (j = 0; j < count; ++j) {
|
||||
SEL selector = method_getName(methods[j]);
|
||||
const char *name = sel_getName(selector);
|
||||
if (strstr(name, "xxGTMMethodCheckMethod") == name) {
|
||||
// Check to make sure that the method we are checking comes
|
||||
// from the same image that we are in. Since GTMMethodCheckMethodChecker
|
||||
// is not exported, we should always find the copy in our local
|
||||
// image. We compare the address of it's image with the address of
|
||||
// the image which implements the method we want to check. If
|
||||
// they match we continue. This does two things:
|
||||
// a) minimizes the amount of calls we make to the xxxGTMMethodCheck
|
||||
// methods. They should only be called once.
|
||||
// b) prevents initializers for various classes being called too early
|
||||
Dl_info methodCheckerInfo;
|
||||
if (!dladdr(GTMMethodCheckMethodChecker,
|
||||
&methodCheckerInfo)) {
|
||||
// COV_NF_START
|
||||
// Don't know how to force this case in a unittest.
|
||||
// Certainly hope we never see it.
|
||||
_GTMDevLog(@"GTMMethodCheckMethodChecker: Unable to get dladdr info "
|
||||
"for GTMMethodCheckMethodChecker while introspecting +[%s %s]]",
|
||||
class_getName(cls), name);
|
||||
continue;
|
||||
// COV_NF_END
|
||||
}
|
||||
Dl_info methodInfo;
|
||||
if (!dladdr(method_getImplementation(methods[j]),
|
||||
&methodInfo)) {
|
||||
// COV_NF_START
|
||||
// Don't know how to force this case in a unittest
|
||||
// Certainly hope we never see it.
|
||||
_GTMDevLog(@"GTMMethodCheckMethodChecker: Unable to get dladdr info "
|
||||
"for %s while introspecting +[%s %s]]", name,
|
||||
class_getName(cls), name);
|
||||
continue;
|
||||
// COV_NF_END
|
||||
}
|
||||
if (methodCheckerInfo.dli_fbase == methodInfo.dli_fbase) {
|
||||
objc_msgSend(cls, selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(methods);
|
||||
}
|
||||
free(classes);
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
36
External/google-plus-ios-sdk/OpenSource/GTMNSDictionary+URLArguments.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// GTMNSDictionary+URLArguments.h
|
||||
//
|
||||
// Copyright 2006-2008 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 <Foundation/Foundation.h>
|
||||
|
||||
/// Utility for building a URL or POST argument string.
|
||||
@interface NSDictionary (GTMNSDictionaryURLArgumentsAdditions)
|
||||
|
||||
/// Returns a dictionary of the decoded key-value pairs in a http arguments
|
||||
/// string of the form key1=value1&key2=value2&...&keyN=valueN.
|
||||
/// Keys and values will be unescaped automatically.
|
||||
/// Only the first value for a repeated key is returned.
|
||||
+ (NSDictionary *)gtm_dictionaryWithHttpArgumentsString:(NSString *)argString;
|
||||
|
||||
/// Gets a string representation of the dictionary in the form
|
||||
/// key1=value1&key2=value2&...&keyN=valueN, suitable for use as either
|
||||
/// URL arguments (after a '?') or POST body. Keys and values will be escaped
|
||||
/// automatically, so should be unescaped in the dictionary.
|
||||
- (NSString *)gtm_httpArgumentsString;
|
||||
|
||||
@end
|
71
External/google-plus-ios-sdk/OpenSource/GTMNSDictionary+URLArguments.m
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
//
|
||||
// GTMNSDictionary+URLArguments.m
|
||||
//
|
||||
// Copyright 2006-2008 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 "GTMNSDictionary+URLArguments.h"
|
||||
#import "GTMNSString+URLArguments.h"
|
||||
#import "GTMMethodCheck.h"
|
||||
#import "GTMDefines.h"
|
||||
|
||||
@implementation NSDictionary (GTMNSDictionaryURLArgumentsAdditions)
|
||||
|
||||
GTM_METHOD_CHECK(NSString, gtm_stringByEscapingForURLArgument);
|
||||
GTM_METHOD_CHECK(NSString, gtm_stringByUnescapingFromURLArgument);
|
||||
|
||||
+ (NSDictionary *)gtm_dictionaryWithHttpArgumentsString:(NSString *)argString {
|
||||
NSMutableDictionary* ret = [NSMutableDictionary dictionary];
|
||||
NSArray* components = [argString componentsSeparatedByString:@"&"];
|
||||
NSString* component;
|
||||
// Use reverse order so that the first occurrence of a key replaces
|
||||
// those subsequent.
|
||||
GTM_FOREACH_ENUMEREE(component, [components reverseObjectEnumerator]) {
|
||||
if ([component length] == 0)
|
||||
continue;
|
||||
NSRange pos = [component rangeOfString:@"="];
|
||||
NSString *key;
|
||||
NSString *val;
|
||||
if (pos.location == NSNotFound) {
|
||||
key = [component gtm_stringByUnescapingFromURLArgument];
|
||||
val = @"";
|
||||
} else {
|
||||
key = [[component substringToIndex:pos.location]
|
||||
gtm_stringByUnescapingFromURLArgument];
|
||||
val = [[component substringFromIndex:pos.location + pos.length]
|
||||
gtm_stringByUnescapingFromURLArgument];
|
||||
}
|
||||
// gtm_stringByUnescapingFromURLArgument returns nil on invalid UTF8
|
||||
// and NSMutableDictionary raises an exception when passed nil values.
|
||||
if (!key) key = @"";
|
||||
if (!val) val = @"";
|
||||
[ret setObject:val forKey:key];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (NSString *)gtm_httpArgumentsString {
|
||||
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:[self count]];
|
||||
NSString* key;
|
||||
GTM_FOREACH_KEY(key, self) {
|
||||
[arguments addObject:[NSString stringWithFormat:@"%@=%@",
|
||||
[key gtm_stringByEscapingForURLArgument],
|
||||
[[[self objectForKey:key] description] gtm_stringByEscapingForURLArgument]]];
|
||||
}
|
||||
|
||||
return [arguments componentsJoinedByString:@"&"];
|
||||
}
|
||||
|
||||
@end
|
41
External/google-plus-ios-sdk/OpenSource/GTMNSString+URLArguments.h
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// GTMNSString+URLArguments.h
|
||||
//
|
||||
// Copyright 2006-2008 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 <Foundation/Foundation.h>
|
||||
|
||||
/// Utilities for encoding and decoding URL arguments.
|
||||
@interface NSString (GTMNSStringURLArgumentsAdditions)
|
||||
|
||||
/// Returns a string that is escaped properly to be a URL argument.
|
||||
//
|
||||
/// This differs from stringByAddingPercentEscapesUsingEncoding: in that it
|
||||
/// will escape all the reserved characters (per RFC 3986
|
||||
/// <http://www.ietf.org/rfc/rfc3986.txt>) which
|
||||
/// stringByAddingPercentEscapesUsingEncoding would leave.
|
||||
///
|
||||
/// This will also escape '%', so this should not be used on a string that has
|
||||
/// already been escaped unless double-escaping is the desired result.
|
||||
- (NSString*)gtm_stringByEscapingForURLArgument;
|
||||
|
||||
/// Returns the unescaped version of a URL argument
|
||||
//
|
||||
/// This has the same behavior as stringByReplacingPercentEscapesUsingEncoding:,
|
||||
/// except that it will also convert '+' to space.
|
||||
- (NSString*)gtm_stringByUnescapingFromURLArgument;
|
||||
|
||||
@end
|
45
External/google-plus-ios-sdk/OpenSource/GTMNSString+URLArguments.m
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// GTMNSString+URLArguments.m
|
||||
//
|
||||
// Copyright 2006-2008 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 "GTMNSString+URLArguments.h"
|
||||
#import "GTMGarbageCollection.h"
|
||||
|
||||
@implementation NSString (GTMNSStringURLArgumentsAdditions)
|
||||
|
||||
- (NSString*)gtm_stringByEscapingForURLArgument {
|
||||
// Encode all the reserved characters, per RFC 3986
|
||||
// (<http://www.ietf.org/rfc/rfc3986.txt>)
|
||||
CFStringRef escaped =
|
||||
CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
|
||||
(CFStringRef)self,
|
||||
NULL,
|
||||
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
|
||||
kCFStringEncodingUTF8);
|
||||
return GTMCFAutorelease(escaped);
|
||||
}
|
||||
|
||||
- (NSString*)gtm_stringByUnescapingFromURLArgument {
|
||||
NSMutableString *resultString = [NSMutableString stringWithString:self];
|
||||
[resultString replaceOccurrencesOfString:@"+"
|
||||
withString:@" "
|
||||
options:NSLiteralSearch
|
||||
range:NSMakeRange(0, [resultString length])];
|
||||
return [resultString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
@end
|
325
External/google-plus-ios-sdk/OpenSource/GTMOAuth2Authentication.h
vendored
Normal file
@ -0,0 +1,325 @@
|
||||
/* 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 <Foundation/Foundation.h>
|
||||
|
||||
// GTMHTTPFetcher.h brings in GTLDefines/GDataDefines
|
||||
#import "GTMHTTPFetcher.h"
|
||||
|
||||
#undef _EXTERN
|
||||
#undef _INITIALIZE_AS
|
||||
#ifdef GTMOAUTH2AUTHENTICATION_DEFINE_GLOBALS
|
||||
#define _EXTERN
|
||||
#define _INITIALIZE_AS(x) =x
|
||||
#else
|
||||
#if defined(__cplusplus)
|
||||
#define _EXTERN extern "C"
|
||||
#else
|
||||
#define _EXTERN extern
|
||||
#endif
|
||||
#define _INITIALIZE_AS(x)
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
// Service provider name allows stored authorization to be associated with
|
||||
// the authorizing service
|
||||
_EXTERN NSString* const kGTMOAuth2ServiceProviderGoogle _INITIALIZE_AS(@"Google");
|
||||
|
||||
//
|
||||
// GTMOAuth2SignIn constants, included here for use by clients
|
||||
//
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorDomain _INITIALIZE_AS(@"com.google.GTMOAuth2");
|
||||
|
||||
// Error userInfo keys
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorMessageKey _INITIALIZE_AS(@"error");
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorRequestKey _INITIALIZE_AS(@"request");
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorJSONKey _INITIALIZE_AS(@"json");
|
||||
|
||||
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 _INITIALIZE_AS(@"kGTMOAuth2FetchStarted");
|
||||
_EXTERN NSString* const kGTMOAuth2FetchStopped _INITIALIZE_AS(@"kGTMOAuth2FetchStopped");
|
||||
|
||||
_EXTERN NSString* const kGTMOAuth2FetcherKey _INITIALIZE_AS(@"fetcher");
|
||||
_EXTERN NSString* const kGTMOAuth2FetchTypeKey _INITIALIZE_AS(@"FetchType");
|
||||
_EXTERN NSString* const kGTMOAuth2FetchTypeToken _INITIALIZE_AS(@"token");
|
||||
_EXTERN NSString* const kGTMOAuth2FetchTypeRefresh _INITIALIZE_AS(@"refresh");
|
||||
_EXTERN NSString* const kGTMOAuth2FetchTypeAssertion _INITIALIZE_AS(@"assertion");
|
||||
_EXTERN NSString* const kGTMOAuth2FetchTypeUserInfo _INITIALIZE_AS(@"userInfo");
|
||||
|
||||
// Token-issuance errors
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorKey _INITIALIZE_AS(@"error");
|
||||
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorInvalidRequest _INITIALIZE_AS(@"invalid_request");
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorInvalidClient _INITIALIZE_AS(@"invalid_client");
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorInvalidGrant _INITIALIZE_AS(@"invalid_grant");
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorUnauthorizedClient _INITIALIZE_AS(@"unauthorized_client");
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorUnsupportedGrantType _INITIALIZE_AS(@"unsupported_grant_type");
|
||||
_EXTERN NSString* const kGTMOAuth2ErrorInvalidScope _INITIALIZE_AS(@"invalid_scope");
|
||||
|
||||
// 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 _INITIALIZE_AS(@"kGTMOAuth2UserSignedIn");
|
||||
|
||||
// Notification for token changes
|
||||
_EXTERN NSString* const kGTMOAuth2AccessTokenRefreshed _INITIALIZE_AS(@"kGTMOAuth2AccessTokenRefreshed");
|
||||
_EXTERN NSString* const kGTMOAuth2RefreshTokenChanged _INITIALIZE_AS(@"kGTMOAuth2RefreshTokenChanged");
|
||||
|
||||
// Notification for WebView loading
|
||||
_EXTERN NSString* const kGTMOAuth2WebViewStartedLoading _INITIALIZE_AS(@"kGTMOAuth2WebViewStartedLoading");
|
||||
_EXTERN NSString* const kGTMOAuth2WebViewStoppedLoading _INITIALIZE_AS(@"kGTMOAuth2WebViewStoppedLoading");
|
||||
_EXTERN NSString* const kGTMOAuth2WebViewKey _INITIALIZE_AS(@"kGTMOAuth2WebViewKey");
|
||||
_EXTERN NSString* const kGTMOAuth2WebViewStopKindKey _INITIALIZE_AS(@"kGTMOAuth2WebViewStopKindKey");
|
||||
_EXTERN NSString* const kGTMOAuth2WebViewFinished _INITIALIZE_AS(@"finished");
|
||||
_EXTERN NSString* const kGTMOAuth2WebViewFailed _INITIALIZE_AS(@"failed");
|
||||
_EXTERN NSString* const kGTMOAuth2WebViewCancelled _INITIALIZE_AS(@"cancelled");
|
||||
|
||||
// Notification for network loss during html sign-in display
|
||||
_EXTERN NSString* const kGTMOAuth2NetworkLost _INITIALIZE_AS(@"kGTMOAuthNetworkLost");
|
||||
_EXTERN NSString* const kGTMOAuth2NetworkFound _INITIALIZE_AS(@"kGTMOAuthNetworkFound");
|
||||
|
||||
@interface GTMOAuth2Authentication : NSObject <GTMFetcherAuthorizationProtocol> {
|
||||
@private
|
||||
NSString *clientID_;
|
||||
NSString *clientSecret_;
|
||||
NSString *redirectURI_;
|
||||
NSMutableDictionary *parameters_;
|
||||
|
||||
// authorization parameters
|
||||
NSURL *tokenURL_;
|
||||
NSDate *expirationDate_;
|
||||
|
||||
NSDictionary *additionalTokenRequestParameters_;
|
||||
|
||||
// queue of requests for authorization waiting for a valid access token
|
||||
GTMHTTPFetcher *refreshFetcher_;
|
||||
NSMutableArray *authorizationQueue_;
|
||||
|
||||
id <GTMHTTPFetcherServiceProtocol> 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;
|
||||
|
||||
// Apps may optionally add parameters here to be provided to the token
|
||||
// endpoint on token requests and refreshes
|
||||
@property (retain) NSDictionary *additionalTokenRequestParameters;
|
||||
|
||||
// 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 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 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 <GTMHTTPFetcherServiceProtocol> 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;
|
||||
|
||||
// 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) GTMHTTPFetcher *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
|
||||
- (void)stopAuthorization;
|
||||
|
||||
// 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
|
||||
- (GTMHTTPFetcher *)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:(GTMHTTPFetcher *)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;
|
||||
|
||||
+ (NSString *)scopeWithStrings:(NSString *)firsStr, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
@end
|
||||
|
||||
#endif // GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES
|
1167
External/google-plus-ios-sdk/OpenSource/GTMOAuth2Authentication.m
vendored
Normal file
174
External/google-plus-ios-sdk/OpenSource/GTMOAuth2SignIn.h
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
/* 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 <Foundation/Foundation.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
// GTMHTTPFetcher brings in GTLDefines/GDataDefines
|
||||
#import "GTMHTTPFetcher.h"
|
||||
|
||||
#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_;
|
||||
|
||||
GTMHTTPFetcher *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;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// Revocation of an authorized token from Google
|
||||
#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT
|
||||
+ (void)revokeTokenForGoogleAuthentication:(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
|
814
External/google-plus-ios-sdk/OpenSource/GTMOAuth2SignIn.m
vendored
Normal file
@ -0,0 +1,814 @@
|
||||
/* 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
|
||||
|
||||
#define GTMOAUTH2SIGNIN_DEFINE_GLOBALS 1
|
||||
#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 GTMOAuth2Authentication (InternalMethods)
|
||||
- (NSDictionary *)dictionaryWithJSONData:(NSData *)data;
|
||||
@end
|
||||
|
||||
@interface GTMOAuth2SignIn ()
|
||||
@property (assign) BOOL hasHandledCallback;
|
||||
@property (retain) GTMHTTPFetcher *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)fetchGoogleUserInfo;
|
||||
#endif
|
||||
- (void)finishSignInWithError:(NSError *)error;
|
||||
|
||||
- (void)handleCallbackReached;
|
||||
|
||||
- (void)auth:(GTMOAuth2Authentication *)auth
|
||||
finishedWithFetcher:(GTMHTTPFetcher *)fetcher
|
||||
error:(NSError *)error;
|
||||
|
||||
#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT
|
||||
- (void)infoFetcher:(GTMHTTPFetcher *)fetcher
|
||||
finishedWithData:(NSData *)data
|
||||
error:(NSError *)error;
|
||||
#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 {
|
||||
NSString *urlStr = @"https://www.googleapis.com/oauth2/v1/userinfo";
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth
|
||||
authorizationURL:(NSURL *)authorizationURL
|
||||
delegate:(id)delegate
|
||||
webRequestSelector:(SEL)webRequestSelector
|
||||
finishedSelector:(SEL)finishedSelector {
|
||||
// check the selectors on debug builds
|
||||
GTMAssertSelectorNilOrImplementedWithArgs(delegate, webRequestSelector,
|
||||
@encode(GTMOAuth2SignIn *), @encode(NSURLRequest *), 0);
|
||||
GTMAssertSelectorNilOrImplementedWithArgs(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
|
||||
GTMOAuth2Authentication *auth = self.authentication;
|
||||
if (self.shouldFetchGoogleUserEmail) {
|
||||
NSString *const emailScope = @"https://www.googleapis.com/auth/userinfo.email";
|
||||
NSString *scope = auth.scope;
|
||||
if ([scope rangeOfString:emailScope].location == NSNotFound) {
|
||||
scope = [GTMOAuth2Authentication scopeWithStrings:scope, emailScope, nil];
|
||||
auth.scope = scope;
|
||||
}
|
||||
}
|
||||
|
||||
if (self.shouldFetchGoogleUserProfile) {
|
||||
NSString *const profileScope = @"https://www.googleapis.com/auth/userinfo.profile";
|
||||
NSString *scope = auth.scope;
|
||||
if ([scope rangeOfString:profileScope].location == NSNotFound) {
|
||||
scope = [GTMOAuth2Authentication scopeWithStrings:scope, profileScope, nil];
|
||||
auth.scope = scope;
|
||||
}
|
||||
}
|
||||
#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 NO;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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
|
||||
// handleCallbackReached 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 handleCallbackReached];
|
||||
}
|
||||
// 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
|
||||
// handleCallbackReached 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 handleCallbackReached];
|
||||
}
|
||||
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)handleCallbackReached {
|
||||
// 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;
|
||||
|
||||
[self closeTheWindow];
|
||||
|
||||
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:);
|
||||
GTMHTTPFetcher *fetcher = [auth beginTokenFetchWithDelegate:self
|
||||
didFinishSelector:sel];
|
||||
if (fetcher == nil) {
|
||||
error = [NSError errorWithDomain:kGTMHTTPFetcherStatusDomain
|
||||
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:(GTMHTTPFetcher *)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
|
||||
- (void)fetchGoogleUserInfo {
|
||||
// fetch the user's email address
|
||||
NSURL *infoURL = [[self class] googleUserInfoURL];
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:infoURL];
|
||||
|
||||
GTMOAuth2Authentication *auth = self.authentication;
|
||||
|
||||
NSString *userAgent = [auth userAgent];
|
||||
[request setValue:userAgent forHTTPHeaderField:@"User-Agent"];
|
||||
|
||||
[request setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"];
|
||||
|
||||
// we can do a synchronous authorization since this method is called
|
||||
// only immediately after a fresh access token has been obtained
|
||||
[auth authorizeRequest:request];
|
||||
|
||||
GTMHTTPFetcher *fetcher;
|
||||
id <GTMHTTPFetcherServiceProtocol> fetcherService = auth.fetcherService;
|
||||
if (fetcherService) {
|
||||
fetcher = [fetcherService fetcherWithRequest:request];
|
||||
} else {
|
||||
fetcher = [GTMHTTPFetcher fetcherWithRequest:request];
|
||||
}
|
||||
fetcher.retryEnabled = YES;
|
||||
fetcher.maxRetryInterval = 15.0;
|
||||
fetcher.comment = @"user info";
|
||||
|
||||
[fetcher beginFetchWithDelegate:self
|
||||
didFinishSelector:@selector(infoFetcher:finishedWithData:error:)];
|
||||
|
||||
self.pendingFetcher = fetcher;
|
||||
|
||||
[auth notifyFetchIsRunning:YES
|
||||
fetcher:fetcher
|
||||
type:kGTMOAuth2FetchTypeUserInfo];
|
||||
}
|
||||
|
||||
- (void)infoFetcher:(GTMHTTPFetcher *)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
|
||||
if (data) {
|
||||
NSDictionary *profileDict = [auth dictionaryWithJSONData:data];
|
||||
if (profileDict) {
|
||||
self.userProfile = profileDict;
|
||||
|
||||
// Save the email into the auth object
|
||||
NSString *email = [profileDict objectForKey:@"email"];
|
||||
[auth setUserEmail:email];
|
||||
|
||||
NSNumber *verified = [profileDict objectForKey:@"verified_email"];
|
||||
[auth setUserEmailIsVerified:[verified stringValue]];
|
||||
}
|
||||
}
|
||||
}
|
||||
[self finishSignInWithError:error];
|
||||
}
|
||||
|
||||
#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.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];
|
||||
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
|
||||
GTMHTTPFetcher *fetcher;
|
||||
id <GTMHTTPFetcherServiceProtocol> fetcherService = auth.fetcherService;
|
||||
if (fetcherService) {
|
||||
fetcher = [fetcherService fetcherWithRequest:request];
|
||||
} else {
|
||||
fetcher = [GTMHTTPFetcher fetcherWithRequest:request];
|
||||
}
|
||||
fetcher.comment = @"revoke token";
|
||||
|
||||
// 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];
|
||||
}
|
||||
#endif // !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT
|
||||
|
||||
@end
|
||||
|
||||
#endif // #if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES
|
344
External/google-plus-ios-sdk/OpenSource/GTMOAuth2ViewControllerTouch.h
vendored
Normal file
@ -0,0 +1,344 @@
|
||||
/* 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 <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "GTMOAuth2Authentication.h"
|
||||
|
||||
#undef _EXTERN
|
||||
#undef _INITIALIZE_AS
|
||||
#ifdef GTMOAUTH2VIEWCONTROLLERTOUCH_DEFINE_GLOBALS
|
||||
#define _EXTERN
|
||||
#define _INITIALIZE_AS(x) =x
|
||||
#else
|
||||
#define _EXTERN extern
|
||||
#define _INITIALIZE_AS(x)
|
||||
#endif
|
||||
|
||||
_EXTERN NSString* const kGTMOAuth2KeychainErrorDomain _INITIALIZE_AS(@"com.google.GTMOAuthKeychain");
|
||||
|
||||
|
||||
@class GTMOAuth2SignIn;
|
||||
@class GTMOAuth2ViewControllerTouch;
|
||||
|
||||
@interface GTMOAuth2ViewControllerTouch : UIViewController<UINavigationControllerDelegate, UIWebViewDelegate> {
|
||||
@private
|
||||
UIButton *backButton_;
|
||||
UIButton *forwardButton_;
|
||||
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
|
||||
void (^completionBlock_)(GTMOAuth2ViewControllerTouch *, GTMOAuth2Authentication *, NSError *);
|
||||
#endif
|
||||
|
||||
NSString *keychainItemName_;
|
||||
CFTypeRef keychainItemAccessibility_;
|
||||
|
||||
// if non-nil, the html string to be displayed immediately upon opening
|
||||
// of the web view
|
||||
NSString *initialHTMLString_;
|
||||
|
||||
// if non-nil, the URL for which cookies will be deleted when the
|
||||
// browser view is dismissed
|
||||
NSURL *browserCookiesURL_;
|
||||
|
||||
id userData_;
|
||||
NSMutableDictionary *properties_;
|
||||
|
||||
// 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_;
|
||||
|
||||
// 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_;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// 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 UIView *navButtonsView;
|
||||
@property (nonatomic, retain) IBOutlet UIBarButtonItem *rightBarButtonItem;
|
||||
@property (nonatomic, retain) IBOutlet UIWebView *webView;
|
||||
|
||||
// the default timeout for an unreachable network during display of the
|
||||
// sign-in page is 10 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
|
||||
//
|
||||
// For Google sign-ins, this is set by default to https://google.com/accounts
|
||||
// but it may be explicitly set to nil to disable clearing of browser cookies
|
||||
@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:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))handler;
|
||||
|
||||
- (id)initWithScope:(NSString *)scope
|
||||
clientID:(NSString *)clientID
|
||||
clientSecret:(NSString *)clientSecret
|
||||
keychainItemName:(NSString *)keychainItemName
|
||||
completionHandler:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))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:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))handler;
|
||||
|
||||
- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth
|
||||
authorizationURL:(NSURL *)authorizationURL
|
||||
keychainItemName:(NSString *)keychainItemName
|
||||
completionHandler:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))handler;
|
||||
#endif
|
||||
|
||||
// Override default in UIViewController. If we have a navigationController, ask
|
||||
// it. else default result (i.e., Portrait mode only).
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
|
||||
|
||||
// subclasses may override authNibName to specify a custom name
|
||||
+ (NSString *)authNibName;
|
||||
|
||||
// subclasses may override authNibBundle to specify a custom bundle
|
||||
+ (NSBundle *)authNibBundle;
|
||||
|
||||
// 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
|
||||
#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT
|
||||
+ (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;
|
||||
|
||||
// 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
|
||||
+ (BOOL)saveParamsToKeychainForName:(NSString *)keychainItemName
|
||||
accessibility:(CFTypeRef)accessibility
|
||||
authentication:(GTMOAuth2Authentication *)auth;
|
||||
|
||||
// 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
|
970
External/google-plus-ios-sdk/OpenSource/GTMOAuth2ViewControllerTouch.m
vendored
Normal file
@ -0,0 +1,970 @@
|
||||
/* 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 <Foundation/Foundation.h>
|
||||
#import <Security/Security.h>
|
||||
|
||||
#if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#define GTMOAUTH2VIEWCONTROLLERTOUCH_DEFINE_GLOBALS 1
|
||||
#import "GTMOAuth2ViewControllerTouch.h"
|
||||
|
||||
#import "GTMOAuth2SignIn.h"
|
||||
#import "GTMOAuth2Authentication.h"
|
||||
|
||||
static NSString * const kGTMOAuth2AccountName = @"OAuth";
|
||||
static GTMOAuth2Keychain* sDefaultKeychain = nil;
|
||||
|
||||
@interface GTMOAuth2ViewControllerTouch()
|
||||
|
||||
@property (nonatomic, copy) NSURLRequest *request;
|
||||
|
||||
- (void)signIn:(GTMOAuth2SignIn *)signIn displayRequest:(NSURLRequest *)request;
|
||||
- (void)signIn:(GTMOAuth2SignIn *)signIn
|
||||
finishedWithAuth:(GTMOAuth2Authentication *)auth
|
||||
error:(NSError *)error;
|
||||
- (BOOL)isNavigationBarTranslucent;
|
||||
- (void)moveWebViewFromUnderNavigationBar;
|
||||
- (void)popView;
|
||||
- (void)clearBrowserCookies;
|
||||
@end
|
||||
|
||||
@implementation GTMOAuth2ViewControllerTouch
|
||||
|
||||
// IBOutlets
|
||||
@synthesize request = request_,
|
||||
backButton = backButton_,
|
||||
forwardButton = forwardButton_,
|
||||
navButtonsView = navButtonsView_,
|
||||
rightBarButtonItem = rightBarButtonItem_,
|
||||
webView = webView_;
|
||||
|
||||
@synthesize keychainItemName = keychainItemName_,
|
||||
keychainItemAccessibility = keychainItemAccessibility_,
|
||||
initialHTMLString = initialHTMLString_,
|
||||
browserCookiesURL = browserCookiesURL_,
|
||||
signIn = signIn_,
|
||||
userData = userData_,
|
||||
properties = properties_;
|
||||
|
||||
#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:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))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:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))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:)];
|
||||
|
||||
// if the user is signing in to a Google service, we'll delete the
|
||||
// Google authentication browser cookies upon completion
|
||||
//
|
||||
// for other service domains, or to disable clearing of the cookies,
|
||||
// set the browserCookiesURL property explicitly
|
||||
NSString *authorizationHost = [signIn_.authorizationURL host];
|
||||
if ([authorizationHost hasSuffix:@".google.com"]) {
|
||||
NSString *urlStr = [NSString stringWithFormat:@"https://%@/",
|
||||
authorizationHost];
|
||||
NSURL *cookiesURL = [NSURL URLWithString:urlStr];
|
||||
[self setBrowserCookiesURL:cookiesURL];
|
||||
}
|
||||
|
||||
[self setKeychainItemName:keychainItemName];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
+ (id)controllerWithAuthentication:(GTMOAuth2Authentication *)auth
|
||||
authorizationURL:(NSURL *)authorizationURL
|
||||
keychainItemName:(NSString *)keychainItemName
|
||||
completionHandler:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))handler {
|
||||
return [[[self alloc] initWithAuthentication:auth
|
||||
authorizationURL:authorizationURL
|
||||
keychainItemName:keychainItemName
|
||||
completionHandler:handler] autorelease];
|
||||
}
|
||||
|
||||
- (id)initWithAuthentication:(GTMOAuth2Authentication *)auth
|
||||
authorizationURL:(NSURL *)authorizationURL
|
||||
keychainItemName:(NSString *)keychainItemName
|
||||
completionHandler:(void (^)(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error))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];
|
||||
[navButtonsView_ release];
|
||||
[rightBarButtonItem_ release];
|
||||
[webView_ release];
|
||||
[signIn_ release];
|
||||
[request_ release];
|
||||
[delegate_ release];
|
||||
#if NS_BLOCKS_AVAILABLE
|
||||
[completionBlock_ 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 {
|
||||
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];
|
||||
return auth;
|
||||
}
|
||||
#endif
|
||||
|
||||
+ (BOOL)authorizeFromKeychainForName:(NSString *)keychainItemName
|
||||
authentication:(GTMOAuth2Authentication *)newAuth {
|
||||
newAuth.accessToken = nil;
|
||||
|
||||
BOOL didGetTokens = NO;
|
||||
GTMOAuth2Keychain *keychain = [GTMOAuth2Keychain defaultKeychain];
|
||||
NSString *password = [keychain passwordForService:keychainItemName
|
||||
account:kGTMOAuth2AccountName
|
||||
error:nil];
|
||||
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];
|
||||
}
|
||||
|
||||
+ (BOOL)saveParamsToKeychainForName:(NSString *)keychainItemName
|
||||
accessibility:(CFTypeRef)accessibility
|
||||
authentication:(GTMOAuth2Authentication *)auth {
|
||||
[self removeAuthFromKeychainForName:keychainItemName];
|
||||
// don't save unless we have a token that can really authorize requests
|
||||
if (![auth canAuthorize]) 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:nil];
|
||||
}
|
||||
|
||||
- (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 {
|
||||
// the app may prefer some html other than blank white to be displayed
|
||||
// before the sign-in web page loads
|
||||
NSString *html = self.initialHTMLString;
|
||||
if ([html length] > 0) {
|
||||
[[self webView] loadHTMLString:html baseURL:nil];
|
||||
}
|
||||
|
||||
rightBarButtonItem_.customView = navButtonsView_;
|
||||
self.navigationItem.rightBarButtonItem = rightBarButtonItem_;
|
||||
}
|
||||
|
||||
- (void)popView {
|
||||
if (self.navigationController.topViewController == self) {
|
||||
if (!self.view.isHidden) {
|
||||
// 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;
|
||||
|
||||
[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)clearBrowserCookies {
|
||||
// if browserCookiesURL is non-nil, then get cookies for that URL
|
||||
// and delete them from the common application cookie storage
|
||||
NSURL *cookiesURL = [self browserCookiesURL];
|
||||
if (cookiesURL) {
|
||||
NSHTTPCookieStorage *cookieStorage;
|
||||
|
||||
cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
|
||||
NSArray *cookies = [cookieStorage cookiesForURL:cookiesURL];
|
||||
|
||||
for (NSHTTPCookie *cookie in cookies) {
|
||||
[cookieStorage deleteCookie:cookie];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
#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 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;
|
||||
BOOL shouldWaitForHTML = ([self.initialHTMLString length] > 0);
|
||||
if (shouldWaitForHTML) {
|
||||
[self.webView performSelector:@selector(loadRequest:)
|
||||
withObject:request
|
||||
afterDelay:0.05];
|
||||
} else {
|
||||
[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 *html = @"<html><body><div align=center><font size='7'>"
|
||||
@"⌚ ?<br><i>System Clock Incorrect</i><br>%@"
|
||||
@"</font></div></body></html>";
|
||||
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];
|
||||
} 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 {
|
||||
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]];
|
||||
}
|
||||
}
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
didViewAppear_ = YES;
|
||||
[super viewDidAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
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];
|
||||
}
|
||||
|
||||
// prevent the next sign-in from showing in the WebView that the user is
|
||||
// already signed in
|
||||
[self clearBrowserCookies];
|
||||
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
- (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
|
||||
// Verify that Javascript is enabled
|
||||
NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"1+1"];
|
||||
NSAssert([result integerValue] == 2, @"GTMOAuth2: Javascript is required");
|
||||
#endif
|
||||
}
|
||||
|
||||
[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]];
|
||||
}
|
||||
}
|
||||
|
||||
- (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;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark Common Code
|
||||
|
||||
@implementation GTMOAuth2Keychain
|
||||
|
||||
+ (GTMOAuth2Keychain *)defaultKeychain {
|
||||
if (sDefaultKeychain == nil) {
|
||||
sDefaultKeychain = [[self alloc] init];
|
||||
}
|
||||
return sDefaultKeychain;
|
||||
}
|
||||
|
||||
|
||||
// For unit tests: allow setting a mock object
|
||||
+ (void)setDefaultKeychain:(GTMOAuth2Keychain *)keychain {
|
||||
if (sDefaultKeychain != keychain) {
|
||||
[sDefaultKeychain release];
|
||||
sDefaultKeychain = [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
|
456
External/google-plus-ios-sdk/OpenSource/GTMOAuth2ViewTouch.xib
vendored
Normal file
@ -0,0 +1,456 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">768</int>
|
||||
<string key="IBDocument.SystemVersion">10J869</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">851</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.35</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">141</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<integer value="4"/>
|
||||
<integer value="15"/>
|
||||
</object>
|
||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys" id="0">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBProxyObject" id="372490531">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="975951072">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUINavigationItem" id="1047805472">
|
||||
<string key="IBUITitle">OAuth</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="961671599">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIStyle">1</int>
|
||||
</object>
|
||||
<object class="IBUIView" id="808907889">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<object class="NSMutableArray" key="NSSubviews">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIButton" id="453250804">
|
||||
<reference key="NSNextResponder" ref="808907889"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrameSize">{30, 30}</string>
|
||||
<reference key="NSSuperview" ref="808907889"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<object class="NSFont" key="IBUIFont" id="530402572">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">24</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
<string key="IBUITitleShadowOffset">{0, -2}</string>
|
||||
<string key="IBUINormalTitle">◀</string>
|
||||
<object class="NSColor" key="IBUIHighlightedTitleColor" id="193465259">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUIDisabledTitleColor">
|
||||
<int key="NSColorSpace">2</int>
|
||||
<bytes key="NSRGB">MC41OTYwNzg0NiAwLjY4NjI3NDUzIDAuOTUyOTQxMjQgMC42MDAwMDAwMgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleColor" ref="193465259"/>
|
||||
<object class="NSColor" key="IBUINormalTitleShadowColor" id="999379443">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MC41AA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUIButton" id="981703116">
|
||||
<reference key="NSNextResponder" ref="808907889"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{30, 0}, {30, 30}}</string>
|
||||
<reference key="NSSuperview" ref="808907889"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<reference key="IBUIFont" ref="530402572"/>
|
||||
<string key="IBUITitleShadowOffset">{0, -2}</string>
|
||||
<string key="IBUINormalTitle">▶</string>
|
||||
<reference key="IBUIHighlightedTitleColor" ref="193465259"/>
|
||||
<object class="NSColor" key="IBUIDisabledTitleColor">
|
||||
<int key="NSColorSpace">2</int>
|
||||
<bytes key="NSRGB">MC41ODQzMTM3NSAwLjY3NDUwOTgyIDAuOTUyOTQxMjQgMC42MDAwMDAwMgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleColor" ref="193465259"/>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="999379443"/>
|
||||
</object>
|
||||
</object>
|
||||
<string key="NSFrameSize">{60, 30}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MSAwAA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
|
||||
<int key="interfaceOrientation">3</int>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUIView" id="426018584">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<object class="NSMutableArray" key="NSSubviews">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIWebView" id="663477729">
|
||||
<reference key="NSNextResponder" ref="426018584"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<string key="NSFrameSize">{320, 460}</string>
|
||||
<reference key="NSSuperview" ref="426018584"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MSAxIDEAA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<bool key="IBUIMultipleTouchEnabled">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIDataDetectorTypes">1</int>
|
||||
<bool key="IBUIDetectsPhoneNumbers">YES</bool>
|
||||
</object>
|
||||
</object>
|
||||
<string key="NSFrameSize">{320, 460}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
<object class="NSColorSpace" key="NSCustomColorSpace">
|
||||
<int key="NSID">2</int>
|
||||
</object>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<object class="NSMutableArray" key="connectionRecords">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="663477729"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">9</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">rightBarButtonItem</string>
|
||||
<reference key="source" ref="1047805472"/>
|
||||
<reference key="destination" ref="961671599"/>
|
||||
</object>
|
||||
<int key="connectionID">14</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">goBack</string>
|
||||
<reference key="source" ref="453250804"/>
|
||||
<reference key="destination" ref="663477729"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">18</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">goForward</string>
|
||||
<reference key="source" ref="981703116"/>
|
||||
<reference key="destination" ref="663477729"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">19</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">rightBarButtonItem</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="961671599"/>
|
||||
</object>
|
||||
<int key="connectionID">20</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">navButtonsView</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="808907889"/>
|
||||
</object>
|
||||
<int key="connectionID">22</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">backButton</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="453250804"/>
|
||||
</object>
|
||||
<int key="connectionID">25</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">forwardButton</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="981703116"/>
|
||||
</object>
|
||||
<int key="connectionID">26</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">view</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="426018584"/>
|
||||
</object>
|
||||
<int key="connectionID">28</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">webView</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="663477729"/>
|
||||
</object>
|
||||
<int key="connectionID">29</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<object class="NSArray" key="orderedObjects">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<reference key="object" ref="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="372490531"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="975951072"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">6</int>
|
||||
<reference key="object" ref="1047805472"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">10</int>
|
||||
<reference key="object" ref="961671599"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">15</int>
|
||||
<reference key="object" ref="808907889"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="453250804"/>
|
||||
<reference ref="981703116"/>
|
||||
</object>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">16</int>
|
||||
<reference key="object" ref="453250804"/>
|
||||
<reference key="parent" ref="808907889"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">17</int>
|
||||
<reference key="object" ref="981703116"/>
|
||||
<reference key="parent" ref="808907889"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">27</int>
|
||||
<reference key="object" ref="426018584"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="663477729"/>
|
||||
</object>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">4</int>
|
||||
<reference key="object" ref="663477729"/>
|
||||
<reference key="parent" ref="426018584"/>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="flattenedProperties">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>-1.CustomClassName</string>
|
||||
<string>-2.CustomClassName</string>
|
||||
<string>10.IBPluginDependency</string>
|
||||
<string>15.IBEditorWindowLastContentRect</string>
|
||||
<string>15.IBPluginDependency</string>
|
||||
<string>16.IBPluginDependency</string>
|
||||
<string>17.IBPluginDependency</string>
|
||||
<string>27.IBEditorWindowLastContentRect</string>
|
||||
<string>27.IBPluginDependency</string>
|
||||
<string>4.IBPluginDependency</string>
|
||||
<string>6.IBPluginDependency</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>GTMOAuth2ViewControllerTouch</string>
|
||||
<string>UIResponder</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>{{34, 1031}, {60, 30}}</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>{{214, 696}, {320, 460}}</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="unlocalizedProperties">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
</object>
|
||||
<nil key="activeLocalization"/>
|
||||
<object class="NSMutableDictionary" key="localizations">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
</object>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">29</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">GTMOAuth2ViewControllerTouch</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<object class="NSMutableDictionary" key="outlets">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>backButton</string>
|
||||
<string>delegate_</string>
|
||||
<string>forwardButton</string>
|
||||
<string>navButtonsView</string>
|
||||
<string>rightBarButtonItem</string>
|
||||
<string>userData_</string>
|
||||
<string>webView</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>UIButton</string>
|
||||
<string>id</string>
|
||||
<string>UIButton</string>
|
||||
<string>UIView</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>id</string>
|
||||
<string>UIWebView</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>backButton</string>
|
||||
<string>delegate_</string>
|
||||
<string>forwardButton</string>
|
||||
<string>navButtonsView</string>
|
||||
<string>rightBarButtonItem</string>
|
||||
<string>userData_</string>
|
||||
<string>webView</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">backButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">delegate_</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">forwardButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">navButtonsView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">rightBarButtonItem</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">userData_</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">webView</string>
|
||||
<string key="candidateClassName">UIWebView</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Touch/GTMOAuth2ViewControllerTouch.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
|
||||
<integer value="768" key="NS.object.0"/>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
|
||||
<integer value="800" key="NS.object.0"/>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
|
||||
<integer value="3000" key="NS.object.0"/>
|
||||
</object>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<string key="IBDocument.LastKnownRelativeProjectPath">../GTMOAuth2.xcodeproj</string>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<string key="IBCocoaTouchPluginVersion">141</string>
|
||||
</data>
|
||||
</archive>
|
113
External/google-plus-ios-sdk/OpenSource/GTMObjC2Runtime.h
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// GTMObjC2Runtime.h
|
||||
//
|
||||
// Copyright 2007-2008 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 <objc/objc-api.h>
|
||||
#import <objc/objc-auto.h>
|
||||
#import "GTMDefines.h"
|
||||
|
||||
// These functions exist for code that we want to compile on both the < 10.5
|
||||
// sdks and on the >= 10.5 sdks without warnings. It basically reimplements
|
||||
// certain parts of the objc2 runtime in terms of the objc1 runtime. It is not
|
||||
// a complete implementation as I've only implemented the routines I know we
|
||||
// use. Feel free to add more as necessary.
|
||||
// These functions are not documented because they conform to the documentation
|
||||
// for the ObjC2 Runtime.
|
||||
|
||||
#if OBJC_API_VERSION >= 2 // Only have optional and req'd keywords in ObjC2.
|
||||
#define AT_OPTIONAL @optional
|
||||
#define AT_REQUIRED @required
|
||||
#else
|
||||
#define AT_OPTIONAL
|
||||
#define AT_REQUIRED
|
||||
#endif
|
||||
|
||||
// The file objc-runtime.h was moved to runtime.h and in Leopard, objc-runtime.h
|
||||
// was just a wrapper around runtime.h. For the iPhone SDK, this objc-runtime.h
|
||||
// is removed in the iPhoneOS2.0 SDK.
|
||||
//
|
||||
// The |Object| class was removed in the iPhone2.0 SDK too.
|
||||
#if GTM_IPHONE_SDK
|
||||
#import <objc/message.h>
|
||||
#import <objc/runtime.h>
|
||||
#else
|
||||
#import <objc/objc-runtime.h>
|
||||
#import <objc/Object.h>
|
||||
#endif
|
||||
|
||||
#import <libkern/OSAtomic.h>
|
||||
|
||||
#if GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
|
||||
#import "objc/Protocol.h"
|
||||
|
||||
OBJC_EXPORT Class object_getClass(id obj);
|
||||
OBJC_EXPORT const char *class_getName(Class cls);
|
||||
OBJC_EXPORT BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
|
||||
OBJC_EXPORT BOOL class_respondsToSelector(Class cls, SEL sel);
|
||||
OBJC_EXPORT Class class_getSuperclass(Class cls);
|
||||
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount);
|
||||
OBJC_EXPORT SEL method_getName(Method m);
|
||||
OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2);
|
||||
OBJC_EXPORT IMP method_getImplementation(Method method);
|
||||
OBJC_EXPORT IMP method_setImplementation(Method method, IMP imp);
|
||||
OBJC_EXPORT struct objc_method_description protocol_getMethodDescription(Protocol *p,
|
||||
SEL aSel,
|
||||
BOOL isRequiredMethod,
|
||||
BOOL isInstanceMethod);
|
||||
OBJC_EXPORT BOOL sel_isEqual(SEL lhs, SEL rhs);
|
||||
|
||||
// If building for 10.4 but using the 10.5 SDK, don't include these.
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
// atomics
|
||||
// On Leopard these are GC aware
|
||||
// Intentionally did not include the non-barrier versions, because I couldn't
|
||||
// come up with a case personally where you wouldn't want to use the
|
||||
// barrier versions.
|
||||
GTM_INLINE bool OSAtomicCompareAndSwapPtrBarrier(void *predicate,
|
||||
void *replacement,
|
||||
void * volatile *theValue) {
|
||||
#if defined(__LP64__) && __LP64__
|
||||
return OSAtomicCompareAndSwap64Barrier((int64_t)predicate,
|
||||
(int64_t)replacement,
|
||||
(int64_t *)theValue);
|
||||
#else // defined(__LP64__) && __LP64__
|
||||
return OSAtomicCompareAndSwap32Barrier((int32_t)predicate,
|
||||
(int32_t)replacement,
|
||||
(int32_t *)theValue);
|
||||
#endif // defined(__LP64__) && __LP64__
|
||||
}
|
||||
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
#endif // GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
|
||||
|
||||
#if GTM_MACOS_SDK && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
|
||||
|
||||
GTM_INLINE BOOL objc_atomicCompareAndSwapGlobalBarrier(id predicate,
|
||||
id replacement,
|
||||
volatile id *objectLocation) {
|
||||
return OSAtomicCompareAndSwapPtrBarrier(predicate,
|
||||
replacement,
|
||||
(void * volatile *)objectLocation);
|
||||
}
|
||||
GTM_INLINE BOOL objc_atomicCompareAndSwapInstanceVariableBarrier(id predicate,
|
||||
id replacement,
|
||||
volatile id *objectLocation) {
|
||||
return OSAtomicCompareAndSwapPtrBarrier(predicate,
|
||||
replacement,
|
||||
(void * volatile *)objectLocation);
|
||||
}
|
||||
#endif // GTM_MACOS_SDK && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
|
163
External/google-plus-ios-sdk/OpenSource/GTMObjC2Runtime.m
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
//
|
||||
// GTMObjC2Runtime.m
|
||||
//
|
||||
// Copyright 2007-2008 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 "GTMObjC2Runtime.h"
|
||||
|
||||
#if GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
|
||||
#import <stdlib.h>
|
||||
#import <string.h>
|
||||
|
||||
Class object_getClass(id obj) {
|
||||
if (!obj) return NULL;
|
||||
return obj->isa;
|
||||
}
|
||||
|
||||
const char *class_getName(Class cls) {
|
||||
if (!cls) return "nil";
|
||||
return cls->name;
|
||||
}
|
||||
|
||||
BOOL class_conformsToProtocol(Class cls, Protocol *protocol) {
|
||||
// We intentionally don't check cls as it crashes on Leopard so we want
|
||||
// to crash on Tiger as well.
|
||||
// I logged
|
||||
// Radar 5572978 class_conformsToProtocol crashes when arg1 is passed as nil
|
||||
// because it seems odd that this API won't accept nil for cls considering
|
||||
// all the other apis will accept nil args.
|
||||
// If this does get fixed, remember to enable the unit tests.
|
||||
if (!protocol) return NO;
|
||||
|
||||
struct objc_protocol_list *protos;
|
||||
for (protos = cls->protocols; protos != NULL; protos = protos->next) {
|
||||
for (long i = 0; i < protos->count; i++) {
|
||||
if ([protos->list[i] conformsTo:protocol]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
Class class_getSuperclass(Class cls) {
|
||||
if (!cls) return NULL;
|
||||
return cls->super_class;
|
||||
}
|
||||
|
||||
BOOL class_respondsToSelector(Class cls, SEL sel) {
|
||||
return class_getInstanceMethod(cls, sel) != nil;
|
||||
}
|
||||
|
||||
Method *class_copyMethodList(Class cls, unsigned int *outCount) {
|
||||
if (!cls) return NULL;
|
||||
|
||||
unsigned int count = 0;
|
||||
void *iterator = NULL;
|
||||
struct objc_method_list *mlist;
|
||||
Method *methods = NULL;
|
||||
if (outCount) *outCount = 0;
|
||||
|
||||
while ( (mlist = class_nextMethodList(cls, &iterator)) ) {
|
||||
if (mlist->method_count == 0) continue;
|
||||
methods = (Method *)realloc(methods,
|
||||
sizeof(Method) * (count + mlist->method_count + 1));
|
||||
if (!methods) {
|
||||
//Memory alloc failed, so what can we do?
|
||||
return NULL; // COV_NF_LINE
|
||||
}
|
||||
for (int i = 0; i < mlist->method_count; i++) {
|
||||
methods[i + count] = &mlist->method_list[i];
|
||||
}
|
||||
count += mlist->method_count;
|
||||
}
|
||||
|
||||
// List must be NULL terminated
|
||||
if (methods) {
|
||||
methods[count] = NULL;
|
||||
}
|
||||
if (outCount) *outCount = count;
|
||||
return methods;
|
||||
}
|
||||
|
||||
SEL method_getName(Method method) {
|
||||
if (!method) return NULL;
|
||||
return method->method_name;
|
||||
}
|
||||
|
||||
IMP method_getImplementation(Method method) {
|
||||
if (!method) return NULL;
|
||||
return method->method_imp;
|
||||
}
|
||||
|
||||
IMP method_setImplementation(Method method, IMP imp) {
|
||||
// We intentionally don't test method for nil.
|
||||
// Leopard fails here, so should we.
|
||||
// I logged this as Radar:
|
||||
// 5572981 method_setImplementation crashes if you pass nil for the
|
||||
// method arg (arg 1)
|
||||
// because it seems odd that this API won't accept nil for method considering
|
||||
// all the other apis will accept nil args.
|
||||
// If this does get fixed, remember to enable the unit tests.
|
||||
// This method works differently on SnowLeopard than
|
||||
// on Leopard. If you pass in a nil for IMP on SnowLeopard
|
||||
// it doesn't change anything. On Leopard it will. Since
|
||||
// attempting to change a sel to nil is probably an error
|
||||
// we follow the SnowLeopard way of doing things.
|
||||
IMP oldImp = NULL;
|
||||
if (imp) {
|
||||
oldImp = method->method_imp;
|
||||
method->method_imp = imp;
|
||||
}
|
||||
return oldImp;
|
||||
}
|
||||
|
||||
void method_exchangeImplementations(Method m1, Method m2) {
|
||||
if (m1 == m2) return;
|
||||
if (!m1 || !m2) return;
|
||||
IMP imp2 = method_getImplementation(m2);
|
||||
IMP imp1 = method_setImplementation(m1, imp2);
|
||||
method_setImplementation(m2, imp1);
|
||||
}
|
||||
|
||||
struct objc_method_description protocol_getMethodDescription(Protocol *p,
|
||||
SEL aSel,
|
||||
BOOL isRequiredMethod,
|
||||
BOOL isInstanceMethod) {
|
||||
struct objc_method_description *descPtr = NULL;
|
||||
// No such thing as required in ObjC1.
|
||||
if (isInstanceMethod) {
|
||||
descPtr = [p descriptionForInstanceMethod:aSel];
|
||||
} else {
|
||||
descPtr = [p descriptionForClassMethod:aSel];
|
||||
}
|
||||
|
||||
struct objc_method_description desc;
|
||||
if (descPtr) {
|
||||
desc = *descPtr;
|
||||
} else {
|
||||
bzero(&desc, sizeof(desc));
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
BOOL sel_isEqual(SEL lhs, SEL rhs) {
|
||||
// Apple (informally) promises this will work in the future:
|
||||
// http://twitter.com/#!/gparker/status/2400099786
|
||||
return (lhs == rhs) ? YES : NO;
|
||||
}
|
||||
|
||||
#endif // GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
|
39
External/google-plus-ios-sdk/README
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
This Google+ iOS SDK allows users to sign in with Google+, share with Google+,
|
||||
and write moments to Google+ history from third-party apps. The SDK contains the
|
||||
following files:
|
||||
|
||||
README -- This file.
|
||||
|
||||
Changelog -- The versions and changes of the SDK.
|
||||
|
||||
lib/ -- Header files and libraries.
|
||||
GooglePlusShare.h -- Header file to include for sharing with Google+.
|
||||
GooglePlusSignIn.h -- Header file to include for signing into Google+.
|
||||
GooglePlusSignInButton.h -- Header file to include for showing a button to
|
||||
sign in with Google+.
|
||||
libGooglePlus.a -- Static library built for iOS device to link into your app.
|
||||
libGooglePlusUniversal.a -- Static library built for both iOS device and
|
||||
simulator to link into your app.
|
||||
|
||||
OpenSource/ -- Google open source files used by the SDK. Add all files in this
|
||||
directory into your project if you're not already using them.
|
||||
Also see comments for the subdirectory below.
|
||||
GTL/ -- Google open source files only used by the sample app. Include them
|
||||
into your project if you're going to use the same functionality,
|
||||
e.g. Add Moments.
|
||||
|
||||
Resources/ -- Resources that can be used in your app.
|
||||
For |GooglePlusSignInButton|, the google_plus_sign_in*.png images
|
||||
are required.
|
||||
google_plus_share.png -- 82x24 Google+ share button image.
|
||||
google_plus_share_large.png -- 112x32 Google+ share button image.
|
||||
google_plus_share@2x.png -- 164x48 Google+ share button image.
|
||||
google_plus_share_large@2x.png -- 224x64 Google+ share button image.
|
||||
google_plus_sign_in.png -- 120x32 Google+ sign-in button image.
|
||||
google_plus_sign_in_wide.png --220x32 Wide Google+ sign-in button image.
|
||||
google_plus_sign_in@2x.png -- 240x64 Google+ sign-in button image.
|
||||
google_plus_sign_in_wide@2x.png -- 440x64 Wide Google+ sign-in button image.
|
||||
|
||||
SampleCode/ -- Sample code for your reference only.
|
||||
Do not include this in your project.
|
||||
GooglePlusSample.xcodeproj/ -- The Xcode project.
|
BIN
External/google-plus-ios-sdk/Resources/google_plus_share.png
vendored
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
External/google-plus-ios-sdk/Resources/google_plus_share@2x.png
vendored
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
External/google-plus-ios-sdk/Resources/google_plus_share_large.png
vendored
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
External/google-plus-ios-sdk/Resources/google_plus_share_large@2x.png
vendored
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
External/google-plus-ios-sdk/Resources/google_plus_sign_in.png
vendored
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
External/google-plus-ios-sdk/Resources/google_plus_sign_in@2x.png
vendored
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
External/google-plus-ios-sdk/Resources/google_plus_sign_in_wide.png
vendored
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
External/google-plus-ios-sdk/Resources/google_plus_sign_in_wide@2x.png
vendored
Normal file
After Width: | Height: | Size: 11 KiB |
74
External/google-plus-ios-sdk/SampleCode/GooglePlusSample-Info.plist
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFiles</key>
|
||||
<array>
|
||||
<string>Icon.png</string>
|
||||
<string>Icon@2x.png</string>
|
||||
</array>
|
||||
<key>CFBundleIcons</key>
|
||||
<dict>
|
||||
<key>CFBundlePrimaryIcon</key>
|
||||
<dict>
|
||||
<key>CFBundleIconFiles</key>
|
||||
<array>
|
||||
<string>Icon.png</string>
|
||||
<string>Icon@2x.png</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.google.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.google.GooglePlusSample</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.google.GooglePlusSample</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
14
External/google-plus-ios-sdk/SampleCode/GooglePlusSample-Prefix.pch
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// Prefix header for all source files of the 'GooglePlusSample' target in the 'GooglePlusSample' project
|
||||
//
|
||||
|
||||
#import <Availability.h>
|
||||
|
||||
#ifndef __IPHONE_4_0
|
||||
#warning "This project uses features only available in iOS SDK 4.0 and later."
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
648
External/google-plus-ios-sdk/SampleCode/GooglePlusSample.xcodeproj/project.pbxproj
vendored
Normal file
@ -0,0 +1,648 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0043C79F1580045B000DF02E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0043C79E1580045B000DF02E /* UIKit.framework */; };
|
||||
0043C7A11580045B000DF02E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0043C7A01580045B000DF02E /* Foundation.framework */; };
|
||||
0043C7A31580045B000DF02E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0043C7A21580045B000DF02E /* CoreGraphics.framework */; };
|
||||
00F70E83158006DC0077799E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 00F70E82158006DC0077799E /* main.m */; };
|
||||
00F70E99158007D90077799E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00F70E98158007D90077799E /* Security.framework */; };
|
||||
00F70E9B158008040077799E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00F70E9A158008040077799E /* SystemConfiguration.framework */; };
|
||||
0C52D6F8158BAB1F001510E6 /* button_background.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C52D6F7158BAB1F001510E6 /* button_background.png */; };
|
||||
D973B402158ABC1F0083A4B5 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D973B401158ABC1F0083A4B5 /* MessageUI.framework */; };
|
||||
D98254A815990D8D0060CA47 /* Icon_2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D98254A615990D8D0060CA47 /* Icon_2x.png */; };
|
||||
D98254A915990D8D0060CA47 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = D98254A715990D8D0060CA47 /* Icon.png */; };
|
||||
D98254F2159937730060CA47 /* GTLPlusPerson.m in Sources */ = {isa = PBXBuildFile; fileRef = D98254F1159937730060CA47 /* GTLPlusPerson.m */; };
|
||||
D9EE743D158A8BD400EC1D05 /* google_plus_share_large.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE7435158A8BD400EC1D05 /* google_plus_share_large.png */; };
|
||||
D9EE743E158A8BD400EC1D05 /* google_plus_share_large@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE7436158A8BD400EC1D05 /* google_plus_share_large@2x.png */; };
|
||||
D9EE743F158A8BD400EC1D05 /* google_plus_share.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE7437158A8BD400EC1D05 /* google_plus_share.png */; };
|
||||
D9EE7440158A8BD400EC1D05 /* google_plus_share@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE7438158A8BD400EC1D05 /* google_plus_share@2x.png */; };
|
||||
D9EE748D158A8C0E00EC1D05 /* GTLBase64.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7449158A8C0E00EC1D05 /* GTLBase64.m */; };
|
||||
D9EE748E158A8C0E00EC1D05 /* GTLBatchQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE744B158A8C0E00EC1D05 /* GTLBatchQuery.m */; };
|
||||
D9EE748F158A8C0E00EC1D05 /* GTLBatchResult.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE744D158A8C0E00EC1D05 /* GTLBatchResult.m */; };
|
||||
D9EE7490158A8C0E00EC1D05 /* GTLDateTime.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE744F158A8C0E00EC1D05 /* GTLDateTime.m */; };
|
||||
D9EE7491158A8C0E00EC1D05 /* GTLErrorObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7452158A8C0E00EC1D05 /* GTLErrorObject.m */; };
|
||||
D9EE7492158A8C0E00EC1D05 /* GTLFramework.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7454158A8C0E00EC1D05 /* GTLFramework.m */; };
|
||||
D9EE7493158A8C0E00EC1D05 /* GTLJSONParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7456158A8C0E00EC1D05 /* GTLJSONParser.m */; };
|
||||
D9EE7494158A8C0E00EC1D05 /* GTLObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7458158A8C0E00EC1D05 /* GTLObject.m */; };
|
||||
D9EE7495158A8C0E00EC1D05 /* GTLPlusConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE745C158A8C0E00EC1D05 /* GTLPlusConstants.m */; };
|
||||
D9EE7496158A8C0E00EC1D05 /* GTLPlusItemScope.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE745E158A8C0E00EC1D05 /* GTLPlusItemScope.m */; };
|
||||
D9EE7497158A8C0E00EC1D05 /* GTLPlusMoment.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7460158A8C0E00EC1D05 /* GTLPlusMoment.m */; };
|
||||
D9EE7499158A8C0E00EC1D05 /* GTLQueryPlus.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7464158A8C0E00EC1D05 /* GTLQueryPlus.m */; };
|
||||
D9EE749A158A8C0E00EC1D05 /* GTLServicePlus.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7466158A8C0E00EC1D05 /* GTLServicePlus.m */; };
|
||||
D9EE749B158A8C0E00EC1D05 /* GTLQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7468158A8C0E00EC1D05 /* GTLQuery.m */; };
|
||||
D9EE749C158A8C0E00EC1D05 /* GTLRuntimeCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE746A158A8C0E00EC1D05 /* GTLRuntimeCommon.m */; };
|
||||
D9EE749D158A8C0E00EC1D05 /* GTLService.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE746C158A8C0E00EC1D05 /* GTLService.m */; };
|
||||
D9EE749E158A8C0E00EC1D05 /* GTLUploadParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE746F158A8C0E00EC1D05 /* GTLUploadParameters.m */; };
|
||||
D9EE749F158A8C0E00EC1D05 /* GTLUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7471158A8C0E00EC1D05 /* GTLUtilities.m */; };
|
||||
D9EE74A0158A8C0E00EC1D05 /* GTMHTTPFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7475158A8C0E00EC1D05 /* GTMHTTPFetcher.m */; };
|
||||
D9EE74A1158A8C0E00EC1D05 /* GTMHTTPFetcherLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7477158A8C0E00EC1D05 /* GTMHTTPFetcherLogging.m */; };
|
||||
D9EE74A2158A8C0E00EC1D05 /* GTMHTTPFetcherService.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7479158A8C0E00EC1D05 /* GTMHTTPFetcherService.m */; };
|
||||
D9EE74A3158A8C0E00EC1D05 /* GTMHTTPFetchHistory.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE747B158A8C0E00EC1D05 /* GTMHTTPFetchHistory.m */; };
|
||||
D9EE74A4158A8C0E00EC1D05 /* GTMLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE747D158A8C0E00EC1D05 /* GTMLogger.m */; };
|
||||
D9EE74A5158A8C0E00EC1D05 /* GTMMethodCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE747F158A8C0E00EC1D05 /* GTMMethodCheck.m */; };
|
||||
D9EE74A6158A8C0E00EC1D05 /* GTMNSDictionary+URLArguments.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7481158A8C0E00EC1D05 /* GTMNSDictionary+URLArguments.m */; };
|
||||
D9EE74A7158A8C0E00EC1D05 /* GTMNSString+URLArguments.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7483158A8C0E00EC1D05 /* GTMNSString+URLArguments.m */; };
|
||||
D9EE74A8158A8C0E00EC1D05 /* GTMOAuth2Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7485158A8C0E00EC1D05 /* GTMOAuth2Authentication.m */; };
|
||||
D9EE74A9158A8C0E00EC1D05 /* GTMOAuth2SignIn.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7487158A8C0E00EC1D05 /* GTMOAuth2SignIn.m */; };
|
||||
D9EE74AA158A8C0E00EC1D05 /* GTMOAuth2ViewControllerTouch.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE7489158A8C0E00EC1D05 /* GTMOAuth2ViewControllerTouch.m */; };
|
||||
D9EE74AB158A8C0E00EC1D05 /* GTMOAuth2ViewTouch.xib in Resources */ = {isa = PBXBuildFile; fileRef = D9EE748A158A8C0E00EC1D05 /* GTMOAuth2ViewTouch.xib */; };
|
||||
D9EE74AC158A8C0E00EC1D05 /* GTMObjC2Runtime.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE748C158A8C0E00EC1D05 /* GTMObjC2Runtime.m */; };
|
||||
D9EE74B0158A8D1E00EC1D05 /* libGooglePlusUniversal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EE74AE158A8D1E00EC1D05 /* libGooglePlusUniversal.a */; };
|
||||
D9EE74C2158A8E0500EC1D05 /* GooglePlusSampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE74B4158A8E0500EC1D05 /* GooglePlusSampleAppDelegate.m */; };
|
||||
D9EE74C3158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE74B6158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.m */; };
|
||||
D9EE74C4158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74B7158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.xib */; };
|
||||
D9EE74C5158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE74B9158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.m */; };
|
||||
D9EE74C6158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74BA158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.xib */; };
|
||||
D9EE74C7158A8E0500EC1D05 /* GooglePlusSampleShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE74BC158A8E0500EC1D05 /* GooglePlusSampleShareViewController.m */; };
|
||||
D9EE74C8158A8E0500EC1D05 /* GooglePlusSampleShareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74BD158A8E0500EC1D05 /* GooglePlusSampleShareViewController.xib */; };
|
||||
D9EE74C9158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EE74BF158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.m */; };
|
||||
D9EE74CA158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74C0158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.xib */; };
|
||||
D9EE74CD158A8E2900EC1D05 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74CB158A8E2900EC1D05 /* InfoPlist.strings */; };
|
||||
D9EE74E4158A9A7D00EC1D05 /* google_plus_sign_in_wide.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74E0158A9A7D00EC1D05 /* google_plus_sign_in_wide.png */; };
|
||||
D9EE74E5158A9A7D00EC1D05 /* google_plus_sign_in_wide@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74E1158A9A7D00EC1D05 /* google_plus_sign_in_wide@2x.png */; };
|
||||
D9EE74E6158A9A7D00EC1D05 /* google_plus_sign_in.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74E2158A9A7D00EC1D05 /* google_plus_sign_in.png */; };
|
||||
D9EE74E7158A9A7D00EC1D05 /* google_plus_sign_in@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EE74E3158A9A7D00EC1D05 /* google_plus_sign_in@2x.png */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0043C79A1580045B000DF02E /* GooglePlusSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GooglePlusSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0043C79E1580045B000DF02E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
0043C7A01580045B000DF02E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
0043C7A21580045B000DF02E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
00F70E82158006DC0077799E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; };
|
||||
00F70E98158007D90077799E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||
00F70E9A158008040077799E /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
0C52D6F7158BAB1F001510E6 /* button_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = button_background.png; path = Resources/button_background.png; sourceTree = SOURCE_ROOT; };
|
||||
D973B401158ABC1F0083A4B5 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
|
||||
D98254A615990D8D0060CA47 /* Icon_2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_2x.png; path = Resources/Icon_2x.png; sourceTree = SOURCE_ROOT; };
|
||||
D98254A715990D8D0060CA47 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon.png; path = Resources/Icon.png; sourceTree = SOURCE_ROOT; };
|
||||
D98254F0159937730060CA47 /* GTLPlusPerson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLPlusPerson.h; sourceTree = "<group>"; };
|
||||
D98254F1159937730060CA47 /* GTLPlusPerson.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLPlusPerson.m; sourceTree = "<group>"; };
|
||||
D9EE7431158A8BAE00EC1D05 /* GooglePlusShare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GooglePlusShare.h; path = ../lib/GooglePlusShare.h; sourceTree = "<group>"; };
|
||||
D9EE7432158A8BAE00EC1D05 /* GooglePlusSignIn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GooglePlusSignIn.h; path = ../lib/GooglePlusSignIn.h; sourceTree = "<group>"; };
|
||||
D9EE7433158A8BAE00EC1D05 /* GooglePlusSignInButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GooglePlusSignInButton.h; path = ../lib/GooglePlusSignInButton.h; sourceTree = "<group>"; };
|
||||
D9EE7435158A8BD400EC1D05 /* google_plus_share_large.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = google_plus_share_large.png; path = ../Resources/google_plus_share_large.png; sourceTree = "<group>"; };
|
||||
D9EE7436158A8BD400EC1D05 /* google_plus_share_large@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "google_plus_share_large@2x.png"; path = "../Resources/google_plus_share_large@2x.png"; sourceTree = "<group>"; };
|
||||
D9EE7437158A8BD400EC1D05 /* google_plus_share.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = google_plus_share.png; path = ../Resources/google_plus_share.png; sourceTree = "<group>"; };
|
||||
D9EE7438158A8BD400EC1D05 /* google_plus_share@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "google_plus_share@2x.png"; path = "../Resources/google_plus_share@2x.png"; sourceTree = "<group>"; };
|
||||
D9EE7448158A8C0E00EC1D05 /* GTLBase64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLBase64.h; sourceTree = "<group>"; };
|
||||
D9EE7449158A8C0E00EC1D05 /* GTLBase64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLBase64.m; sourceTree = "<group>"; };
|
||||
D9EE744A158A8C0E00EC1D05 /* GTLBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLBatchQuery.h; sourceTree = "<group>"; };
|
||||
D9EE744B158A8C0E00EC1D05 /* GTLBatchQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLBatchQuery.m; sourceTree = "<group>"; };
|
||||
D9EE744C158A8C0E00EC1D05 /* GTLBatchResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLBatchResult.h; sourceTree = "<group>"; };
|
||||
D9EE744D158A8C0E00EC1D05 /* GTLBatchResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLBatchResult.m; sourceTree = "<group>"; };
|
||||
D9EE744E158A8C0E00EC1D05 /* GTLDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLDateTime.h; sourceTree = "<group>"; };
|
||||
D9EE744F158A8C0E00EC1D05 /* GTLDateTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLDateTime.m; sourceTree = "<group>"; };
|
||||
D9EE7450158A8C0E00EC1D05 /* GTLDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLDefines.h; sourceTree = "<group>"; };
|
||||
D9EE7451158A8C0E00EC1D05 /* GTLErrorObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLErrorObject.h; sourceTree = "<group>"; };
|
||||
D9EE7452158A8C0E00EC1D05 /* GTLErrorObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLErrorObject.m; sourceTree = "<group>"; };
|
||||
D9EE7453158A8C0E00EC1D05 /* GTLFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLFramework.h; sourceTree = "<group>"; };
|
||||
D9EE7454158A8C0E00EC1D05 /* GTLFramework.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLFramework.m; sourceTree = "<group>"; };
|
||||
D9EE7455158A8C0E00EC1D05 /* GTLJSONParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLJSONParser.h; sourceTree = "<group>"; };
|
||||
D9EE7456158A8C0E00EC1D05 /* GTLJSONParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLJSONParser.m; sourceTree = "<group>"; };
|
||||
D9EE7457158A8C0E00EC1D05 /* GTLObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLObject.h; sourceTree = "<group>"; };
|
||||
D9EE7458158A8C0E00EC1D05 /* GTLObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLObject.m; sourceTree = "<group>"; };
|
||||
D9EE745A158A8C0E00EC1D05 /* GTLPlus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLPlus.h; sourceTree = "<group>"; };
|
||||
D9EE745B158A8C0E00EC1D05 /* GTLPlusConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLPlusConstants.h; sourceTree = "<group>"; };
|
||||
D9EE745C158A8C0E00EC1D05 /* GTLPlusConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLPlusConstants.m; sourceTree = "<group>"; };
|
||||
D9EE745D158A8C0E00EC1D05 /* GTLPlusItemScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLPlusItemScope.h; sourceTree = "<group>"; };
|
||||
D9EE745E158A8C0E00EC1D05 /* GTLPlusItemScope.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLPlusItemScope.m; sourceTree = "<group>"; };
|
||||
D9EE745F158A8C0E00EC1D05 /* GTLPlusMoment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLPlusMoment.h; sourceTree = "<group>"; };
|
||||
D9EE7460158A8C0E00EC1D05 /* GTLPlusMoment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLPlusMoment.m; sourceTree = "<group>"; };
|
||||
D9EE7463158A8C0E00EC1D05 /* GTLQueryPlus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLQueryPlus.h; sourceTree = "<group>"; };
|
||||
D9EE7464158A8C0E00EC1D05 /* GTLQueryPlus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLQueryPlus.m; sourceTree = "<group>"; };
|
||||
D9EE7465158A8C0E00EC1D05 /* GTLServicePlus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLServicePlus.h; sourceTree = "<group>"; };
|
||||
D9EE7466158A8C0E00EC1D05 /* GTLServicePlus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLServicePlus.m; sourceTree = "<group>"; };
|
||||
D9EE7467158A8C0E00EC1D05 /* GTLQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLQuery.h; sourceTree = "<group>"; };
|
||||
D9EE7468158A8C0E00EC1D05 /* GTLQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLQuery.m; sourceTree = "<group>"; };
|
||||
D9EE7469158A8C0E00EC1D05 /* GTLRuntimeCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLRuntimeCommon.h; sourceTree = "<group>"; };
|
||||
D9EE746A158A8C0E00EC1D05 /* GTLRuntimeCommon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLRuntimeCommon.m; sourceTree = "<group>"; };
|
||||
D9EE746B158A8C0E00EC1D05 /* GTLService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLService.h; sourceTree = "<group>"; };
|
||||
D9EE746C158A8C0E00EC1D05 /* GTLService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLService.m; sourceTree = "<group>"; };
|
||||
D9EE746D158A8C0E00EC1D05 /* GTLTargetNamespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLTargetNamespace.h; sourceTree = "<group>"; };
|
||||
D9EE746E158A8C0E00EC1D05 /* GTLUploadParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLUploadParameters.h; sourceTree = "<group>"; };
|
||||
D9EE746F158A8C0E00EC1D05 /* GTLUploadParameters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLUploadParameters.m; sourceTree = "<group>"; };
|
||||
D9EE7470158A8C0E00EC1D05 /* GTLUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTLUtilities.h; sourceTree = "<group>"; };
|
||||
D9EE7471158A8C0E00EC1D05 /* GTLUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTLUtilities.m; sourceTree = "<group>"; };
|
||||
D9EE7472158A8C0E00EC1D05 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDefines.h; sourceTree = "<group>"; };
|
||||
D9EE7473158A8C0E00EC1D05 /* GTMGarbageCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMGarbageCollection.h; sourceTree = "<group>"; };
|
||||
D9EE7474158A8C0E00EC1D05 /* GTMHTTPFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMHTTPFetcher.h; sourceTree = "<group>"; };
|
||||
D9EE7475158A8C0E00EC1D05 /* GTMHTTPFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMHTTPFetcher.m; sourceTree = "<group>"; };
|
||||
D9EE7476158A8C0E00EC1D05 /* GTMHTTPFetcherLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMHTTPFetcherLogging.h; sourceTree = "<group>"; };
|
||||
D9EE7477158A8C0E00EC1D05 /* GTMHTTPFetcherLogging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMHTTPFetcherLogging.m; sourceTree = "<group>"; };
|
||||
D9EE7478158A8C0E00EC1D05 /* GTMHTTPFetcherService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMHTTPFetcherService.h; sourceTree = "<group>"; };
|
||||
D9EE7479158A8C0E00EC1D05 /* GTMHTTPFetcherService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMHTTPFetcherService.m; sourceTree = "<group>"; };
|
||||
D9EE747A158A8C0E00EC1D05 /* GTMHTTPFetchHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMHTTPFetchHistory.h; sourceTree = "<group>"; };
|
||||
D9EE747B158A8C0E00EC1D05 /* GTMHTTPFetchHistory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMHTTPFetchHistory.m; sourceTree = "<group>"; };
|
||||
D9EE747C158A8C0E00EC1D05 /* GTMLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMLogger.h; sourceTree = "<group>"; };
|
||||
D9EE747D158A8C0E00EC1D05 /* GTMLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMLogger.m; sourceTree = "<group>"; };
|
||||
D9EE747E158A8C0E00EC1D05 /* GTMMethodCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMMethodCheck.h; sourceTree = "<group>"; };
|
||||
D9EE747F158A8C0E00EC1D05 /* GTMMethodCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMMethodCheck.m; sourceTree = "<group>"; };
|
||||
D9EE7480158A8C0E00EC1D05 /* GTMNSDictionary+URLArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSDictionary+URLArguments.h"; sourceTree = "<group>"; };
|
||||
D9EE7481158A8C0E00EC1D05 /* GTMNSDictionary+URLArguments.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSDictionary+URLArguments.m"; sourceTree = "<group>"; };
|
||||
D9EE7482158A8C0E00EC1D05 /* GTMNSString+URLArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSString+URLArguments.h"; sourceTree = "<group>"; };
|
||||
D9EE7483158A8C0E00EC1D05 /* GTMNSString+URLArguments.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSString+URLArguments.m"; sourceTree = "<group>"; };
|
||||
D9EE7484158A8C0E00EC1D05 /* GTMOAuth2Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMOAuth2Authentication.h; sourceTree = "<group>"; };
|
||||
D9EE7485158A8C0E00EC1D05 /* GTMOAuth2Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMOAuth2Authentication.m; sourceTree = "<group>"; };
|
||||
D9EE7486158A8C0E00EC1D05 /* GTMOAuth2SignIn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMOAuth2SignIn.h; sourceTree = "<group>"; };
|
||||
D9EE7487158A8C0E00EC1D05 /* GTMOAuth2SignIn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMOAuth2SignIn.m; sourceTree = "<group>"; };
|
||||
D9EE7488158A8C0E00EC1D05 /* GTMOAuth2ViewControllerTouch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMOAuth2ViewControllerTouch.h; sourceTree = "<group>"; };
|
||||
D9EE7489158A8C0E00EC1D05 /* GTMOAuth2ViewControllerTouch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMOAuth2ViewControllerTouch.m; sourceTree = "<group>"; };
|
||||
D9EE748A158A8C0E00EC1D05 /* GTMOAuth2ViewTouch.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GTMOAuth2ViewTouch.xib; sourceTree = "<group>"; };
|
||||
D9EE748B158A8C0E00EC1D05 /* GTMObjC2Runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMObjC2Runtime.h; sourceTree = "<group>"; };
|
||||
D9EE748C158A8C0E00EC1D05 /* GTMObjC2Runtime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMObjC2Runtime.m; sourceTree = "<group>"; };
|
||||
D9EE74AD158A8D1E00EC1D05 /* libGooglePlus.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libGooglePlus.a; path = ../lib/libGooglePlus.a; sourceTree = "<group>"; };
|
||||
D9EE74AE158A8D1E00EC1D05 /* libGooglePlusUniversal.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libGooglePlusUniversal.a; path = ../lib/libGooglePlusUniversal.a; sourceTree = "<group>"; };
|
||||
D9EE74B1158A8E0500EC1D05 /* GooglePlusSample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GooglePlusSample-Info.plist"; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B2158A8E0500EC1D05 /* GooglePlusSample-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GooglePlusSample-Prefix.pch"; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B3158A8E0500EC1D05 /* GooglePlusSampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusSampleAppDelegate.h; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B4158A8E0500EC1D05 /* GooglePlusSampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GooglePlusSampleAppDelegate.m; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B5158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusSampleMasterViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B6158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GooglePlusSampleMasterViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B7158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GooglePlusSampleMasterViewController.xib; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B8158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusSampleMomentsViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74B9158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GooglePlusSampleMomentsViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74BA158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GooglePlusSampleMomentsViewController.xib; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74BB158A8E0500EC1D05 /* GooglePlusSampleShareViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusSampleShareViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74BC158A8E0500EC1D05 /* GooglePlusSampleShareViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GooglePlusSampleShareViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74BD158A8E0500EC1D05 /* GooglePlusSampleShareViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GooglePlusSampleShareViewController.xib; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74BE158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusSampleSignInViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74BF158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GooglePlusSampleSignInViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74C0158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GooglePlusSampleSignInViewController.xib; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74CC158A8E2900EC1D05 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; };
|
||||
D9EE74E0158A9A7D00EC1D05 /* google_plus_sign_in_wide.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = google_plus_sign_in_wide.png; path = ../Resources/google_plus_sign_in_wide.png; sourceTree = "<group>"; };
|
||||
D9EE74E1158A9A7D00EC1D05 /* google_plus_sign_in_wide@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "google_plus_sign_in_wide@2x.png"; path = "../Resources/google_plus_sign_in_wide@2x.png"; sourceTree = "<group>"; };
|
||||
D9EE74E2158A9A7D00EC1D05 /* google_plus_sign_in.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = google_plus_sign_in.png; path = ../Resources/google_plus_sign_in.png; sourceTree = "<group>"; };
|
||||
D9EE74E3158A9A7D00EC1D05 /* google_plus_sign_in@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "google_plus_sign_in@2x.png"; path = "../Resources/google_plus_sign_in@2x.png"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
0043C7971580045B000DF02E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D973B402158ABC1F0083A4B5 /* MessageUI.framework in Frameworks */,
|
||||
00F70E9B158008040077799E /* SystemConfiguration.framework in Frameworks */,
|
||||
00F70E99158007D90077799E /* Security.framework in Frameworks */,
|
||||
0043C79F1580045B000DF02E /* UIKit.framework in Frameworks */,
|
||||
0043C7A11580045B000DF02E /* Foundation.framework in Frameworks */,
|
||||
0043C7A31580045B000DF02E /* CoreGraphics.framework in Frameworks */,
|
||||
D9EE74B0158A8D1E00EC1D05 /* libGooglePlusUniversal.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
0043C78F1580045B000DF02E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9EE7434158A8BB500EC1D05 /* GooglePlusSDK */,
|
||||
D9EE7446158A8C0E00EC1D05 /* GoogleOpenSource */,
|
||||
0043C7A41580045B000DF02E /* GooglePlusSample */,
|
||||
0043C79D1580045B000DF02E /* Frameworks */,
|
||||
0043C79B1580045B000DF02E /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0043C79B1580045B000DF02E /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0043C79A1580045B000DF02E /* GooglePlusSample.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0043C79D1580045B000DF02E /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D973B401158ABC1F0083A4B5 /* MessageUI.framework */,
|
||||
00F70E9A158008040077799E /* SystemConfiguration.framework */,
|
||||
00F70E98158007D90077799E /* Security.framework */,
|
||||
0043C79E1580045B000DF02E /* UIKit.framework */,
|
||||
0043C7A01580045B000DF02E /* Foundation.framework */,
|
||||
0043C7A21580045B000DF02E /* CoreGraphics.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0043C7A41580045B000DF02E /* GooglePlusSample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9EE74B3158A8E0500EC1D05 /* GooglePlusSampleAppDelegate.h */,
|
||||
D9EE74B4158A8E0500EC1D05 /* GooglePlusSampleAppDelegate.m */,
|
||||
D9EE74B5158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.h */,
|
||||
D9EE74B6158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.m */,
|
||||
D9EE74B7158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.xib */,
|
||||
D9EE74B8158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.h */,
|
||||
D9EE74B9158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.m */,
|
||||
D9EE74BA158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.xib */,
|
||||
D9EE74BB158A8E0500EC1D05 /* GooglePlusSampleShareViewController.h */,
|
||||
D9EE74BC158A8E0500EC1D05 /* GooglePlusSampleShareViewController.m */,
|
||||
D9EE74BD158A8E0500EC1D05 /* GooglePlusSampleShareViewController.xib */,
|
||||
D9EE74BE158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.h */,
|
||||
D9EE74BF158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.m */,
|
||||
D9EE74C0158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.xib */,
|
||||
D98254AB15990DBC0060CA47 /* Resources */,
|
||||
0043C7A51580045B000DF02E /* Supporting Files */,
|
||||
);
|
||||
path = GooglePlusSample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0043C7A51580045B000DF02E /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00F70E82158006DC0077799E /* main.m */,
|
||||
D9EE74CB158A8E2900EC1D05 /* InfoPlist.strings */,
|
||||
D9EE74B1158A8E0500EC1D05 /* GooglePlusSample-Info.plist */,
|
||||
D9EE74B2158A8E0500EC1D05 /* GooglePlusSample-Prefix.pch */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D98254AB15990DBC0060CA47 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D98254A615990D8D0060CA47 /* Icon_2x.png */,
|
||||
D98254A715990D8D0060CA47 /* Icon.png */,
|
||||
0C52D6F7158BAB1F001510E6 /* button_background.png */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9EE7434158A8BB500EC1D05 /* GooglePlusSDK */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9EE7431158A8BAE00EC1D05 /* GooglePlusShare.h */,
|
||||
D9EE7432158A8BAE00EC1D05 /* GooglePlusSignIn.h */,
|
||||
D9EE7433158A8BAE00EC1D05 /* GooglePlusSignInButton.h */,
|
||||
D9EE74AD158A8D1E00EC1D05 /* libGooglePlus.a */,
|
||||
D9EE74AE158A8D1E00EC1D05 /* libGooglePlusUniversal.a */,
|
||||
D9EE7445158A8BDB00EC1D05 /* Resources */,
|
||||
);
|
||||
name = GooglePlusSDK;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9EE7445158A8BDB00EC1D05 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9EE74E0158A9A7D00EC1D05 /* google_plus_sign_in_wide.png */,
|
||||
D9EE74E1158A9A7D00EC1D05 /* google_plus_sign_in_wide@2x.png */,
|
||||
D9EE74E2158A9A7D00EC1D05 /* google_plus_sign_in.png */,
|
||||
D9EE74E3158A9A7D00EC1D05 /* google_plus_sign_in@2x.png */,
|
||||
D9EE7435158A8BD400EC1D05 /* google_plus_share_large.png */,
|
||||
D9EE7436158A8BD400EC1D05 /* google_plus_share_large@2x.png */,
|
||||
D9EE7437158A8BD400EC1D05 /* google_plus_share.png */,
|
||||
D9EE7438158A8BD400EC1D05 /* google_plus_share@2x.png */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9EE7446158A8C0E00EC1D05 /* GoogleOpenSource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9EE7447158A8C0E00EC1D05 /* GTL */,
|
||||
D9EE7472158A8C0E00EC1D05 /* GTMDefines.h */,
|
||||
D9EE7473158A8C0E00EC1D05 /* GTMGarbageCollection.h */,
|
||||
D9EE7474158A8C0E00EC1D05 /* GTMHTTPFetcher.h */,
|
||||
D9EE7475158A8C0E00EC1D05 /* GTMHTTPFetcher.m */,
|
||||
D9EE7476158A8C0E00EC1D05 /* GTMHTTPFetcherLogging.h */,
|
||||
D9EE7477158A8C0E00EC1D05 /* GTMHTTPFetcherLogging.m */,
|
||||
D9EE7478158A8C0E00EC1D05 /* GTMHTTPFetcherService.h */,
|
||||
D9EE7479158A8C0E00EC1D05 /* GTMHTTPFetcherService.m */,
|
||||
D9EE747A158A8C0E00EC1D05 /* GTMHTTPFetchHistory.h */,
|
||||
D9EE747B158A8C0E00EC1D05 /* GTMHTTPFetchHistory.m */,
|
||||
D9EE747C158A8C0E00EC1D05 /* GTMLogger.h */,
|
||||
D9EE747D158A8C0E00EC1D05 /* GTMLogger.m */,
|
||||
D9EE747E158A8C0E00EC1D05 /* GTMMethodCheck.h */,
|
||||
D9EE747F158A8C0E00EC1D05 /* GTMMethodCheck.m */,
|
||||
D9EE7480158A8C0E00EC1D05 /* GTMNSDictionary+URLArguments.h */,
|
||||
D9EE7481158A8C0E00EC1D05 /* GTMNSDictionary+URLArguments.m */,
|
||||
D9EE7482158A8C0E00EC1D05 /* GTMNSString+URLArguments.h */,
|
||||
D9EE7483158A8C0E00EC1D05 /* GTMNSString+URLArguments.m */,
|
||||
D9EE7484158A8C0E00EC1D05 /* GTMOAuth2Authentication.h */,
|
||||
D9EE7485158A8C0E00EC1D05 /* GTMOAuth2Authentication.m */,
|
||||
D9EE7486158A8C0E00EC1D05 /* GTMOAuth2SignIn.h */,
|
||||
D9EE7487158A8C0E00EC1D05 /* GTMOAuth2SignIn.m */,
|
||||
D9EE7488158A8C0E00EC1D05 /* GTMOAuth2ViewControllerTouch.h */,
|
||||
D9EE7489158A8C0E00EC1D05 /* GTMOAuth2ViewControllerTouch.m */,
|
||||
D9EE748A158A8C0E00EC1D05 /* GTMOAuth2ViewTouch.xib */,
|
||||
D9EE748B158A8C0E00EC1D05 /* GTMObjC2Runtime.h */,
|
||||
D9EE748C158A8C0E00EC1D05 /* GTMObjC2Runtime.m */,
|
||||
);
|
||||
name = GoogleOpenSource;
|
||||
path = ../OpenSource;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9EE7447158A8C0E00EC1D05 /* GTL */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9EE7459158A8C0E00EC1D05 /* GTLPlus */,
|
||||
D9EE7448158A8C0E00EC1D05 /* GTLBase64.h */,
|
||||
D9EE7449158A8C0E00EC1D05 /* GTLBase64.m */,
|
||||
D9EE744A158A8C0E00EC1D05 /* GTLBatchQuery.h */,
|
||||
D9EE744B158A8C0E00EC1D05 /* GTLBatchQuery.m */,
|
||||
D9EE744C158A8C0E00EC1D05 /* GTLBatchResult.h */,
|
||||
D9EE744D158A8C0E00EC1D05 /* GTLBatchResult.m */,
|
||||
D9EE744E158A8C0E00EC1D05 /* GTLDateTime.h */,
|
||||
D9EE744F158A8C0E00EC1D05 /* GTLDateTime.m */,
|
||||
D9EE7450158A8C0E00EC1D05 /* GTLDefines.h */,
|
||||
D9EE7451158A8C0E00EC1D05 /* GTLErrorObject.h */,
|
||||
D9EE7452158A8C0E00EC1D05 /* GTLErrorObject.m */,
|
||||
D9EE7453158A8C0E00EC1D05 /* GTLFramework.h */,
|
||||
D9EE7454158A8C0E00EC1D05 /* GTLFramework.m */,
|
||||
D9EE7455158A8C0E00EC1D05 /* GTLJSONParser.h */,
|
||||
D9EE7456158A8C0E00EC1D05 /* GTLJSONParser.m */,
|
||||
D9EE7457158A8C0E00EC1D05 /* GTLObject.h */,
|
||||
D9EE7458158A8C0E00EC1D05 /* GTLObject.m */,
|
||||
D9EE7467158A8C0E00EC1D05 /* GTLQuery.h */,
|
||||
D9EE7468158A8C0E00EC1D05 /* GTLQuery.m */,
|
||||
D9EE7469158A8C0E00EC1D05 /* GTLRuntimeCommon.h */,
|
||||
D9EE746A158A8C0E00EC1D05 /* GTLRuntimeCommon.m */,
|
||||
D9EE746B158A8C0E00EC1D05 /* GTLService.h */,
|
||||
D9EE746C158A8C0E00EC1D05 /* GTLService.m */,
|
||||
D9EE746D158A8C0E00EC1D05 /* GTLTargetNamespace.h */,
|
||||
D9EE746E158A8C0E00EC1D05 /* GTLUploadParameters.h */,
|
||||
D9EE746F158A8C0E00EC1D05 /* GTLUploadParameters.m */,
|
||||
D9EE7470158A8C0E00EC1D05 /* GTLUtilities.h */,
|
||||
D9EE7471158A8C0E00EC1D05 /* GTLUtilities.m */,
|
||||
);
|
||||
path = GTL;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9EE7459158A8C0E00EC1D05 /* GTLPlus */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9EE745A158A8C0E00EC1D05 /* GTLPlus.h */,
|
||||
D9EE745B158A8C0E00EC1D05 /* GTLPlusConstants.h */,
|
||||
D9EE745C158A8C0E00EC1D05 /* GTLPlusConstants.m */,
|
||||
D9EE745D158A8C0E00EC1D05 /* GTLPlusItemScope.h */,
|
||||
D9EE745E158A8C0E00EC1D05 /* GTLPlusItemScope.m */,
|
||||
D9EE745F158A8C0E00EC1D05 /* GTLPlusMoment.h */,
|
||||
D9EE7460158A8C0E00EC1D05 /* GTLPlusMoment.m */,
|
||||
D98254F0159937730060CA47 /* GTLPlusPerson.h */,
|
||||
D98254F1159937730060CA47 /* GTLPlusPerson.m */,
|
||||
D9EE7463158A8C0E00EC1D05 /* GTLQueryPlus.h */,
|
||||
D9EE7464158A8C0E00EC1D05 /* GTLQueryPlus.m */,
|
||||
D9EE7465158A8C0E00EC1D05 /* GTLServicePlus.h */,
|
||||
D9EE7466158A8C0E00EC1D05 /* GTLServicePlus.m */,
|
||||
);
|
||||
path = GTLPlus;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
0043C7991580045B000DF02E /* GooglePlusSample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0043C7B21580045B000DF02E /* Build configuration list for PBXNativeTarget "GooglePlusSample" */;
|
||||
buildPhases = (
|
||||
0043C7961580045B000DF02E /* Sources */,
|
||||
0043C7971580045B000DF02E /* Frameworks */,
|
||||
0043C7981580045B000DF02E /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = GooglePlusSample;
|
||||
productName = GooglePlusSample;
|
||||
productReference = 0043C79A1580045B000DF02E /* GooglePlusSample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
0043C7911580045B000DF02E /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0420;
|
||||
ORGANIZATIONNAME = "Google Inc";
|
||||
};
|
||||
buildConfigurationList = 0043C7941580045B000DF02E /* Build configuration list for PBXProject "GooglePlusSample" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 0043C78F1580045B000DF02E;
|
||||
productRefGroup = 0043C79B1580045B000DF02E /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
0043C7991580045B000DF02E /* GooglePlusSample */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
0043C7981580045B000DF02E /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D9EE743D158A8BD400EC1D05 /* google_plus_share_large.png in Resources */,
|
||||
D9EE743E158A8BD400EC1D05 /* google_plus_share_large@2x.png in Resources */,
|
||||
D9EE743F158A8BD400EC1D05 /* google_plus_share.png in Resources */,
|
||||
D9EE7440158A8BD400EC1D05 /* google_plus_share@2x.png in Resources */,
|
||||
D9EE74E4158A9A7D00EC1D05 /* google_plus_sign_in_wide.png in Resources */,
|
||||
D9EE74E5158A9A7D00EC1D05 /* google_plus_sign_in_wide@2x.png in Resources */,
|
||||
D9EE74E6158A9A7D00EC1D05 /* google_plus_sign_in.png in Resources */,
|
||||
D9EE74E7158A9A7D00EC1D05 /* google_plus_sign_in@2x.png in Resources */,
|
||||
D9EE74AB158A8C0E00EC1D05 /* GTMOAuth2ViewTouch.xib in Resources */,
|
||||
D9EE74C4158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.xib in Resources */,
|
||||
D9EE74C6158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.xib in Resources */,
|
||||
D9EE74C8158A8E0500EC1D05 /* GooglePlusSampleShareViewController.xib in Resources */,
|
||||
D9EE74CA158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.xib in Resources */,
|
||||
D9EE74CD158A8E2900EC1D05 /* InfoPlist.strings in Resources */,
|
||||
0C52D6F8158BAB1F001510E6 /* button_background.png in Resources */,
|
||||
D98254A815990D8D0060CA47 /* Icon_2x.png in Resources */,
|
||||
D98254A915990D8D0060CA47 /* Icon.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
0043C7961580045B000DF02E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
00F70E83158006DC0077799E /* main.m in Sources */,
|
||||
D9EE748D158A8C0E00EC1D05 /* GTLBase64.m in Sources */,
|
||||
D9EE748E158A8C0E00EC1D05 /* GTLBatchQuery.m in Sources */,
|
||||
D9EE748F158A8C0E00EC1D05 /* GTLBatchResult.m in Sources */,
|
||||
D9EE7490158A8C0E00EC1D05 /* GTLDateTime.m in Sources */,
|
||||
D9EE7491158A8C0E00EC1D05 /* GTLErrorObject.m in Sources */,
|
||||
D9EE7492158A8C0E00EC1D05 /* GTLFramework.m in Sources */,
|
||||
D9EE7493158A8C0E00EC1D05 /* GTLJSONParser.m in Sources */,
|
||||
D9EE7494158A8C0E00EC1D05 /* GTLObject.m in Sources */,
|
||||
D9EE7495158A8C0E00EC1D05 /* GTLPlusConstants.m in Sources */,
|
||||
D9EE7496158A8C0E00EC1D05 /* GTLPlusItemScope.m in Sources */,
|
||||
D9EE7497158A8C0E00EC1D05 /* GTLPlusMoment.m in Sources */,
|
||||
D9EE7499158A8C0E00EC1D05 /* GTLQueryPlus.m in Sources */,
|
||||
D9EE749A158A8C0E00EC1D05 /* GTLServicePlus.m in Sources */,
|
||||
D9EE749B158A8C0E00EC1D05 /* GTLQuery.m in Sources */,
|
||||
D9EE749C158A8C0E00EC1D05 /* GTLRuntimeCommon.m in Sources */,
|
||||
D9EE749D158A8C0E00EC1D05 /* GTLService.m in Sources */,
|
||||
D9EE749E158A8C0E00EC1D05 /* GTLUploadParameters.m in Sources */,
|
||||
D9EE749F158A8C0E00EC1D05 /* GTLUtilities.m in Sources */,
|
||||
D9EE74A0158A8C0E00EC1D05 /* GTMHTTPFetcher.m in Sources */,
|
||||
D9EE74A1158A8C0E00EC1D05 /* GTMHTTPFetcherLogging.m in Sources */,
|
||||
D9EE74A2158A8C0E00EC1D05 /* GTMHTTPFetcherService.m in Sources */,
|
||||
D9EE74A3158A8C0E00EC1D05 /* GTMHTTPFetchHistory.m in Sources */,
|
||||
D9EE74A4158A8C0E00EC1D05 /* GTMLogger.m in Sources */,
|
||||
D9EE74A5158A8C0E00EC1D05 /* GTMMethodCheck.m in Sources */,
|
||||
D9EE74A6158A8C0E00EC1D05 /* GTMNSDictionary+URLArguments.m in Sources */,
|
||||
D9EE74A7158A8C0E00EC1D05 /* GTMNSString+URLArguments.m in Sources */,
|
||||
D9EE74A8158A8C0E00EC1D05 /* GTMOAuth2Authentication.m in Sources */,
|
||||
D9EE74A9158A8C0E00EC1D05 /* GTMOAuth2SignIn.m in Sources */,
|
||||
D9EE74AA158A8C0E00EC1D05 /* GTMOAuth2ViewControllerTouch.m in Sources */,
|
||||
D9EE74AC158A8C0E00EC1D05 /* GTMObjC2Runtime.m in Sources */,
|
||||
D9EE74C2158A8E0500EC1D05 /* GooglePlusSampleAppDelegate.m in Sources */,
|
||||
D9EE74C3158A8E0500EC1D05 /* GooglePlusSampleMasterViewController.m in Sources */,
|
||||
D9EE74C5158A8E0500EC1D05 /* GooglePlusSampleMomentsViewController.m in Sources */,
|
||||
D9EE74C7158A8E0500EC1D05 /* GooglePlusSampleShareViewController.m in Sources */,
|
||||
D9EE74C9158A8E0500EC1D05 /* GooglePlusSampleSignInViewController.m in Sources */,
|
||||
D98254F2159937730060CA47 /* GTLPlusPerson.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
D9EE74CB158A8E2900EC1D05 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
D9EE74CC158A8E2900EC1D05 /* en */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
0043C7B01580045B000DF02E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
"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_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-all_load",
|
||||
"-ObjC",
|
||||
);
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
0043C7B11580045B000DF02E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
|
||||
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
||||
OTHER_LDFLAGS = (
|
||||
"-all_load",
|
||||
"-ObjC",
|
||||
);
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
0043C7B31580045B000DF02E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "GooglePlusSample-Prefix.pch";
|
||||
INFOPLIST_FILE = "GooglePlusSample-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)\"",
|
||||
"\"$(SRCROOT)/../lib\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-all_load",
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
0043C7B41580045B000DF02E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "GooglePlusSample-Prefix.pch";
|
||||
INFOPLIST_FILE = "GooglePlusSample-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)\"",
|
||||
"\"$(SRCROOT)/../lib\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-all_load",
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
0043C7941580045B000DF02E /* Build configuration list for PBXProject "GooglePlusSample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
0043C7B01580045B000DF02E /* Debug */,
|
||||
0043C7B11580045B000DF02E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
0043C7B21580045B000DF02E /* Build configuration list for PBXNativeTarget "GooglePlusSample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
0043C7B31580045B000DF02E /* Debug */,
|
||||
0043C7B41580045B000DF02E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 0043C7911580045B000DF02E /* Project object */;
|
||||
}
|
7
External/google-plus-ios-sdk/SampleCode/GooglePlusSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:GooglePlusSample.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0043C7991580045B000DF02E"
|
||||
BuildableName = "GooglePlusSample.app"
|
||||
BlueprintName = "GooglePlusSample"
|
||||
ReferencedContainer = "container:GooglePlusSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0043C7991580045B000DF02E"
|
||||
BuildableName = "GooglePlusSample.app"
|
||||
BlueprintName = "GooglePlusSample"
|
||||
ReferencedContainer = "container:GooglePlusSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0043C7991580045B000DF02E"
|
||||
BuildableName = "GooglePlusSample.app"
|
||||
BlueprintName = "GooglePlusSample"
|
||||
ReferencedContainer = "container:GooglePlusSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0043C7991580045B000DF02E"
|
||||
BuildableName = "GooglePlusSample.app"
|
||||
BlueprintName = "GooglePlusSample"
|
||||
ReferencedContainer = "container:GooglePlusSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>GooglePlusSample.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>0043C7991580045B000DF02E</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
41
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleAppDelegate.h
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// GooglePlusSampleAppDelegate.h
|
||||
//
|
||||
// Copyright 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 <UIKit/UIKit.h>
|
||||
|
||||
@class GooglePlusShare;
|
||||
@class GooglePlusSignInButton;
|
||||
@class GTMOAuth2Authentication;
|
||||
|
||||
@interface GooglePlusSampleAppDelegate : UIResponder<UIApplicationDelegate>
|
||||
|
||||
// The sample app's |UIWindow|.
|
||||
@property (retain, nonatomic) UIWindow *window;
|
||||
// The navigation controller.
|
||||
@property (retain, nonatomic) UINavigationController *navigationController;
|
||||
// The Google+ sign-in button to handle the URL redirect.
|
||||
@property (retain, nonatomic) GooglePlusSignInButton *signInButton;
|
||||
// The OAuth 2.0 authentication used in the application.
|
||||
@property (retain, nonatomic) GTMOAuth2Authentication *auth;
|
||||
// The Google+ share object to handle the URL redirect.
|
||||
@property (retain, nonatomic) GooglePlusShare *share;
|
||||
|
||||
// The OAuth 2.0 client ID to be used for Google+ sign-in, share, and moments.
|
||||
+ (NSString *)clientID;
|
||||
|
||||
@end
|
89
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleAppDelegate.m
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
//
|
||||
// GooglePlusSampleAppDelegate.m
|
||||
//
|
||||
// Copyright 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 "GooglePlusSampleAppDelegate.h"
|
||||
|
||||
#import "GooglePlusSampleMasterViewController.h"
|
||||
#import "GooglePlusSignIn.h"
|
||||
#import "GooglePlusSignInButton.h"
|
||||
|
||||
@implementation GooglePlusSampleAppDelegate
|
||||
|
||||
@synthesize window = window_;
|
||||
@synthesize navigationController = navigationController_;
|
||||
@synthesize signInButton = signInButton_;
|
||||
@synthesize auth = auth_;
|
||||
@synthesize share = share_;
|
||||
|
||||
// DO NOT USE THIS CLIENT ID. IT WILL NOT WORK FOR YOUR APP.
|
||||
// Please use the client ID created for you by Google.
|
||||
static NSString * const kClientID = @"571459971810-"
|
||||
@"2bpoda566pap5kkc0aqljqfjki8tgeb6.apps.googleusercontent.com";
|
||||
|
||||
+ (NSString *)clientID {
|
||||
return kClientID;
|
||||
}
|
||||
|
||||
#pragma mark Object life-cycle.
|
||||
|
||||
- (void)dealloc {
|
||||
[window_ release];
|
||||
[navigationController_ release];
|
||||
[signInButton_ release];
|
||||
[auth_ release];
|
||||
[share_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
self.window = [[[UIWindow alloc]
|
||||
initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
|
||||
GooglePlusSampleMasterViewController *masterViewController =
|
||||
[[[GooglePlusSampleMasterViewController alloc]
|
||||
initWithNibName:@"GooglePlusSampleMasterViewController"
|
||||
bundle:nil] autorelease];
|
||||
self.navigationController =
|
||||
[[[UINavigationController alloc]
|
||||
initWithRootViewController:masterViewController] autorelease];
|
||||
self.window.rootViewController = self.navigationController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
openURL:(NSURL *)url
|
||||
sourceApplication:(NSString *)sourceApplication
|
||||
annotation:(id)annotation {
|
||||
// Handle Google+ share dialog URL.
|
||||
if ([share_ handleURL:url
|
||||
sourceApplication:sourceApplication
|
||||
annotation:annotation]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Handle Google+ sign-in button URL.
|
||||
if ([signInButton_ handleURL:url
|
||||
sourceApplication:sourceApplication
|
||||
annotation:annotation]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
23
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleMasterViewController.h
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// GooglePlusSampleMasterViewController.h
|
||||
//
|
||||
// Copyright 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface GooglePlusSampleMasterViewController : UITableViewController
|
||||
|
||||
@end
|
98
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleMasterViewController.m
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// GooglePlusSampleMasterViewController.m
|
||||
//
|
||||
// Copyright 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 "GooglePlusSampleMasterViewController.h"
|
||||
|
||||
#import "GooglePlusSampleShareViewController.h"
|
||||
#import "GooglePlusSampleSignInViewController.h"
|
||||
#import "GooglePlusSampleMomentsViewController.h"
|
||||
|
||||
static const int kNumViewControllers = 3;
|
||||
static NSString * const kMenuOptions[kNumViewControllers] = {
|
||||
@"Sign In", @"Share", @"Moments" };
|
||||
static NSString * const kNibNames[kNumViewControllers] = {
|
||||
@"GooglePlusSampleSignInViewController",
|
||||
@"GooglePlusSampleShareViewController",
|
||||
@"GooglePlusSampleMomentsViewController" };
|
||||
|
||||
@implementation GooglePlusSampleMasterViewController
|
||||
|
||||
- (id)initWithNibName:(NSString *)nibNameOrNil
|
||||
bundle:(NSBundle *)nibBundleOrNil {
|
||||
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
||||
if (self) {
|
||||
self.title = @"Google+ SDK Sample";
|
||||
UIBarButtonItem *backButton = [[[UIBarButtonItem alloc]
|
||||
initWithTitle:@"Back"
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:self
|
||||
action:@selector(backPressed)] autorelease];
|
||||
self.navigationItem.backBarButtonItem = backButton;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)
|
||||
interfaceOrientation {
|
||||
if ([[UIDevice currentDevice] userInterfaceIdiom] ==
|
||||
UIUserInterfaceIdiomPhone) {
|
||||
return interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate/UITableViewDataSource
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView
|
||||
numberOfRowsInSection:(NSInteger)section {
|
||||
return kNumViewControllers;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView
|
||||
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
static NSString * const kCellIdentifier = @"Cell";
|
||||
UITableViewCell *cell =
|
||||
[tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
|
||||
if (cell == nil) {
|
||||
cell =
|
||||
[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
|
||||
reuseIdentifier:kCellIdentifier] autorelease];
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
}
|
||||
|
||||
cell.textLabel.text = kMenuOptions[indexPath.row];
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView
|
||||
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
Class nibClass = NSClassFromString(kNibNames[indexPath.row]);
|
||||
UIViewController *controller =
|
||||
[[[nibClass alloc] initWithNibName:nil bundle:nil] autorelease];
|
||||
controller.navigationItem.title = kMenuOptions[indexPath.row];
|
||||
|
||||
[self.navigationController pushViewController:controller animated:YES];
|
||||
}
|
||||
|
||||
@end
|
251
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleMasterViewController.xib
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1280</int>
|
||||
<string key="IBDocument.SystemVersion">10K549</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">1938</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.36</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">933</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBUINavigationItem</string>
|
||||
<string>IBUITableView</string>
|
||||
<string>IBUITableViewController</string>
|
||||
<string>IBUINavigationController</string>
|
||||
<string>IBUINavigationBar</string>
|
||||
<string>IBProxyObject</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</array>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<object class="IBProxyObject" id="841351856">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="371349661">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUITableView" id="709618507">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<string key="NSFrame">{{0, 20}, {320, 460}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor" id="800680415">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIAlwaysBounceVertical">YES</bool>
|
||||
<int key="IBUISeparatorStyle">1</int>
|
||||
<int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
|
||||
<bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
|
||||
<float key="IBUIRowHeight">44</float>
|
||||
<float key="IBUISectionHeaderHeight">22</float>
|
||||
<float key="IBUISectionFooterHeight">22</float>
|
||||
</object>
|
||||
<object class="IBUINavigationController" id="271496582">
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
<object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
|
||||
<int key="IBUIInterfaceOrientation">1</int>
|
||||
<int key="interfaceOrientation">1</int>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIHorizontal">NO</bool>
|
||||
<object class="IBUINavigationBar" key="IBUINavigationBar" id="264651278">
|
||||
<nil key="NSNextResponder"/>
|
||||
<int key="NSvFlags">256</int>
|
||||
<string key="NSFrameSize">{0, 0}</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<bool key="IBUIMultipleTouchEnabled">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<array key="IBUIViewControllers">
|
||||
<object class="IBUITableViewController" id="84492071">
|
||||
<object class="IBUITableView" key="IBUIView" id="1024288683">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<string key="NSFrame">{{0, 64}, {320, 416}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<reference key="IBUIBackgroundColor" ref="800680415"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIAlwaysBounceVertical">YES</bool>
|
||||
<int key="IBUISeparatorStyle">1</int>
|
||||
<int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
|
||||
<bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
|
||||
<float key="IBUIRowHeight">44</float>
|
||||
<float key="IBUISectionHeaderHeight">22</float>
|
||||
<float key="IBUISectionFooterHeight">22</float>
|
||||
</object>
|
||||
<object class="IBUINavigationItem" key="IBUINavigationItem" id="848890509">
|
||||
<reference key="IBUINavigationBar"/>
|
||||
<string key="IBUITitle">Google Plus Sample App</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<reference key="IBUIParentViewController" ref="271496582"/>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
<object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
|
||||
<int key="IBUIInterfaceOrientation">1</int>
|
||||
<int key="interfaceOrientation">1</int>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIHorizontal">NO</bool>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<array class="NSMutableArray" key="connectionRecords">
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">view</string>
|
||||
<reference key="source" ref="841351856"/>
|
||||
<reference key="destination" ref="709618507"/>
|
||||
</object>
|
||||
<int key="connectionID">3</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">dataSource</string>
|
||||
<reference key="source" ref="709618507"/>
|
||||
<reference key="destination" ref="841351856"/>
|
||||
</object>
|
||||
<int key="connectionID">4</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="709618507"/>
|
||||
<reference key="destination" ref="841351856"/>
|
||||
</object>
|
||||
<int key="connectionID">5</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="1024288683"/>
|
||||
<reference key="destination" ref="84492071"/>
|
||||
</object>
|
||||
<int key="connectionID">12</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">dataSource</string>
|
||||
<reference key="source" ref="1024288683"/>
|
||||
<reference key="destination" ref="84492071"/>
|
||||
</object>
|
||||
<int key="connectionID">13</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<array key="object" id="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="841351856"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="371349661"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">2</int>
|
||||
<reference key="object" ref="709618507"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">6</int>
|
||||
<reference key="object" ref="271496582"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="264651278"/>
|
||||
<reference ref="84492071"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">7</int>
|
||||
<reference key="object" ref="264651278"/>
|
||||
<reference key="parent" ref="271496582"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">10</int>
|
||||
<reference key="object" ref="84492071"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="1024288683"/>
|
||||
<reference ref="848890509"/>
|
||||
</array>
|
||||
<reference key="parent" ref="271496582"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">11</int>
|
||||
<reference key="object" ref="1024288683"/>
|
||||
<reference key="parent" ref="84492071"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">14</int>
|
||||
<reference key="object" ref="848890509"/>
|
||||
<reference key="parent" ref="84492071"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
<string key="-1.CustomClassName">GooglePlusSampleMasterViewController</string>
|
||||
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="-2.CustomClassName">UIResponder</string>
|
||||
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="11.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">14</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">GooglePlusSampleMasterViewController</string>
|
||||
<string key="superclassName">UITableViewController</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/GooglePlusSampleMasterViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<string key="IBCocoaTouchPluginVersion">933</string>
|
||||
</data>
|
||||
</archive>
|
45
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleMomentsViewController.h
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// GooglePlusSampleMomentsViewController.h
|
||||
//
|
||||
// Copyright 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 <UIKit/UIKit.h>
|
||||
|
||||
@class GTLServicePlus;
|
||||
|
||||
// A view controller for writing different kinds of moments to Google+ history.
|
||||
// The open-source GTLPlus libraries are required. For more details, see
|
||||
// https://developers.google.com/+/history/ .
|
||||
@interface GooglePlusSampleMomentsViewController : UIViewController<
|
||||
UITableViewDelegate,
|
||||
UITableViewDataSource,
|
||||
UITextFieldDelegate> {
|
||||
BOOL keyboardVisible_;
|
||||
}
|
||||
|
||||
// The table that displays the different kinds of moments available.
|
||||
@property (retain, nonatomic) IBOutlet UITableView *momentsTable;
|
||||
// The target URL to associate with this moment.
|
||||
@property (retain, nonatomic) IBOutlet UITextField *momentURL;
|
||||
// A label to display the result of writing a moment.
|
||||
@property (retain, nonatomic) IBOutlet UILabel *momentStatus;
|
||||
// The "Add Moment" button.
|
||||
@property (retain, nonatomic) IBOutlet UIButton *addButton;
|
||||
|
||||
// Called when the user presses the "Add Moment" button.
|
||||
- (IBAction)momentButton:(id)sender;
|
||||
|
||||
@end
|
334
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleMomentsViewController.m
vendored
Normal file
@ -0,0 +1,334 @@
|
||||
//
|
||||
// GooglePlusSampleMomentsViewController.m
|
||||
//
|
||||
// Copyright 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 "GooglePlusSampleMomentsViewController.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "GTLPlus.h"
|
||||
#import "GTLPlusConstants.h"
|
||||
#import "GTLPlusItemScope.h"
|
||||
#import "GTLPlusMoment.h"
|
||||
#import "GTLQueryPlus.h"
|
||||
#import "GTLServicePlus.h"
|
||||
#import "GTMLogger.h"
|
||||
#import "GTMOAuth2Authentication.h"
|
||||
#import "GooglePlusSampleAppDelegate.h"
|
||||
|
||||
@interface GooglePlusSampleMomentsViewController ()
|
||||
- (GTLPlusItemScope *)resultFor:(NSString *)selectedMoment;
|
||||
- (void)animateKeyboard:(NSNotification *)notification
|
||||
shouldShow:(BOOL)shouldShow;
|
||||
- (NSString *)momentURLForIndex:(int)i;
|
||||
- (void)reportAuthStatus;
|
||||
@end
|
||||
|
||||
@implementation GooglePlusSampleMomentsViewController
|
||||
|
||||
@synthesize momentsTable = momentsTable_;
|
||||
@synthesize momentURL = momentURL_;
|
||||
@synthesize momentStatus = momentStatus_;
|
||||
@synthesize addButton = addButton_;
|
||||
|
||||
// The different kinds of moments.
|
||||
static const int kNumMomentTypes = 9;
|
||||
static NSString * const kMomentTypes[kNumMomentTypes] = {
|
||||
@"AddActivity",
|
||||
@"BuyActivity",
|
||||
@"CheckInActivity",
|
||||
@"CommentActivity",
|
||||
@"CreateActivity",
|
||||
@"ListenActivity",
|
||||
@"ReserveActivity",
|
||||
@"ReviewActivity",
|
||||
@"ViewActivity" };
|
||||
static NSString * const kMomentURLs[kNumMomentTypes] = {
|
||||
@"thing",
|
||||
@"a-book",
|
||||
@"place",
|
||||
@"blog-entry",
|
||||
@"photo",
|
||||
@"song",
|
||||
@"restaurant",
|
||||
@"widget",
|
||||
@"video" };
|
||||
static NSString * const kMomentURLFormat =
|
||||
@"https://developers.google.com/+/plugins/snippet/examples/%@";
|
||||
|
||||
#pragma mark - Object lifecycle
|
||||
|
||||
- (void)dealloc {
|
||||
// Unregister for keyboard notifications while not visible.
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
[momentsTable_ release];
|
||||
[momentURL_ release];
|
||||
[momentStatus_ release];
|
||||
[addButton_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
- (void)viewDidLoad {
|
||||
// Set up "Add Moment" button.
|
||||
[[addButton_ layer] setCornerRadius:5];
|
||||
[[addButton_ layer] setMasksToBounds:YES];
|
||||
CGColorRef borderColor = [[UIColor colorWithWhite:203.0/255.0
|
||||
alpha:1.0] CGColor];
|
||||
[[addButton_ layer] setBorderColor:borderColor];
|
||||
[[addButton_ layer] setBorderWidth:1.0];
|
||||
|
||||
// Set up sample view of writing moments.
|
||||
int selectedRow = [[momentsTable_ indexPathForSelectedRow] row];
|
||||
momentURL_.text = [self momentURLForIndex:selectedRow];
|
||||
|
||||
[self reportAuthStatus];
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Register for keyboard notifications while visible.
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(keyboardWillShow:)
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(keyboardWillHide:)
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
// Unregister for keyboard notifications while not visible.
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
#pragma mark - IBActions
|
||||
|
||||
- (IBAction)momentButton:(id)sender {
|
||||
GooglePlusSampleAppDelegate *appDelegate = (GooglePlusSampleAppDelegate *)
|
||||
[[UIApplication sharedApplication] delegate];
|
||||
if (!appDelegate.auth) {
|
||||
// To authenticate, use Google+ sign-in button.
|
||||
momentStatus_.text = @"Status: Not authenticated";
|
||||
return;
|
||||
}
|
||||
|
||||
// Here is an example of writing a moment to Google+ history:
|
||||
// 1. Create a |GTLServicePlus| instance to send a request to Google+.
|
||||
GTLServicePlus* plusService = [[[GTLServicePlus alloc] init] autorelease];
|
||||
plusService.retryEnabled = YES;
|
||||
|
||||
// 2. Set a valid |GTMOAuth2Authentication| object as the authorizer.
|
||||
[plusService setAuthorizer:appDelegate.auth];
|
||||
|
||||
// 3. Create a |GTLPlusMoment| object with required fields. For reference, see
|
||||
// https://developers.google.com/+/history/ .
|
||||
int selectedRow = [[momentsTable_ indexPathForSelectedRow] row];
|
||||
NSString *selectedMoment = kMomentTypes[selectedRow];
|
||||
|
||||
GTLPlusMoment *moment = [[[GTLPlusMoment alloc] init] autorelease];
|
||||
moment.type = [NSString stringWithFormat:@"https://schemas.google.com/%@",
|
||||
selectedMoment];
|
||||
GTLPlusItemScope *target = [[[GTLPlusItemScope alloc] init] autorelease];
|
||||
target.url = momentURL_.text;
|
||||
if ([target.url isEqualToString:@""]) {
|
||||
target.url = [self momentURLForIndex:selectedRow];
|
||||
}
|
||||
moment.target = target;
|
||||
|
||||
// CommentActivity, ReserveActivity, and ReviewActivity require setting a
|
||||
// |result| field in the request.
|
||||
GTLPlusItemScope *result = [self resultFor:selectedMoment];
|
||||
if (result) {
|
||||
moment.result = result;
|
||||
}
|
||||
|
||||
// 4. Create a |GTLQuery| object to write a moment.
|
||||
GTLQueryPlus *query =
|
||||
[GTLQueryPlus queryForMomentsInsertWithObject:moment
|
||||
userId:@"me"
|
||||
collection:kGTLPlusCollectionVault];
|
||||
|
||||
[plusService executeQuery:query
|
||||
completionHandler:^(GTLServiceTicket *ticket,
|
||||
id object,
|
||||
NSError *error) {
|
||||
if (error) {
|
||||
GTMLoggerError(@"Error: %@", error);
|
||||
momentStatus_.text =
|
||||
[NSString stringWithFormat:@"Status: Error: %@", error];
|
||||
} else {
|
||||
momentStatus_.text = [NSString stringWithFormat:
|
||||
@"Status: Saved to Google+ history (%@)",
|
||||
selectedMoment];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate/UITableViewDataSource
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView
|
||||
numberOfRowsInSection:(NSInteger)section {
|
||||
return kNumMomentTypes;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView
|
||||
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
static NSString * const kCellIdentifier = @"Cell";
|
||||
UITableViewCell *cell =
|
||||
[tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
|
||||
if (cell == nil) {
|
||||
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
|
||||
reuseIdentifier:kCellIdentifier]
|
||||
autorelease];
|
||||
cell.accessoryType = UITableViewCellAccessoryNone;
|
||||
}
|
||||
|
||||
// Configure the cell.
|
||||
cell.textLabel.text = kMomentTypes[indexPath.row];
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView
|
||||
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
int selectedRow = [[momentsTable_ indexPathForSelectedRow] row];
|
||||
momentURL_.text = [self momentURLForIndex:selectedRow];
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - UIKeyboard
|
||||
|
||||
- (void)keyboardWillShow:(NSNotification *)notification {
|
||||
[self animateKeyboard:notification shouldShow:YES];
|
||||
}
|
||||
|
||||
- (void)keyboardWillHide:(NSNotification *)notification {
|
||||
[self animateKeyboard:notification shouldShow:NO];
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
// Helps set required result field for select moment types.
|
||||
- (GTLPlusItemScope *)resultFor:(NSString *)selectedMoment {
|
||||
GTLPlusItemScope *result = [[[GTLPlusItemScope alloc] init] autorelease];
|
||||
if ([selectedMoment isEqualToString:@"CommentActivity"]) {
|
||||
result.type = @"http://schema.org/Comment";
|
||||
result.url =
|
||||
@"https://developers.google.com/+/plugins/snippet/examples/blog-entry#comment-1";
|
||||
result.name = @"This is amazing!";
|
||||
result.text = @"I can't wait to use it on my site :)";
|
||||
return result;
|
||||
} else if ([selectedMoment isEqualToString:@"ReserveActivity"]) {
|
||||
result.type = @"http://schema.org/Reservation";
|
||||
result.startDate = @"2012-06-28T19:00:00-08:00";
|
||||
result.attendeeCount = [[[NSNumber alloc] initWithInt:3] autorelease];
|
||||
return result;
|
||||
} else if ([selectedMoment isEqualToString:@"ReviewActivity"]) {
|
||||
result.type = @"http://schema.org/Review";
|
||||
result.name = @"A Humble Review of Widget";
|
||||
result.url =
|
||||
@"https://developers.google.com/+/plugins/snippet/examples/review";
|
||||
result.text =
|
||||
@"It's amazingly effective at whatever it is that it's supposed to do.";
|
||||
GTLPlusItemScope *rating = [[[GTLPlusItemScope alloc] init] autorelease];
|
||||
rating.type = @"http://schema.org/Rating";
|
||||
rating.ratingValue = @"100";
|
||||
rating.bestRating = @"100";
|
||||
rating.worstRating = @"0";
|
||||
result.reviewRating =
|
||||
[[[NSArray alloc] initWithObjects:rating, nil] autorelease];
|
||||
return result;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Helps animate keyboard for target URL text field.
|
||||
- (void)animateKeyboard:(NSNotification *)notification
|
||||
shouldShow:(BOOL)shouldShow {
|
||||
NSDictionary *userInfo = [notification userInfo];
|
||||
CGFloat height = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey]
|
||||
CGRectValue].size.height;
|
||||
CGFloat duration = [[userInfo
|
||||
objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
|
||||
[UIView beginAnimations:nil context:NULL];
|
||||
[UIView setAnimationDuration:duration];
|
||||
CGRect newFrame = self.view.frame;
|
||||
if (shouldShow) {
|
||||
newFrame.size.height -= height;
|
||||
} else {
|
||||
newFrame.size.height += height;
|
||||
}
|
||||
self.view.frame = newFrame;
|
||||
[UIView commitAnimations];
|
||||
if (shouldShow) {
|
||||
keyboardVisible_ = YES;
|
||||
} else {
|
||||
keyboardVisible_ = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)momentURLForIndex:(int)i {
|
||||
return [NSString stringWithFormat:kMomentURLFormat, kMomentURLs[i]];
|
||||
}
|
||||
|
||||
- (void)reportAuthStatus {
|
||||
NSString *authStatus = @"";
|
||||
GooglePlusSampleAppDelegate *appDelegate = (GooglePlusSampleAppDelegate *)
|
||||
[[UIApplication sharedApplication] delegate];
|
||||
|
||||
if (appDelegate.auth) {
|
||||
authStatus = @"Status: Authenticated";
|
||||
} else {
|
||||
// To authenticate, use Google+ sign-in button.
|
||||
authStatus = @"Status: Not authenticated";
|
||||
}
|
||||
|
||||
momentStatus_.text = authStatus;
|
||||
}
|
||||
|
||||
@end
|
462
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleMomentsViewController.xib
vendored
Normal file
@ -0,0 +1,462 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1280</int>
|
||||
<string key="IBDocument.SystemVersion">10K549</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">1938</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.36</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">933</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBUITextField</string>
|
||||
<string>IBUITableView</string>
|
||||
<string>IBUIButton</string>
|
||||
<string>IBUIView</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBProxyObject</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</array>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<object class="IBProxyObject" id="372490531">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="975951072">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUIView" id="191373211">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUILabel" id="29623071">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">290</int>
|
||||
<string key="NSFrame">{{10, 5}, {296, 21}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="1013113918"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Select an activity (scroll for more)</string>
|
||||
<object class="NSColor" key="IBUITextColor" id="216027142">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MCAwIDAAA</bytes>
|
||||
</object>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">1</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription" id="950407250">
|
||||
<int key="type">1</int>
|
||||
<double key="pointSize">17</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont" id="63576769">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">17</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUITableView" id="1013113918">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<string key="NSFrame">{{0, 32}, {320, 132}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="885245054"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor" id="373936525">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIAlwaysBounceVertical">YES</bool>
|
||||
<int key="IBUISeparatorStyle">1</int>
|
||||
<int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
|
||||
<bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
|
||||
<float key="IBUIRowHeight">44</float>
|
||||
<float key="IBUISectionHeaderHeight">22</float>
|
||||
<float key="IBUISectionFooterHeight">22</float>
|
||||
</object>
|
||||
<object class="IBUIView" id="885245054">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">266</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUILabel" id="625104685">
|
||||
<reference key="NSNextResponder" ref="885245054"/>
|
||||
<int key="NSvFlags">266</int>
|
||||
<string key="NSFrame">{{11, 20}, {296, 21}}</string>
|
||||
<reference key="NSSuperview" ref="885245054"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="621451586"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Enter a Moment URL</string>
|
||||
<reference key="IBUITextColor" ref="216027142"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">1</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<reference key="IBUIFontDescription" ref="950407250"/>
|
||||
<reference key="IBUIFont" ref="63576769"/>
|
||||
</object>
|
||||
<object class="IBUITextField" id="621451586">
|
||||
<reference key="NSNextResponder" ref="885245054"/>
|
||||
<int key="NSvFlags">266</int>
|
||||
<string key="NSFrame">{{11, 51}, {291, 31}}</string>
|
||||
<reference key="NSSuperview" ref="885245054"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="525343048"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<string key="IBUIText"/>
|
||||
<int key="IBUIBorderStyle">3</int>
|
||||
<object class="NSColor" key="IBUITextColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MAA</bytes>
|
||||
<object class="NSColorSpace" key="NSCustomColorSpace" id="523142132">
|
||||
<int key="NSID">2</int>
|
||||
</object>
|
||||
</object>
|
||||
<bool key="IBUIAdjustsFontSizeToFit">YES</bool>
|
||||
<float key="IBUIMinimumFontSize">17</float>
|
||||
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription">
|
||||
<int key="type">1</int>
|
||||
<double key="pointSize">14</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">14</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUIButton" id="525343048">
|
||||
<reference key="NSNextResponder" ref="885245054"/>
|
||||
<int key="NSvFlags">264</int>
|
||||
<string key="NSFrame">{{12, 113}, {142, 37}}</string>
|
||||
<reference key="NSSuperview" ref="885245054"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="851809288"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<string key="IBUINormalTitle">Add Moment</string>
|
||||
<object class="NSColor" key="IBUIHighlightedTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC40MzkyMTU2ODYzIDAuMTI1NDkwMTk2MSAwLjA2Mjc0NTA5ODA0AA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC42MzUyOTQxMTc2IDAuMzIxNTY4NjI3NSAwLjI1ODgyMzUyOTQAA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleShadowColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MC41AA</bytes>
|
||||
</object>
|
||||
<object class="NSCustomResource" key="IBUINormalBackgroundImage">
|
||||
<string key="NSClassName">NSImage</string>
|
||||
<string key="NSResourceName">button_background.png</string>
|
||||
</object>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription">
|
||||
<int key="type">2</int>
|
||||
<double key="pointSize">15</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">15</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUILabel" id="851809288">
|
||||
<reference key="NSNextResponder" ref="885245054"/>
|
||||
<int key="NSvFlags">266</int>
|
||||
<string key="NSFrame">{{11, 180}, {290, 21}}</string>
|
||||
<reference key="NSSuperview" ref="885245054"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Status:</string>
|
||||
<reference key="IBUITextColor" ref="216027142"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">1</int>
|
||||
<float key="IBUIMinimumFontSize">11</float>
|
||||
<reference key="IBUIFontDescription" ref="950407250"/>
|
||||
<reference key="IBUIFont" ref="63576769"/>
|
||||
</object>
|
||||
</array>
|
||||
<string key="NSFrame">{{0, 172}, {320, 244}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="625104685"/>
|
||||
<reference key="IBUIBackgroundColor" ref="373936525"/>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
</array>
|
||||
<string key="NSFrame">{{0, 64}, {320, 416}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="29623071"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
<reference key="NSCustomColorSpace" ref="523142132"/>
|
||||
</object>
|
||||
<array key="IBUIGestureRecognizers" id="0"/>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
<object class="IBUISimulatedNavigationBarMetrics" key="IBUISimulatedTopBarMetrics">
|
||||
<bool key="IBUIPrompted">NO</bool>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<array class="NSMutableArray" key="connectionRecords">
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">view</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="191373211"/>
|
||||
</object>
|
||||
<int key="connectionID">3</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">momentsTable</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="1013113918"/>
|
||||
</object>
|
||||
<int key="connectionID">17</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">momentStatus</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="851809288"/>
|
||||
</object>
|
||||
<int key="connectionID">25</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">addButton</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="525343048"/>
|
||||
</object>
|
||||
<int key="connectionID">28</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">momentURL</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="621451586"/>
|
||||
</object>
|
||||
<int key="connectionID">30</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">dataSource</string>
|
||||
<reference key="source" ref="1013113918"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">18</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="1013113918"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">19</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="621451586"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">31</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">momentButton:</string>
|
||||
<reference key="source" ref="525343048"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">20</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<reference key="object" ref="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">1</int>
|
||||
<reference key="object" ref="191373211"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="29623071"/>
|
||||
<reference ref="885245054"/>
|
||||
<reference ref="1013113918"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="372490531"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="975951072"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">7</int>
|
||||
<reference key="object" ref="1013113918"/>
|
||||
<array class="NSMutableArray" key="children"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">26</int>
|
||||
<reference key="object" ref="29623071"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">27</int>
|
||||
<reference key="object" ref="885245054"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="621451586"/>
|
||||
<reference ref="525343048"/>
|
||||
<reference ref="625104685"/>
|
||||
<reference ref="851809288"/>
|
||||
</array>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">13</int>
|
||||
<reference key="object" ref="625104685"/>
|
||||
<reference key="parent" ref="885245054"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">12</int>
|
||||
<reference key="object" ref="621451586"/>
|
||||
<reference key="parent" ref="885245054"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">16</int>
|
||||
<reference key="object" ref="525343048"/>
|
||||
<reference key="parent" ref="885245054"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">22</int>
|
||||
<reference key="object" ref="851809288"/>
|
||||
<reference key="parent" ref="885245054"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
<string key="-1.CustomClassName">GooglePlusSampleMomentsViewController</string>
|
||||
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="-2.CustomClassName">UIResponder</string>
|
||||
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="13.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="16.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<real value="0.0" key="16.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
|
||||
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="26.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="27.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">31</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">GooglePlusSampleMomentsViewController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<object class="NSMutableDictionary" key="actions">
|
||||
<string key="NS.key.0">momentButton:</string>
|
||||
<string key="NS.object.0">id</string>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="actionInfosByName">
|
||||
<string key="NS.key.0">momentButton:</string>
|
||||
<object class="IBActionInfo" key="NS.object.0">
|
||||
<string key="name">momentButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="outlets">
|
||||
<string key="addButton">UIButton</string>
|
||||
<string key="momentStatus">UILabel</string>
|
||||
<string key="momentURL">UITextField</string>
|
||||
<string key="momentsTable">UITableView</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<object class="IBToOneOutletInfo" key="addButton">
|
||||
<string key="name">addButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="momentStatus">
|
||||
<string key="name">momentStatus</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="momentURL">
|
||||
<string key="name">momentURL</string>
|
||||
<string key="candidateClassName">UITextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="momentsTable">
|
||||
<string key="name">momentsTable</string>
|
||||
<string key="candidateClassName">UITableView</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/GooglePlusSampleMomentsViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
|
||||
<string key="NS.key.0">button_background.png</string>
|
||||
<string key="NS.object.0">{1, 1}</string>
|
||||
</object>
|
||||
<string key="IBCocoaTouchPluginVersion">933</string>
|
||||
</data>
|
||||
</archive>
|
50
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleShareViewController.h
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// GooglePlusSampleShareViewController.h
|
||||
//
|
||||
// Copyright 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 <MessageUI/MFMailComposeViewController.h>
|
||||
#import <MessageUI/MessageUI.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "GooglePlusShare.h"
|
||||
|
||||
// A view controller for the Google+ share dialog which contains a text field
|
||||
// to prefill the user comment, and a text field for an optional URL to share.
|
||||
// A Google+ share button is provided to launch the share dialog.
|
||||
@interface GooglePlusSampleShareViewController : UIViewController<
|
||||
GooglePlusShareDelegate,
|
||||
UITextFieldDelegate,
|
||||
UIActionSheetDelegate,
|
||||
MFMailComposeViewControllerDelegate> {
|
||||
// The Google+ share object to manage the share dialog.
|
||||
GooglePlusShare *share_;
|
||||
}
|
||||
|
||||
// The text to prefill the user comment in the share dialog.
|
||||
@property (retain, nonatomic) IBOutlet UITextField *sharePrefillText;
|
||||
// The URL resource to share in the share dialog.
|
||||
@property (retain, nonatomic) IBOutlet UITextField *shareURL;
|
||||
// A label to display the result of the share action.
|
||||
@property (retain, nonatomic) IBOutlet UILabel *shareStatus;
|
||||
// A toolbar to share via Google+ or email.
|
||||
@property (retain, nonatomic) IBOutlet UIToolbar *shareToolbar;
|
||||
|
||||
// Called when the share button is pressed.
|
||||
- (IBAction)shareButton:(id)sender;
|
||||
// Called when the toolbar share button is pressed.
|
||||
- (IBAction)shareToolbar:(id)sender;
|
||||
|
||||
@end
|
145
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleShareViewController.m
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
//
|
||||
// GooglePlusSampleShareViewController.m
|
||||
//
|
||||
// Copyright 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 "GooglePlusSampleShareViewController.h"
|
||||
|
||||
#import "GooglePlusSampleAppDelegate.h"
|
||||
|
||||
@implementation GooglePlusSampleShareViewController
|
||||
|
||||
@synthesize sharePrefillText = sharePrefillText_;
|
||||
@synthesize shareURL = shareURL_;
|
||||
@synthesize shareStatus = shareStatus_;
|
||||
@synthesize shareToolbar = shareToolbar_;
|
||||
|
||||
- (void)dealloc {
|
||||
[sharePrefillText_ release];
|
||||
[shareURL_ release];
|
||||
[shareStatus_ release];
|
||||
[share_ release];
|
||||
[shareToolbar_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
- (void)viewDidLoad {
|
||||
// Set up Google+ share dialog.
|
||||
GooglePlusSampleAppDelegate *appDelegate = (GooglePlusSampleAppDelegate *)
|
||||
[[UIApplication sharedApplication] delegate];
|
||||
NSString *clientID = [GooglePlusSampleAppDelegate clientID];
|
||||
share_ = [[GooglePlusShare alloc] initWithClientID:clientID];
|
||||
share_.delegate = self;
|
||||
appDelegate.share = share_;
|
||||
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewDidUnload {
|
||||
GooglePlusSampleAppDelegate *appDelegate = (GooglePlusSampleAppDelegate *)
|
||||
[[UIApplication sharedApplication] delegate];
|
||||
appDelegate.share = nil;
|
||||
share_.delegate = nil;
|
||||
[share_ release];
|
||||
share_ = nil;
|
||||
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - GooglePlusShareDelegate
|
||||
|
||||
- (void)finishedSharing:(BOOL)shared {
|
||||
NSString *text = shared ? @"Success" : @"Canceled";
|
||||
shareStatus_.text = [NSString stringWithFormat:@"Status: %@", text];
|
||||
}
|
||||
|
||||
#pragma mark - UIActionSheetDelegate
|
||||
|
||||
- (void)actionSheet:(UIActionSheet *)actionSheet
|
||||
didDismissWithButtonIndex:(NSInteger)buttonIndex {
|
||||
if (buttonIndex == 0) {
|
||||
[self shareButton:nil];
|
||||
} else if (buttonIndex == 1) {
|
||||
shareStatus_.text = @"Status: Sharing...";
|
||||
MFMailComposeViewController *picker =
|
||||
[[[MFMailComposeViewController alloc] init] autorelease];
|
||||
picker.mailComposeDelegate = self;
|
||||
[picker setSubject:sharePrefillText_.text];
|
||||
[picker setMessageBody:shareURL_.text isHTML:NO];
|
||||
|
||||
[self presentModalViewController:picker animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - MFMailComposeViewControllerDelegate
|
||||
|
||||
- (void)mailComposeController:(MFMailComposeViewController *)controller
|
||||
didFinishWithResult:(MFMailComposeResult)result
|
||||
error:(NSError*)error {
|
||||
NSString *text;
|
||||
switch (result) {
|
||||
case MFMailComposeResultCancelled:
|
||||
text = @"Canceled";
|
||||
break;
|
||||
case MFMailComposeResultSaved:
|
||||
text = @"Saved";
|
||||
break;
|
||||
case MFMailComposeResultSent:
|
||||
text = @"Sent";
|
||||
break;
|
||||
case MFMailComposeResultFailed:
|
||||
text = @"Failed";
|
||||
break;
|
||||
default:
|
||||
text = @"Not sent";
|
||||
break;
|
||||
}
|
||||
shareStatus_.text = [NSString stringWithFormat:@"Status: %@", text];
|
||||
[self dismissModalViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
#pragma mark - IBActions
|
||||
|
||||
- (IBAction)shareButton:(id)sender {
|
||||
NSString *inputURL = shareURL_.text;
|
||||
NSURL *urlToShare = [inputURL length] ? [NSURL URLWithString:inputURL] : nil;
|
||||
NSString *inputText = sharePrefillText_.text;
|
||||
NSString *text = [inputText length] ? inputText : nil;
|
||||
shareStatus_.text = @"Status: Sharing...";
|
||||
[[[[share_ shareDialog] setURLToShare:urlToShare] setPrefillText:text] open];
|
||||
}
|
||||
|
||||
- (IBAction)shareToolbar:(id)sender {
|
||||
UIActionSheet *actionSheet =
|
||||
[[[UIActionSheet alloc] initWithTitle:@"Share this post"
|
||||
delegate:self
|
||||
cancelButtonTitle:@"Cancel"
|
||||
destructiveButtonTitle:nil
|
||||
otherButtonTitles:@"Google+", @"Email", nil]
|
||||
autorelease];
|
||||
[actionSheet showFromToolbar:shareToolbar_];
|
||||
}
|
||||
|
||||
@end
|
493
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleShareViewController.xib
vendored
Normal file
@ -0,0 +1,493 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1280</int>
|
||||
<string key="IBDocument.SystemVersion">10K549</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">1938</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.36</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">933</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBUIView</string>
|
||||
<string>IBProxyObject</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBUIToolbar</string>
|
||||
<string>IBUIBarButtonItem</string>
|
||||
<string>IBUITextField</string>
|
||||
<string>IBUIButton</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</array>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<object class="IBProxyObject" id="372490531">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="975951072">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUIView" id="191373211">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUITextField" id="914769097">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 55}, {280, 31}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="72662020"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<string key="IBUIText">http://developers.google.com/</string>
|
||||
<int key="IBUIBorderStyle">3</int>
|
||||
<object class="NSColor" key="IBUITextColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MAA</bytes>
|
||||
<object class="NSColorSpace" key="NSCustomColorSpace" id="191774102">
|
||||
<int key="NSID">2</int>
|
||||
</object>
|
||||
</object>
|
||||
<bool key="IBUIAdjustsFontSizeToFit">YES</bool>
|
||||
<float key="IBUIMinimumFontSize">17</float>
|
||||
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription" id="494599157">
|
||||
<int key="type">1</int>
|
||||
<double key="pointSize">14</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont" id="583966885">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">14</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUITextField" id="410760382">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 144}, {280, 31}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="483186074"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<string key="IBUIText">Welcome to Google+ Platform</string>
|
||||
<int key="IBUIBorderStyle">3</int>
|
||||
<object class="NSColor" key="IBUITextColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MAA</bytes>
|
||||
<reference key="NSCustomColorSpace" ref="191774102"/>
|
||||
</object>
|
||||
<bool key="IBUIAdjustsFontSizeToFit">YES</bool>
|
||||
<float key="IBUIMinimumFontSize">17</float>
|
||||
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<reference key="IBUIFontDescription" ref="494599157"/>
|
||||
<reference key="IBUIFont" ref="583966885"/>
|
||||
</object>
|
||||
<object class="IBUILabel" id="108661184">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 26}, {179, 21}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="914769097"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">URL to Share (optional)</string>
|
||||
<object class="NSColor" key="IBUITextColor" id="867790682">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MCAwIDAAA</bytes>
|
||||
</object>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">1</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription" id="1056628031">
|
||||
<int key="type">1</int>
|
||||
<double key="pointSize">17</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont" id="1071033096">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">17</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUILabel" id="72662020">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 115}, {156, 21}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="410760382"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Prefill Text (optional)</string>
|
||||
<reference key="IBUITextColor" ref="867790682"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">1</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<reference key="IBUIFontDescription" ref="1056628031"/>
|
||||
<reference key="IBUIFont" ref="1071033096"/>
|
||||
</object>
|
||||
<object class="IBUIButton" id="483186074">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{21, 209}, {112, 32}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="94975264"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<object class="NSColor" key="IBUIHighlightedTitleColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleShadowColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MC41AA</bytes>
|
||||
</object>
|
||||
<object class="NSCustomResource" key="IBUINormalBackgroundImage">
|
||||
<string key="NSClassName">NSImage</string>
|
||||
<string key="NSResourceName">google_plus_share_large.png</string>
|
||||
</object>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription">
|
||||
<int key="type">2</int>
|
||||
<double key="pointSize">15</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">15</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUILabel" id="94975264">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">290</int>
|
||||
<string key="NSFrame">{{20, 283}, {280, 21}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="819777366"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Status:</string>
|
||||
<reference key="IBUITextColor" ref="867790682"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">1</int>
|
||||
<float key="IBUIMinimumFontSize">15</float>
|
||||
<reference key="IBUIFontDescription" ref="1056628031"/>
|
||||
<reference key="IBUIFont" ref="1071033096"/>
|
||||
</object>
|
||||
<object class="IBUIToolbar" id="819777366">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">266</int>
|
||||
<string key="NSFrame">{{0, 372}, {320, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<array class="NSMutableArray" key="IBUIItems">
|
||||
<object class="IBUIBarButtonItem" id="937701942">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<reference key="IBUIToolbar" ref="819777366"/>
|
||||
<int key="IBUISystemItemIdentifier">5</int>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="47552833">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIStyle">1</int>
|
||||
<reference key="IBUIToolbar" ref="819777366"/>
|
||||
<int key="IBUISystemItemIdentifier">9</int>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
</array>
|
||||
<string key="NSFrame">{{0, 64}, {320, 416}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="108661184"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
<reference key="NSCustomColorSpace" ref="191774102"/>
|
||||
</object>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
<object class="IBUISimulatedNavigationBarMetrics" key="IBUISimulatedTopBarMetrics">
|
||||
<bool key="IBUIPrompted">NO</bool>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<array class="NSMutableArray" key="connectionRecords">
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">view</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="191373211"/>
|
||||
</object>
|
||||
<int key="connectionID">3</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">sharePrefillText</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="410760382"/>
|
||||
</object>
|
||||
<int key="connectionID">11</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">shareStatus</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="94975264"/>
|
||||
</object>
|
||||
<int key="connectionID">14</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">shareToolbar</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="819777366"/>
|
||||
</object>
|
||||
<int key="connectionID">19</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">shareURL</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="914769097"/>
|
||||
</object>
|
||||
<int key="connectionID">21</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="914769097"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">23</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="410760382"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">22</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">shareButton:</string>
|
||||
<reference key="source" ref="483186074"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">10</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">shareToolbar:</string>
|
||||
<reference key="source" ref="47552833"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">20</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<array key="object" id="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">1</int>
|
||||
<reference key="object" ref="191373211"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="108661184"/>
|
||||
<reference ref="914769097"/>
|
||||
<reference ref="72662020"/>
|
||||
<reference ref="410760382"/>
|
||||
<reference ref="483186074"/>
|
||||
<reference ref="94975264"/>
|
||||
<reference ref="819777366"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="372490531"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="975951072"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">5</int>
|
||||
<reference key="object" ref="914769097"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">6</int>
|
||||
<reference key="object" ref="410760382"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">7</int>
|
||||
<reference key="object" ref="108661184"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">8</int>
|
||||
<reference key="object" ref="72662020"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">9</int>
|
||||
<reference key="object" ref="483186074"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">13</int>
|
||||
<reference key="object" ref="94975264"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">15</int>
|
||||
<reference key="object" ref="819777366"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="47552833"/>
|
||||
<reference ref="937701942"/>
|
||||
</array>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">17</int>
|
||||
<reference key="object" ref="47552833"/>
|
||||
<reference key="parent" ref="819777366"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">18</int>
|
||||
<reference key="object" ref="937701942"/>
|
||||
<reference key="parent" ref="819777366"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
<string key="-1.CustomClassName">GooglePlusSampleShareViewController</string>
|
||||
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="-2.CustomClassName">UIResponder</string>
|
||||
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="13.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="15.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="17.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="18.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">23</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">GooglePlusSampleShareViewController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<dictionary class="NSMutableDictionary" key="actions">
|
||||
<string key="shareButton:">id</string>
|
||||
<string key="shareToolbar:">id</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="actionInfosByName">
|
||||
<object class="IBActionInfo" key="shareButton:">
|
||||
<string key="name">shareButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="shareToolbar:">
|
||||
<string key="name">shareToolbar:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="outlets">
|
||||
<string key="sharePrefillText">UITextField</string>
|
||||
<string key="shareStatus">UILabel</string>
|
||||
<string key="shareToolbar">UIToolbar</string>
|
||||
<string key="shareURL">UITextField</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<object class="IBToOneOutletInfo" key="sharePrefillText">
|
||||
<string key="name">sharePrefillText</string>
|
||||
<string key="candidateClassName">UITextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="shareStatus">
|
||||
<string key="name">shareStatus</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="shareToolbar">
|
||||
<string key="name">shareToolbar</string>
|
||||
<string key="candidateClassName">UIToolbar</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="shareURL">
|
||||
<string key="name">shareURL</string>
|
||||
<string key="candidateClassName">UITextField</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/GooglePlusSampleShareViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
|
||||
<string key="NS.key.0">google_plus_share_large.png</string>
|
||||
<string key="NS.object.0">{112, 32}</string>
|
||||
</object>
|
||||
<string key="IBCocoaTouchPluginVersion">933</string>
|
||||
</data>
|
||||
</archive>
|
40
External/google-plus-ios-sdk/SampleCode/GooglePlusSampleSignInViewController.h
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// GooglePlusSignInViewController.h
|
||||
//
|
||||
// Copyright 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 <UIKit/UIKit.h>
|
||||
#import "GooglePlusSignIn.h"
|
||||
|
||||
@class GooglePlusSignInButton;
|
||||
|
||||
// A view controller for the Google+ sign-in button which initiates a standard
|
||||
// OAuth 2.0 flow and provides an access token and a refresh token. A "Sign out"
|
||||
// button is provided to allow users to sign out of this application.
|
||||
@interface GooglePlusSampleSignInViewController : UIViewController<
|
||||
GooglePlusSignInDelegate>
|
||||
|
||||
// The button that handles Google+ sign-in.
|
||||
@property (retain, nonatomic) IBOutlet GooglePlusSignInButton *signInButton;
|
||||
// A label to display the result of the sign-in action.
|
||||
@property (retain, nonatomic) IBOutlet UILabel *signInAuthStatus;
|
||||
// A button to sign out of this application.
|
||||
@property (retain, nonatomic) IBOutlet UIButton *signOutButton;
|
||||
|
||||
// Called when the user presses the "Sign out" button.
|
||||
- (IBAction)signOut:(id)sender;
|
||||
|
||||
@end
|