PageRenderTime 135ms CodeModel.GetById 11ms app.highlight 119ms RepoModel.GetById 1ms app.codeStats 0ms

/core/externals/update-engine/Core/KSTicket.m

http://macfuse.googlecode.com/
Objective C | 490 lines | 401 code | 59 blank | 30 comment | 82 complexity | 9fa0c4d0ca1752584f33e4100c80b7a6 MD5 | raw file
  1// Copyright 2008 Google Inc.
  2//
  3// Licensed under the Apache License, Version 2.0 (the "License");
  4// you may not use this file except in compliance with the License.
  5// You may obtain a copy of the License at
  6//
  7//     http://www.apache.org/licenses/LICENSE-2.0
  8//
  9// Unless required by applicable law or agreed to in writing, software
 10// distributed under the License is distributed on an "AS IS" BASIS,
 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12// See the License for the specific language governing permissions and
 13// limitations under the License.
 14
 15#import "KSTicket.h"
 16#import "KSExistenceChecker.h"
 17
 18// When reading a plist file pointed to by a tag, brandcode, or version
 19// path, don't bother reading files over this size.  Chances are
 20// someone is trying to feed us a bad file and forcing a crash.  The
 21// largest plist found on my Leopard system was 4 megs.
 22#define MAX_DATA_FILE_SIZE (5 * 1024 * 1024)
 23
 24// If we are getting the tag, brandcode, or version from a path/tag
 25// combination, make sure that the tag itself isn't unreasonably huge.
 26#define MAX_PATHTAG_SIZE	1024
 27
 28
 29@implementation KSTicket
 30
 31+ (KSTicket *)ticketWithParameters:(NSDictionary *)args {
 32  return [[[self alloc] initWithParameters:args] autorelease];
 33}
 34
 35+ (id)ticketWithProductID:(NSString *)productid
 36                  version:(NSString *)version
 37         existenceChecker:(KSExistenceChecker *)xc
 38                serverURL:(NSURL *)serverURL {
 39  return [[[self alloc] initWithProductID:productid
 40                                  version:version
 41                         existenceChecker:xc
 42                                serverURL:serverURL
 43                       trustedTesterToken:nil] autorelease];
 44}
 45
 46+ (id)ticketWithProductID:(NSString *)productid
 47                  version:(NSString *)version
 48         existenceChecker:(KSExistenceChecker *)xc
 49                serverURL:(NSURL *)serverURL
 50       trustedTesterToken:(NSString *)trustedTesterToken {
 51  return [[[self alloc] initWithProductID:productid
 52                                  version:version
 53                         existenceChecker:xc
 54                                serverURL:serverURL
 55                       trustedTesterToken:trustedTesterToken] autorelease];
 56}
 57
 58+ (id)ticketWithProductID:(NSString *)productid
 59                  version:(NSString *)version
 60         existenceChecker:(KSExistenceChecker *)xc
 61                serverURL:(NSURL *)serverURL
 62       trustedTesterToken:(NSString *)trustedTesterToken
 63             creationDate:(NSDate *)creationDate {
 64  return [[[self alloc] initWithProductID:productid
 65                                  version:version
 66                         existenceChecker:xc
 67                                serverURL:serverURL
 68                       trustedTesterToken:trustedTesterToken
 69                             creationDate:creationDate] autorelease];
 70}
 71
 72+ (id)ticketWithProductID:(NSString *)productid
 73                  version:(NSString *)version
 74         existenceChecker:(KSExistenceChecker *)xc
 75                serverURL:(NSURL *)serverURL
 76       trustedTesterToken:(NSString *)trustedTesterToken
 77             creationDate:(NSDate *)creationDate
 78                      tag:(NSString *)tag {
 79  return [[[self alloc] initWithProductID:productid
 80                                  version:version
 81                         existenceChecker:xc
 82                                serverURL:serverURL
 83                       trustedTesterToken:trustedTesterToken
 84                             creationDate:creationDate
 85                                      tag:tag] autorelease];
 86}
 87
 88- (id)initWithParameters:(NSDictionary *)args {
 89  if ((self = [super init])) {
 90    productID_ = [[args objectForKey:KSTicketProductIDKey] copy];
 91    version_ = [[args objectForKey:KSTicketVersionKey] copy];
 92    existenceChecker_ =
 93      [[args objectForKey:KSTicketExistenceCheckerKey] retain];
 94    serverURL_ = [[args objectForKey:KSTicketServerURLKey] retain];
 95    trustedTesterToken_ =
 96      [[args objectForKey:KSTicketTrustedTesterTokenKey] copy];
 97    creationDate_ = [[args objectForKey:KSTicketCreationDateKey] retain];
 98    tag_ = [[args objectForKey:KSTicketTagKey] copy];
 99    tagPath_ = [[args objectForKey:KSTicketTagPathKey] copy];
100    tagKey_ = [[args objectForKey:KSTicketTagKeyKey] copy];
101    brandPath_ = [[args objectForKey:KSTicketBrandPathKey] copy];
102    brandKey_ = [[args objectForKey:KSTicketBrandKeyKey] copy];
103    versionPath_ = [[args objectForKey:KSTicketVersionPathKey] copy];
104    versionKey_ = [[args objectForKey:KSTicketVersionKeyKey] copy];
105
106    if (creationDate_ == nil) creationDate_ = [[NSDate alloc] init];
107
108    // Ensure that these ivars are not nil.
109    if (productID_ == nil || version_ == nil ||
110        existenceChecker_ == nil || serverURL_ == nil) {
111      [self release];
112      return nil;
113    }
114  }
115  return self;
116}
117
118- (id)init {
119  return [self initWithParameters:[NSDictionary dictionary]];
120}
121
122- (NSDictionary *)parametersForProductID:(NSString *)productid
123                                 version:(NSString *)version
124                        existenceChecker:(KSExistenceChecker *)xc
125                               serverURL:(NSURL *)serverURL
126                      trustedTesterToken:(NSString *)ttt
127                            creationDate:(NSDate *)creationDate
128                                     tag:(NSString *)tag {
129  NSMutableDictionary *args = [NSMutableDictionary dictionary];
130
131  if (productid) [args setObject:productid forKey:KSTicketProductIDKey];
132  if (version) [args setObject:version forKey:KSTicketVersionKey];
133  if (xc) [args setObject:xc forKey:KSTicketExistenceCheckerKey];
134  if (serverURL) [args setObject:serverURL forKey:KSTicketServerURLKey];
135  if (ttt) [args setObject:ttt forKey:KSTicketTrustedTesterTokenKey];
136  if (creationDate) [args setObject:creationDate
137                             forKey:KSTicketCreationDateKey];
138  if (tag) [args setObject:tag forKey:KSTicketTagKey];
139  return args;
140}
141
142- (id)initWithProductID:(NSString *)productid
143                version:(NSString *)version
144       existenceChecker:(KSExistenceChecker *)xc
145              serverURL:(NSURL *)serverURL {
146  NSDictionary *args = [self parametersForProductID:productid
147                                            version:version
148                                   existenceChecker:xc
149                                          serverURL:serverURL
150                                 trustedTesterToken:nil
151                                       creationDate:nil
152                                                tag:nil];
153  return [self initWithParameters:args];
154}
155
156
157- (id)initWithProductID:(NSString *)productid
158                version:(NSString *)version
159       existenceChecker:(KSExistenceChecker *)xc
160              serverURL:(NSURL *)serverURL
161     trustedTesterToken:(NSString *)ttt {
162  NSDictionary *args = [self parametersForProductID:productid
163                                            version:version
164                                   existenceChecker:xc
165                                          serverURL:serverURL
166                                 trustedTesterToken:ttt
167                                       creationDate:nil
168                                                tag:nil];
169  return [self initWithParameters:args];
170}
171
172- (id)initWithProductID:(NSString *)productid
173                version:(NSString *)version
174       existenceChecker:(KSExistenceChecker *)xc
175              serverURL:(NSURL *)serverURL
176     trustedTesterToken:(NSString *)ttt
177           creationDate:(NSDate *)creationDate {
178  NSDictionary *args = [self parametersForProductID:productid
179                                            version:version
180                                   existenceChecker:xc
181                                          serverURL:serverURL
182                                 trustedTesterToken:ttt
183                                       creationDate:creationDate
184                                                tag:nil];
185  return [self initWithParameters:args];
186}
187
188- (id)initWithProductID:(NSString *)productid
189                version:(NSString *)version
190       existenceChecker:(KSExistenceChecker *)xc
191              serverURL:(NSURL *)serverURL
192     trustedTesterToken:(NSString *)ttt
193           creationDate:(NSDate *)creationDate
194                    tag:(NSString *)tag {
195  NSDictionary *args = [self parametersForProductID:productid
196                                            version:version
197                                   existenceChecker:xc
198                                          serverURL:serverURL
199                                 trustedTesterToken:ttt
200                                       creationDate:creationDate
201                                                tag:tag];
202  return [self initWithParameters:args];
203}
204
205- (id)initWithCoder:(NSCoder *)coder {
206  if ((self = [super init])) {
207    productID_ = [[coder decodeObjectForKey:@"product_id"] retain];
208    version_ = [[coder decodeObjectForKey:@"version"] retain];
209    existenceChecker_ =
210      [[coder decodeObjectForKey:@"existence_checker"] retain];
211    serverURL_ = [[coder decodeObjectForKey:@"server_url"] retain];
212    creationDate_ = [[coder decodeObjectForKey:@"creation_date"] retain];
213    if ([coder containsValueForKey:@"trusted_tester_token"]) {
214      trustedTesterToken_ =
215        [[coder decodeObjectForKey:@"trusted_tester_token"] retain];
216    }
217    if ([coder containsValueForKey:@"tag"]) {
218      tag_ = [[coder decodeObjectForKey:@"tag"] retain];
219    }
220    if ([coder containsValueForKey:@"tagPath"]) {
221      tagPath_ = [[coder decodeObjectForKey:@"tagPath"] retain];
222    }
223    if ([coder containsValueForKey:@"tagKey"]) {
224      tagKey_ = [[coder decodeObjectForKey:@"tagKey"] retain];
225    }
226    if ([coder containsValueForKey:@"brandPath"]) {
227      brandPath_ = [[coder decodeObjectForKey:@"brandPath"] retain];
228    }
229    if ([coder containsValueForKey:@"brandKey"]) {
230      brandKey_ = [[coder decodeObjectForKey:@"brandKey"] retain];
231    }
232    if ([coder containsValueForKey:@"versionPath"]) {
233      versionPath_ = [[coder decodeObjectForKey:@"versionPath"] retain];
234    }
235    if ([coder containsValueForKey:@"versionKey"]) {
236      versionKey_ = [[coder decodeObjectForKey:@"versionKey"] retain];
237    }
238  }
239  return self;
240}
241
242- (void)dealloc {
243  [productID_ release];
244  [version_ release];
245  [existenceChecker_ release];
246  [serverURL_ release];
247  [creationDate_ release];
248  [trustedTesterToken_ release];
249  [tag_ release];
250  [tagPath_ release];
251  [tagKey_ release];
252  [brandPath_ release];
253  [brandKey_ release];
254  [versionPath_ release];
255  [versionKey_ release];
256  [super dealloc];
257}
258
259- (void)encodeWithCoder:(NSCoder *)coder {
260  [coder encodeObject:productID_ forKey:@"product_id"];
261  [coder encodeObject:version_ forKey:@"version"];
262  [coder encodeObject:existenceChecker_ forKey:@"existence_checker"];
263  [coder encodeObject:serverURL_ forKey:@"server_url"];
264  [coder encodeObject:creationDate_ forKey:@"creation_date"];
265  if (trustedTesterToken_)
266    [coder encodeObject:trustedTesterToken_ forKey:@"trusted_tester_token"];
267  if (tag_) [coder encodeObject:tag_ forKey:@"tag"];
268  if (tagPath_) [coder encodeObject:tagPath_ forKey:@"tagPath"];
269  if (tagKey_) [coder encodeObject:tagKey_ forKey:@"tagKey"];
270  if (brandPath_) [coder encodeObject:brandPath_ forKey:@"brandPath"];
271  if (brandKey_) [coder encodeObject:brandKey_ forKey:@"brandKey"];
272  if (versionPath_) [coder encodeObject:versionPath_ forKey:@"versionPath"];
273  if (versionKey_) [coder encodeObject:versionKey_ forKey:@"versionKey"];
274}
275
276// The trustedTesterToken_, tag, and brand are intentionally excluded from hash.
277- (unsigned)hash {
278  return [productID_ hash] + [version_ hash] + [existenceChecker_ hash]
279       + [serverURL_ hash] + [creationDate_ hash];
280}
281
282- (BOOL)isEqual:(id)other {
283  if (other == self)
284    return YES;
285  if (!other || ![other isKindOfClass:[self class]])
286    return NO;
287  return [self isEqualToTicket:other];
288}
289
290- (BOOL)isEqualToTicket:(KSTicket *)ticket {
291  if (ticket == self)
292    return YES;
293  if (![productID_ isEqualToString:[ticket productID]])
294    return NO;
295  if (![version_ isEqualToString:[ticket version]])
296    return NO;
297  if (![existenceChecker_ isEqual:[ticket existenceChecker]])
298    return NO;
299  if (![serverURL_ isEqual:[ticket serverURL]])
300    return NO;
301  if (![creationDate_ isEqual:[ticket creationDate]])
302    return NO;
303  if (trustedTesterToken_ &&
304      ![trustedTesterToken_ isEqual:[ticket trustedTesterToken]])
305    return NO;
306  if (tag_ && ![tag_ isEqual:[ticket tag]])
307    return NO;
308  if (tagPath_ && ![tagPath_ isEqual:[ticket tagPath]])
309    return NO;
310  if (tagKey_ && ![tagKey_ isEqual:[ticket tagKey]])
311    return NO;
312  if (brandPath_ && ![brandPath_ isEqual:[ticket brandPath]])
313    return NO;
314  if (brandKey_ && ![brandKey_ isEqual:[ticket brandKey]])
315    return NO;
316  if (versionPath_ && ![versionPath_ isEqual:[ticket versionPath]])
317    return NO;
318  if (versionKey_ && ![versionKey_ isEqual:[ticket versionKey]])
319    return NO;
320
321  return YES;
322}
323
324- (NSString *)description {
325  // Please keep the description stable.  Clients may depend on the output.
326  NSString *tttokenString = @"";
327  if (trustedTesterToken_) {
328    tttokenString = [NSString stringWithFormat:@"\n\ttrustedTesterToken=%@",
329                              trustedTesterToken_];
330  }
331  NSString *tagString = @"";
332  if (tag_) {
333    tagString = [NSString stringWithFormat:@"\n\ttag=%@", tag_];
334  }
335  NSString *tagPathString = @"";
336  if (tagPath_ && tagKey_) {
337    tagPathString = [NSString stringWithFormat:@"\n\ttagPath=%@\n\ttagKey=%@",
338                              tagPath_, tagKey_];
339  }
340  NSString *brandPathString = @"";
341  if (brandPath_ && brandKey_) {
342    brandPathString =
343      [NSString stringWithFormat:@"\n\tbrandPath=%@\n\tbrandKey=%@",
344                brandPath_, brandKey_];
345  }
346  NSString *versionPathString = @"";
347  if (versionPath_ && versionKey_) {
348    versionPathString =
349      [NSString stringWithFormat:@"\n\tversionPath=%@\n\tversionKey=%@",
350                versionPath_, versionKey_];
351  }
352
353  return [NSString stringWithFormat:
354                   @"<%@:%p\n\tproductID=%@\n\tversion=%@\n\t"
355                   @"xc=%@\n\turl=%@\n\tcreationDate=%@%@%@%@%@%@\n>",
356                   [self class], self, productID_,
357                   version_, existenceChecker_, serverURL_, creationDate_,
358                   tttokenString, tagString, tagPathString, brandPathString,
359                   versionPathString];
360}
361
362- (id)plistForPath:(NSString *)path {
363  NSString *fullPath = [path stringByExpandingTildeInPath];
364
365  // Make sure it exists.
366  NSFileManager *fm = [NSFileManager defaultManager];
367  if (![fm fileExistsAtPath:fullPath]) return nil;
368
369  // Make sure file is not too big.
370  NSDictionary *fileAttrs = [fm fileAttributesAtPath:fullPath traverseLink:YES];
371  NSNumber *sizeNumber = [fileAttrs valueForKey:NSFileSize];
372  if (sizeNumber == nil) return nil;
373
374  long fileSize = [sizeNumber longValue];
375  if (fileSize > MAX_DATA_FILE_SIZE) return nil;
376
377  // Use NSPropertyListSerialization to read the file.
378  NSData *data = [NSData dataWithContentsOfFile:fullPath];
379  if (data == nil) return nil;
380
381  id plist = [NSPropertyListSerialization
382               propertyListFromData:data
383                   mutabilityOption:NSPropertyListImmutable
384                             format:NULL
385                   errorDescription:NULL];
386
387  if (![plist isKindOfClass:[NSDictionary class]]) return nil;
388
389  return plist;
390}
391
392- (NSString *)productID {
393  return productID_;
394}
395
396- (NSString *)version {
397  return version_;
398}
399
400- (NSString *)versionPath {
401  return versionPath_;
402}
403
404- (NSString *)versionKey {
405  return versionKey_;
406}
407
408// Common code for determining the brand, tag, or version given a file system
409// path to a plist, a key within that plist, and an optional default value.
410- (NSString *)determineThingForPath:(NSString *)path
411                                key:(NSString *)key
412                       defaultValue:(NSString *)defaultValue {
413  NSString *thing = defaultValue;
414
415  if (path && key) {
416    id plist = [self plistForPath:path];
417    if (plist) {
418      thing = [plist objectForKey:key];
419      // Only strings allowed.
420      if (![thing isKindOfClass:[NSString class]]) thing = nil;
421      // Empty string means no thing.
422      if ([thing isEqualToString:@""]) thing = nil;
423      if ([thing length] > MAX_PATHTAG_SIZE) thing = nil;
424    }
425  }
426
427  return thing;
428}
429
430- (NSString *)determineVersion {
431  NSString *version = [self determineThingForPath:versionPath_
432                                              key:versionKey_
433                                     defaultValue:nil];
434  // No such thing as no version.
435  if (!version) version = version_;
436
437  return version;
438}
439
440- (KSExistenceChecker *)existenceChecker {
441  return existenceChecker_;
442}
443
444- (NSURL *)serverURL {
445  return serverURL_;
446}
447
448- (NSDate *)creationDate {
449  return creationDate_;
450}
451
452- (NSString *)trustedTesterToken {
453  return trustedTesterToken_;
454}
455
456- (NSString *)tag {
457  return tag_;
458}
459
460- (NSString *)tagPath {
461  return tagPath_;
462}
463
464- (NSString *)tagKey {
465  return tagKey_;
466}
467
468- (NSString *)determineTag {
469  NSString *tag = [self determineThingForPath:tagPath_
470                                          key:tagKey_
471                                 defaultValue:tag_];
472  return tag;
473}
474
475- (NSString *)brandPath {
476  return brandPath_;
477}
478
479- (NSString *)brandKey {
480  return brandKey_;
481}
482
483- (NSString *)determineBrand {
484  NSString *brand = [self determineThingForPath:brandPath_
485                                            key:brandKey_
486                                   defaultValue:nil];
487  return brand;
488}
489
490@end