// Copyright 2021 Google LLC // // 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 "GoogleSignIn/Sources/Public/GoogleSignIn/GIDProfileData.h" #import "GoogleSignIn/Sources/GIDProfileData_Private.h" NS_ASSUME_NONNULL_BEGIN // Key constants used for encode and decode. static NSString *const kEmailKey = @"email"; static NSString *const kNameKey = @"name"; static NSString *const kGivenNameKey = @"given_name"; static NSString *const kFamilyNameKey = @"family_name"; static NSString *const kImageURLKey = @"image_url"; static NSString *const kOldImageURLStringKey = @"picture"; @implementation GIDProfileData { NSURL *_imageURL; } - (instancetype)initWithEmail:(NSString *)email name:(NSString *)name givenName:(NSString *)givenName familyName:(NSString *)familyName imageURL:(NSURL *)imageURL { self = [super init]; if (self) { _email = [email copy]; _name = [name copy]; _givenName = [givenName copy]; _familyName = [familyName copy]; _imageURL = [imageURL copy]; } return self; } - (BOOL)hasImage { return _imageURL != nil; } - (NSURL *)imageURLWithDimension:(NSUInteger)dimension { if (!_imageURL) { return nil; } if ([self isFIFEAvatarURL:_imageURL]) { return [NSURL URLWithString: [NSString stringWithFormat:@"%@=s%lu", _imageURL, (unsigned long)dimension]]; } else { return [NSURL URLWithString: [NSString stringWithFormat:@"%@?sz=%lu", _imageURL, (unsigned long)dimension]]; } } - (BOOL)isFIFEAvatarURL:(NSURL *)url { static NSString *const AvatarURLPattern = @"lh[3-6](-tt|-d[a-g,z]|-testonly)?\\.(google|googleusercontent)\\.[a-z]+\\/(a|a-)\\/"; NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:AvatarURLPattern options:0 error:&error]; if (!regex) { return NO; } NSUInteger matches = [regex numberOfMatchesInString:url.absoluteString options:0 range:NSMakeRange(0, url.absoluteString.length)]; if (matches) { return YES; } return NO; } #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; } - (nullable instancetype)initWithCoder:(NSCoder *)decoder { self = [super init]; if (self) { _email = [decoder decodeObjectOfClass:[NSString class] forKey:kEmailKey]; _name = [decoder decodeObjectOfClass:[NSString class] forKey:kNameKey]; _givenName = [decoder decodeObjectOfClass:[NSString class] forKey:kGivenNameKey]; _familyName = [decoder decodeObjectOfClass:[NSString class] forKey:kFamilyNameKey]; _imageURL = [decoder decodeObjectOfClass:[NSURL class] forKey:kImageURLKey]; // Check to see if this is an old archive, if so, try decoding the old image URL string key. if ([decoder containsValueForKey:kOldImageURLStringKey]) { _imageURL = [NSURL URLWithString:[decoder decodeObjectOfClass:[NSString class] forKey:kOldImageURLStringKey]]; } } return self; } - (void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeObject:_email forKey:kEmailKey]; [encoder encodeObject:_name forKey:kNameKey]; [encoder encodeObject:_givenName forKey:kGivenNameKey]; [encoder encodeObject:_familyName forKey:kFamilyNameKey]; [encoder encodeObject:_imageURL forKey:kImageURLKey]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(nullable NSZone *)zone { // Instances of this class are immutable so we'll return self per NSCopying docs guidance. return self; } @end NS_ASSUME_NONNULL_END