[
  {
    "path": ".gitignore",
    "content": "\n#global\n*.orig\n\n#ios\n.DS_Store\nbuild/\n*~\nproject.xcworkspace/\nxcuserdata/\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/DoubanAPIEngine-Prefix.pch",
    "content": "//\n// Prefix header for all source files of the 'DoubanAPIEngine' target in the 'DoubanAPIEngine' project\n//\n\n#ifdef __OBJC__\n  #import <Foundation/Foundation.h>\n#endif\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIAuthenticationDialog.h",
    "content": "//\n//  ASIAuthenticationDialog.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 21/08/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n@class ASIHTTPRequest;\n\ntypedef enum _ASIAuthenticationType {\n\tASIStandardAuthenticationType = 0,\n    ASIProxyAuthenticationType = 1\n} ASIAuthenticationType;\n\n@interface ASIAutorotatingViewController : UIViewController\n@end\n\n@interface ASIAuthenticationDialog : ASIAutorotatingViewController <UIActionSheetDelegate, UITableViewDelegate, UITableViewDataSource> {\n\tASIHTTPRequest *request;\n\tASIAuthenticationType type;\n\tUITableView *tableView;\n\tUIViewController *presentingController;\n\tBOOL didEnableRotationNotifications;\n}\n+ (void)presentAuthenticationDialogForRequest:(ASIHTTPRequest *)request;\n+ (void)dismiss;\n\n@property (retain) ASIHTTPRequest *request;\n@property (assign) ASIAuthenticationType type;\n@property (assign) BOOL didEnableRotationNotifications;\n@property (retain, nonatomic) UIViewController *presentingController;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIAuthenticationDialog.m",
    "content": "//\n//  ASIAuthenticationDialog.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 21/08/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIAuthenticationDialog.h\"\n#import \"ASIHTTPRequest.h\"\n#import <QuartzCore/QuartzCore.h>\n\nstatic ASIAuthenticationDialog *sharedDialog = nil;\nBOOL isDismissing = NO;\nstatic NSMutableArray *requestsNeedingAuthentication = nil;\n\nstatic const NSUInteger kUsernameRow = 0;\nstatic const NSUInteger kUsernameSection = 0;\nstatic const NSUInteger kPasswordRow = 1;\nstatic const NSUInteger kPasswordSection = 0;\nstatic const NSUInteger kDomainRow = 0;\nstatic const NSUInteger kDomainSection = 1;\n\n\n@implementation ASIAutorotatingViewController\n\n- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation\n{\n\treturn YES;\n}\n\n@end\n\n\n@interface ASIAuthenticationDialog ()\n- (void)showTitle;\n- (void)show;\n- (NSArray *)requestsRequiringTheseCredentials;\n- (void)presentNextDialog;\n- (void)keyboardWillShow:(NSNotification *)notification;\n- (void)orientationChanged:(NSNotification *)notification;\n- (void)cancelAuthenticationFromDialog:(id)sender;\n- (void)loginWithCredentialsFromDialog:(id)sender;\n@property (retain) UITableView *tableView;\n@end\n\n@implementation ASIAuthenticationDialog\n\n#pragma mark init / dealloc\n\n+ (void)initialize\n{\n\tif (self == [ASIAuthenticationDialog class]) {\n\t\trequestsNeedingAuthentication = [[NSMutableArray array] retain];\n\t}\n}\n\n+ (void)presentAuthenticationDialogForRequest:(ASIHTTPRequest *)theRequest\n{\n\t// No need for a lock here, this will always be called on the main thread\n\tif (!sharedDialog) {\n\t\tsharedDialog = [[self alloc] init];\n\t\t[sharedDialog setRequest:theRequest];\n\t\tif ([theRequest authenticationNeeded] == ASIProxyAuthenticationNeeded) {\n\t\t\t[sharedDialog setType:ASIProxyAuthenticationType];\n\t\t} else {\n\t\t\t[sharedDialog setType:ASIStandardAuthenticationType];\n\t\t}\n\t\t[sharedDialog show];\n\t} else {\n\t\t[requestsNeedingAuthentication addObject:theRequest];\n\t}\n}\n\n- (id)init\n{\n\tif ((self = [self initWithNibName:nil bundle:nil])) {\n\t\t[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];\n\n#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2\n\t\tif (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {\n#endif\n\t\t\tif (![UIDevice currentDevice].generatesDeviceOrientationNotifications) {\n\t\t\t\t[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];\n\t\t\t\t[self setDidEnableRotationNotifications:YES];\n\t\t\t}\n\t\t\t[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];\n#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2\n\t\t}\n#endif\n\t}\n\treturn self;\n}\n\n- (void)dealloc\n{\n\tif ([self didEnableRotationNotifications]) {\n\t\t[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];\n\t}\n\t[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];\n\n\t[request release];\n\t[tableView release];\n\t[presentingController.view removeFromSuperview];\n\t[presentingController release];\n\t[super dealloc];\n}\n\n#pragma mark keyboard notifications\n\n- (void)keyboardWillShow:(NSNotification *)notification\n{\n#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2\n\tif (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {\n#endif\n#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_2\n\t\tNSValue *keyboardBoundsValue = [[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey];\n#else\n\t\tNSValue *keyboardBoundsValue = [[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey];\n#endif\n\t\tCGRect keyboardBounds;\n\t\t[keyboardBoundsValue getValue:&keyboardBounds];\n\t\tUIEdgeInsets e = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0);\n\t\t[[self tableView] setScrollIndicatorInsets:e];\n\t\t[[self tableView] setContentInset:e];\n#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2\n\t}\n#endif\n}\n\n// Manually handles orientation changes on iPhone\n- (void)orientationChanged:(NSNotification *)notification\n{\n\t[self showTitle];\n\t\n\tUIInterfaceOrientation o = (UIInterfaceOrientation)[[UIApplication sharedApplication] statusBarOrientation];\n\tCGFloat angle = 0;\n\tswitch (o) {\n\t\tcase UIDeviceOrientationLandscapeLeft: angle = 90; break;\n\t\tcase UIDeviceOrientationLandscapeRight: angle = -90; break;\n\t\tcase UIDeviceOrientationPortraitUpsideDown: angle = 180; break;\n\t\tdefault: break;\n\t}\n\n\tCGRect f = [[UIScreen mainScreen] applicationFrame];\n\n\t// Swap the frame height and width if necessary\n \tif (UIDeviceOrientationIsLandscape(o)) {\n\t\tCGFloat t;\n\t\tt = f.size.width;\n\t\tf.size.width = f.size.height;\n\t\tf.size.height = t;\n\t}\n\n\tCGAffineTransform previousTransform = self.view.layer.affineTransform;\n\tCGAffineTransform newTransform = CGAffineTransformMakeRotation((CGFloat)(angle * M_PI / 180.0));\n\n\t// Reset the transform so we can set the size\n\tself.view.layer.affineTransform = CGAffineTransformIdentity;\n\tself.view.frame = (CGRect){ { 0, 0 }, f.size};\n\n\t// Revert to the previous transform for correct animation\n\tself.view.layer.affineTransform = previousTransform;\n\n\t[UIView beginAnimations:nil context:NULL];\n\t[UIView setAnimationDuration:0.3];\n\n\t// Set the new transform\n\tself.view.layer.affineTransform = newTransform;\n\n\t// Fix the view origin\n\tself.view.frame = (CGRect){ { f.origin.x, f.origin.y },self.view.frame.size};\n    [UIView commitAnimations];\n}\n\t\t \n#pragma mark utilities\n\n- (UIViewController *)presentingController\n{\n\tif (!presentingController) {\n\t\tpresentingController = [[ASIAutorotatingViewController alloc] initWithNibName:nil bundle:nil];\n\n\t\t// Attach to the window, but don't interfere.\n\t\tUIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];\n\t\t[window addSubview:[presentingController view]];\n\t\t[[presentingController view] setFrame:CGRectZero];\n\t\t[[presentingController view] setUserInteractionEnabled:NO];\n\t}\n\n\treturn presentingController;\n}\n\n- (UITextField *)textFieldInRow:(NSUInteger)row section:(NSUInteger)section\n{\n\treturn [[[[[self tableView] cellForRowAtIndexPath:\n\t\t\t   [NSIndexPath indexPathForRow:row inSection:section]]\n\t\t\t  contentView] subviews] objectAtIndex:0];\n}\n\n- (UITextField *)usernameField\n{\n\treturn [self textFieldInRow:kUsernameRow section:kUsernameSection];\n}\n\n- (UITextField *)passwordField\n{\n\treturn [self textFieldInRow:kPasswordRow section:kPasswordSection];\n}\n\n- (UITextField *)domainField\n{\n\treturn [self textFieldInRow:kDomainRow section:kDomainSection];\n}\n\n#pragma mark show / dismiss\n\n+ (void)dismiss\n{\n\t[[sharedDialog parentViewController] dismissModalViewControllerAnimated:YES];\n}\n\n- (void)viewDidDisappear:(BOOL)animated\n{\n\t[self retain];\n\t[sharedDialog release];\n\tsharedDialog = nil;\n\t[self performSelector:@selector(presentNextDialog) withObject:nil afterDelay:0];\n\t[self release];\n}\n\n- (void)dismiss\n{\n\tif (self == sharedDialog) {\n\t\t[[self class] dismiss];\n\t} else {\n\t\t[[self parentViewController] dismissModalViewControllerAnimated:YES];\n\t}\n}\n\n- (void)showTitle\n{\n\tUINavigationBar *navigationBar = [[[self view] subviews] objectAtIndex:0];\n\tUINavigationItem *navItem = [[navigationBar items] objectAtIndex:0];\n\tif (UIInterfaceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {\n\t\t// Setup the title\n\t\tif ([self type] == ASIProxyAuthenticationType) {\n\t\t\t[navItem setPrompt:@\"Login to this secure proxy server.\"];\n\t\t} else {\n\t\t\t[navItem setPrompt:@\"Login to this secure server.\"];\n\t\t}\n\t} else {\n\t\t[navItem setPrompt:nil];\n\t}\n\t[navigationBar sizeToFit];\n\tCGRect f = [[self view] bounds];\n\tf.origin.y = [navigationBar frame].size.height;\n\tf.size.height -= f.origin.y;\n\t[[self tableView] setFrame:f];\n}\n\n- (void)show\n{\n\t// Remove all subviews\n\tUIView *v;\n\twhile ((v = [[[self view] subviews] lastObject])) {\n\t\t[v removeFromSuperview];\n\t}\n\n\t// Setup toolbar\n\tUINavigationBar *bar = [[[UINavigationBar alloc] init] autorelease];\n\t[bar setAutoresizingMask:UIViewAutoresizingFlexibleWidth];\n\n\tUINavigationItem *navItem = [[[UINavigationItem alloc] init] autorelease];\n\tbar.items = [NSArray arrayWithObject:navItem];\n\n\t[[self view] addSubview:bar];\n\n\t[self showTitle];\n\n\t// Setup toolbar buttons\n\tif ([self type] == ASIProxyAuthenticationType) {\n\t\t[navItem setTitle:[[self request] proxyHost]];\n\t} else {\n\t\t[navItem setTitle:[[[self request] url] host]];\n\t}\n\n\t[navItem setLeftBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelAuthenticationFromDialog:)] autorelease]];\n\t[navItem setRightBarButtonItem:[[[UIBarButtonItem alloc] initWithTitle:@\"Login\" style:UIBarButtonItemStyleDone target:self action:@selector(loginWithCredentialsFromDialog:)] autorelease]];\n\n\t// We show the login form in a table view, similar to Safari's authentication dialog\n\t[bar sizeToFit];\n\tCGRect f = [[self view] bounds];\n\tf.origin.y = [bar frame].size.height;\n\tf.size.height -= f.origin.y;\n\n\t[self setTableView:[[[UITableView alloc] initWithFrame:f style:UITableViewStyleGrouped] autorelease]];\n\t[[self tableView] setDelegate:self];\n\t[[self tableView] setDataSource:self];\n\t[[self tableView] setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];\n\t[[self view] addSubview:[self tableView]];\n\n\t// Force reload the table content, and focus the first field to show the keyboard\n\t[[self tableView] reloadData];\n\t[[[[[self tableView] cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]].contentView subviews] objectAtIndex:0] becomeFirstResponder];\n\n#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2\n\tif (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {\n\t\t[self setModalPresentationStyle:UIModalPresentationFormSheet];\n\t}\n#endif\n\n\t[[self presentingController] presentModalViewController:self animated:YES];\n}\n\n#pragma mark button callbacks\n\n- (void)cancelAuthenticationFromDialog:(id)sender\n{\n\tfor (ASIHTTPRequest *theRequest in [self requestsRequiringTheseCredentials]) {\n\t\t[theRequest cancelAuthentication];\n\t\t[requestsNeedingAuthentication removeObject:theRequest];\n\t}\n\t[self dismiss];\n}\n\n- (NSArray *)requestsRequiringTheseCredentials\n{\n\tNSMutableArray *requestsRequiringTheseCredentials = [NSMutableArray array];\n\tNSURL *requestURL = [[self request] url];\n\tfor (ASIHTTPRequest *otherRequest in requestsNeedingAuthentication) {\n\t\tNSURL *theURL = [otherRequest url];\n\t\tif (([otherRequest authenticationNeeded] == [[self request] authenticationNeeded]) && [[theURL host] isEqualToString:[requestURL host]] && ([theURL port] == [requestURL port] || ([requestURL port] && [[theURL port] isEqualToNumber:[requestURL port]])) && [[theURL scheme] isEqualToString:[requestURL scheme]] && ((![otherRequest authenticationRealm] && ![[self request] authenticationRealm]) || ([otherRequest authenticationRealm] && [[self request] authenticationRealm] && [[[self request] authenticationRealm] isEqualToString:[otherRequest authenticationRealm]]))) {\n\t\t\t[requestsRequiringTheseCredentials addObject:otherRequest];\n\t\t}\n\t}\n\t[requestsRequiringTheseCredentials addObject:[self request]];\n\treturn requestsRequiringTheseCredentials;\n}\n\n- (void)presentNextDialog\n{\n\tif ([requestsNeedingAuthentication count]) {\n\t\tASIHTTPRequest *nextRequest = [requestsNeedingAuthentication objectAtIndex:0];\n\t\t[requestsNeedingAuthentication removeObjectAtIndex:0];\n\t\t[[self class] presentAuthenticationDialogForRequest:nextRequest];\n\t}\n}\n\n\n- (void)loginWithCredentialsFromDialog:(id)sender\n{\n\tfor (ASIHTTPRequest *theRequest in [self requestsRequiringTheseCredentials]) {\n\n\t\tNSString *username = [[self usernameField] text];\n\t\tNSString *password = [[self passwordField] text];\n\n\t\tif (username == nil) { username = @\"\"; }\n\t\tif (password == nil) { password = @\"\"; }\n\n\t\tif ([self type] == ASIProxyAuthenticationType) {\n\t\t\t[theRequest setProxyUsername:username];\n\t\t\t[theRequest setProxyPassword:password];\n\t\t} else {\n\t\t\t[theRequest setUsername:username];\n\t\t\t[theRequest setPassword:password];\n\t\t}\n\n\t\t// Handle NTLM domains\n\t\tNSString *scheme = ([self type] == ASIStandardAuthenticationType) ? [[self request] authenticationScheme] : [[self request] proxyAuthenticationScheme];\n\t\tif ([scheme isEqualToString:(NSString *)kCFHTTPAuthenticationSchemeNTLM]) {\n\t\t\tNSString *domain = [[self domainField] text];\n\t\t\tif ([self type] == ASIProxyAuthenticationType) {\n\t\t\t\t[theRequest setProxyDomain:domain];\n\t\t\t} else {\n\t\t\t\t[theRequest setDomain:domain];\n\t\t\t}\n\t\t}\n\n\t\t[theRequest retryUsingSuppliedCredentials];\n\t\t[requestsNeedingAuthentication removeObject:theRequest];\n\t}\n\t[self dismiss];\n}\n\n#pragma mark table view data source\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView\n{\n\tNSString *scheme = ([self type] == ASIStandardAuthenticationType) ? [[self request] authenticationScheme] : [[self request] proxyAuthenticationScheme];\n\tif ([scheme isEqualToString:(NSString *)kCFHTTPAuthenticationSchemeNTLM]) {\n\t\treturn 2;\n\t}\n\treturn 1;\n}\n\n- (CGFloat)tableView:(UITableView *)aTableView heightForFooterInSection:(NSInteger)section\n{\n\tif (section == [self numberOfSectionsInTableView:aTableView]-1) {\n\t\treturn 30;\n\t}\n\treturn 0;\n}\n\n- (CGFloat)tableView:(UITableView *)aTableView heightForHeaderInSection:(NSInteger)section\n{\n\tif (section == 0) {\n#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2\n\t\tif (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {\n\t\t\treturn 54;\n\t\t}\n#endif\n\t\treturn 30;\n\t}\n\treturn 0;\n}\n\n- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section\n{\n\tif (section == 0) {\n\t\treturn [[self request] authenticationRealm];\n\t}\n\treturn nil;\n}\n\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\n{\n#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0\n\tUITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];\n#else\n\tUITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0,0,0,0) reuseIdentifier:nil] autorelease];\n#endif\n\n\t[cell setSelectionStyle:UITableViewCellSelectionStyleNone];\n\n\tCGRect f = CGRectInset([cell bounds], 10, 10);\n\tUITextField *textField = [[[UITextField alloc] initWithFrame:f] autorelease];\n\t[textField setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];\n\t[textField setAutocapitalizationType:UITextAutocapitalizationTypeNone];\n\t[textField setAutocorrectionType:UITextAutocorrectionTypeNo];\n\n\tNSUInteger s = [indexPath section];\n\tNSUInteger r = [indexPath row];\n\n\tif (s == kUsernameSection && r == kUsernameRow) {\n\t\t[textField setPlaceholder:@\"User\"];\n\t} else if (s == kPasswordSection && r == kPasswordRow) {\n\t\t[textField setPlaceholder:@\"Password\"];\n\t\t[textField setSecureTextEntry:YES];\n\t} else if (s == kDomainSection && r == kDomainRow) {\n\t\t[textField setPlaceholder:@\"Domain\"];\n\t}\n\t[cell.contentView addSubview:textField];\n\n\treturn cell;\n}\n\n- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section\n{\n\tif (section == 0) {\n\t\treturn 2;\n\t} else {\n\t\treturn 1;\n\t}\n}\n\n- (NSString *)tableView:(UITableView *)aTableView titleForFooterInSection:(NSInteger)section\n{\n\tif (section == [self numberOfSectionsInTableView:aTableView]-1) {\n\t\t// If we're using Basic authentication and the connection is not using SSL, we'll show the plain text message\n\t\tif ([[[self request] authenticationScheme] isEqualToString:(NSString *)kCFHTTPAuthenticationSchemeBasic] && ![[[[self request] url] scheme] isEqualToString:@\"https\"]) {\n\t\t\treturn @\"Password will be sent in the clear.\";\n\t\t// We are using Digest, NTLM, or any scheme over SSL\n\t\t} else {\n\t\t\treturn @\"Password will be sent securely.\";\n\t\t}\n\t}\n\treturn nil;\n}\n\n#pragma mark -\n\n@synthesize request;\n@synthesize type;\n@synthesize tableView;\n@synthesize didEnableRotationNotifications;\n@synthesize presentingController;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASICacheDelegate.h",
    "content": "//\n//  ASICacheDelegate.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 01/05/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n@class ASIHTTPRequest;\n\n// Cache policies control the behaviour of a cache and how requests use the cache\n// When setting a cache policy, you can use a combination of these values as a bitmask\n// For example: [request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy|ASIDoNotWriteToCacheCachePolicy];\n// Note that some of the behaviours below are mutally exclusive - you cannot combine ASIAskServerIfModifiedWhenStaleCachePolicy and ASIAskServerIfModifiedCachePolicy, for example.\ntypedef enum _ASICachePolicy {\n\n\t// The default cache policy. When you set a request to use this, it will use the cache's defaultCachePolicy\n\t// ASIDownloadCache's default cache policy is 'ASIAskServerIfModifiedWhenStaleCachePolicy'\n\tASIUseDefaultCachePolicy = 0,\n\n\t// Tell the request not to read from the cache\n\tASIDoNotReadFromCacheCachePolicy = 1,\n\n\t// The the request not to write to the cache\n\tASIDoNotWriteToCacheCachePolicy = 2,\n\n\t// Ask the server if there is an updated version of this resource (using a conditional GET) ONLY when the cached data is stale\n\tASIAskServerIfModifiedWhenStaleCachePolicy = 4,\n\n\t// Always ask the server if there is an updated version of this resource (using a conditional GET)\n\tASIAskServerIfModifiedCachePolicy = 8,\n\n\t// If cached data exists, use it even if it is stale. This means requests will not talk to the server unless the resource they are requesting is not in the cache\n\tASIOnlyLoadIfNotCachedCachePolicy = 16,\n\n\t// If cached data exists, use it even if it is stale. If cached data does not exist, stop (will not set an error on the request)\n\tASIDontLoadCachePolicy = 32,\n\n\t// Specifies that cached data may be used if the request fails. If cached data is used, the request will succeed without error. Usually used in combination with other options above.\n\tASIFallbackToCacheIfLoadFailsCachePolicy = 64\n} ASICachePolicy;\n\n// Cache storage policies control whether cached data persists between application launches (ASICachePermanentlyCacheStoragePolicy) or not (ASICacheForSessionDurationCacheStoragePolicy)\n// Calling [ASIHTTPRequest clearSession] will remove any data stored using ASICacheForSessionDurationCacheStoragePolicy\ntypedef enum _ASICacheStoragePolicy {\n\tASICacheForSessionDurationCacheStoragePolicy = 0,\n\tASICachePermanentlyCacheStoragePolicy = 1\n} ASICacheStoragePolicy;\n\n\n@protocol ASICacheDelegate <NSObject>\n\n@required\n\n// Should return the cache policy that will be used when requests have their cache policy set to ASIUseDefaultCachePolicy\n- (ASICachePolicy)defaultCachePolicy;\n\n// Returns the date a cached response should expire on. Pass a non-zero max age to specify a custom date.\n- (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Updates cached response headers with a new expiry date. Pass a non-zero max age to specify a custom date.\n- (void)updateExpiryForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Looks at the request's cache policy and any cached headers to determine if the cache data is still valid\n- (BOOL)canUseCachedDataForRequest:(ASIHTTPRequest *)request;\n\n// Removes cached data for a particular request\n- (void)removeCachedDataForRequest:(ASIHTTPRequest *)request;\n\n// Should return YES if the cache considers its cached response current for the request\n// Should return NO is the data is not cached, or (for example) if the cached headers state the request should have expired\n- (BOOL)isCachedDataCurrentForRequest:(ASIHTTPRequest *)request;\n\n// Should store the response for the passed request in the cache\n// When a non-zero maxAge is passed, it should be used as the expiry time for the cached response\n- (void)storeResponseForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Removes cached data for a particular url\n- (void)removeCachedDataForURL:(NSURL *)url;\n\n// Should return an NSDictionary of cached headers for the passed URL, if it is stored in the cache\n- (NSDictionary *)cachedResponseHeadersForURL:(NSURL *)url;\n\n// Should return the cached body of a response for the passed URL, if it is stored in the cache\n- (NSData *)cachedResponseDataForURL:(NSURL *)url;\n\n// Returns a path to the cached response data, if it exists\n- (NSString *)pathToCachedResponseDataForURL:(NSURL *)url;\n\n// Returns a path to the cached response headers, if they url\n- (NSString *)pathToCachedResponseHeadersForURL:(NSURL *)url;\n\n// Returns the location to use to store cached response headers for a particular request\n- (NSString *)pathToStoreCachedResponseHeadersForRequest:(ASIHTTPRequest *)request;\n\n// Returns the location to use to store a cached response body for a particular request\n- (NSString *)pathToStoreCachedResponseDataForRequest:(ASIHTTPRequest *)request;\n\n// Clear cached data stored for the passed storage policy\n- (void)clearCachedResponsesForStoragePolicy:(ASICacheStoragePolicy)cachePolicy;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIDataCompressor.h",
    "content": "//\n//  ASIDataCompressor.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 17/08/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n// This is a helper class used by ASIHTTPRequest to handle deflating (compressing) data in memory and on disk\n// You may also find it helpful if you need to deflate data and files yourself - see the class methods below\n// Most of the zlib stuff is based on the sample code by Mark Adler available at http://zlib.net\n\n#import <Foundation/Foundation.h>\n#import <zlib.h>\n\n@interface ASIDataCompressor : NSObject {\n\tBOOL streamReady;\n\tz_stream zStream;\n}\n\n// Convenience constructor will call setupStream for you\n+ (id)compressor;\n\n// Compress the passed chunk of data\n// Passing YES for shouldFinish will finalize the deflated data - you must pass YES when you are on the last chunk of data\n- (NSData *)compressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err shouldFinish:(BOOL)shouldFinish;\n\n// Convenience method - pass it some data, and you'll get deflated data back\n+ (NSData *)compressData:(NSData*)uncompressedData error:(NSError **)err;\n\n// Convenience method - pass it a file containing the data to compress in sourcePath, and it will write deflated data to destinationPath\n+ (BOOL)compressDataFromFile:(NSString *)sourcePath toFile:(NSString *)destinationPath error:(NSError **)err;\n\n// Sets up zlib to handle the inflating. You only need to call this yourself if you aren't using the convenience constructor 'compressor'\n- (NSError *)setupStream;\n\n// Tells zlib to clean up. You need to call this if you need to cancel deflating part way through\n// If deflating finishes or fails, this method will be called automatically\n- (NSError *)closeStream;\n\n@property (assign, readonly) BOOL streamReady;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIDataCompressor.m",
    "content": "//\n//  ASIDataCompressor.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 17/08/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIDataCompressor.h\"\n#import \"ASIHTTPRequest.h\"\n\n#define DATA_CHUNK_SIZE 262144 // Deal with gzipped data in 256KB chunks\n#define COMPRESSION_AMOUNT Z_DEFAULT_COMPRESSION\n\n@interface ASIDataCompressor ()\n+ (NSError *)deflateErrorWithCode:(int)code;\n@end\n\n@implementation ASIDataCompressor\n\n+ (id)compressor\n{\n\tASIDataCompressor *compressor = [[[self alloc] init] autorelease];\n\t[compressor setupStream];\n\treturn compressor;\n}\n\n- (void)dealloc\n{\n\tif (streamReady) {\n\t\t[self closeStream];\n\t}\n\t[super dealloc];\n}\n\n- (NSError *)setupStream\n{\n\tif (streamReady) {\n\t\treturn nil;\n\t}\n\t// Setup the inflate stream\n\tzStream.zalloc = Z_NULL;\n\tzStream.zfree = Z_NULL;\n\tzStream.opaque = Z_NULL;\n\tzStream.avail_in = 0;\n\tzStream.next_in = 0;\n\tint status = deflateInit2(&zStream, COMPRESSION_AMOUNT, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);\n\tif (status != Z_OK) {\n\t\treturn [[self class] deflateErrorWithCode:status];\n\t}\n\tstreamReady = YES;\n\treturn nil;\n}\n\n- (NSError *)closeStream\n{\n\tif (!streamReady) {\n\t\treturn nil;\n\t}\n\t// Close the deflate stream\n\tstreamReady = NO;\n\tint status = deflateEnd(&zStream);\n\tif (status != Z_OK) {\n\t\treturn [[self class] deflateErrorWithCode:status];\n\t}\n\treturn nil;\n}\n\n- (NSData *)compressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err shouldFinish:(BOOL)shouldFinish\n{\n\tif (length == 0) return nil;\n\t\n\tNSUInteger halfLength = length/2;\n\t\n\t// We'll take a guess that the compressed data will fit in half the size of the original (ie the max to compress at once is half DATA_CHUNK_SIZE), if not, we'll increase it below\n\tNSMutableData *outputData = [NSMutableData dataWithLength:length/2]; \n\t\n\tint status;\n\t\n\tzStream.next_in = bytes;\n\tzStream.avail_in = (unsigned int)length;\n\tzStream.avail_out = 0;\n\n\tNSInteger bytesProcessedAlready = zStream.total_out;\n\twhile (zStream.avail_out == 0) {\n\t\t\n\t\tif (zStream.total_out-bytesProcessedAlready >= [outputData length]) {\n\t\t\t[outputData increaseLengthBy:halfLength];\n\t\t}\n\t\t\n\t\tzStream.next_out = (Bytef*)[outputData mutableBytes] + zStream.total_out-bytesProcessedAlready;\n\t\tzStream.avail_out = (unsigned int)([outputData length] - (zStream.total_out-bytesProcessedAlready));\n\t\tstatus = deflate(&zStream, shouldFinish ? Z_FINISH : Z_NO_FLUSH);\n\t\t\n\t\tif (status == Z_STREAM_END) {\n\t\t\tbreak;\n\t\t} else if (status != Z_OK) {\n\t\t\tif (err) {\n\t\t\t\t*err = [[self class] deflateErrorWithCode:status];\n\t\t\t}\n\t\t\treturn NO;\n\t\t}\n\t}\n\n\t// Set real length\n\t[outputData setLength: zStream.total_out-bytesProcessedAlready];\n\treturn outputData;\n}\n\n\n+ (NSData *)compressData:(NSData*)uncompressedData error:(NSError **)err\n{\n\tNSError *theError = nil;\n\tNSData *outputData = [[ASIDataCompressor compressor] compressBytes:(Bytef *)[uncompressedData bytes] length:[uncompressedData length] error:&theError shouldFinish:YES];\n\tif (theError) {\n\t\tif (err) {\n\t\t\t*err = theError;\n\t\t}\n\t\treturn nil;\n\t}\n\treturn outputData;\n}\n\n\n\n+ (BOOL)compressDataFromFile:(NSString *)sourcePath toFile:(NSString *)destinationPath error:(NSError **)err\n{\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\t// Create an empty file at the destination path\n\tif (![fileManager createFileAtPath:destinationPath contents:[NSData data] attributes:nil]) {\n\t\tif (err) {\n\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Compression of %@ failed because we were to create a file at %@\",sourcePath,destinationPath],NSLocalizedDescriptionKey,nil]];\n\t\t}\n\t\treturn NO;\n\t}\n\t\n\t// Ensure the source file exists\n\tif (![fileManager fileExistsAtPath:sourcePath]) {\n\t\tif (err) {\n\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Compression of %@ failed the file does not exist\",sourcePath],NSLocalizedDescriptionKey,nil]];\n\t\t}\n\t\treturn NO;\n\t}\n\t\n\tUInt8 inputData[DATA_CHUNK_SIZE];\n\tNSData *outputData;\n\tNSInteger readLength;\n\tNSError *theError = nil;\n\t\n\tASIDataCompressor *compressor = [ASIDataCompressor compressor];\n\t\n\tNSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:sourcePath];\n\t[inputStream open];\n\tNSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:destinationPath append:NO];\n\t[outputStream open];\n\t\n    while ([compressor streamReady]) {\n\t\t\n\t\t// Read some data from the file\n\t\treadLength = [inputStream read:inputData maxLength:DATA_CHUNK_SIZE];\n\n\t\t// Make sure nothing went wrong\n\t\tif ([inputStream streamStatus] == NSStreamEventErrorOccurred) {\n\t\t\tif (err) {\n\t\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Compression of %@ failed because we were unable to read from the source data file\",sourcePath],NSLocalizedDescriptionKey,[inputStream streamError],NSUnderlyingErrorKey,nil]];\n\t\t\t}\n\t\t\t[compressor closeStream];\n\t\t\treturn NO;\n\t\t}\n\t\t// Have we reached the end of the input data?\n\t\tif (!readLength) {\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\t// Attempt to deflate the chunk of data\n\t\toutputData = [compressor compressBytes:inputData length:readLength error:&theError shouldFinish:readLength < DATA_CHUNK_SIZE ];\n\t\tif (theError) {\n\t\t\tif (err) {\n\t\t\t\t*err = theError;\n\t\t\t}\n\t\t\t[compressor closeStream];\n\t\t\treturn NO;\n\t\t}\n\t\t\n\t\t// Write the deflated data out to the destination file\n\t\t[outputStream write:(const uint8_t *)[outputData bytes] maxLength:[outputData length]];\n\t\t\n\t\t// Make sure nothing went wrong\n\t\tif ([inputStream streamStatus] == NSStreamEventErrorOccurred) {\n\t\t\tif (err) {\n\t\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Compression of %@ failed because we were unable to write to the destination data file at %@\",sourcePath,destinationPath],NSLocalizedDescriptionKey,[outputStream streamError],NSUnderlyingErrorKey,nil]];\n            }\n\t\t\t[compressor closeStream];\n\t\t\treturn NO;\n\t\t}\n\t\t\n    }\n\t[inputStream close];\n\t[outputStream close];\n\n\tNSError *error = [compressor closeStream];\n\tif (error) {\n\t\tif (err) {\n\t\t\t*err = error;\n\t\t}\n\t\treturn NO;\n\t}\n\n\treturn YES;\n}\n\n+ (NSError *)deflateErrorWithCode:(int)code\n{\n\treturn [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Compression of data failed with code %hi\",code],NSLocalizedDescriptionKey,nil]];\n}\n\n@synthesize streamReady;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIDataDecompressor.h",
    "content": "//\n//  ASIDataDecompressor.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 17/08/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n// This is a helper class used by ASIHTTPRequest to handle inflating (decompressing) data in memory and on disk\n// You may also find it helpful if you need to inflate data and files yourself - see the class methods below\n// Most of the zlib stuff is based on the sample code by Mark Adler available at http://zlib.net\n\n#import <Foundation/Foundation.h>\n#import <zlib.h>\n\n@interface ASIDataDecompressor : NSObject {\n\tBOOL streamReady;\n\tz_stream zStream;\n}\n\n// Convenience constructor will call setupStream for you\n+ (id)decompressor;\n\n// Uncompress the passed chunk of data\n- (NSData *)uncompressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err;\n\n// Convenience method - pass it some deflated data, and you'll get inflated data back\n+ (NSData *)uncompressData:(NSData*)compressedData error:(NSError **)err;\n\n// Convenience method - pass it a file containing deflated data in sourcePath, and it will write inflated data to destinationPath\n+ (BOOL)uncompressDataFromFile:(NSString *)sourcePath toFile:(NSString *)destinationPath error:(NSError **)err;\n\n// Sets up zlib to handle the inflating. You only need to call this yourself if you aren't using the convenience constructor 'decompressor'\n- (NSError *)setupStream;\n\n// Tells zlib to clean up. You need to call this if you need to cancel inflating part way through\n// If inflating finishes or fails, this method will be called automatically\n- (NSError *)closeStream;\n\n@property (assign, readonly) BOOL streamReady;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIDataDecompressor.m",
    "content": "//\n//  ASIDataDecompressor.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 17/08/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIDataDecompressor.h\"\n#import \"ASIHTTPRequest.h\"\n\n#define DATA_CHUNK_SIZE 262144 // Deal with gzipped data in 256KB chunks\n\n@interface ASIDataDecompressor ()\n+ (NSError *)inflateErrorWithCode:(int)code;\n@end;\n\n@implementation ASIDataDecompressor\n\n+ (id)decompressor\n{\n\tASIDataDecompressor *decompressor = [[[self alloc] init] autorelease];\n\t[decompressor setupStream];\n\treturn decompressor;\n}\n\n- (void)dealloc\n{\n\tif (streamReady) {\n\t\t[self closeStream];\n\t}\n\t[super dealloc];\n}\n\n- (NSError *)setupStream\n{\n\tif (streamReady) {\n\t\treturn nil;\n\t}\n\t// Setup the inflate stream\n\tzStream.zalloc = Z_NULL;\n\tzStream.zfree = Z_NULL;\n\tzStream.opaque = Z_NULL;\n\tzStream.avail_in = 0;\n\tzStream.next_in = 0;\n\tint status = inflateInit2(&zStream, (15+32));\n\tif (status != Z_OK) {\n\t\treturn [[self class] inflateErrorWithCode:status];\n\t}\n\tstreamReady = YES;\n\treturn nil;\n}\n\n- (NSError *)closeStream\n{\n\tif (!streamReady) {\n\t\treturn nil;\n\t}\n\t// Close the inflate stream\n\tstreamReady = NO;\n\tint status = inflateEnd(&zStream);\n\tif (status != Z_OK) {\n\t\treturn [[self class] inflateErrorWithCode:status];\n\t}\n\treturn nil;\n}\n\n- (NSData *)uncompressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err\n{\n\tif (length == 0) return nil;\n\t\n\tNSUInteger halfLength = length/2;\n\tNSMutableData *outputData = [NSMutableData dataWithLength:length+halfLength];\n\n\tint status;\n\t\n\tzStream.next_in = bytes;\n\tzStream.avail_in = (unsigned int)length;\n\tzStream.avail_out = 0;\n\t\n\tNSInteger bytesProcessedAlready = zStream.total_out;\n\twhile (zStream.avail_in != 0) {\n\t\t\n\t\tif (zStream.total_out-bytesProcessedAlready >= [outputData length]) {\n\t\t\t[outputData increaseLengthBy:halfLength];\n\t\t}\n\t\t\n\t\tzStream.next_out = (Bytef*)[outputData mutableBytes] + zStream.total_out-bytesProcessedAlready;\n\t\tzStream.avail_out = (unsigned int)([outputData length] - (zStream.total_out-bytesProcessedAlready));\n\t\t\n\t\tstatus = inflate(&zStream, Z_NO_FLUSH);\n\t\t\n\t\tif (status == Z_STREAM_END) {\n\t\t\tbreak;\n\t\t} else if (status != Z_OK) {\n\t\t\tif (err) {\n\t\t\t\t*err = [[self class] inflateErrorWithCode:status];\n\t\t\t}\n\t\t\treturn nil;\n\t\t}\n\t}\n\t\n\t// Set real length\n\t[outputData setLength: zStream.total_out-bytesProcessedAlready];\n\treturn outputData;\n}\n\n\n+ (NSData *)uncompressData:(NSData*)compressedData error:(NSError **)err\n{\n\tNSError *theError = nil;\n\tNSData *outputData = [[ASIDataDecompressor decompressor] uncompressBytes:(Bytef *)[compressedData bytes] length:[compressedData length] error:&theError];\n\tif (theError) {\n\t\tif (err) {\n\t\t\t*err = theError;\n\t\t}\n\t\treturn nil;\n\t}\n\treturn outputData;\n}\n\n+ (BOOL)uncompressDataFromFile:(NSString *)sourcePath toFile:(NSString *)destinationPath error:(NSError **)err\n{\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\t// Create an empty file at the destination path\n\tif (![fileManager createFileAtPath:destinationPath contents:[NSData data] attributes:nil]) {\n\t\tif (err) {\n\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Decompression of %@ failed because we were to create a file at %@\",sourcePath,destinationPath],NSLocalizedDescriptionKey,nil]];\n\t\t}\n\t\treturn NO;\n\t}\n\t\n\t// Ensure the source file exists\n\tif (![fileManager fileExistsAtPath:sourcePath]) {\n\t\tif (err) {\n\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Decompression of %@ failed the file does not exist\",sourcePath],NSLocalizedDescriptionKey,nil]];\n\t\t}\n\t\treturn NO;\n\t}\n\t\n\tUInt8 inputData[DATA_CHUNK_SIZE];\n\tNSData *outputData;\n\tNSInteger readLength;\n\tNSError *theError = nil;\n\t\n\n\tASIDataDecompressor *decompressor = [ASIDataDecompressor decompressor];\n\n\tNSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:sourcePath];\n\t[inputStream open];\n\tNSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:destinationPath append:NO];\n\t[outputStream open];\n\t\n    while ([decompressor streamReady]) {\n\t\t\n\t\t// Read some data from the file\n\t\treadLength = [inputStream read:inputData maxLength:DATA_CHUNK_SIZE]; \n\t\t\n\t\t// Make sure nothing went wrong\n\t\tif ([inputStream streamStatus] == NSStreamEventErrorOccurred) {\n\t\t\tif (err) {\n\t\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Decompression of %@ failed because we were unable to read from the source data file\",sourcePath],NSLocalizedDescriptionKey,[inputStream streamError],NSUnderlyingErrorKey,nil]];\n\t\t\t}\n            [decompressor closeStream];\n\t\t\treturn NO;\n\t\t}\n\t\t// Have we reached the end of the input data?\n\t\tif (!readLength) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// Attempt to inflate the chunk of data\n\t\toutputData = [decompressor uncompressBytes:inputData length:readLength error:&theError];\n\t\tif (theError) {\n\t\t\tif (err) {\n\t\t\t\t*err = theError;\n\t\t\t}\n\t\t\t[decompressor closeStream];\n\t\t\treturn NO;\n\t\t}\n\t\t\n\t\t// Write the inflated data out to the destination file\n\t\t[outputStream write:(Bytef*)[outputData bytes] maxLength:[outputData length]];\n\t\t\n\t\t// Make sure nothing went wrong\n\t\tif ([inputStream streamStatus] == NSStreamEventErrorOccurred) {\n\t\t\tif (err) {\n\t\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Decompression of %@ failed because we were unable to write to the destination data file at %@\",sourcePath,destinationPath],NSLocalizedDescriptionKey,[outputStream streamError],NSUnderlyingErrorKey,nil]];\n            }\n\t\t\t[decompressor closeStream];\n\t\t\treturn NO;\n\t\t}\n\t\t\n    }\n\t\n\t[inputStream close];\n\t[outputStream close];\n\n\tNSError *error = [decompressor closeStream];\n\tif (error) {\n\t\tif (err) {\n\t\t\t*err = error;\n\t\t}\n\t\treturn NO;\n\t}\n\n\treturn YES;\n}\n\n\n+ (NSError *)inflateErrorWithCode:(int)code\n{\n\treturn [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Decompression of data failed with code %hi\",code],NSLocalizedDescriptionKey,nil]];\n}\n\n@synthesize streamReady;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIDownloadCache.h",
    "content": "//\n//  ASIDownloadCache.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 01/05/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"ASICacheDelegate.h\"\n\n@interface ASIDownloadCache : NSObject <ASICacheDelegate> {\n\t\n\t// The default cache policy for this cache\n\t// Requests that store data in the cache will use this cache policy if their cache policy is set to ASIUseDefaultCachePolicy\n\t// Defaults to ASIAskServerIfModifiedWhenStaleCachePolicy\n\tASICachePolicy defaultCachePolicy;\n\t\n\t// The directory in which cached data will be stored\n\t// Defaults to a directory called 'ASIHTTPRequestCache' in the temporary directory\n\tNSString *storagePath;\n\t\n\t// Mediates access to the cache\n\tNSRecursiveLock *accessLock;\n\t\n\t// When YES, the cache will look for cache-control / pragma: no-cache headers, and won't reuse store responses if it finds them\n\tBOOL shouldRespectCacheControlHeaders;\n}\n\n// Returns a static instance of an ASIDownloadCache\n// In most circumstances, it will make sense to use this as a global cache, rather than creating your own cache\n// To make ASIHTTPRequests use it automatically, use [ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];\n+ (id)sharedCache;\n\n// A helper function that determines if the server has requested data should not be cached by looking at the request's response headers\n+ (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request;\n\n// A list of file extensions that we know won't be readable by a webview when accessed locally\n// If we're asking for a path to cache a particular url and it has one of these extensions, we change it to '.html'\n+ (NSArray *)fileExtensionsToHandleAsHTML;\n\n@property (assign, nonatomic) ASICachePolicy defaultCachePolicy;\n@property (retain, nonatomic) NSString *storagePath;\n@property (retain) NSRecursiveLock *accessLock;\n@property (assign) BOOL shouldRespectCacheControlHeaders;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIDownloadCache.m",
    "content": "//\n//  ASIDownloadCache.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 01/05/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIDownloadCache.h\"\n#import \"ASIHTTPRequest.h\"\n#import <CommonCrypto/CommonHMAC.h>\n\nstatic ASIDownloadCache *sharedCache = nil;\n\nstatic NSString *sessionCacheFolder = @\"SessionStore\";\nstatic NSString *permanentCacheFolder = @\"PermanentStore\";\nstatic NSArray *fileExtensionsToHandleAsHTML = nil;\n\n@interface ASIDownloadCache ()\n+ (NSString *)keyForURL:(NSURL *)url;\n- (NSString *)pathToFile:(NSString *)file;\n@end\n\n@implementation ASIDownloadCache\n\n+ (void)initialize\n{\n\tif (self == [ASIDownloadCache class]) {\n\t\t// Obviously this is not an exhaustive list, but hopefully these are the most commonly used and this will 'just work' for the widest range of people\n\t\t// I imagine many web developers probably use url rewriting anyway\n\t\tfileExtensionsToHandleAsHTML = [[NSArray alloc] initWithObjects:@\"asp\",@\"aspx\",@\"jsp\",@\"php\",@\"rb\",@\"py\",@\"pl\",@\"cgi\", nil];\n\t}\n}\n\n- (id)init\n{\n\tself = [super init];\n\t[self setShouldRespectCacheControlHeaders:YES];\n\t[self setDefaultCachePolicy:ASIUseDefaultCachePolicy];\n\t[self setAccessLock:[[[NSRecursiveLock alloc] init] autorelease]];\n\treturn self;\n}\n\n+ (id)sharedCache\n{\n\tif (!sharedCache) {\n\t\t@synchronized(self) {\n\t\t\tif (!sharedCache) {\n\t\t\t\tsharedCache = [[self alloc] init];\n\t\t\t\t[sharedCache setStoragePath:[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@\"ASIHTTPRequestCache\"]];\n\t\t\t}\n\t\t}\n\t}\n\treturn sharedCache;\n}\n\n- (void)dealloc\n{\n\t[storagePath release];\n\t[accessLock release];\n\t[super dealloc];\n}\n\n- (NSString *)storagePath\n{\n\t[[self accessLock] lock];\n\tNSString *p = [[storagePath retain] autorelease];\n\t[[self accessLock] unlock];\n\treturn p;\n}\n\n\n- (void)setStoragePath:(NSString *)path\n{\n\t[[self accessLock] lock];\n\t[self clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];\n\t[storagePath release];\n\tstoragePath = [path retain];\n\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\tBOOL isDirectory = NO;\n\tNSArray *directories = [NSArray arrayWithObjects:path,[path stringByAppendingPathComponent:sessionCacheFolder],[path stringByAppendingPathComponent:permanentCacheFolder],nil];\n\tfor (NSString *directory in directories) {\n\t\tBOOL exists = [fileManager fileExistsAtPath:directory isDirectory:&isDirectory];\n\t\tif (exists && !isDirectory) {\n\t\t\t[[self accessLock] unlock];\n\t\t\t[NSException raise:@\"FileExistsAtCachePath\" format:@\"Cannot create a directory for the cache at '%@', because a file already exists\",directory];\n\t\t} else if (!exists) {\n\t\t\t[fileManager createDirectoryAtPath:directory withIntermediateDirectories:NO attributes:nil error:nil];\n\t\t\tif (![fileManager fileExistsAtPath:directory]) {\n\t\t\t\t[[self accessLock] unlock];\n\t\t\t\t[NSException raise:@\"FailedToCreateCacheDirectory\" format:@\"Failed to create a directory for the cache at '%@'\",directory];\n\t\t\t}\n\t\t}\n\t}\n\t[self clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];\n\t[[self accessLock] unlock];\n}\n\n- (void)updateExpiryForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge\n{\n\tNSString *headerPath = [self pathToStoreCachedResponseHeadersForRequest:request];\n\tNSMutableDictionary *cachedHeaders = [NSMutableDictionary dictionaryWithContentsOfFile:headerPath];\n\tif (!cachedHeaders) {\n\t\treturn;\n\t}\n\tNSDate *expires = [self expiryDateForRequest:request maxAge:maxAge];\n\tif (!expires) {\n\t\treturn;\n\t}\n\t[cachedHeaders setObject:[NSNumber numberWithDouble:[expires timeIntervalSince1970]] forKey:@\"X-ASIHTTPRequest-Expires\"];\n\t[cachedHeaders writeToFile:headerPath atomically:NO];\n}\n\n- (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge\n{\n  return [ASIHTTPRequest expiryDateForRequest:request maxAge:maxAge];\n}\n\n- (void)storeResponseForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge\n{\n\t[[self accessLock] lock];\n\n\tif ([request error] || ![request responseHeaders] || ([request cachePolicy] & ASIDoNotWriteToCacheCachePolicy)) {\n\t\t[[self accessLock] unlock];\n\t\treturn;\n\t}\n\n\t// We only cache 200/OK or redirect reponses (redirect responses are cached so the cache works better with no internet connection)\n\tint responseCode = [request responseStatusCode];\n\tif (responseCode != 200 && responseCode != 301 && responseCode != 302 && responseCode != 303 && responseCode != 307) {\n\t\t[[self accessLock] unlock];\n\t\treturn;\n\t}\n\n\tif ([self shouldRespectCacheControlHeaders] && ![[self class] serverAllowsResponseCachingForRequest:request]) {\n\t\t[[self accessLock] unlock];\n\t\treturn;\n\t}\n\n\tNSString *headerPath = [self pathToStoreCachedResponseHeadersForRequest:request];\n\tNSString *dataPath = [self pathToStoreCachedResponseDataForRequest:request];\n\n\tNSMutableDictionary *responseHeaders = [NSMutableDictionary dictionaryWithDictionary:[request responseHeaders]];\n\tif ([request isResponseCompressed]) {\n\t\t[responseHeaders removeObjectForKey:@\"Content-Encoding\"];\n\t}\n\n\t// Create a special 'X-ASIHTTPRequest-Expires' header\n\t// This is what we use for deciding if cached data is current, rather than parsing the expires / max-age headers individually each time\n\t// We store this as a timestamp to make reading it easier as NSDateFormatter is quite expensive\n\n\tNSDate *expires = [self expiryDateForRequest:request maxAge:maxAge];\n\tif (expires) {\n\t\t[responseHeaders setObject:[NSNumber numberWithDouble:[expires timeIntervalSince1970]] forKey:@\"X-ASIHTTPRequest-Expires\"];\n\t}\n\n\t// Store the response code in a custom header so we can reuse it later\n\n\t// We'll change 304/Not Modified to 200/OK because this is likely to be us updating the cached headers with a conditional GET\n\tint statusCode = [request responseStatusCode];\n\tif (statusCode == 304) {\n\t\tstatusCode = 200;\n\t}\n\t[responseHeaders setObject:[NSNumber numberWithInt:statusCode] forKey:@\"X-ASIHTTPRequest-Response-Status-Code\"];\n\n\t[responseHeaders writeToFile:headerPath atomically:NO];\n\n\tif ([request responseData]) {\n\t\t[[request responseData] writeToFile:dataPath atomically:NO];\n\t} else if ([request downloadDestinationPath] && ![[request downloadDestinationPath] isEqualToString:dataPath]) {        \n\t\tNSError *error = nil;\n        NSFileManager* manager = [[NSFileManager alloc] init];\n        if ([manager fileExistsAtPath:dataPath]) {\n            [manager removeItemAtPath:dataPath error:&error];\n        }\n        [manager copyItemAtPath:[request downloadDestinationPath] toPath:dataPath error:&error];\n        [manager release];\n\t}\n\t[[self accessLock] unlock];\n}\n\n- (NSDictionary *)cachedResponseHeadersForURL:(NSURL *)url\n{\n\tNSString *path = [self pathToCachedResponseHeadersForURL:url];\n\tif (path) {\n\t\treturn [NSDictionary dictionaryWithContentsOfFile:path];\n\t}\n\treturn nil;\n}\n\n- (NSData *)cachedResponseDataForURL:(NSURL *)url\n{\n\tNSString *path = [self pathToCachedResponseDataForURL:url];\n\tif (path) {\n\t\treturn [NSData dataWithContentsOfFile:path];\n\t}\n\treturn nil;\n}\n\n- (NSString *)pathToCachedResponseDataForURL:(NSURL *)url\n{\n\t// Grab the file extension, if there is one. We do this so we can save the cached response with the same file extension - this is important if you want to display locally cached data in a web view \n\tNSString *extension = [[url path] pathExtension];\n\n\t// If the url doesn't have an extension, we'll add one so a webview can read it when locally cached\n\t// If the url has the extension of a common web scripting language, we'll change the extension on the cached path to html for the same reason\n\tif (![extension length] || [[[self class] fileExtensionsToHandleAsHTML] containsObject:[extension lowercaseString]]) {\n\t\textension = @\"html\";\n\t}\n\treturn [self pathToFile:[[[self class] keyForURL:url] stringByAppendingPathExtension:extension]];\n}\n\n+ (NSArray *)fileExtensionsToHandleAsHTML\n{\n\treturn fileExtensionsToHandleAsHTML;\n}\n\n\n- (NSString *)pathToCachedResponseHeadersForURL:(NSURL *)url\n{\n\treturn [self pathToFile:[[[self class] keyForURL:url] stringByAppendingPathExtension:@\"cachedheaders\"]];\n}\n\n- (NSString *)pathToFile:(NSString *)file\n{\n\t[[self accessLock] lock];\n\tif (![self storagePath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn nil;\n\t}\n\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\t// Look in the session store\n\tNSString *dataPath = [[[self storagePath] stringByAppendingPathComponent:sessionCacheFolder] stringByAppendingPathComponent:file];\n\tif ([fileManager fileExistsAtPath:dataPath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn dataPath;\n\t}\n\t// Look in the permanent store\n\tdataPath = [[[self storagePath] stringByAppendingPathComponent:permanentCacheFolder] stringByAppendingPathComponent:file];\n\tif ([fileManager fileExistsAtPath:dataPath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn dataPath;\n\t}\n\t[[self accessLock] unlock];\n\treturn nil;\n}\n\n\n- (NSString *)pathToStoreCachedResponseDataForRequest:(ASIHTTPRequest *)request\n{\n\t[[self accessLock] lock];\n\tif (![self storagePath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn nil;\n\t}\n\n\tNSString *path = [[self storagePath] stringByAppendingPathComponent:([request cacheStoragePolicy] == ASICacheForSessionDurationCacheStoragePolicy ? sessionCacheFolder : permanentCacheFolder)];\n\n\t// Grab the file extension, if there is one. We do this so we can save the cached response with the same file extension - this is important if you want to display locally cached data in a web view \n\tNSString *extension = [[[request url] path] pathExtension];\n\n\t// If the url doesn't have an extension, we'll add one so a webview can read it when locally cached\n\t// If the url has the extension of a common web scripting language, we'll change the extension on the cached path to html for the same reason\n\tif (![extension length] || [[[self class] fileExtensionsToHandleAsHTML] containsObject:[extension lowercaseString]]) {\n\t\textension = @\"html\";\n\t}\n\tpath =  [path stringByAppendingPathComponent:[[[self class] keyForURL:[request url]] stringByAppendingPathExtension:extension]];\n\t[[self accessLock] unlock];\n\treturn path;\n}\n\n- (NSString *)pathToStoreCachedResponseHeadersForRequest:(ASIHTTPRequest *)request\n{\n\t[[self accessLock] lock];\n\tif (![self storagePath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn nil;\n\t}\n\tNSString *path = [[self storagePath] stringByAppendingPathComponent:([request cacheStoragePolicy] == ASICacheForSessionDurationCacheStoragePolicy ? sessionCacheFolder : permanentCacheFolder)];\n\tpath =  [path stringByAppendingPathComponent:[[[self class] keyForURL:[request url]] stringByAppendingPathExtension:@\"cachedheaders\"]];\n\t[[self accessLock] unlock];\n\treturn path;\n}\n\n- (void)removeCachedDataForURL:(NSURL *)url\n{\n\t[[self accessLock] lock];\n\tif (![self storagePath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn;\n\t}\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\tNSString *path = [self pathToCachedResponseHeadersForURL:url];\n\tif (path) {\n\t\t[fileManager removeItemAtPath:path error:NULL];\n\t}\n\n\tpath = [self pathToCachedResponseDataForURL:url];\n\tif (path) {\n\t\t[fileManager removeItemAtPath:path error:NULL];\n\t}\n\t[[self accessLock] unlock];\n}\n\n- (void)removeCachedDataForRequest:(ASIHTTPRequest *)request\n{\n\t[self removeCachedDataForURL:[request url]];\n}\n\n- (BOOL)isCachedDataCurrentForRequest:(ASIHTTPRequest *)request\n{\n\t[[self accessLock] lock];\n\tif (![self storagePath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn NO;\n\t}\n\tNSDictionary *cachedHeaders = [self cachedResponseHeadersForURL:[request url]];\n\tif (!cachedHeaders) {\n\t\t[[self accessLock] unlock];\n\t\treturn NO;\n\t}\n\tNSString *dataPath = [self pathToCachedResponseDataForURL:[request url]];\n\tif (!dataPath) {\n\t\t[[self accessLock] unlock];\n\t\treturn NO;\n\t}\n\n\t// New content is not different\n\tif ([request responseStatusCode] == 304) {\n\t\t[[self accessLock] unlock];\n\t\treturn YES;\n\t}\n\n\t// If we already have response headers for this request, check to see if the new content is different\n\t// We check [request complete] so that we don't end up comparing response headers from a redirection with these\n\tif ([request responseHeaders] && [request complete]) {\n\n\t\t// If the Etag or Last-Modified date are different from the one we have, we'll have to fetch this resource again\n\t\tNSArray *headersToCompare = [NSArray arrayWithObjects:@\"Etag\",@\"Last-Modified\",nil];\n\t\tfor (NSString *header in headersToCompare) {\n\t\t\tif (![[[request responseHeaders] objectForKey:header] isEqualToString:[cachedHeaders objectForKey:header]]) {\n\t\t\t\t[[self accessLock] unlock];\n\t\t\t\treturn NO;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ([self shouldRespectCacheControlHeaders]) {\n\n\t\t// Look for X-ASIHTTPRequest-Expires header to see if the content is out of date\n\t\tNSNumber *expires = [cachedHeaders objectForKey:@\"X-ASIHTTPRequest-Expires\"];\n\t\tif (expires) {\n\t\t\tif ([[NSDate dateWithTimeIntervalSince1970:[expires doubleValue]] timeIntervalSinceNow] >= 0) {\n\t\t\t\t[[self accessLock] unlock];\n\t\t\t\treturn YES;\n\t\t\t}\n\t\t}\n\n\t\t// No explicit expiration time sent by the server\n\t\t[[self accessLock] unlock];\n\t\treturn NO;\n\t}\n\t\n\n\t[[self accessLock] unlock];\n\treturn YES;\n}\n\n- (ASICachePolicy)defaultCachePolicy\n{\n\t[[self accessLock] lock];\n\tASICachePolicy cp = defaultCachePolicy;\n\t[[self accessLock] unlock];\n\treturn cp;\n}\n\n\n- (void)setDefaultCachePolicy:(ASICachePolicy)cachePolicy\n{\n\t[[self accessLock] lock];\n\tif (!cachePolicy) {\n\t\tdefaultCachePolicy = ASIAskServerIfModifiedWhenStaleCachePolicy;\n\t}  else {\n\t\tdefaultCachePolicy = cachePolicy;\t\n\t}\n\t[[self accessLock] unlock];\n}\n\n- (void)clearCachedResponsesForStoragePolicy:(ASICacheStoragePolicy)storagePolicy\n{\n\t[[self accessLock] lock];\n\tif (![self storagePath]) {\n\t\t[[self accessLock] unlock];\n\t\treturn;\n\t}\n\tNSString *path = [[self storagePath] stringByAppendingPathComponent:(storagePolicy == ASICacheForSessionDurationCacheStoragePolicy ? sessionCacheFolder : permanentCacheFolder)];\n\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\tBOOL isDirectory = NO;\n\tBOOL exists = [fileManager fileExistsAtPath:path isDirectory:&isDirectory];\n\tif (!exists || !isDirectory) {\n\t\t[[self accessLock] unlock];\n\t\treturn;\n\t}\n\tNSError *error = nil;\n\tNSArray *cacheFiles = [fileManager contentsOfDirectoryAtPath:path error:&error];\n\tif (error) {\n\t\t[[self accessLock] unlock];\n\t\t[NSException raise:@\"FailedToTraverseCacheDirectory\" format:@\"Listing cache directory failed at path '%@'\",path];\t\n\t}\n\tfor (NSString *file in cacheFiles) {\n\t\t[fileManager removeItemAtPath:[path stringByAppendingPathComponent:file] error:&error];\n\t\tif (error) {\n\t\t\t[[self accessLock] unlock];\n\t\t\t[NSException raise:@\"FailedToRemoveCacheFile\" format:@\"Failed to remove cached data at path '%@'\",path];\n\t\t}\n\t}\n\t[[self accessLock] unlock];\n}\n\n+ (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request\n{\n\tNSString *cacheControl = [[[request responseHeaders] objectForKey:@\"Cache-Control\"] lowercaseString];\n\tif (cacheControl) {\n\t\tif ([cacheControl isEqualToString:@\"no-cache\"] || [cacheControl isEqualToString:@\"no-store\"]) {\n\t\t\treturn NO;\n\t\t}\n\t}\n\tNSString *pragma = [[[request responseHeaders] objectForKey:@\"Pragma\"] lowercaseString];\n\tif (pragma) {\n\t\tif ([pragma isEqualToString:@\"no-cache\"]) {\n\t\t\treturn NO;\n\t\t}\n\t}\n\treturn YES;\n}\n\n+ (NSString *)keyForURL:(NSURL *)url\n{\n\tNSString *urlString = [url absoluteString];\n\tif ([urlString length] == 0) {\n\t\treturn nil;\n\t}\n\n\t// Strip trailing slashes so http://allseeing-i.com/ASIHTTPRequest/ is cached the same as http://allseeing-i.com/ASIHTTPRequest\n\tif ([[urlString substringFromIndex:[urlString length]-1] isEqualToString:@\"/\"]) {\n\t\turlString = [urlString substringToIndex:[urlString length]-1];\n\t}\n\n\t// Borrowed from: http://stackoverflow.com/questions/652300/using-md5-hash-on-a-string-in-cocoa\n\tconst char *cStr = [urlString UTF8String];\n\tunsigned char result[16];\n\tCC_MD5(cStr, (CC_LONG)strlen(cStr), result);\n\treturn [NSString stringWithFormat:@\"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\",result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],result[8], result[9], result[10], result[11],result[12], result[13], result[14], result[15]]; \t\n}\n\n- (BOOL)canUseCachedDataForRequest:(ASIHTTPRequest *)request\n{\n\t// Ensure the request is allowed to read from the cache\n\tif ([request cachePolicy] & ASIDoNotReadFromCacheCachePolicy) {\n\t\treturn NO;\n\n\t// If we don't want to load the request whatever happens, always pretend we have cached data even if we don't\n\t} else if ([request cachePolicy] & ASIDontLoadCachePolicy) {\n\t\treturn YES;\n\t}\n\n\tNSDictionary *headers = [self cachedResponseHeadersForURL:[request url]];\n\tif (!headers) {\n\t\treturn NO;\n\t}\n\tNSString *dataPath = [self pathToCachedResponseDataForURL:[request url]];\n\tif (!dataPath) {\n\t\treturn NO;\n\t}\n\n\t// If we get here, we have cached data\n\n\t// If we have cached data, we can use it\n\tif ([request cachePolicy] & ASIOnlyLoadIfNotCachedCachePolicy) {\n\t\treturn YES;\n\n\t// If we want to fallback to the cache after an error\n\t} else if ([request complete] && [request cachePolicy] & ASIFallbackToCacheIfLoadFailsCachePolicy) {\n\t\treturn YES;\n\n\t// If we have cached data that is current, we can use it\n\t} else if ([request cachePolicy] & ASIAskServerIfModifiedWhenStaleCachePolicy) {\n\t\tif ([self isCachedDataCurrentForRequest:request]) {\n\t\t\treturn YES;\n\t\t}\n\n\t// If we've got headers from a conditional GET and the cached data is still current, we can use it\n\t} else if ([request cachePolicy] & ASIAskServerIfModifiedCachePolicy) {\n\t\tif (![request responseHeaders]) {\n\t\t\treturn NO;\n\t\t} else if ([self isCachedDataCurrentForRequest:request]) {\n\t\t\treturn YES;\n\t\t}\n\t}\n\treturn NO;\n}\n\n@synthesize storagePath;\n@synthesize defaultCachePolicy;\n@synthesize accessLock;\n@synthesize shouldRespectCacheControlHeaders;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIFormDataRequest.h",
    "content": "//\n//  ASIFormDataRequest.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 07/11/2008.\n//  Copyright 2008-2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"ASIHTTPRequest.h\"\n#import \"ASIHTTPRequestConfig.h\"\n\ntypedef enum _ASIPostFormat {\n    ASIMultipartFormDataPostFormat = 0,\n    ASIURLEncodedPostFormat = 1\n\t\n} ASIPostFormat;\n\n@interface ASIFormDataRequest : ASIHTTPRequest <NSCopying> {\n\n\t// Parameters that will be POSTed to the url\n\tNSMutableArray *postData;\n\t\n\t// Files that will be POSTed to the url\n\tNSMutableArray *fileData;\n\t\n\tASIPostFormat postFormat;\n\t\n\tNSStringEncoding stringEncoding;\n\t\n#if DEBUG_FORM_DATA_REQUEST\n\t// Will store a string version of the request body that will be printed to the console when ASIHTTPREQUEST_DEBUG is set in GCC_PREPROCESSOR_DEFINITIONS\n\tNSString *debugBodyString;\n#endif\n\t\n}\n\n#pragma mark utilities \n- (NSString*)encodeURL:(NSString *)string; \n \n#pragma mark setup request\n\n// Add a POST variable to the request\n- (void)addPostValue:(id <NSObject>)value forKey:(NSString *)key;\n\n// Set a POST variable for this request, clearing any others with the same key\n- (void)setPostValue:(id <NSObject>)value forKey:(NSString *)key;\n\n// Add the contents of a local file to the request\n- (void)addFile:(NSString *)filePath forKey:(NSString *)key;\n\n// Same as above, but you can specify the content-type and file name\n- (void)addFile:(NSString *)filePath withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key;\n\n// Add the contents of a local file to the request, clearing any others with the same key\n- (void)setFile:(NSString *)filePath forKey:(NSString *)key;\n\n// Same as above, but you can specify the content-type and file name\n- (void)setFile:(NSString *)filePath withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key;\n\n// Add the contents of an NSData object to the request\n- (void)addData:(NSData *)data forKey:(NSString *)key;\n\n// Same as above, but you can specify the content-type and file name\n- (void)addData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key;\n\n// Add the contents of an NSData object to the request, clearing any others with the same key\n- (void)setData:(NSData *)data forKey:(NSString *)key;\n\n// Same as above, but you can specify the content-type and file name\n- (void)setData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key;\n\n\n@property (assign) ASIPostFormat postFormat;\n@property (assign) NSStringEncoding stringEncoding;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIFormDataRequest.m",
    "content": "//\n//  ASIFormDataRequest.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 07/11/2008.\n//  Copyright 2008-2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIFormDataRequest.h\"\n\n\n// Private stuff\n@interface ASIFormDataRequest ()\n- (void)buildMultipartFormDataPostBody;\n- (void)buildURLEncodedPostBody;\n- (void)appendPostString:(NSString *)string;\n\n@property (retain) NSMutableArray *postData;\n@property (retain) NSMutableArray *fileData;\n\n#if DEBUG_FORM_DATA_REQUEST\n- (void)addToDebugBody:(NSString *)string;\n@property (retain, nonatomic) NSString *debugBodyString;\n#endif\n\n@end\n\n@implementation ASIFormDataRequest\n\n#pragma mark utilities\n- (NSString*)encodeURL:(NSString *)string\n{\n\tNSString *newString = [NSMakeCollectable(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(\":/?#[]@!$ &'()*+,;=\\\"<>%{}|\\\\^~`\"), CFStringConvertNSStringEncodingToEncoding([self stringEncoding]))) autorelease];\n\tif (newString) {\n\t\treturn newString;\n\t}\n\treturn @\"\";\n}\n\n#pragma mark init / dealloc\n\n+ (id)requestWithURL:(NSURL *)newURL\n{\n\treturn [[[self alloc] initWithURL:newURL] autorelease];\n}\n\n- (id)initWithURL:(NSURL *)newURL\n{\n\tself = [super initWithURL:newURL];\n\t[self setPostFormat:ASIURLEncodedPostFormat];\n\t[self setStringEncoding:NSUTF8StringEncoding];\n        [self setRequestMethod:@\"POST\"];\n\treturn self;\n}\n\n- (void)dealloc\n{\n#if DEBUG_FORM_DATA_REQUEST\n\t[debugBodyString release]; \n#endif\n\t\n\t[postData release];\n\t[fileData release];\n\t[super dealloc];\n}\n\n#pragma mark setup request\n\n- (void)addPostValue:(id <NSObject>)value forKey:(NSString *)key\n{\n\tif (!key) {\n\t\treturn;\n\t}\n\tif (![self postData]) {\n\t\t[self setPostData:[NSMutableArray array]];\n\t}\n\tNSMutableDictionary *keyValuePair = [NSMutableDictionary dictionaryWithCapacity:2];\n\t[keyValuePair setValue:key forKey:@\"key\"];\n\t[keyValuePair setValue:[value description] forKey:@\"value\"];\n\t[[self postData] addObject:keyValuePair];\n}\n\n- (void)setPostValue:(id <NSObject>)value forKey:(NSString *)key\n{\n\t// Remove any existing value\n\tNSUInteger i;\n\tfor (i=0; i<[[self postData] count]; i++) {\n\t\tNSDictionary *val = [[self postData] objectAtIndex:i];\n\t\tif ([[val objectForKey:@\"key\"] isEqualToString:key]) {\n\t\t\t[[self postData] removeObjectAtIndex:i];\n\t\t\ti--;\n\t\t}\n\t}\n\t[self addPostValue:value forKey:key];\n}\n\n\n- (void)addFile:(NSString *)filePath forKey:(NSString *)key\n{\n\t[self addFile:filePath withFileName:nil andContentType:nil forKey:key];\n}\n\n- (void)addFile:(NSString *)filePath withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key\n{\n\tBOOL isDirectory = NO;\n\tBOOL fileExists = [[[[NSFileManager alloc] init] autorelease] fileExistsAtPath:filePath isDirectory:&isDirectory];\n\tif (!fileExists || isDirectory) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"No file exists at %@\",filePath],NSLocalizedDescriptionKey,nil]]];\n\t}\n\n\t// If the caller didn't specify a custom file name, we'll use the file name of the file we were passed\n\tif (!fileName) {\n\t\tfileName = [filePath lastPathComponent];\n\t}\n\n\t// If we were given the path to a file, and the user didn't specify a mime type, we can detect it from the file extension\n\tif (!contentType) {\n\t\tcontentType = [ASIHTTPRequest mimeTypeForFileAtPath:filePath];\n\t}\n\t[self addData:filePath withFileName:fileName andContentType:contentType forKey:key];\n}\n\n- (void)setFile:(NSString *)filePath forKey:(NSString *)key\n{\n\t[self setFile:filePath withFileName:nil andContentType:nil forKey:key];\n}\n\n- (void)setFile:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key\n{\n\t// Remove any existing value\n\tNSUInteger i;\n\tfor (i=0; i<[[self fileData] count]; i++) {\n\t\tNSDictionary *val = [[self fileData] objectAtIndex:i];\n\t\tif ([[val objectForKey:@\"key\"] isEqualToString:key]) {\n\t\t\t[[self fileData] removeObjectAtIndex:i];\n\t\t\ti--;\n\t\t}\n\t}\n\t[self addFile:data withFileName:fileName andContentType:contentType forKey:key];\n}\n\n- (void)addData:(NSData *)data forKey:(NSString *)key\n{\n\t[self addData:data withFileName:@\"file\" andContentType:nil forKey:key];\n}\n\n- (void)addData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key\n{\n\tif (![self fileData]) {\n\t\t[self setFileData:[NSMutableArray array]];\n\t}\n\tif (!contentType) {\n\t\tcontentType = @\"application/octet-stream\";\n\t}\n\n\tNSMutableDictionary *fileInfo = [NSMutableDictionary dictionaryWithCapacity:4];\n\t[fileInfo setValue:key forKey:@\"key\"];\n\t[fileInfo setValue:fileName forKey:@\"fileName\"];\n\t[fileInfo setValue:contentType forKey:@\"contentType\"];\n\t[fileInfo setValue:data forKey:@\"data\"];\n\n\t[[self fileData] addObject:fileInfo];\n}\n\n- (void)setData:(NSData *)data forKey:(NSString *)key\n{\n\t[self setData:data withFileName:@\"file\" andContentType:nil forKey:key];\n}\n\n- (void)setData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key\n{\n\t// Remove any existing value\n\tNSUInteger i;\n\tfor (i=0; i<[[self fileData] count]; i++) {\n\t\tNSDictionary *val = [[self fileData] objectAtIndex:i];\n\t\tif ([[val objectForKey:@\"key\"] isEqualToString:key]) {\n\t\t\t[[self fileData] removeObjectAtIndex:i];\n\t\t\ti--;\n\t\t}\n\t}\n\t[self addData:data withFileName:fileName andContentType:contentType forKey:key];\n}\n\n- (void)buildPostBody\n{\n\tif ([self haveBuiltPostBody]) {\n\t\treturn;\n\t}\n\t\n#if DEBUG_FORM_DATA_REQUEST\n\t[self setDebugBodyString:@\"\"];\t\n#endif\n\t\n\tif (![self postData] && ![self fileData]) {\n\t\t[super buildPostBody];\n\t\treturn;\n\t}\t\n\tif ([[self fileData] count] > 0) {\n\t\t[self setShouldStreamPostDataFromDisk:YES];\n\t}\n\t\n\tif ([self postFormat] == ASIURLEncodedPostFormat) {\n\t\t[self buildURLEncodedPostBody];\n\t} else {\n\t\t[self buildMultipartFormDataPostBody];\n\t}\n\n\t[super buildPostBody];\n\t\n#if DEBUG_FORM_DATA_REQUEST\n\tASI_DEBUG_LOG(@\"%@\",[self debugBodyString]);\n\t[self setDebugBodyString:nil];\n#endif\n}\n\n\n- (void)buildMultipartFormDataPostBody\n{\n#if DEBUG_FORM_DATA_REQUEST\n\t[self addToDebugBody:@\"\\r\\n==== Building a multipart/form-data body ====\\r\\n\"];\n#endif\n\t\n\tNSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding([self stringEncoding]));\n\t\n\t// We don't bother to check if post data contains the boundary, since it's pretty unlikely that it does.\n\tCFUUIDRef uuid = CFUUIDCreate(nil);\n\tNSString *uuidString = [(NSString*)CFUUIDCreateString(nil, uuid) autorelease];\n\tCFRelease(uuid);\n\tNSString *stringBoundary = [NSString stringWithFormat:@\"0xKhTmLbOuNdArY-%@\",uuidString];\n\t\n\t[self addRequestHeader:@\"Content-Type\" value:[NSString stringWithFormat:@\"multipart/form-data; charset=%@; boundary=%@\", charset, stringBoundary]];\n\t\n\t[self appendPostString:[NSString stringWithFormat:@\"--%@\\r\\n\",stringBoundary]];\n\t\n\t// Adds post data\n\tNSString *endItemBoundary = [NSString stringWithFormat:@\"\\r\\n--%@\\r\\n\",stringBoundary];\n\tNSUInteger i=0;\n\tfor (NSDictionary *val in [self postData]) {\n\t\t[self appendPostString:[NSString stringWithFormat:@\"Content-Disposition: form-data; name=\\\"%@\\\"\\r\\n\\r\\n\",[val objectForKey:@\"key\"]]];\n\t\t[self appendPostString:[val objectForKey:@\"value\"]];\n\t\ti++;\n\t\tif (i != [[self postData] count] || [[self fileData] count] > 0) { //Only add the boundary if this is not the last item in the post body\n\t\t\t[self appendPostString:endItemBoundary];\n\t\t}\n\t}\n\t\n\t// Adds files to upload\n\ti=0;\n\tfor (NSDictionary *val in [self fileData]) {\n\n\t\t[self appendPostString:[NSString stringWithFormat:@\"Content-Disposition: form-data; name=\\\"%@\\\"; filename=\\\"%@\\\"\\r\\n\", [val objectForKey:@\"key\"], [val objectForKey:@\"fileName\"]]];\n\t\t[self appendPostString:[NSString stringWithFormat:@\"Content-Type: %@\\r\\n\\r\\n\", [val objectForKey:@\"contentType\"]]];\n\t\t\n\t\tid data = [val objectForKey:@\"data\"];\n\t\tif ([data isKindOfClass:[NSString class]]) {\n\t\t\t[self appendPostDataFromFile:data];\n\t\t} else {\n\t\t\t[self appendPostData:data];\n\t\t}\n\t\ti++;\n\t\t// Only add the boundary if this is not the last item in the post body\n\t\tif (i != [[self fileData] count]) { \n\t\t\t[self appendPostString:endItemBoundary];\n\t\t}\n\t}\n\t\n\t[self appendPostString:[NSString stringWithFormat:@\"\\r\\n--%@--\\r\\n\",stringBoundary]];\n\t\n#if DEBUG_FORM_DATA_REQUEST\n\t[self addToDebugBody:@\"==== End of multipart/form-data body ====\\r\\n\"];\n#endif\n}\n\n- (void)buildURLEncodedPostBody\n{\n\n\t// We can't post binary data using application/x-www-form-urlencoded\n\tif ([[self fileData] count] > 0) {\n\t\t[self setPostFormat:ASIMultipartFormDataPostFormat];\n\t\t[self buildMultipartFormDataPostBody];\n\t\treturn;\n\t}\n\t\n#if DEBUG_FORM_DATA_REQUEST\n\t[self addToDebugBody:@\"\\r\\n==== Building an application/x-www-form-urlencoded body ====\\r\\n\"]; \n#endif\n\t\n\t\n\tNSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding([self stringEncoding]));\n\n\t[self addRequestHeader:@\"Content-Type\" value:[NSString stringWithFormat:@\"application/x-www-form-urlencoded; charset=%@\",charset]];\n\n\t\n\tNSUInteger i=0;\n\tNSUInteger count = [[self postData] count]-1;\n\tfor (NSDictionary *val in [self postData]) {\n        NSString *data = [NSString stringWithFormat:@\"%@=%@%@\", [self encodeURL:[val objectForKey:@\"key\"]], [self encodeURL:[val objectForKey:@\"value\"]],(i<count ?  @\"&\" : @\"\")]; \n\t\t[self appendPostString:data];\n\t\ti++;\n\t}\n#if DEBUG_FORM_DATA_REQUEST\n\t[self addToDebugBody:@\"\\r\\n==== End of application/x-www-form-urlencoded body ====\\r\\n\"]; \n#endif\n}\n\n- (void)appendPostString:(NSString *)string\n{\n#if DEBUG_FORM_DATA_REQUEST\n\t[self addToDebugBody:string];\n#endif\n\t[super appendPostData:[string dataUsingEncoding:[self stringEncoding]]];\n}\n\n#if DEBUG_FORM_DATA_REQUEST\n- (void)appendPostData:(NSData *)data\n{\n\t[self addToDebugBody:[NSString stringWithFormat:@\"[%lu bytes of data]\",(unsigned long)[data length]]];\n\t[super appendPostData:data];\n}\n\n- (void)appendPostDataFromFile:(NSString *)file\n{\n\tNSError *err = nil;\n\tunsigned long long fileSize = [[[[[[NSFileManager alloc] init] autorelease] attributesOfItemAtPath:file error:&err] objectForKey:NSFileSize] unsignedLongLongValue];\n\tif (err) {\n\t\t[self addToDebugBody:[NSString stringWithFormat:@\"[Error: Failed to obtain the size of the file at '%@']\",file]];\n\t} else {\n\t\t[self addToDebugBody:[NSString stringWithFormat:@\"[%llu bytes of data from file '%@']\",fileSize,file]];\n\t}\n\n\t[super appendPostDataFromFile:file];\n}\n\n- (void)addToDebugBody:(NSString *)string\n{\n\tif (string) {\n\t\t[self setDebugBodyString:[[self debugBodyString] stringByAppendingString:string]];\n\t}\n}\n#endif\n\n#pragma mark NSCopying\n\n- (id)copyWithZone:(NSZone *)zone\n{\n\tASIFormDataRequest *newRequest = [super copyWithZone:zone];\n\t[newRequest setPostData:[[[self postData] mutableCopyWithZone:zone] autorelease]];\n\t[newRequest setFileData:[[[self fileData] mutableCopyWithZone:zone] autorelease]];\n\t[newRequest setPostFormat:[self postFormat]];\n\t[newRequest setStringEncoding:[self stringEncoding]];\n\t[newRequest setRequestMethod:[self requestMethod]];\n\treturn newRequest;\n}\n\n@synthesize postData;\n@synthesize fileData;\n@synthesize postFormat;\n@synthesize stringEncoding;\n#if DEBUG_FORM_DATA_REQUEST\n@synthesize debugBodyString;\n#endif\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIHTTPRequest.h",
    "content": "//\n//  ASIHTTPRequest.h\n//\n//  Created by Ben Copsey on 04/10/2007.\n//  Copyright 2007-2011 All-Seeing Interactive. All rights reserved.\n//\n//  A guide to the main features is available at:\n//  http://allseeing-i.com/ASIHTTPRequest\n//\n//  Portions are based on the ImageClient example from Apple:\n//  See: http://developer.apple.com/samplecode/ImageClient/listing37.html\n\n#import <Foundation/Foundation.h>\n#if TARGET_OS_IPHONE\n\t#import <CFNetwork/CFNetwork.h>\n\t#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n\t#import <UIKit/UIKit.h> // Necessary for background task support\n\t#endif\n#endif\n\n#import <stdio.h>\n#import \"ASIHTTPRequestConfig.h\"\n#import \"ASIHTTPRequestDelegate.h\"\n#import \"ASIProgressDelegate.h\"\n#import \"ASICacheDelegate.h\"\n\n@class ASIDataDecompressor;\n\nextern NSString *ASIHTTPRequestVersion;\n\n// Make targeting different platforms more reliable\n// See: http://www.blumtnwerx.com/blog/2009/06/cross-sdk-code-hygiene-in-xcode/\n#ifndef __IPHONE_3_2\n\t#define __IPHONE_3_2 30200\n#endif\n#ifndef __IPHONE_4_0\n\t#define __IPHONE_4_0 40000\n#endif\n#ifndef __MAC_10_5\n\t#define __MAC_10_5 1050\n#endif\n#ifndef __MAC_10_6\n\t#define __MAC_10_6 1060\n#endif\n\ntypedef enum _ASIAuthenticationState {\n\tASINoAuthenticationNeededYet = 0,\n\tASIHTTPAuthenticationNeeded = 1,\n\tASIProxyAuthenticationNeeded = 2\n} ASIAuthenticationState;\n\ntypedef enum _ASINetworkErrorType {\n  ASIConnectionFailureErrorType = 1,\n  ASIRequestTimedOutErrorType = 2,\n  ASIAuthenticationErrorType = 3,\n  ASIRequestCancelledErrorType = 4,\n  ASIUnableToCreateRequestErrorType = 5,\n  ASIInternalErrorWhileBuildingRequestType  = 6,\n  ASIInternalErrorWhileApplyingCredentialsType  = 7,\n\tASIFileManagementError = 8,\n\tASITooMuchRedirectionErrorType = 9,\n\tASIUnhandledExceptionError = 10,\n\tASICompressionError = 11\n\t\n} ASINetworkErrorType;\n\n\n// The error domain that all errors generated by ASIHTTPRequest use\nextern NSString* const NetworkRequestErrorDomain;\n\n// You can use this number to throttle upload and download bandwidth in iPhone OS apps send or receive a large amount of data\n// This may help apps that might otherwise be rejected for inclusion into the app store for using excessive bandwidth\n// This number is not official, as far as I know there is no officially documented bandwidth limit\nextern unsigned long const ASIWWANBandwidthThrottleAmount;\n\n#if NS_BLOCKS_AVAILABLE\ntypedef void (^ASIBasicBlock)(void);\ntypedef void (^ASIHeadersBlock)(NSDictionary *responseHeaders);\ntypedef void (^ASISizeBlock)(long long size);\ntypedef void (^ASIProgressBlock)(unsigned long long size, unsigned long long total);\ntypedef void (^ASIDataBlock)(NSData *data);\n#endif\n\n@interface ASIHTTPRequest : NSOperation <NSCopying> {\n\t\n\t// The url for this operation, should include GET params in the query string where appropriate\n\tNSURL *url; \n\t\n\t// Will always contain the original url used for making the request (the value of url can change when a request is redirected)\n\tNSURL *originalURL;\n\t\n\t// Temporarily stores the url we are about to redirect to. Will be nil again when we do redirect\n\tNSURL *redirectURL;\n\n\t// The delegate - will be notified of various changes in state via the ASIHTTPRequestDelegate protocol\n\tid <ASIHTTPRequestDelegate> delegate;\n\t\n\t// Another delegate that is also notified of request status changes and progress updates\n\t// Generally, you won't use this directly, but ASINetworkQueue sets itself as the queue so it can proxy updates to its own delegates\n\t// NOTE: WILL BE RETAINED BY THE REQUEST\n\tid <ASIHTTPRequestDelegate, ASIProgressDelegate> queue;\n\t\n\t// HTTP method to use (eg: GET / POST / PUT / DELETE / HEAD etc). Defaults to GET\n\tNSString *requestMethod;\n\t\n\t// Request body - only used when the whole body is stored in memory (shouldStreamPostDataFromDisk is false)\n\tNSMutableData *postBody;\n\t\n\t// gzipped request body used when shouldCompressRequestBody is YES\n\tNSData *compressedPostBody;\n\t\n\t// When true, post body will be streamed from a file on disk, rather than loaded into memory at once (useful for large uploads)\n\t// Automatically set to true in ASIFormDataRequests when using setFile:forKey:\n\tBOOL shouldStreamPostDataFromDisk;\n\t\n\t// Path to file used to store post body (when shouldStreamPostDataFromDisk is true)\n\t// You can set this yourself - useful if you want to PUT a file from local disk \n\tNSString *postBodyFilePath;\n\t\n\t// Path to a temporary file used to store a deflated post body (when shouldCompressPostBody is YES)\n\tNSString *compressedPostBodyFilePath;\n\t\n\t// Set to true when ASIHTTPRequest automatically created a temporary file containing the request body (when true, the file at postBodyFilePath will be deleted at the end of the request)\n\tBOOL didCreateTemporaryPostDataFile;\n\t\n\t// Used when writing to the post body when shouldStreamPostDataFromDisk is true (via appendPostData: or appendPostDataFromFile:)\n\tNSOutputStream *postBodyWriteStream;\n\t\n\t// Used for reading from the post body when sending the request\n\tNSInputStream *postBodyReadStream;\n\t\n\t// Dictionary for custom HTTP request headers\n\tNSMutableDictionary *requestHeaders;\n\t\n\t// Set to YES when the request header dictionary has been populated, used to prevent this happening more than once\n\tBOOL haveBuiltRequestHeaders;\n\t\n\t// Will be populated with HTTP response headers from the server\n\tNSDictionary *responseHeaders;\n\t\n\t// Can be used to manually insert cookie headers to a request, but it's more likely that sessionCookies will do this for you\n\tNSMutableArray *requestCookies;\n\t\n\t// Will be populated with cookies\n\tNSArray *responseCookies;\n\t\n\t// If use useCookiePersistence is true, network requests will present valid cookies from previous requests\n\tBOOL useCookiePersistence;\n\t\n\t// If useKeychainPersistence is true, network requests will attempt to read credentials from the keychain, and will save them in the keychain when they are successfully presented\n\tBOOL useKeychainPersistence;\n\t\n\t// If useSessionPersistence is true, network requests will save credentials and reuse for the duration of the session (until clearSession is called)\n\tBOOL useSessionPersistence;\n\t\n\t// If allowCompressedResponse is true, requests will inform the server they can accept compressed data, and will automatically decompress gzipped responses. Default is true.\n\tBOOL allowCompressedResponse;\n\t\n\t// If shouldCompressRequestBody is true, the request body will be gzipped. Default is false.\n\t// You will probably need to enable this feature on your webserver to make this work. Tested with apache only.\n\tBOOL shouldCompressRequestBody;\n\t\n\t// When downloadDestinationPath is set, the result of this request will be downloaded to the file at this location\n\t// If downloadDestinationPath is not set, download data will be stored in memory\n\tNSString *downloadDestinationPath;\n\t\n\t// The location that files will be downloaded to. Once a download is complete, files will be decompressed (if necessary) and moved to downloadDestinationPath\n\tNSString *temporaryFileDownloadPath;\n\t\n\t// If the response is gzipped and shouldWaitToInflateCompressedResponses is NO, a file will be created at this path containing the inflated response as it comes in\n\tNSString *temporaryUncompressedDataDownloadPath;\n\t\n\t// Used for writing data to a file when downloadDestinationPath is set\n\tNSOutputStream *fileDownloadOutputStream;\n\t\n\tNSOutputStream *inflatedFileDownloadOutputStream;\n\t\n\t// When the request fails or completes successfully, complete will be true\n\tBOOL complete;\n\t\n  // external \"finished\" indicator, subject of KVO notifications; updates after 'complete'\n  BOOL finished;\n    \n  // True if our 'cancel' selector has been called\n  BOOL cancelled;\n    \n\t// If an error occurs, error will contain an NSError\n\t// If error code is = ASIConnectionFailureErrorType (1, Connection failure occurred) - inspect [[error userInfo] objectForKey:NSUnderlyingErrorKey] for more information\n\tNSError *error;\n\t\n\t// Username and password used for authentication\n\tNSString *username;\n\tNSString *password;\n\t\n\t// User-Agent for this request\n\tNSString *userAgent;\n\t\n\t// Domain used for NTLM authentication\n\tNSString *domain;\n\t\n\t// Username and password used for proxy authentication\n\tNSString *proxyUsername;\n\tNSString *proxyPassword;\n\t\n\t// Domain used for NTLM proxy authentication\n\tNSString *proxyDomain;\n\t\n\t// Delegate for displaying upload progress (usually an NSProgressIndicator, but you can supply a different object and handle this yourself)\n\tid <ASIProgressDelegate> uploadProgressDelegate;\n\t\n\t// Delegate for displaying download progress (usually an NSProgressIndicator, but you can supply a different object and handle this yourself)\n\tid <ASIProgressDelegate> downloadProgressDelegate;\n\t\n\t// Whether we've seen the headers of the response yet\n    BOOL haveExaminedHeaders;\n\t\n\t// Data we receive will be stored here. Data may be compressed unless allowCompressedResponse is false - you should use [request responseData] instead in most cases\n\tNSMutableData *rawResponseData;\n\t\n\t// Used for sending and receiving data\n    CFHTTPMessageRef request;\t\n\tNSInputStream *readStream;\n\t\n\t// Used for authentication\n    CFHTTPAuthenticationRef requestAuthentication; \n\tNSDictionary *requestCredentials;\n\t\n\t// Used during NTLM authentication\n\tint authenticationRetryCount;\n\t\n\t// Authentication scheme (Basic, Digest, NTLM)\n\t// If you are using Basic authentication and want to force ASIHTTPRequest to send an authorization header without waiting for a 401, you must set this to (NSString *)kCFHTTPAuthenticationSchemeBasic\n\tNSString *authenticationScheme;\n\t\n\t// Realm for authentication when credentials are required\n\tNSString *authenticationRealm;\n\t\n\t// When YES, ASIHTTPRequest will present a dialog allowing users to enter credentials when no-matching credentials were found for a server that requires authentication\n\t// The dialog will not be shown if your delegate responds to authenticationNeededForRequest:\n\t// Default is NO.\n\tBOOL shouldPresentAuthenticationDialog;\n\t\n\t// When YES, ASIHTTPRequest will present a dialog allowing users to enter credentials when no-matching credentials were found for a proxy server that requires authentication\n\t// The dialog will not be shown if your delegate responds to proxyAuthenticationNeededForRequest:\n\t// Default is YES (basically, because most people won't want the hassle of adding support for authenticating proxies to their apps)\n\tBOOL shouldPresentProxyAuthenticationDialog;\t\n\t\n\t// Used for proxy authentication\n    CFHTTPAuthenticationRef proxyAuthentication; \n\tNSDictionary *proxyCredentials;\n\t\n\t// Used during authentication with an NTLM proxy\n\tint proxyAuthenticationRetryCount;\n\t\n\t// Authentication scheme for the proxy (Basic, Digest, NTLM)\n\tNSString *proxyAuthenticationScheme;\t\n\t\n\t// Realm for proxy authentication when credentials are required\n\tNSString *proxyAuthenticationRealm;\n\t\n\t// HTTP status code, eg: 200 = OK, 404 = Not found etc\n\tint responseStatusCode;\n\t\n\t// Description of the HTTP status code\n\tNSString *responseStatusMessage;\n\t\n\t// Size of the response\n\tunsigned long long contentLength;\n\t\n\t// Size of the partially downloaded content\n\tunsigned long long partialDownloadSize;\n\t\n\t// Size of the POST payload\n\tunsigned long long postLength;\t\n\t\n\t// The total amount of downloaded data\n\tunsigned long long totalBytesRead;\n\t\n\t// The total amount of uploaded data\n\tunsigned long long totalBytesSent;\n\t\n\t// Last amount of data read (used for incrementing progress)\n\tunsigned long long lastBytesRead;\n\t\n\t// Last amount of data sent (used for incrementing progress)\n\tunsigned long long lastBytesSent;\n\t\n\t// This lock prevents the operation from being cancelled at an inopportune moment\n\tNSRecursiveLock *cancelledLock;\n\t\n\t// Called on the delegate (if implemented) when the request starts. Default is requestStarted:\n\tSEL didStartSelector;\n\t\n\t// Called on the delegate (if implemented) when the request receives response headers. Default is request:didReceiveResponseHeaders:\n\tSEL didReceiveResponseHeadersSelector;\n\n\t// Called on the delegate (if implemented) when the request receives a Location header and shouldRedirect is YES\n\t// The delegate can then change the url if needed, and can restart the request by calling [request redirectToURL:], or simply cancel it\n\tSEL willRedirectSelector;\n\n\t// Called on the delegate (if implemented) when the request completes successfully. Default is requestFinished:\n\tSEL didFinishSelector;\n\t\n\t// Called on the delegate (if implemented) when the request fails. Default is requestFailed:\n\tSEL didFailSelector;\n\t\n\t// Called on the delegate (if implemented) when the request receives data. Default is request:didReceiveData:\n\t// If you set this and implement the method in your delegate, you must handle the data yourself - ASIHTTPRequest will not populate responseData or write the data to downloadDestinationPath\n\tSEL didReceiveDataSelector;\n\t\n\t// Used for recording when something last happened during the request, we will compare this value with the current date to time out requests when appropriate\n\tNSDate *lastActivityTime;\n\t\n\t// Number of seconds to wait before timing out - default is 10\n\tNSTimeInterval timeOutSeconds;\n\t\n\t// Will be YES when a HEAD request will handle the content-length before this request starts\n\tBOOL shouldResetUploadProgress;\n\tBOOL shouldResetDownloadProgress;\n\t\n\t// Used by HEAD requests when showAccurateProgress is YES to preset the content-length for this request\n\tASIHTTPRequest *mainRequest;\n\t\n\t// When NO, this request will only update the progress indicator when it completes\n\t// When YES, this request will update the progress indicator according to how much data it has received so far\n\t// The default for requests is YES\n\t// Also see the comments in ASINetworkQueue.h\n\tBOOL showAccurateProgress;\n\t\n\t// Used to ensure the progress indicator is only incremented once when showAccurateProgress = NO\n\tBOOL updatedProgress;\n\t\n\t// Prevents the body of the post being built more than once (largely for subclasses)\n\tBOOL haveBuiltPostBody;\n\t\n\t// Used internally, may reflect the size of the internal buffer used by CFNetwork\n\t// POST / PUT operations with body sizes greater than uploadBufferSize will not timeout unless more than uploadBufferSize bytes have been sent\n\t// Likely to be 32KB on iPhone 3.0, 128KB on Mac OS X Leopard and iPhone 2.2.x\n\tunsigned long long uploadBufferSize;\n\t\n\t// Text encoding for responses that do not send a Content-Type with a charset value. Defaults to NSISOLatin1StringEncoding\n\tNSStringEncoding defaultResponseEncoding;\n\t\n\t// The text encoding of the response, will be defaultResponseEncoding if the server didn't specify. Can't be set.\n\tNSStringEncoding responseEncoding;\n\t\n\t// Tells ASIHTTPRequest not to delete partial downloads, and allows it to use an existing file to resume a download. Defaults to NO.\n\tBOOL allowResumeForFileDownloads;\n\t\n\t// Custom user information associated with the request (not sent to the server)\n\tNSDictionary *userInfo;\n\tNSInteger tag;\n\t\n\t// Use HTTP 1.0 rather than 1.1 (defaults to false)\n\tBOOL useHTTPVersionOne;\n\t\n\t// When YES, requests will automatically redirect when they get a HTTP 30x header (defaults to YES)\n\tBOOL shouldRedirect;\n\t\n\t// Used internally to tell the main loop we need to stop and retry with a new url\n\tBOOL needsRedirect;\n\t\n\t// Incremented every time this request redirects. When it reaches 5, we give up\n\tint redirectCount;\n\t\n\t// When NO, requests will not check the secure certificate is valid (use for self-signed certificates during development, DO NOT USE IN PRODUCTION) Default is YES\n\tBOOL validatesSecureCertificate;\n    \n    // If not nil and the URL scheme is https, CFNetwork configured to supply a client certificate\n    SecIdentityRef clientCertificateIdentity;\n\tNSArray *clientCertificates;\n\t\n\t// Details on the proxy to use - you could set these yourself, but it's probably best to let ASIHTTPRequest detect the system proxy settings\n\tNSString *proxyHost;\n\tint proxyPort;\n\t\n\t// ASIHTTPRequest will assume kCFProxyTypeHTTP if the proxy type could not be automatically determined\n\t// Set to kCFProxyTypeSOCKS if you are manually configuring a SOCKS proxy\n\tNSString *proxyType;\n\n\t// URL for a PAC (Proxy Auto Configuration) file. If you want to set this yourself, it's probably best if you use a local file\n\tNSURL *PACurl;\n\t\n\t// See ASIAuthenticationState values above. 0 == default == No authentication needed yet\n\tASIAuthenticationState authenticationNeeded;\n\t\n\t// When YES, ASIHTTPRequests will present credentials from the session store for requests to the same server before being asked for them\n\t// This avoids an extra round trip for requests after authentication has succeeded, which is much for efficient for authenticated requests with large bodies, or on slower connections\n\t// Set to NO to only present credentials when explicitly asked for them\n\t// This only affects credentials stored in the session cache when useSessionPersistence is YES. Credentials from the keychain are never presented unless the server asks for them\n\t// Default is YES\n\t// For requests using Basic authentication, set authenticationScheme to (NSString *)kCFHTTPAuthenticationSchemeBasic, and credentials can be sent on the very first request when shouldPresentCredentialsBeforeChallenge is YES\n\tBOOL shouldPresentCredentialsBeforeChallenge;\n\t\n\t// YES when the request hasn't finished yet. Will still be YES even if the request isn't doing anything (eg it's waiting for delegate authentication). READ-ONLY\n\tBOOL inProgress;\n\t\n\t// Used internally to track whether the stream is scheduled on the run loop or not\n\t// Bandwidth throttling can unschedule the stream to slow things down while a request is in progress\n\tBOOL readStreamIsScheduled;\n\t\n\t// Set to allow a request to automatically retry itself on timeout\n\t// Default is zero - timeout will stop the request\n\tint numberOfTimesToRetryOnTimeout;\n\n\t// The number of times this request has retried (when numberOfTimesToRetryOnTimeout > 0)\n\tint retryCount;\n\n\t// Temporarily set to YES when a closed connection forces a retry (internally, this stops ASIHTTPRequest cleaning up a temporary post body)\n\tBOOL willRetryRequest;\n\n\t// When YES, requests will keep the connection to the server alive for a while to allow subsequent requests to re-use it for a substantial speed-boost\n\t// Persistent connections will not be used if the server explicitly closes the connection\n\t// Default is YES\n\tBOOL shouldAttemptPersistentConnection;\n\n\t// Number of seconds to keep an inactive persistent connection open on the client side\n\t// Default is 60\n\t// If we get a keep-alive header, this is this value is replaced with how long the server told us to keep the connection around\n\t// A future date is created from this and used for expiring the connection, this is stored in connectionInfo's expires value\n\tNSTimeInterval persistentConnectionTimeoutSeconds;\n\t\n\t// Set to yes when an appropriate keep-alive header is found\n\tBOOL connectionCanBeReused;\n\t\n\t// Stores information about the persistent connection that is currently in use.\n\t// It may contain:\n\t// * The id we set for a particular connection, incremented every time we want to specify that we need a new connection\n\t// * The date that connection should expire\n\t// * A host, port and scheme for the connection. These are used to determine whether that connection can be reused by a subsequent request (all must match the new request)\n\t// * An id for the request that is currently using the connection. This is used for determining if a connection is available or not (we store a number rather than a reference to the request so we don't need to hang onto a request until the connection expires)\n\t// * A reference to the stream that is currently using the connection. This is necessary because we need to keep the old stream open until we've opened a new one.\n\t//   The stream will be closed + released either when another request comes to use the connection, or when the timer fires to tell the connection to expire\n\tNSMutableDictionary *connectionInfo;\n\t\n\t// When set to YES, 301 and 302 automatic redirects will use the original method and and body, according to the HTTP 1.1 standard\n\t// Default is NO (to follow the behaviour of most browsers)\n\tBOOL shouldUseRFC2616RedirectBehaviour;\n\t\n\t// Used internally to record when a request has finished downloading data\n\tBOOL downloadComplete;\n\t\n\t// An ID that uniquely identifies this request - primarily used for debugging persistent connections\n\tNSNumber *requestID;\n\t\n\t// Will be ASIHTTPRequestRunLoopMode for synchronous requests, NSDefaultRunLoopMode for all other requests\n\tNSString *runLoopMode;\n\t\n\t// This timer checks up on the request every 0.25 seconds, and updates progress\n\tNSTimer *statusTimer;\n\t\n\t// The download cache that will be used for this request (use [ASIHTTPRequest setDefaultCache:cache] to configure a default cache\n\tid <ASICacheDelegate> downloadCache;\n\t\n\t// The cache policy that will be used for this request - See ASICacheDelegate.h for possible values\n\tASICachePolicy cachePolicy;\n\t\n\t// The cache storage policy that will be used for this request - See ASICacheDelegate.h for possible values\n\tASICacheStoragePolicy cacheStoragePolicy;\n\t\n\t// Will be true when the response was pulled from the cache rather than downloaded\n\tBOOL didUseCachedResponse;\n\n\t// Set secondsToCache to use a custom time interval for expiring the response when it is stored in a cache\n\tNSTimeInterval secondsToCache;\n\n\t#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n\tBOOL shouldContinueWhenAppEntersBackground;\n\tUIBackgroundTaskIdentifier backgroundTask;\n\t#endif\n\t\n\t// When downloading a gzipped response, the request will use this helper object to inflate the response\n\tASIDataDecompressor *dataDecompressor;\n\t\n\t// Controls how responses with a gzipped encoding are inflated (decompressed)\n\t// When set to YES (This is the default):\n\t// * gzipped responses for requests without a downloadDestinationPath will be inflated only when [request responseData] / [request responseString] is called\n\t// * gzipped responses for requests with a downloadDestinationPath set will be inflated only when the request completes\n\t//\n\t// When set to NO\n\t// All requests will inflate the response as it comes in\n\t// * If the request has no downloadDestinationPath set, the raw (compressed) response is discarded and rawResponseData will contain the decompressed response\n\t// * If the request has a downloadDestinationPath, the raw response will be stored in temporaryFileDownloadPath as normal, the inflated response will be stored in temporaryUncompressedDataDownloadPath\n\t//   Once the request completes successfully, the contents of temporaryUncompressedDataDownloadPath are moved into downloadDestinationPath\n\t//\n\t// Setting this to NO may be especially useful for users using ASIHTTPRequest in conjunction with a streaming parser, as it will allow partial gzipped responses to be inflated and passed on to the parser while the request is still running\n\tBOOL shouldWaitToInflateCompressedResponses;\n\n\t// Will be YES if this is a request created behind the scenes to download a PAC file - these requests do not attempt to configure their own proxies\n\tBOOL isPACFileRequest;\n\n\t// Used for downloading PAC files from http / https webservers\n\tASIHTTPRequest *PACFileRequest;\n\n\t// Used for asynchronously reading PAC files from file:// URLs\n\tNSInputStream *PACFileReadStream;\n\n\t// Used for storing PAC data from file URLs as it is downloaded\n\tNSMutableData *PACFileData;\n\n\t// Set to YES in startSynchronous. Currently used by proxy detection to download PAC files synchronously when appropriate\n\tBOOL isSynchronous;\n\n\t#if NS_BLOCKS_AVAILABLE\n\t//block to execute when request starts\n\tASIBasicBlock startedBlock;\n\n\t//block to execute when headers are received\n\tASIHeadersBlock headersReceivedBlock;\n\n\t//block to execute when request completes successfully\n\tASIBasicBlock completionBlock;\n\n\t//block to execute when request fails\n\tASIBasicBlock failureBlock;\n\n\t//block for when bytes are received\n\tASIProgressBlock bytesReceivedBlock;\n\n\t//block for when bytes are sent\n\tASIProgressBlock bytesSentBlock;\n\n\t//block for when download size is incremented\n\tASISizeBlock downloadSizeIncrementedBlock;\n\n\t//block for when upload size is incremented\n\tASISizeBlock uploadSizeIncrementedBlock;\n\n\t//block for handling raw bytes received\n\tASIDataBlock dataReceivedBlock;\n\n\t//block for handling authentication\n\tASIBasicBlock authenticationNeededBlock;\n\n\t//block for handling proxy authentication\n\tASIBasicBlock proxyAuthenticationNeededBlock;\n\t\n    //block for handling redirections, if you want to\n    ASIBasicBlock requestRedirectedBlock;\n\t#endif\n}\n\n#pragma mark init / dealloc\n\n// Should be an HTTP or HTTPS url, may include username and password if appropriate\n- (id)initWithURL:(NSURL *)newURL;\n\n// Convenience constructor\n+ (id)requestWithURL:(NSURL *)newURL;\n\n+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache;\n+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache andCachePolicy:(ASICachePolicy)policy;\n\n#if NS_BLOCKS_AVAILABLE\n- (void)setStartedBlock:(ASIBasicBlock)aStartedBlock;\n- (void)setHeadersReceivedBlock:(ASIHeadersBlock)aReceivedBlock;\n- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock;\n- (void)setFailedBlock:(ASIBasicBlock)aFailedBlock;\n- (void)setBytesReceivedBlock:(ASIProgressBlock)aBytesReceivedBlock;\n- (void)setBytesSentBlock:(ASIProgressBlock)aBytesSentBlock;\n- (void)setDownloadSizeIncrementedBlock:(ASISizeBlock) aDownloadSizeIncrementedBlock;\n- (void)setUploadSizeIncrementedBlock:(ASISizeBlock) anUploadSizeIncrementedBlock;\n- (void)setDataReceivedBlock:(ASIDataBlock)aReceivedBlock;\n- (void)setAuthenticationNeededBlock:(ASIBasicBlock)anAuthenticationBlock;\n- (void)setProxyAuthenticationNeededBlock:(ASIBasicBlock)aProxyAuthenticationBlock;\n- (void)setRequestRedirectedBlock:(ASIBasicBlock)aRedirectBlock;\n#endif\n\n#pragma mark setup request\n\n// Add a custom header to the request\n- (void)addRequestHeader:(NSString *)header value:(NSString *)value;\n\n// Called during buildRequestHeaders and after a redirect to create a cookie header from request cookies and the global store\n- (void)applyCookieHeader;\n\n// Populate the request headers dictionary. Called before a request is started, or by a HEAD request that needs to borrow them\n- (void)buildRequestHeaders;\n\n// Used to apply authorization header to a request before it is sent (when shouldPresentCredentialsBeforeChallenge is YES)\n- (void)applyAuthorizationHeader;\n\n\n// Create the post body\n- (void)buildPostBody;\n\n// Called to add data to the post body. Will append to postBody when shouldStreamPostDataFromDisk is false, or write to postBodyWriteStream when true\n- (void)appendPostData:(NSData *)data;\n- (void)appendPostDataFromFile:(NSString *)file;\n\n#pragma mark get information about this request\n\n// Returns the contents of the result as an NSString (not appropriate for binary data - used responseData instead)\n- (NSString *)responseString;\n\n// Response data, automatically uncompressed where appropriate\n- (NSData *)responseData;\n\n// Returns true if the response was gzip compressed\n- (BOOL)isResponseCompressed;\n\n#pragma mark running a request\n\n\n// Run a request synchronously, and return control when the request completes or fails\n- (void)startSynchronous;\n\n// Run request in the background\n- (void)startAsynchronous;\n\n// Clears all delegates and blocks, then cancels the request\n- (void)clearDelegatesAndCancel;\n\n#pragma mark HEAD request\n\n// Used by ASINetworkQueue to create a HEAD request appropriate for this request with the same headers (though you can use it yourself)\n- (ASIHTTPRequest *)HEADRequest;\n\n#pragma mark upload/download progress\n\n// Called approximately every 0.25 seconds to update the progress delegates\n- (void)updateProgressIndicators;\n\n// Updates upload progress (notifies the queue and/or uploadProgressDelegate of this request)\n- (void)updateUploadProgress;\n\n// Updates download progress (notifies the queue and/or uploadProgressDelegate of this request)\n- (void)updateDownloadProgress;\n\n// Called when authorisation is needed, as we only find out we don't have permission to something when the upload is complete\n- (void)removeUploadProgressSoFar;\n\n// Called when we get a content-length header and shouldResetDownloadProgress is true\n- (void)incrementDownloadSizeBy:(long long)length;\n\n// Called when a request starts and shouldResetUploadProgress is true\n// Also called (with a negative length) to remove the size of the underlying buffer used for uploading\n- (void)incrementUploadSizeBy:(long long)length;\n\n// Helper method for interacting with progress indicators to abstract the details of different APIS (NSProgressIndicator and UIProgressView)\n+ (void)updateProgressIndicator:(id *)indicator withProgress:(unsigned long long)progress ofTotal:(unsigned long long)total;\n\n// Helper method used for performing invocations on the main thread (used for progress)\n+ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount callerToRetain:(id)caller;\n\n#pragma mark talking to delegates\n\n// Called when a request starts, lets the delegate know via didStartSelector\n- (void)requestStarted;\n\n// Called when a request receives response headers, lets the delegate know via didReceiveResponseHeadersSelector\n- (void)requestReceivedResponseHeaders:(NSDictionary *)newHeaders;\n\n// Called when a request completes successfully, lets the delegate know via didFinishSelector\n- (void)requestFinished;\n\n// Called when a request fails, and lets the delegate know via didFailSelector\n- (void)failWithError:(NSError *)theError;\n\n// Called to retry our request when our persistent connection is closed\n// Returns YES if we haven't already retried, and connection will be restarted\n// Otherwise, returns NO, and nothing will happen\n- (BOOL)retryUsingNewConnection;\n\n// Can be called by delegates from inside their willRedirectSelector implementations to restart the request with a new url\n- (void)redirectToURL:(NSURL *)newURL;\n\n#pragma mark parsing HTTP response headers\n\n// Reads the response headers to find the content length, encoding, cookies for the session \n// Also initiates request redirection when shouldRedirect is true\n// And works out if HTTP auth is required\n- (void)readResponseHeaders;\n\n// Attempts to set the correct encoding by looking at the Content-Type header, if this is one\n- (void)parseStringEncodingFromHeaders;\n\n+ (void)parseMimeType:(NSString **)mimeType andResponseEncoding:(NSStringEncoding *)stringEncoding fromContentType:(NSString *)contentType;\n\n#pragma mark http authentication stuff\n\n// Apply credentials to this request\n- (BOOL)applyCredentials:(NSDictionary *)newCredentials;\n- (BOOL)applyProxyCredentials:(NSDictionary *)newCredentials;\n\n// Attempt to obtain credentials for this request from the URL, username and password or keychain\n- (NSMutableDictionary *)findCredentials;\n- (NSMutableDictionary *)findProxyCredentials;\n\n// Unlock (unpause) the request thread so it can resume the request\n// Should be called by delegates when they have populated the authentication information after an authentication challenge\n- (void)retryUsingSuppliedCredentials;\n\n// Should be called by delegates when they wish to cancel authentication and stop\n- (void)cancelAuthentication;\n\n// Apply authentication information and resume the request after an authentication challenge\n- (void)attemptToApplyCredentialsAndResume;\n- (void)attemptToApplyProxyCredentialsAndResume;\n\n// Attempt to show the built-in authentication dialog, returns YES if credentials were supplied, NO if user cancelled dialog / dialog is disabled / running on main thread\n// Currently only used on iPhone OS\n- (BOOL)showProxyAuthenticationDialog;\n- (BOOL)showAuthenticationDialog;\n\n// Construct a basic authentication header from the username and password supplied, and add it to the request headers\n// Used when shouldPresentCredentialsBeforeChallenge is YES\n- (void)addBasicAuthenticationHeaderWithUsername:(NSString *)theUsername andPassword:(NSString *)thePassword;\n\n#pragma mark stream status handlers\n\n// CFnetwork event handlers\n- (void)handleNetworkEvent:(CFStreamEventType)type;\n- (void)handleBytesAvailable;\n- (void)handleStreamComplete;\n- (void)handleStreamError;\n\n#pragma mark cleanup\n\n// Cleans up and lets the queue know this operation is finished.\n// Appears in this header for subclassing only, do not call this method from outside your request!\n- (void)markAsFinished;\n\n// Cleans up temporary files. There's normally no reason to call these yourself, they are called automatically when a request completes or fails\n\n// Clean up the temporary file used to store the downloaded data when it comes in (if downloadDestinationPath is set)\n- (BOOL)removeTemporaryDownloadFile;\n\n// Clean up the temporary file used to store data that is inflated (decompressed) as it comes in\n- (BOOL)removeTemporaryUncompressedDownloadFile;\n\n// Clean up the temporary file used to store the request body (when shouldStreamPostDataFromDisk is YES)\n- (BOOL)removeTemporaryUploadFile;\n\n// Clean up the temporary file used to store a deflated (compressed) request body when shouldStreamPostDataFromDisk is YES\n- (BOOL)removeTemporaryCompressedUploadFile;\n\n// Remove a file on disk, returning NO and populating the passed error pointer if it fails\n+ (BOOL)removeFileAtPath:(NSString *)path error:(NSError **)err;\n\n#pragma mark persistent connections\n\n// Get the ID of the connection this request used (only really useful in tests and debugging)\n- (NSNumber *)connectionID;\n\n// Called automatically when a request is started to clean up any persistent connections that have expired\n+ (void)expirePersistentConnections;\n\n#pragma mark default time out\n\n+ (NSTimeInterval)defaultTimeOutSeconds;\n+ (void)setDefaultTimeOutSeconds:(NSTimeInterval)newTimeOutSeconds;\n\n#pragma mark client certificate\n\n- (void)setClientCertificateIdentity:(SecIdentityRef)anIdentity;\n\n#pragma mark session credentials\n\n+ (NSMutableArray *)sessionProxyCredentialsStore;\n+ (NSMutableArray *)sessionCredentialsStore;\n\n+ (void)storeProxyAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials;\n+ (void)storeAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials;\n\n+ (void)removeProxyAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials;\n+ (void)removeAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials;\n\n- (NSDictionary *)findSessionProxyAuthenticationCredentials;\n- (NSDictionary *)findSessionAuthenticationCredentials;\n\n#pragma mark keychain storage\n\n// Save credentials for this request to the keychain\n- (void)saveCredentialsToKeychain:(NSDictionary *)newCredentials;\n\n// Save credentials to the keychain\n+ (void)saveCredentials:(NSURLCredential *)credentials forHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n+ (void)saveCredentials:(NSURLCredential *)credentials forProxy:(NSString *)host port:(int)port realm:(NSString *)realm;\n\n// Return credentials from the keychain\n+ (NSURLCredential *)savedCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n+ (NSURLCredential *)savedCredentialsForProxy:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n\n// Remove credentials from the keychain\n+ (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n+ (void)removeCredentialsForProxy:(NSString *)host port:(int)port realm:(NSString *)realm;\n\n// We keep track of any cookies we accept, so that we can remove them from the persistent store later\n+ (void)setSessionCookies:(NSMutableArray *)newSessionCookies;\n+ (NSMutableArray *)sessionCookies;\n\n// Adds a cookie to our list of cookies we've accepted, checking first for an old version of the same cookie and removing that\n+ (void)addSessionCookie:(NSHTTPCookie *)newCookie;\n\n// Dump all session data (authentication and cookies)\n+ (void)clearSession;\n\n#pragma mark get user agent\n\n// Will be used as a user agent if requests do not specify a custom user agent\n// Is only used when you have specified a Bundle Display Name (CFDisplayBundleName) or Bundle Name (CFBundleName) in your plist\n+ (NSString *)defaultUserAgentString;\n+ (void)setDefaultUserAgentString:(NSString *)agent;\n\n#pragma mark mime-type detection\n\n// Return the mime type for a file\n+ (NSString *)mimeTypeForFileAtPath:(NSString *)path;\n\n#pragma mark bandwidth measurement / throttling\n\n// The maximum number of bytes ALL requests can send / receive in a second\n// This is a rough figure. The actual amount used will be slightly more, this does not include HTTP headers\n+ (unsigned long)maxBandwidthPerSecond;\n+ (void)setMaxBandwidthPerSecond:(unsigned long)bytes;\n\n// Get a rough average (for the last 5 seconds) of how much bandwidth is being used, in bytes\n+ (unsigned long)averageBandwidthUsedPerSecond;\n\n- (void)performThrottling;\n\n// Will return YES is bandwidth throttling is currently in use\n+ (BOOL)isBandwidthThrottled;\n\n// Used internally to record bandwidth use, and by ASIInputStreams when uploading. It's probably best if you don't mess with this.\n+ (void)incrementBandwidthUsedInLastSecond:(unsigned long)bytes;\n\n// On iPhone, ASIHTTPRequest can automatically turn throttling on and off as the connection type changes between WWAN and WiFi\n\n#if TARGET_OS_IPHONE\n// Set to YES to automatically turn on throttling when WWAN is connected, and automatically turn it off when it isn't\n+ (void)setShouldThrottleBandwidthForWWAN:(BOOL)throttle;\n\n// Turns on throttling automatically when WWAN is connected using a custom limit, and turns it off automatically when it isn't\n+ (void)throttleBandwidthForWWANUsingLimit:(unsigned long)limit;\n\n#pragma mark reachability\n\n// Returns YES when an iPhone OS device is connected via WWAN, false when connected via WIFI or not connected\n+ (BOOL)isNetworkReachableViaWWAN;\n\n#endif\n\n#pragma mark queue\n\n// Returns the shared queue\n+ (NSOperationQueue *)sharedQueue;\n\n#pragma mark cache\n\n+ (void)setDefaultCache:(id <ASICacheDelegate>)cache;\n+ (id <ASICacheDelegate>)defaultCache;\n\n// Returns the maximum amount of data we can read as part of the current measurement period, and sleeps this thread if our allowance is used up\n+ (unsigned long)maxUploadReadLength;\n\n#pragma mark network activity\n\n+ (BOOL)isNetworkInUse;\n\n+ (void)setShouldUpdateNetworkActivityIndicator:(BOOL)shouldUpdate;\n\n// Shows the network activity spinner thing on iOS. You may wish to override this to do something else in Mac projects\n+ (void)showNetworkActivityIndicator;\n\n// Hides the network activity spinner thing on iOS\n+ (void)hideNetworkActivityIndicator;\n\n#pragma mark miscellany\n\n// Used for generating Authorization header when using basic authentication when shouldPresentCredentialsBeforeChallenge is true\n// And also by ASIS3Request\n+ (NSString *)base64forData:(NSData *)theData;\n\n// Returns the expiration date for the request.\n// Calculated from the Expires response header property, unless maxAge is non-zero or\n// there exists a non-zero max-age property in the Cache-Control response header.\n+ (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Returns a date from a string in RFC1123 format\n+ (NSDate *)dateFromRFC1123String:(NSString *)string;\n\n\n// Used for detecting multitasking support at runtime (for backgrounding requests)\n#if TARGET_OS_IPHONE\n+ (BOOL)isMultitaskingSupported;\n#endif\n\n#pragma mark threading behaviour\n\n// In the default implementation, all requests run in a single background thread\n// Advanced users only: Override this method in a subclass for a different threading behaviour\n// Eg: return [NSThread mainThread] to run all requests in the main thread\n// Alternatively, you can create a thread on demand, or manage a pool of threads\n// Threads returned by this method will need to run the runloop in default mode (eg CFRunLoopRun())\n// Requests will stop the runloop when they complete\n// If you have multiple requests sharing the thread you'll need to restart the runloop when this happens\n+ (NSThread *)threadForRequest:(ASIHTTPRequest *)request;\n\n\n#pragma mark ===\n\n@property (retain) NSString *username;\n@property (retain) NSString *password;\n@property (retain) NSString *userAgent;\n@property (retain) NSString *domain;\n\n@property (retain) NSString *proxyUsername;\n@property (retain) NSString *proxyPassword;\n@property (retain) NSString *proxyDomain;\n\n@property (retain) NSString *proxyHost;\n@property (assign) int proxyPort;\n@property (retain) NSString *proxyType;\n\n@property (retain,setter=setURL:, nonatomic) NSURL *url;\n@property (retain) NSURL *originalURL;\n@property (assign, nonatomic) id delegate;\n@property (retain, nonatomic) id queue;\n@property (assign, nonatomic) id uploadProgressDelegate;\n@property (assign, nonatomic) id downloadProgressDelegate;\n@property (assign) BOOL useKeychainPersistence;\n@property (assign) BOOL useSessionPersistence;\n@property (retain) NSString *downloadDestinationPath;\n@property (retain) NSString *temporaryFileDownloadPath;\n@property (retain) NSString *temporaryUncompressedDataDownloadPath;\n@property (assign) SEL didStartSelector;\n@property (assign) SEL didReceiveResponseHeadersSelector;\n@property (assign) SEL willRedirectSelector;\n@property (assign) SEL didFinishSelector;\n@property (assign) SEL didFailSelector;\n@property (assign) SEL didReceiveDataSelector;\n@property (retain,readonly) NSString *authenticationRealm;\n@property (retain,readonly) NSString *proxyAuthenticationRealm;\n@property (retain) NSError *error;\n@property (assign,readonly) BOOL complete;\n@property (retain) NSDictionary *responseHeaders;\n@property (retain) NSMutableDictionary *requestHeaders;\n@property (retain) NSMutableArray *requestCookies;\n@property (retain,readonly) NSArray *responseCookies;\n@property (assign) BOOL useCookiePersistence;\n@property (retain) NSDictionary *requestCredentials;\n@property (retain) NSDictionary *proxyCredentials;\n@property (assign,readonly) int responseStatusCode;\n@property (retain,readonly) NSString *responseStatusMessage;\n@property (retain) NSMutableData *rawResponseData;\n@property (assign) NSTimeInterval timeOutSeconds;\n@property (retain, nonatomic) NSString *requestMethod;\n@property (retain) NSMutableData *postBody;\n@property (assign) unsigned long long contentLength;\n@property (assign) unsigned long long postLength;\n@property (assign) BOOL shouldResetDownloadProgress;\n@property (assign) BOOL shouldResetUploadProgress;\n@property (assign) ASIHTTPRequest *mainRequest;\n@property (assign) BOOL showAccurateProgress;\n@property (assign) unsigned long long totalBytesRead;\n@property (assign) unsigned long long totalBytesSent;\n@property (assign) NSStringEncoding defaultResponseEncoding;\n@property (assign) NSStringEncoding responseEncoding;\n@property (assign) BOOL allowCompressedResponse;\n@property (assign) BOOL allowResumeForFileDownloads;\n@property (retain) NSDictionary *userInfo;\n@property (assign) NSInteger tag;\n@property (retain) NSString *postBodyFilePath;\n@property (assign) BOOL shouldStreamPostDataFromDisk;\n@property (assign) BOOL didCreateTemporaryPostDataFile;\n@property (assign) BOOL useHTTPVersionOne;\n@property (assign, readonly) unsigned long long partialDownloadSize;\n@property (assign) BOOL shouldRedirect;\n@property (assign) BOOL validatesSecureCertificate;\n@property (assign) BOOL shouldCompressRequestBody;\n@property (retain) NSURL *PACurl;\n@property (retain) NSString *authenticationScheme;\n@property (retain) NSString *proxyAuthenticationScheme;\n@property (assign) BOOL shouldPresentAuthenticationDialog;\n@property (assign) BOOL shouldPresentProxyAuthenticationDialog;\n@property (assign, readonly) ASIAuthenticationState authenticationNeeded;\n@property (assign) BOOL shouldPresentCredentialsBeforeChallenge;\n@property (assign, readonly) int authenticationRetryCount;\n@property (assign, readonly) int proxyAuthenticationRetryCount;\n@property (assign) BOOL haveBuiltRequestHeaders;\n@property (assign, nonatomic) BOOL haveBuiltPostBody;\n@property (assign, readonly) BOOL inProgress;\n@property (assign) int numberOfTimesToRetryOnTimeout;\n@property (assign, readonly) int retryCount;\n@property (assign) BOOL shouldAttemptPersistentConnection;\n@property (assign) NSTimeInterval persistentConnectionTimeoutSeconds;\n@property (assign) BOOL shouldUseRFC2616RedirectBehaviour;\n@property (assign, readonly) BOOL connectionCanBeReused;\n@property (retain, readonly) NSNumber *requestID;\n@property (assign) id <ASICacheDelegate> downloadCache;\n@property (assign) ASICachePolicy cachePolicy;\n@property (assign) ASICacheStoragePolicy cacheStoragePolicy;\n@property (assign, readonly) BOOL didUseCachedResponse;\n@property (assign) NSTimeInterval secondsToCache;\n@property (retain) NSArray *clientCertificates;\n#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n@property (assign) BOOL shouldContinueWhenAppEntersBackground;\n#endif\n@property (retain) ASIDataDecompressor *dataDecompressor;\n@property (assign) BOOL shouldWaitToInflateCompressedResponses;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIHTTPRequest.m",
    "content": "//\n//  ASIHTTPRequest.m\n//\n//  Created by Ben Copsey on 04/10/2007.\n//  Copyright 2007-2011 All-Seeing Interactive. All rights reserved.\n//\n//  A guide to the main features is available at:\n//  http://allseeing-i.com/ASIHTTPRequest\n//\n//  Portions are based on the ImageClient example from Apple:\n//  See: http://developer.apple.com/samplecode/ImageClient/listing37.html\n\n#import \"ASIHTTPRequest.h\"\n\n#if TARGET_OS_IPHONE\n#import \"Reachability.h\"\n#import \"ASIAuthenticationDialog.h\"\n#import <MobileCoreServices/MobileCoreServices.h>\n#else\n#import <SystemConfiguration/SystemConfiguration.h>\n#endif\n#import \"ASIInputStream.h\"\n#import \"ASIDataDecompressor.h\"\n#import \"ASIDataCompressor.h\"\n\n// Automatically set on build\nNSString *ASIHTTPRequestVersion = @\"v1.8.1-61 2011-09-19\";\n\nstatic NSString *defaultUserAgent = nil;\n\nNSString* const NetworkRequestErrorDomain = @\"ASIHTTPRequestErrorDomain\";\n\nstatic NSString *ASIHTTPRequestRunLoopMode = @\"ASIHTTPRequestRunLoopMode\";\n\nstatic const CFOptionFlags kNetworkEvents =  kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred;\n\n// In memory caches of credentials, used on when useSessionPersistence is YES\nstatic NSMutableArray *sessionCredentialsStore = nil;\nstatic NSMutableArray *sessionProxyCredentialsStore = nil;\n\n// This lock mediates access to session credentials\nstatic NSRecursiveLock *sessionCredentialsLock = nil;\n\n// We keep track of cookies we have received here so we can remove them from the sharedHTTPCookieStorage later\nstatic NSMutableArray *sessionCookies = nil;\n\n// The number of times we will allow requests to redirect before we fail with a redirection error\nconst int RedirectionLimit = 5;\n\n// The default number of seconds to use for a timeout\nstatic NSTimeInterval defaultTimeOutSeconds = 10;\n\nstatic void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventType type, void *clientCallBackInfo) {\n    [((ASIHTTPRequest*)clientCallBackInfo) handleNetworkEvent: type];\n}\n\n// This lock prevents the operation from being cancelled while it is trying to update the progress, and vice versa\nstatic NSRecursiveLock *progressLock;\n\nstatic NSError *ASIRequestCancelledError;\nstatic NSError *ASIRequestTimedOutError;\nstatic NSError *ASIAuthenticationError;\nstatic NSError *ASIUnableToCreateRequestError;\nstatic NSError *ASITooMuchRedirectionError;\n\nstatic NSMutableArray *bandwidthUsageTracker = nil;\nstatic unsigned long averageBandwidthUsedPerSecond = 0;\n\n// These are used for queuing persistent connections on the same connection\n\n// Incremented every time we specify we want a new connection\nstatic unsigned int nextConnectionNumberToCreate = 0;\n\n// An array of connectionInfo dictionaries.\n// When attempting a persistent connection, we look here to try to find an existing connection to the same server that is currently not in use\nstatic NSMutableArray *persistentConnectionsPool = nil;\n\n// Mediates access to the persistent connections pool\nstatic NSRecursiveLock *connectionsLock = nil;\n\n// Each request gets a new id, we store this rather than a ref to the request itself in the connectionInfo dictionary.\n// We do this so we don't have to keep the request around while we wait for the connection to expire\nstatic unsigned int nextRequestID = 0;\n\n// Records how much bandwidth all requests combined have used in the last second\nstatic unsigned long bandwidthUsedInLastSecond = 0; \n\n// A date one second in the future from the time it was created\nstatic NSDate *bandwidthMeasurementDate = nil;\n\n// Since throttling variables are shared among all requests, we'll use a lock to mediate access\nstatic NSLock *bandwidthThrottlingLock = nil;\n\n// the maximum number of bytes that can be transmitted in one second\nstatic unsigned long maxBandwidthPerSecond = 0;\n\n// A default figure for throttling bandwidth on mobile devices\nunsigned long const ASIWWANBandwidthThrottleAmount = 14800;\n\n#if TARGET_OS_IPHONE\n// YES when bandwidth throttling is active\n// This flag does not denote whether throttling is turned on - rather whether it is currently in use\n// It will be set to NO when throttling was turned on with setShouldThrottleBandwidthForWWAN, but a WI-FI connection is active\nstatic BOOL isBandwidthThrottled = NO;\n\n// When YES, bandwidth will be automatically throttled when using WWAN (3G/Edge/GPRS)\n// Wifi will not be throttled\nstatic BOOL shouldThrottleBandwidthForWWANOnly = NO;\n#endif\n\n// Mediates access to the session cookies so requests\nstatic NSRecursiveLock *sessionCookiesLock = nil;\n\n// This lock ensures delegates only receive one notification that authentication is required at once\n// When using ASIAuthenticationDialogs, it also ensures only one dialog is shown at once\n// If a request can't acquire the lock immediately, it means a dialog is being shown or a delegate is handling the authentication challenge\n// Once it gets the lock, it will try to look for existing credentials again rather than showing the dialog / notifying the delegate\n// This is so it can make use of any credentials supplied for the other request, if they are appropriate\nstatic NSRecursiveLock *delegateAuthenticationLock = nil;\n\n// When throttling bandwidth, Set to a date in future that we will allow all requests to wake up and reschedule their streams\nstatic NSDate *throttleWakeUpTime = nil;\n\nstatic id <ASICacheDelegate> defaultCache = nil;\n\n// Used for tracking when requests are using the network\nstatic unsigned int runningRequestCount = 0;\n\n// You can use [ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:NO] if you want to manage it yourself\n// Alternatively, override showNetworkActivityIndicator / hideNetworkActivityIndicator\n// By default this does nothing on Mac OS X, but again override the above methods for a different behaviour\nstatic BOOL shouldUpdateNetworkActivityIndicator = YES;\n\n// The thread all requests will run on\n// Hangs around forever, but will be blocked unless there are requests underway\nstatic NSThread *networkThread = nil;\n\nstatic NSOperationQueue *sharedQueue = nil;\n\n// Private stuff\n@interface ASIHTTPRequest ()\n\n- (void)cancelLoad;\n\n- (void)destroyReadStream;\n- (void)scheduleReadStream;\n- (void)unscheduleReadStream;\n\n- (BOOL)willAskDelegateForCredentials;\n- (BOOL)willAskDelegateForProxyCredentials;\n- (void)askDelegateForProxyCredentials;\n- (void)askDelegateForCredentials;\n- (void)failAuthentication;\n\n+ (void)measureBandwidthUsage;\n+ (void)recordBandwidthUsage;\n\n- (void)startRequest;\n- (void)updateStatus:(NSTimer *)timer;\n- (void)checkRequestStatus;\n- (void)reportFailure;\n- (void)reportFinished;\n- (void)markAsFinished;\n- (void)performRedirect;\n- (BOOL)shouldTimeOut;\n- (BOOL)willRedirect;\n- (BOOL)willAskDelegateToConfirmRedirect;\n\n+ (void)performInvocation:(NSInvocation *)invocation onTarget:(id *)target releasingObject:(id)objectToRelease;\n+ (void)hideNetworkActivityIndicatorAfterDelay;\n+ (void)hideNetworkActivityIndicatorIfNeeeded;\n+ (void)runRequests;\n\n// Handling Proxy autodetection and PAC file downloads\n- (BOOL)configureProxies;\n- (void)fetchPACFile;\n- (void)finishedDownloadingPACFile:(ASIHTTPRequest *)theRequest;\n- (void)runPACScript:(NSString *)script;\n- (void)timeOutPACRead;\n\n- (void)useDataFromCache;\n\n// Called to update the size of a partial download when starting a request, or retrying after a timeout\n- (void)updatePartialDownloadSize;\n\n#if TARGET_OS_IPHONE\n+ (void)registerForNetworkReachabilityNotifications;\n+ (void)unsubscribeFromNetworkReachabilityNotifications;\n// Called when the status of the network changes\n+ (void)reachabilityChanged:(NSNotification *)note;\n#endif\n\n#if NS_BLOCKS_AVAILABLE\n- (void)performBlockOnMainThread:(ASIBasicBlock)block;\n- (void)releaseBlocksOnMainThread;\n+ (void)releaseBlocks:(NSArray *)blocks;\n- (void)callBlock:(ASIBasicBlock)block;\n#endif\n\n\n\n\n\n@property (assign) BOOL complete;\n@property (retain) NSArray *responseCookies;\n@property (assign) int responseStatusCode;\n@property (retain, nonatomic) NSDate *lastActivityTime;\n\n@property (assign) unsigned long long partialDownloadSize;\n@property (assign, nonatomic) unsigned long long uploadBufferSize;\n@property (retain, nonatomic) NSOutputStream *postBodyWriteStream;\n@property (retain, nonatomic) NSInputStream *postBodyReadStream;\n@property (assign, nonatomic) unsigned long long lastBytesRead;\n@property (assign, nonatomic) unsigned long long lastBytesSent;\n@property (retain) NSRecursiveLock *cancelledLock;\n@property (retain, nonatomic) NSOutputStream *fileDownloadOutputStream;\n@property (retain, nonatomic) NSOutputStream *inflatedFileDownloadOutputStream;\n@property (assign) int authenticationRetryCount;\n@property (assign) int proxyAuthenticationRetryCount;\n@property (assign, nonatomic) BOOL updatedProgress;\n@property (assign, nonatomic) BOOL needsRedirect;\n@property (assign, nonatomic) int redirectCount;\n@property (retain, nonatomic) NSData *compressedPostBody;\n@property (retain, nonatomic) NSString *compressedPostBodyFilePath;\n@property (retain) NSString *authenticationRealm;\n@property (retain) NSString *proxyAuthenticationRealm;\n@property (retain) NSString *responseStatusMessage;\n@property (assign) BOOL inProgress;\n@property (assign) int retryCount;\n@property (assign) BOOL willRetryRequest;\n@property (assign) BOOL connectionCanBeReused;\n@property (retain, nonatomic) NSMutableDictionary *connectionInfo;\n@property (retain, nonatomic) NSInputStream *readStream;\n@property (assign) ASIAuthenticationState authenticationNeeded;\n@property (assign, nonatomic) BOOL readStreamIsScheduled;\n@property (assign, nonatomic) BOOL downloadComplete;\n@property (retain) NSNumber *requestID;\n@property (assign, nonatomic) NSString *runLoopMode;\n@property (retain, nonatomic) NSTimer *statusTimer;\n@property (assign) BOOL didUseCachedResponse;\n@property (retain, nonatomic) NSURL *redirectURL;\n\n@property (assign, nonatomic) BOOL isPACFileRequest;\n@property (retain, nonatomic) ASIHTTPRequest *PACFileRequest;\n@property (retain, nonatomic) NSInputStream *PACFileReadStream;\n@property (retain, nonatomic) NSMutableData *PACFileData;\n\n@property (assign, nonatomic, setter=setSynchronous:) BOOL isSynchronous;\n@end\n\n\n@implementation ASIHTTPRequest\n\n#pragma mark init / dealloc\n\n+ (void)initialize\n{\n\tif (self == [ASIHTTPRequest class]) {\n\t\tpersistentConnectionsPool = [[NSMutableArray alloc] init];\n\t\tconnectionsLock = [[NSRecursiveLock alloc] init];\n\t\tprogressLock = [[NSRecursiveLock alloc] init];\n\t\tbandwidthThrottlingLock = [[NSLock alloc] init];\n\t\tsessionCookiesLock = [[NSRecursiveLock alloc] init];\n\t\tsessionCredentialsLock = [[NSRecursiveLock alloc] init];\n\t\tdelegateAuthenticationLock = [[NSRecursiveLock alloc] init];\n\t\tbandwidthUsageTracker = [[NSMutableArray alloc] initWithCapacity:5];\n\t\tASIRequestTimedOutError = [[NSError alloc] initWithDomain:NetworkRequestErrorDomain code:ASIRequestTimedOutErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"The request timed out\",NSLocalizedDescriptionKey,nil]];  \n\t\tASIAuthenticationError = [[NSError alloc] initWithDomain:NetworkRequestErrorDomain code:ASIAuthenticationErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Authentication needed\",NSLocalizedDescriptionKey,nil]];\n\t\tASIRequestCancelledError = [[NSError alloc] initWithDomain:NetworkRequestErrorDomain code:ASIRequestCancelledErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"The request was cancelled\",NSLocalizedDescriptionKey,nil]];\n\t\tASIUnableToCreateRequestError = [[NSError alloc] initWithDomain:NetworkRequestErrorDomain code:ASIUnableToCreateRequestErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Unable to create request (bad url?)\",NSLocalizedDescriptionKey,nil]];\n\t\tASITooMuchRedirectionError = [[NSError alloc] initWithDomain:NetworkRequestErrorDomain code:ASITooMuchRedirectionErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"The request failed because it redirected too many times\",NSLocalizedDescriptionKey,nil]];\n\t\tsharedQueue = [[NSOperationQueue alloc] init];\n\t\t[sharedQueue setMaxConcurrentOperationCount:4];\n\n\t}\n}\n\n\n- (id)initWithURL:(NSURL *)newURL\n{\n\tself = [self init];\n\t[self setRequestMethod:@\"GET\"];\n\n\t[self setRunLoopMode:NSDefaultRunLoopMode];\n\t[self setShouldAttemptPersistentConnection:YES];\n\t[self setPersistentConnectionTimeoutSeconds:60.0];\n\t[self setShouldPresentCredentialsBeforeChallenge:YES];\n\t[self setShouldRedirect:YES];\n\t[self setShowAccurateProgress:YES];\n\t[self setShouldResetDownloadProgress:YES];\n\t[self setShouldResetUploadProgress:YES];\n\t[self setAllowCompressedResponse:YES];\n\t[self setShouldWaitToInflateCompressedResponses:YES];\n\t[self setDefaultResponseEncoding:NSISOLatin1StringEncoding];\n\t[self setShouldPresentProxyAuthenticationDialog:YES];\n\t\n\t[self setTimeOutSeconds:[ASIHTTPRequest defaultTimeOutSeconds]];\n\t[self setUseSessionPersistence:YES];\n\t[self setUseCookiePersistence:YES];\n\t[self setValidatesSecureCertificate:YES];\n\t[self setRequestCookies:[[[NSMutableArray alloc] init] autorelease]];\n\t[self setDidStartSelector:@selector(requestStarted:)];\n\t[self setDidReceiveResponseHeadersSelector:@selector(request:didReceiveResponseHeaders:)];\n\t[self setWillRedirectSelector:@selector(request:willRedirectToURL:)];\n\t[self setDidFinishSelector:@selector(requestFinished:)];\n\t[self setDidFailSelector:@selector(requestFailed:)];\n\t[self setDidReceiveDataSelector:@selector(request:didReceiveData:)];\n\t[self setURL:newURL];\n\t[self setCancelledLock:[[[NSRecursiveLock alloc] init] autorelease]];\n\t[self setDownloadCache:[[self class] defaultCache]];\n\treturn self;\n}\n\n+ (id)requestWithURL:(NSURL *)newURL\n{\n\treturn [[[self alloc] initWithURL:newURL] autorelease];\n}\n\n+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache\n{\n\treturn [self requestWithURL:newURL usingCache:cache andCachePolicy:ASIUseDefaultCachePolicy];\n}\n\n+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache andCachePolicy:(ASICachePolicy)policy\n{\n\tASIHTTPRequest *request = [[[self alloc] initWithURL:newURL] autorelease];\n\t[request setDownloadCache:cache];\n\t[request setCachePolicy:policy];\n\treturn request;\n}\n\n- (void)dealloc\n{\n\t[self setAuthenticationNeeded:ASINoAuthenticationNeededYet];\n\tif (requestAuthentication) {\n\t\tCFRelease(requestAuthentication);\n\t}\n\tif (proxyAuthentication) {\n\t\tCFRelease(proxyAuthentication);\n\t}\n\tif (request) {\n\t\tCFRelease(request);\n\t}\n\tif (clientCertificateIdentity) {\n\t\tCFRelease(clientCertificateIdentity);\n\t}\n\t[self cancelLoad];\n\t[redirectURL release];\n\t[statusTimer invalidate];\n\t[statusTimer release];\n\t[queue release];\n\t[userInfo release];\n\t[postBody release];\n\t[compressedPostBody release];\n\t[error release];\n\t[requestHeaders release];\n\t[requestCookies release];\n\t[downloadDestinationPath release];\n\t[temporaryFileDownloadPath release];\n\t[temporaryUncompressedDataDownloadPath release];\n\t[fileDownloadOutputStream release];\n\t[inflatedFileDownloadOutputStream release];\n\t[username release];\n\t[password release];\n\t[domain release];\n\t[authenticationRealm release];\n\t[authenticationScheme release];\n\t[requestCredentials release];\n\t[proxyHost release];\n\t[proxyType release];\n\t[proxyUsername release];\n\t[proxyPassword release];\n\t[proxyDomain release];\n\t[proxyAuthenticationRealm release];\n\t[proxyAuthenticationScheme release];\n\t[proxyCredentials release];\n\t[url release];\n\t[originalURL release];\n\t[lastActivityTime release];\n\t[responseCookies release];\n\t[rawResponseData release];\n\t[responseHeaders release];\n\t[requestMethod release];\n\t[cancelledLock release];\n\t[postBodyFilePath release];\n\t[compressedPostBodyFilePath release];\n\t[postBodyWriteStream release];\n\t[postBodyReadStream release];\n\t[PACurl release];\n\t[clientCertificates release];\n\t[responseStatusMessage release];\n\t[connectionInfo release];\n\t[requestID release];\n\t[dataDecompressor release];\n\t[userAgent release];\n\n\t#if NS_BLOCKS_AVAILABLE\n\t[self releaseBlocksOnMainThread];\n\t#endif\n\n\t[super dealloc];\n}\n\n#if NS_BLOCKS_AVAILABLE\n- (void)releaseBlocksOnMainThread\n{\n\tNSMutableArray *blocks = [NSMutableArray array];\n\tif (completionBlock) {\n\t\t[blocks addObject:completionBlock];\n\t\t[completionBlock release];\n\t\tcompletionBlock = nil;\n\t}\n\tif (failureBlock) {\n\t\t[blocks addObject:failureBlock];\n\t\t[failureBlock release];\n\t\tfailureBlock = nil;\n\t}\n\tif (startedBlock) {\n\t\t[blocks addObject:startedBlock];\n\t\t[startedBlock release];\n\t\tstartedBlock = nil;\n\t}\n\tif (headersReceivedBlock) {\n\t\t[blocks addObject:headersReceivedBlock];\n\t\t[headersReceivedBlock release];\n\t\theadersReceivedBlock = nil;\n\t}\n\tif (bytesReceivedBlock) {\n\t\t[blocks addObject:bytesReceivedBlock];\n\t\t[bytesReceivedBlock release];\n\t\tbytesReceivedBlock = nil;\n\t}\n\tif (bytesSentBlock) {\n\t\t[blocks addObject:bytesSentBlock];\n\t\t[bytesSentBlock release];\n\t\tbytesSentBlock = nil;\n\t}\n\tif (downloadSizeIncrementedBlock) {\n\t\t[blocks addObject:downloadSizeIncrementedBlock];\n\t\t[downloadSizeIncrementedBlock release];\n\t\tdownloadSizeIncrementedBlock = nil;\n\t}\n\tif (uploadSizeIncrementedBlock) {\n\t\t[blocks addObject:uploadSizeIncrementedBlock];\n\t\t[uploadSizeIncrementedBlock release];\n\t\tuploadSizeIncrementedBlock = nil;\n\t}\n\tif (dataReceivedBlock) {\n\t\t[blocks addObject:dataReceivedBlock];\n\t\t[dataReceivedBlock release];\n\t\tdataReceivedBlock = nil;\n\t}\n\tif (proxyAuthenticationNeededBlock) {\n\t\t[blocks addObject:proxyAuthenticationNeededBlock];\n\t\t[proxyAuthenticationNeededBlock release];\n\t\tproxyAuthenticationNeededBlock = nil;\n\t}\n\tif (authenticationNeededBlock) {\n\t\t[blocks addObject:authenticationNeededBlock];\n\t\t[authenticationNeededBlock release];\n\t\tauthenticationNeededBlock = nil;\n\t}\n\t[[self class] performSelectorOnMainThread:@selector(releaseBlocks:) withObject:blocks waitUntilDone:[NSThread isMainThread]];\n}\n// Always called on main thread\n+ (void)releaseBlocks:(NSArray *)blocks\n{\n\t// Blocks will be released when this method exits\n}\n#endif\n\n\n#pragma mark setup request\n\n- (void)addRequestHeader:(NSString *)header value:(NSString *)value\n{\n\tif (!requestHeaders) {\n\t\t[self setRequestHeaders:[NSMutableDictionary dictionaryWithCapacity:1]];\n\t}\n\t[requestHeaders setObject:value forKey:header];\n}\n\n// This function will be called either just before a request starts, or when postLength is needed, whichever comes first\n// postLength must be set by the time this function is complete\n- (void)buildPostBody\n{\n\n\tif ([self haveBuiltPostBody]) {\n\t\treturn;\n\t}\n\t\n\t// Are we submitting the request body from a file on disk\n\tif ([self postBodyFilePath]) {\n\t\t\n\t\t// If we were writing to the post body via appendPostData or appendPostDataFromFile, close the write stream\n\t\tif ([self postBodyWriteStream]) {\n\t\t\t[[self postBodyWriteStream] close];\n\t\t\t[self setPostBodyWriteStream:nil];\n\t\t}\n\n\t\t\n\t\tNSString *path;\n\t\tif ([self shouldCompressRequestBody]) {\n\t\t\tif (![self compressedPostBodyFilePath]) {\n\t\t\t\t[self setCompressedPostBodyFilePath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]];\n\t\t\t\t\n\t\t\t\tNSError *err = nil;\n\t\t\t\tif (![ASIDataCompressor compressDataFromFile:[self postBodyFilePath] toFile:[self compressedPostBodyFilePath] error:&err]) {\n\t\t\t\t\t[self failWithError:err];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpath = [self compressedPostBodyFilePath];\n\t\t} else {\n\t\t\tpath = [self postBodyFilePath];\n\t\t}\n\t\tNSError *err = nil;\n\t\t[self setPostLength:[[[[[NSFileManager alloc] init] autorelease] attributesOfItemAtPath:path error:&err] fileSize]];\n\t\tif (err) {\n\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Failed to get attributes for file at path '%@'\",path],NSLocalizedDescriptionKey,error,NSUnderlyingErrorKey,nil]]];\n\t\t\treturn;\n\t\t}\n\t\t\n\t// Otherwise, we have an in-memory request body\n\t} else {\n\t\tif ([self shouldCompressRequestBody]) {\n\t\t\tNSError *err = nil;\n\t\t\tNSData *compressedBody = [ASIDataCompressor compressData:[self postBody] error:&err];\n\t\t\tif (err) {\n\t\t\t\t[self failWithError:err];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t[self setCompressedPostBody:compressedBody];\n\t\t\t[self setPostLength:[[self compressedPostBody] length]];\n\t\t} else {\n\t\t\t[self setPostLength:[[self postBody] length]];\n\t\t}\n\t}\n\t\t\n\tif ([self postLength] > 0) {\n\t\tif ([requestMethod isEqualToString:@\"GET\"] || [requestMethod isEqualToString:@\"DELETE\"] || [requestMethod isEqualToString:@\"HEAD\"]) {\n\t\t\t[self setRequestMethod:@\"POST\"];\n\t\t}\n\t\t[self addRequestHeader:@\"Content-Length\" value:[NSString stringWithFormat:@\"%llu\",[self postLength]]];\n\t}\n\t[self setHaveBuiltPostBody:YES];\n\n}\n\n// Sets up storage for the post body\n- (void)setupPostBody\n{\n\tif ([self shouldStreamPostDataFromDisk]) {\n\t\tif (![self postBodyFilePath]) {\n\t\t\t[self setPostBodyFilePath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]];\n\t\t\t[self setDidCreateTemporaryPostDataFile:YES];\n\t\t}\n\t\tif (![self postBodyWriteStream]) {\n\t\t\t[self setPostBodyWriteStream:[[[NSOutputStream alloc] initToFileAtPath:[self postBodyFilePath] append:NO] autorelease]];\n\t\t\t[[self postBodyWriteStream] open];\n\t\t}\n\t} else {\n\t\tif (![self postBody]) {\n\t\t\t[self setPostBody:[[[NSMutableData alloc] init] autorelease]];\n\t\t}\n\t}\t\n}\n\n- (void)appendPostData:(NSData *)data\n{\n\t[self setupPostBody];\n\tif ([data length] == 0) {\n\t\treturn;\n\t}\n\tif ([self shouldStreamPostDataFromDisk]) {\n\t\t[[self postBodyWriteStream] write:[data bytes] maxLength:[data length]];\n\t} else {\n\t\t[[self postBody] appendData:data];\n\t}\n}\n\n- (void)appendPostDataFromFile:(NSString *)file\n{\n\t[self setupPostBody];\n\tNSInputStream *stream = [[[NSInputStream alloc] initWithFileAtPath:file] autorelease];\n\t[stream open];\n\tNSUInteger bytesRead;\n\twhile ([stream hasBytesAvailable]) {\n\t\t\n\t\tunsigned char buffer[1024*256];\n\t\tbytesRead = [stream read:buffer maxLength:sizeof(buffer)];\n\t\tif (bytesRead == 0) {\n\t\t\tbreak;\n\t\t}\n\t\tif ([self shouldStreamPostDataFromDisk]) {\n\t\t\t[[self postBodyWriteStream] write:buffer maxLength:bytesRead];\n\t\t} else {\n\t\t\t[[self postBody] appendData:[NSData dataWithBytes:buffer length:bytesRead]];\n\t\t}\n\t}\n\t[stream close];\n}\n\n- (NSString *)requestMethod\n{\n\t[[self cancelledLock] lock];\n\tNSString *m = requestMethod;\n\t[[self cancelledLock] unlock];\n\treturn m;\n}\n\n- (void)setRequestMethod:(NSString *)newRequestMethod\n{\n\t[[self cancelledLock] lock];\n\tif (requestMethod != newRequestMethod) {\n\t\t[requestMethod release];\n\t\trequestMethod = [newRequestMethod retain];\n\t\tif ([requestMethod isEqualToString:@\"POST\"] || [requestMethod isEqualToString:@\"PUT\"] || [postBody length] || postBodyFilePath) {\n\t\t\t[self setShouldAttemptPersistentConnection:NO];\n\t\t}\n\t}\n\t[[self cancelledLock] unlock];\n}\n\n- (NSURL *)url\n{\n\t[[self cancelledLock] lock];\n\tNSURL *u = url;\n\t[[self cancelledLock] unlock];\n\treturn u;\n}\n\n\n- (void)setURL:(NSURL *)newURL\n{\n\t[[self cancelledLock] lock];\n\tif ([newURL isEqual:[self url]]) {\n\t\t[[self cancelledLock] unlock];\n\t\treturn;\n\t}\n\t[url release];\n\turl = [newURL retain];\n\tif (requestAuthentication) {\n\t\tCFRelease(requestAuthentication);\n\t\trequestAuthentication = NULL;\n\t}\n\tif (proxyAuthentication) {\n\t\tCFRelease(proxyAuthentication);\n\t\tproxyAuthentication = NULL;\n\t}\n\tif (request) {\n\t\tCFRelease(request);\n\t\trequest = NULL;\n\t}\n\t[self setRedirectURL:nil];\n\t[[self cancelledLock] unlock];\n}\n\n- (id)delegate\n{\n\t[[self cancelledLock] lock];\n\tid d = delegate;\n\t[[self cancelledLock] unlock];\n\treturn d;\n}\n\n- (void)setDelegate:(id)newDelegate\n{\n\t[[self cancelledLock] lock];\n\tdelegate = newDelegate;\n\t[[self cancelledLock] unlock];\n}\n\n- (id)queue\n{\n\t[[self cancelledLock] lock];\n\tid q = queue;\n\t[[self cancelledLock] unlock];\n\treturn q;\n}\n\n\n- (void)setQueue:(id)newQueue\n{\n\t[[self cancelledLock] lock];\n\tif (newQueue != queue) {\n\t\t[queue release];\n\t\tqueue = [newQueue retain];\n\t}\n\t[[self cancelledLock] unlock];\n}\n\n#pragma mark get information about this request\n\n// cancel the request - this must be run on the same thread as the request is running on\n- (void)cancelOnRequestThread\n{\n\t#if DEBUG_REQUEST_STATUS\n\tASI_DEBUG_LOG(@\"[STATUS] Request cancelled: %@\",self);\n\t#endif\n    \n\t[[self cancelledLock] lock];\n\n    if ([self isCancelled] || [self complete]) {\n\t\t[[self cancelledLock] unlock];\n\t\treturn;\n\t}\n\t[self failWithError:ASIRequestCancelledError];\n\t[self setComplete:YES];\n\t[self cancelLoad];\n\t\n\tCFRetain(self);\n    [self willChangeValueForKey:@\"isCancelled\"];\n    cancelled = YES;\n    [self didChangeValueForKey:@\"isCancelled\"];\n    \n\t[[self cancelledLock] unlock];\n\tCFRelease(self);\n}\n\n- (void)cancel\n{\n    [self performSelector:@selector(cancelOnRequestThread) onThread:[[self class] threadForRequest:self] withObject:nil waitUntilDone:NO];    \n}\n\n- (void)clearDelegatesAndCancel\n{\n\t[[self cancelledLock] lock];\n\n\t// Clear delegates\n\t[self setDelegate:nil];\n\t[self setQueue:nil];\n\t[self setDownloadProgressDelegate:nil];\n\t[self setUploadProgressDelegate:nil];\n\n\t#if NS_BLOCKS_AVAILABLE\n\t// Clear blocks\n\t[self releaseBlocksOnMainThread];\n\t#endif\n\n\t[[self cancelledLock] unlock];\n\t[self cancel];\n}\n\n\n- (BOOL)isCancelled\n{\n    BOOL result;\n    \n\t[[self cancelledLock] lock];\n    result = cancelled;\n    [[self cancelledLock] unlock];\n    \n    return result;\n}\n\n// Call this method to get the received data as an NSString. Don't use for binary data!\n- (NSString *)responseString\n{\n\tNSData *data = [self responseData];\n\tif (!data) {\n\t\treturn nil;\n\t}\n\t\n\treturn [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:[self responseEncoding]] autorelease];\n}\n\n- (BOOL)isResponseCompressed\n{\n\tNSString *encoding = [[self responseHeaders] objectForKey:@\"Content-Encoding\"];\n\treturn encoding && [encoding rangeOfString:@\"gzip\"].location != NSNotFound;\n}\n\n- (NSData *)responseData\n{\t\n\tif ([self isResponseCompressed] && [self shouldWaitToInflateCompressedResponses]) {\n\t\treturn [ASIDataDecompressor uncompressData:[self rawResponseData] error:NULL];\n\t} else {\n\t\treturn [self rawResponseData];\n\t}\n\treturn nil;\n}\n\n#pragma mark running a request\n\n- (void)startSynchronous\n{\n#if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING\n\tASI_DEBUG_LOG(@\"[STATUS] Starting synchronous request %@\",self);\n#endif\n\t[self setSynchronous:YES];\n\t[self setRunLoopMode:ASIHTTPRequestRunLoopMode];\n\t[self setInProgress:YES];\n\n\tif (![self isCancelled] && ![self complete]) {\n\t\t[self main];\n\t\twhile (!complete) {\n\t\t\t[[NSRunLoop currentRunLoop] runMode:[self runLoopMode] beforeDate:[NSDate distantFuture]];\n\t\t}\n\t}\n\n\t[self setInProgress:NO];\n}\n\n- (void)start\n{\n\t[self setInProgress:YES];\n\t[self performSelector:@selector(main) onThread:[[self class] threadForRequest:self] withObject:nil waitUntilDone:NO];\n}\n\n- (void)startAsynchronous\n{\n#if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING\n\tASI_DEBUG_LOG(@\"[STATUS] Starting asynchronous request %@\",self);\n#endif\n\t[sharedQueue addOperation:self];\n}\n\n#pragma mark concurrency\n\n- (BOOL)isConcurrent\n{\n    return YES;\n}\n\n- (BOOL)isFinished \n{\n\treturn finished;\n}\n\n- (BOOL)isExecuting {\n\treturn [self inProgress];\n}\n\n#pragma mark request logic\n\n// Create the request\n- (void)main\n{\n\t@try {\n\t\t\n\t\t[[self cancelledLock] lock];\n\t\t\n\t\t#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n\t\tif ([ASIHTTPRequest isMultitaskingSupported] && [self shouldContinueWhenAppEntersBackground]) {\n\t\t\tbackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{\n\t\t\t\t// Synchronize the cleanup call on the main thread in case\n\t\t\t\t// the task actually finishes at around the same time.\n\t\t\t\tdispatch_async(dispatch_get_main_queue(), ^{\n\t\t\t\t\tif (backgroundTask != UIBackgroundTaskInvalid)\n\t\t\t\t\t{\n\t\t\t\t\t\t[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];\n\t\t\t\t\t\tbackgroundTask = UIBackgroundTaskInvalid;\n\t\t\t\t\t\t[self cancel];\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}];\n\t\t}\n\t\t#endif\n\n\n\t\t// A HEAD request generated by an ASINetworkQueue may have set the error already. If so, we should not proceed.\n\t\tif ([self error]) {\n\t\t\t[self setComplete:YES];\n\t\t\t[self markAsFinished];\n\t\t\treturn;\t\t\n\t\t}\n\n\t\t[self setComplete:NO];\n\t\t[self setDidUseCachedResponse:NO];\n\t\t\n\t\tif (![self url]) {\n\t\t\t[self failWithError:ASIUnableToCreateRequestError];\n\t\t\treturn;\t\t\n\t\t}\n\t\t\n\t\t// Must call before we create the request so that the request method can be set if needs be\n\t\tif (![self mainRequest]) {\n\t\t\t[self buildPostBody];\n\t\t}\n\t\t\n\t\tif (![[self requestMethod] isEqualToString:@\"GET\"]) {\n\t\t\t[self setDownloadCache:nil];\n\t\t}\n\t\t\n\t\t\n\t\t// If we're redirecting, we'll already have a CFHTTPMessageRef\n\t\tif (request) {\n\t\t\tCFRelease(request);\n\t\t}\n\n\t\t// Create a new HTTP request.\n\t\trequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)[self requestMethod], (CFURLRef)[self url], [self useHTTPVersionOne] ? kCFHTTPVersion1_0 : kCFHTTPVersion1_1);\n\t\tif (!request) {\n\t\t\t[self failWithError:ASIUnableToCreateRequestError];\n\t\t\treturn;\n\t\t}\n\n\t\t//If this is a HEAD request generated by an ASINetworkQueue, we need to let the main request generate its headers first so we can use them\n\t\tif ([self mainRequest]) {\n\t\t\t[[self mainRequest] buildRequestHeaders];\n\t\t}\n\t\t\n\t\t// Even if this is a HEAD request with a mainRequest, we still need to call to give subclasses a chance to add their own to HEAD requests (ASIS3Request does this)\n\t\t[self buildRequestHeaders];\n\t\t\n\t\tif ([self downloadCache]) {\n\n\t\t\t// If this request should use the default policy, set its policy to the download cache's default policy\n\t\t\tif (![self cachePolicy]) {\n\t\t\t\t[self setCachePolicy:[[self downloadCache] defaultCachePolicy]];\n\t\t\t}\n\n\t\t\t// If have have cached data that is valid for this request, use that and stop\n\t\t\tif ([[self downloadCache] canUseCachedDataForRequest:self]) {\n\t\t\t\t[self useDataFromCache];\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If cached data is stale, or we have been told to ask the server if it has been modified anyway, we need to add headers for a conditional GET\n\t\t\tif ([self cachePolicy] & (ASIAskServerIfModifiedWhenStaleCachePolicy|ASIAskServerIfModifiedCachePolicy)) {\n\n\t\t\t\tNSDictionary *cachedHeaders = [[self downloadCache] cachedResponseHeadersForURL:[self url]];\n\t\t\t\tif (cachedHeaders) {\n\t\t\t\t\tNSString *etag = [cachedHeaders objectForKey:@\"Etag\"];\n\t\t\t\t\tif (etag) {\n\t\t\t\t\t\t[[self requestHeaders] setObject:etag forKey:@\"If-None-Match\"];\n\t\t\t\t\t}\n\t\t\t\t\tNSString *lastModified = [cachedHeaders objectForKey:@\"Last-Modified\"];\n\t\t\t\t\tif (lastModified) {\n\t\t\t\t\t\t[[self requestHeaders] setObject:lastModified forKey:@\"If-Modified-Since\"];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t[self applyAuthorizationHeader];\n\t\t\n\t\t\n\t\tNSString *header;\n\t\tfor (header in [self requestHeaders]) {\n\t\t\tCFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[[self requestHeaders] objectForKey:header]);\n\t\t}\n\n\t\t// If we immediately have access to proxy settings, start the request\n\t\t// Otherwise, we'll start downloading the proxy PAC file, and call startRequest once that process is complete\n\t\tif ([self configureProxies]) {\n\t\t\t[self startRequest];\n\t\t}\n\n\t} @catch (NSException *exception) {\n\t\tNSError *underlyingError = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASIUnhandledExceptionError userInfo:[exception userInfo]];\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIUnhandledExceptionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[exception name],NSLocalizedDescriptionKey,[exception reason],NSLocalizedFailureReasonErrorKey,underlyingError,NSUnderlyingErrorKey,nil]]];\n\n\t} @finally {\n\t\t[[self cancelledLock] unlock];\n\t}\n}\n\n- (void)applyAuthorizationHeader\n{\n\t// Do we want to send credentials before we are asked for them?\n\tif (![self shouldPresentCredentialsBeforeChallenge]) {\n\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will not send credentials to the server until it asks for them\",self);\n\t\t#endif\n\t\treturn;\n\t}\n\n\tNSDictionary *credentials = nil;\n\n\t// Do we already have an auth header?\n\tif (![[self requestHeaders] objectForKey:@\"Authorization\"]) {\n\n\t\t// If we have basic authentication explicitly set and a username and password set on the request, add a basic auth header\n\t\tif ([self username] && [self password] && [[self authenticationScheme] isEqualToString:(NSString *)kCFHTTPAuthenticationSchemeBasic]) {\n\t\t\t[self addBasicAuthenticationHeaderWithUsername:[self username] andPassword:[self password]];\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ has a username and password set, and was manually configured to use BASIC. Will send credentials without waiting for an authentication challenge\",self);\t\n\t\t\t#endif\n\n\t\t} else {\n\n\t\t\t// See if we have any cached credentials we can use in the session store\n\t\t\tif ([self useSessionPersistence]) {\n\t\t\t\tcredentials = [self findSessionAuthenticationCredentials];\n\n\t\t\t\tif (credentials) {\n\n\t\t\t\t\t// When the Authentication key is set, the credentials were stored after an authentication challenge, so we can let CFNetwork apply them\n\t\t\t\t\t// (credentials for Digest and NTLM will always be stored like this)\n\t\t\t\t\tif ([credentials objectForKey:@\"Authentication\"]) {\n\n\t\t\t\t\t\t// If we've already talked to this server and have valid credentials, let's apply them to the request\n\t\t\t\t\t\tif (CFHTTPMessageApplyCredentialDictionary(request, (CFHTTPAuthenticationRef)[credentials objectForKey:@\"Authentication\"], (CFDictionaryRef)[credentials objectForKey:@\"Credentials\"], NULL)) {\n\t\t\t\t\t\t\t[self setAuthenticationScheme:[credentials objectForKey:@\"AuthenticationScheme\"]];\n\t\t\t\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ found cached credentials (%@), will reuse without waiting for an authentication challenge\",self,[credentials objectForKey:@\"AuthenticationScheme\"]);\n\t\t\t\t\t\t\t#endif\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t[[self class] removeAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@\"Credentials\"]];\n\t\t\t\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Failed to apply cached credentials to request %@. These will be removed from the session store, and this request will wait for an authentication challenge\",self);\n\t\t\t\t\t\t\t#endif\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// If the Authentication key is not set, these credentials were stored after a username and password set on a previous request passed basic authentication\n\t\t\t\t\t// When this happens, we'll need to create the Authorization header ourselves\n\t\t\t\t\t} else {\n\t\t\t\t\t\tNSDictionary *usernameAndPassword = [credentials objectForKey:@\"Credentials\"];\n\t\t\t\t\t\t[self addBasicAuthenticationHeaderWithUsername:[usernameAndPassword objectForKey:(NSString *)kCFHTTPAuthenticationUsername] andPassword:[usernameAndPassword objectForKey:(NSString *)kCFHTTPAuthenticationPassword]];\n\t\t\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ found cached BASIC credentials from a previous request. Will send credentials without waiting for an authentication challenge\",self);\n\t\t\t\t\t\t#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply proxy authentication credentials\n\tif ([self useSessionPersistence]) {\n\t\tcredentials = [self findSessionProxyAuthenticationCredentials];\n\t\tif (credentials) {\n\t\t\tif (!CFHTTPMessageApplyCredentialDictionary(request, (CFHTTPAuthenticationRef)[credentials objectForKey:@\"Authentication\"], (CFDictionaryRef)[credentials objectForKey:@\"Credentials\"], NULL)) {\n\t\t\t\t[[self class] removeProxyAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@\"Credentials\"]];\n\t\t\t}\n\t\t}\n\t}\n}\n\n- (void)applyCookieHeader\n{\n\t// Add cookies from the persistent (mac os global) store\n\tif ([self useCookiePersistence]) {\n\t\tNSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[[self url] absoluteURL]];\n\t\tif (cookies) {\n\t\t\t[[self requestCookies] addObjectsFromArray:cookies];\n\t\t}\n\t}\n\t\n\t// Apply request cookies\n\tNSArray *cookies;\n\tif ([self mainRequest]) {\n\t\tcookies = [[self mainRequest] requestCookies];\n\t} else {\n\t\tcookies = [self requestCookies];\n\t}\n\tif ([cookies count] > 0) {\n\t\tNSHTTPCookie *cookie;\n\t\tNSString *cookieHeader = nil;\n\t\tfor (cookie in cookies) {\n\t\t\tif (!cookieHeader) {\n\t\t\t\tcookieHeader = [NSString stringWithFormat: @\"%@=%@\",[cookie name],[cookie value]];\n\t\t\t} else {\n\t\t\t\tcookieHeader = [NSString stringWithFormat: @\"%@; %@=%@\",cookieHeader,[cookie name],[cookie value]];\n\t\t\t}\n\t\t}\n\t\tif (cookieHeader) {\n\t\t\t[self addRequestHeader:@\"Cookie\" value:cookieHeader];\n\t\t}\n\t}\t\n}\n\n- (void)buildRequestHeaders\n{\n\tif ([self haveBuiltRequestHeaders]) {\n\t\treturn;\n\t}\n\t[self setHaveBuiltRequestHeaders:YES];\n\t\n\tif ([self mainRequest]) {\n\t\tfor (NSString *header in [[self mainRequest] requestHeaders]) {\n\t\t\t[self addRequestHeader:header value:[[[self mainRequest] requestHeaders] valueForKey:header]];\n\t\t}\n\t\treturn;\n\t}\n\t\n\t[self applyCookieHeader];\n\t\n\t// Build and set the user agent string if the request does not already have a custom user agent specified\n\tif (![[self requestHeaders] objectForKey:@\"User-Agent\"]) {\n\t\tNSString *userAgentString = [self userAgent];\n\t\tif (!userAgentString) {\n\t\t\tuserAgentString = [ASIHTTPRequest defaultUserAgentString];\n\t\t}\n\t\tif (userAgentString) {\n\t\t\t[self addRequestHeader:@\"User-Agent\" value:userAgentString];\n\t\t}\n\t}\n\t\n\t\n\t// Accept a compressed response\n\tif ([self allowCompressedResponse]) {\n\t\t[self addRequestHeader:@\"Accept-Encoding\" value:@\"gzip\"];\n\t}\n\t\n\t// Configure a compressed request body\n\tif ([self shouldCompressRequestBody]) {\n\t\t[self addRequestHeader:@\"Content-Encoding\" value:@\"gzip\"];\n\t}\n\t\n\t// Should this request resume an existing download?\n\t[self updatePartialDownloadSize];\n\tif ([self partialDownloadSize]) {\n\t\t[self addRequestHeader:@\"Range\" value:[NSString stringWithFormat:@\"bytes=%llu-\",[self partialDownloadSize]]];\n\t}\n}\n\n- (void)updatePartialDownloadSize\n{\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\tif ([self allowResumeForFileDownloads] && [self downloadDestinationPath] && [self temporaryFileDownloadPath] && [fileManager fileExistsAtPath:[self temporaryFileDownloadPath]]) {\n\t\tNSError *err = nil;\n\t\t[self setPartialDownloadSize:[[fileManager attributesOfItemAtPath:[self temporaryFileDownloadPath] error:&err] fileSize]];\n\t\tif (err) {\n\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Failed to get attributes for file at path '%@'\",[self temporaryFileDownloadPath]],NSLocalizedDescriptionKey,error,NSUnderlyingErrorKey,nil]]];\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n- (void)startRequest\n{\n\tif ([self isCancelled]) {\n\t\treturn;\n\t}\n\t\n\t[self performSelectorOnMainThread:@selector(requestStarted) withObject:nil waitUntilDone:[NSThread isMainThread]];\n\t\n\t[self setDownloadComplete:NO];\n\t[self setComplete:NO];\n\t[self setTotalBytesRead:0];\n\t[self setLastBytesRead:0];\n\t\n\tif ([self redirectCount] == 0) {\n\t\t[self setOriginalURL:[self url]];\n\t}\n\t\n\t// If we're retrying a request, let's remove any progress we made\n\tif ([self lastBytesSent] > 0) {\n\t\t[self removeUploadProgressSoFar];\n\t}\n\t\n\t[self setLastBytesSent:0];\n\t[self setContentLength:0];\n\t[self setResponseHeaders:nil];\n\tif (![self downloadDestinationPath]) {\n\t\t[self setRawResponseData:[[[NSMutableData alloc] init] autorelease]];\n    }\n\t\n\t\n    //\n\t// Create the stream for the request\n\t//\n\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\t[self setReadStreamIsScheduled:NO];\n\t\n\t// Do we need to stream the request body from disk\n\tif ([self shouldStreamPostDataFromDisk] && [self postBodyFilePath] && [fileManager fileExistsAtPath:[self postBodyFilePath]]) {\n\t\t\n\t\t// Are we gzipping the request body?\n\t\tif ([self compressedPostBodyFilePath] && [fileManager fileExistsAtPath:[self compressedPostBodyFilePath]]) {\n\t\t\t[self setPostBodyReadStream:[ASIInputStream inputStreamWithFileAtPath:[self compressedPostBodyFilePath] request:self]];\n\t\t} else {\n\t\t\t[self setPostBodyReadStream:[ASIInputStream inputStreamWithFileAtPath:[self postBodyFilePath] request:self]];\n\t\t}\n\t\t[self setReadStream:[NSMakeCollectable(CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, request,(CFReadStreamRef)[self postBodyReadStream])) autorelease]];    \n    } else {\n\t\t\n\t\t// If we have a request body, we'll stream it from memory using our custom stream, so that we can measure bandwidth use and it can be bandwidth-throttled if necessary\n\t\tif ([self postBody] && [[self postBody] length] > 0) {\n\t\t\tif ([self shouldCompressRequestBody] && [self compressedPostBody]) {\n\t\t\t\t[self setPostBodyReadStream:[ASIInputStream inputStreamWithData:[self compressedPostBody] request:self]];\n\t\t\t} else if ([self postBody]) {\n\t\t\t\t[self setPostBodyReadStream:[ASIInputStream inputStreamWithData:[self postBody] request:self]];\n\t\t\t}\n\t\t\t[self setReadStream:[NSMakeCollectable(CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, request,(CFReadStreamRef)[self postBodyReadStream])) autorelease]];\n\t\t\n\t\t} else {\n\t\t\t[self setReadStream:[NSMakeCollectable(CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request)) autorelease]];\n\t\t}\n\t}\n\n\tif (![self readStream]) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Unable to create read stream\",NSLocalizedDescriptionKey,nil]]];\n        return;\n    }\n\n\n    \n    \n    //\n    // Handle SSL certificate settings\n    //\n\n    if([[[[self url] scheme] lowercaseString] isEqualToString:@\"https\"]) {       \n       \n        // Tell CFNetwork not to validate SSL certificates\n        if (![self validatesSecureCertificate]) {\n            // see: http://iphonedevelopment.blogspot.com/2010/05/nsstream-tcp-and-ssl.html\n            \n            NSDictionary *sslProperties = [[NSDictionary alloc] initWithObjectsAndKeys:\n                                      [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,\n                                      [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,\n                                      [NSNumber numberWithBool:NO],  kCFStreamSSLValidatesCertificateChain,\n                                      kCFNull,kCFStreamSSLPeerName,\n                                      nil];\n            \n            CFReadStreamSetProperty((CFReadStreamRef)[self readStream], \n                                    kCFStreamPropertySSLSettings, \n                                    (CFTypeRef)sslProperties);\n        } \n        \n        // Tell CFNetwork to use a client certificate\n        if (clientCertificateIdentity) {\n            NSMutableDictionary *sslProperties = [NSMutableDictionary dictionaryWithCapacity:1];\n            \n\t\t\tNSMutableArray *certificates = [NSMutableArray arrayWithCapacity:[clientCertificates count]+1];\n\n\t\t\t// The first object in the array is our SecIdentityRef\n\t\t\t[certificates addObject:(id)clientCertificateIdentity];\n\n\t\t\t// If we've added any additional certificates, add them too\n\t\t\tfor (id cert in clientCertificates) {\n\t\t\t\t[certificates addObject:cert];\n\t\t\t}\n            \n            [sslProperties setObject:certificates forKey:(NSString *)kCFStreamSSLCertificates];\n            \n            CFReadStreamSetProperty((CFReadStreamRef)[self readStream], kCFStreamPropertySSLSettings, sslProperties);\n        }\n        \n    }\n\n\t//\n\t// Handle proxy settings\n\t//\n\n \tif ([self proxyHost] && [self proxyPort]) {\n\t\tNSString *hostKey;\n\t\tNSString *portKey;\n\n\t\tif (![self proxyType]) {\n\t\t\t[self setProxyType:(NSString *)kCFProxyTypeHTTP];\n\t\t}\n\n\t\tif ([[self proxyType] isEqualToString:(NSString *)kCFProxyTypeSOCKS]) {\n\t\t\thostKey = (NSString *)kCFStreamPropertySOCKSProxyHost;\n\t\t\tportKey = (NSString *)kCFStreamPropertySOCKSProxyPort;\n\t\t} else {\n\t\t\thostKey = (NSString *)kCFStreamPropertyHTTPProxyHost;\n\t\t\tportKey = (NSString *)kCFStreamPropertyHTTPProxyPort;\n\t\t\tif ([[[[self url] scheme] lowercaseString] isEqualToString:@\"https\"]) {\n\t\t\t\thostKey = (NSString *)kCFStreamPropertyHTTPSProxyHost;\n\t\t\t\tportKey = (NSString *)kCFStreamPropertyHTTPSProxyPort;\n\t\t\t}\n\t\t}\n\t\tNSMutableDictionary *proxyToUse = [NSMutableDictionary dictionaryWithObjectsAndKeys:[self proxyHost],hostKey,[NSNumber numberWithInt:[self proxyPort]],portKey,nil];\n\n\t\tif ([[self proxyType] isEqualToString:(NSString *)kCFProxyTypeSOCKS]) {\n\t\t\tCFReadStreamSetProperty((CFReadStreamRef)[self readStream], kCFStreamPropertySOCKSProxy, proxyToUse);\n\t\t} else {\n\t\t\tCFReadStreamSetProperty((CFReadStreamRef)[self readStream], kCFStreamPropertyHTTPProxy, proxyToUse);\n\t\t}\n\t}\n\n\n\t//\n\t// Handle persistent connections\n\t//\n\t\n\t[ASIHTTPRequest expirePersistentConnections];\n\n\t[connectionsLock lock];\n\t\n\t\n\tif (![[self url] host] || ![[self url] scheme]) {\n\t\t[self setConnectionInfo:nil];\n\t\t[self setShouldAttemptPersistentConnection:NO];\n\t}\n\t\n\t// Will store the old stream that was using this connection (if there was one) so we can clean it up once we've opened our own stream\n\tNSInputStream *oldStream = nil;\n\t\n\t// Use a persistent connection if possible\n\tif ([self shouldAttemptPersistentConnection]) {\n\t\t\n\n\t\t// If we are redirecting, we will re-use the current connection only if we are connecting to the same server\n\t\tif ([self connectionInfo]) {\n\t\t\t\n\t\t\tif (![[[self connectionInfo] objectForKey:@\"host\"] isEqualToString:[[self url] host]] || ![[[self connectionInfo] objectForKey:@\"scheme\"] isEqualToString:[[self url] scheme]] || [(NSNumber *)[[self connectionInfo] objectForKey:@\"port\"] intValue] != [[[self url] port] intValue]) {\n\t\t\t\t[self setConnectionInfo:nil];\n\n\t\t\t// Check if we should have expired this connection\n\t\t\t} else if ([[[self connectionInfo] objectForKey:@\"expires\"] timeIntervalSinceNow] < 0) {\n\t\t\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\t\t\tASI_DEBUG_LOG(@\"[CONNECTION] Not re-using connection #%i because it has expired\",[[[self connectionInfo] objectForKey:@\"id\"] intValue]);\n\t\t\t\t#endif\n\t\t\t\t[persistentConnectionsPool removeObject:[self connectionInfo]];\n\t\t\t\t[self setConnectionInfo:nil];\n\n\t\t\t} else if ([[self connectionInfo] objectForKey:@\"request\"] != nil) {\n                //Some other request reused this connection already - we'll have to create a new one\n\t\t\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n                ASI_DEBUG_LOG(@\"%@ - Not re-using connection #%i for request #%i because it is already used by request #%i\",self,[[[self connectionInfo] objectForKey:@\"id\"] intValue],[[self requestID] intValue],[[[self connectionInfo] objectForKey:@\"request\"] intValue]);\n\t\t\t\t#endif\n                [self setConnectionInfo:nil];\n            }\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\tif (![self connectionInfo] && [[self url] host] && [[self url] scheme]) { // We must have a proper url with a host and scheme, or this will explode\n\t\t\t\n\t\t\t// Look for a connection to the same server in the pool\n\t\t\tfor (NSMutableDictionary *existingConnection in persistentConnectionsPool) {\n\t\t\t\tif (![existingConnection objectForKey:@\"request\"] && [[existingConnection objectForKey:@\"host\"] isEqualToString:[[self url] host]] && [[existingConnection objectForKey:@\"scheme\"] isEqualToString:[[self url] scheme]] && [(NSNumber *)[existingConnection objectForKey:@\"port\"] intValue] == [[[self url] port] intValue]) {\n\t\t\t\t\t[self setConnectionInfo:existingConnection];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif ([[self connectionInfo] objectForKey:@\"stream\"]) {\n\t\t\toldStream = [[[self connectionInfo] objectForKey:@\"stream\"] retain];\n\n\t\t}\n\t\t\n\t\t// No free connection was found in the pool matching the server/scheme/port we're connecting to, we'll need to create a new one\n\t\tif (![self connectionInfo]) {\n\t\t\t[self setConnectionInfo:[NSMutableDictionary dictionary]];\n\t\t\tnextConnectionNumberToCreate++;\n\t\t\t[[self connectionInfo] setObject:[NSNumber numberWithInt:nextConnectionNumberToCreate] forKey:@\"id\"];\n\t\t\t[[self connectionInfo] setObject:[[self url] host] forKey:@\"host\"];\n\t\t\t[[self connectionInfo] setObject:[NSNumber numberWithInt:[[[self url] port] intValue]] forKey:@\"port\"];\n\t\t\t[[self connectionInfo] setObject:[[self url] scheme] forKey:@\"scheme\"];\n\t\t\t[persistentConnectionsPool addObject:[self connectionInfo]];\n\t\t}\n\t\t\n\t\t// If we are retrying this request, it will already have a requestID\n\t\tif (![self requestID]) {\n\t\t\tnextRequestID++;\n\t\t\t[self setRequestID:[NSNumber numberWithUnsignedInt:nextRequestID]];\n\t\t}\n\t\t[[self connectionInfo] setObject:[self requestID] forKey:@\"request\"];\t\t\n\t\t[[self connectionInfo] setObject:[self readStream] forKey:@\"stream\"];\n\t\tCFReadStreamSetProperty((CFReadStreamRef)[self readStream],  kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanTrue);\n\t\t\n\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\tASI_DEBUG_LOG(@\"[CONNECTION] Request #%@ will use connection #%i\",[self requestID],[[[self connectionInfo] objectForKey:@\"id\"] intValue]);\n\t\t#endif\n\t\t\n\t\t\n\t\t// Tag the stream with an id that tells it which connection to use behind the scenes\n\t\t// See http://lists.apple.com/archives/macnetworkprog/2008/Dec/msg00001.html for details on this approach\n\t\t\n\t\tCFReadStreamSetProperty((CFReadStreamRef)[self readStream], CFSTR(\"ASIStreamID\"), [[self connectionInfo] objectForKey:@\"id\"]);\n\t\n\t} else {\n\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\tASI_DEBUG_LOG(@\"[CONNECTION] Request %@ will not use a persistent connection\",self);\n\t\t#endif\n\t}\n\t\n\t[connectionsLock unlock];\n\n\t// Schedule the stream\n\tif (![self readStreamIsScheduled] && (!throttleWakeUpTime || [throttleWakeUpTime timeIntervalSinceDate:[NSDate date]] < 0)) {\n\t\t[self scheduleReadStream];\n\t}\n\t\n\tBOOL streamSuccessfullyOpened = NO;\n\n\n   // Start the HTTP connection\n\tCFStreamClientContext ctxt = {0, self, NULL, NULL, NULL};\n    if (CFReadStreamSetClient((CFReadStreamRef)[self readStream], kNetworkEvents, ReadStreamClientCallBack, &ctxt)) {\n\t\tif (CFReadStreamOpen((CFReadStreamRef)[self readStream])) {\n\t\t\tstreamSuccessfullyOpened = YES;\n\t\t}\n\t}\n\t\n\t// Here, we'll close the stream that was previously using this connection, if there was one\n\t// We've kept it open until now (when we've just opened a new stream) so that the new stream can make use of the old connection\n\t// http://lists.apple.com/archives/Macnetworkprog/2006/Mar/msg00119.html\n\tif (oldStream) {\n\t\t[oldStream close];\n\t\t[oldStream release];\n\t\toldStream = nil;\n\t}\n\n\tif (!streamSuccessfullyOpened) {\n\t\t[self setConnectionCanBeReused:NO];\n\t\t[self destroyReadStream];\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Unable to start HTTP connection\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\t\n\t}\n\t\n\tif (![self mainRequest]) {\n\t\tif ([self shouldResetUploadProgress]) {\n\t\t\tif ([self showAccurateProgress]) {\n\t\t\t\t[self incrementUploadSizeBy:[self postLength]];\n\t\t\t} else {\n\t\t\t\t[self incrementUploadSizeBy:1];\t \n\t\t\t}\n\t\t\t[ASIHTTPRequest updateProgressIndicator:&uploadProgressDelegate withProgress:0 ofTotal:1];\n\t\t}\n\t\tif ([self shouldResetDownloadProgress] && ![self partialDownloadSize]) {\n\t\t\t[ASIHTTPRequest updateProgressIndicator:&downloadProgressDelegate withProgress:0 ofTotal:1];\n\t\t}\n\t}\t\n\t\n\t\n\t// Record when the request started, so we can timeout if nothing happens\n\t[self setLastActivityTime:[NSDate date]];\n\t[self setStatusTimer:[NSTimer timerWithTimeInterval:0.25 target:self selector:@selector(updateStatus:) userInfo:nil repeats:YES]];\n\t[[NSRunLoop currentRunLoop] addTimer:[self statusTimer] forMode:[self runLoopMode]];\n}\n\n- (void)setStatusTimer:(NSTimer *)timer\n{\n\tCFRetain(self);\n\t// We must invalidate the old timer here, not before we've created and scheduled a new timer\n\t// This is because the timer may be the only thing retaining an asynchronous request\n\tif (statusTimer && timer != statusTimer) {\n\t\t[statusTimer invalidate];\n\t\t[statusTimer release];\n\t}\n\tstatusTimer = [timer retain];\n\tCFRelease(self);\n}\n\n// This gets fired every 1/4 of a second to update the progress and work out if we need to timeout\n- (void)updateStatus:(NSTimer*)timer\n{\n\t[self checkRequestStatus];\n\tif (![self inProgress]) {\n\t\t[self setStatusTimer:nil];\n\t}\n}\n\n- (void)performRedirect\n{\n\t[self setURL:[self redirectURL]];\n\t[self setComplete:YES];\n\t[self setNeedsRedirect:NO];\n\t[self setRedirectCount:[self redirectCount]+1];\n\n\tif ([self redirectCount] > RedirectionLimit) {\n\t\t// Some naughty / badly coded website is trying to force us into a redirection loop. This is not cool.\n\t\t[self failWithError:ASITooMuchRedirectionError];\n\t\t[self setComplete:YES];\n\t} else {\n\t\t// Go all the way back to the beginning and build the request again, so that we can apply any new cookies\n\t\t[self main];\n\t}\n}\n\n// Called by delegate to resume loading with a new url after the delegate received request:willRedirectToURL:\n- (void)redirectToURL:(NSURL *)newURL\n{\n\t[self setRedirectURL:newURL];\n\t[self performSelector:@selector(performRedirect) onThread:[[self class] threadForRequest:self] withObject:nil waitUntilDone:NO];\n}\n\n- (BOOL)shouldTimeOut\n{\n\tNSTimeInterval secondsSinceLastActivity = [[NSDate date] timeIntervalSinceDate:lastActivityTime];\n\t// See if we need to timeout\n\tif ([self readStream] && [self readStreamIsScheduled] && [self lastActivityTime] && [self timeOutSeconds] > 0 && secondsSinceLastActivity > [self timeOutSeconds]) {\n\t\t\n\t\t// We have no body, or we've sent more than the upload buffer size,so we can safely time out here\n\t\tif ([self postLength] == 0 || ([self uploadBufferSize] > 0 && [self totalBytesSent] > [self uploadBufferSize])) {\n\t\t\treturn YES;\n\t\t\t\n\t\t// ***Black magic warning***\n\t\t// We have a body, but we've taken longer than timeOutSeconds to upload the first small chunk of data\n\t\t// Since there's no reliable way to track upload progress for the first 32KB (iPhone) or 128KB (Mac) with CFNetwork, we'll be slightly more forgiving on the timeout, as there's a strong chance our connection is just very slow.\n\t\t} else if (secondsSinceLastActivity > [self timeOutSeconds]*1.5) {\n\t\t\treturn YES;\n\t\t}\n\t}\n\treturn NO;\n}\n\n- (void)checkRequestStatus\n{\n\t// We won't let the request cancel while we're updating progress / checking for a timeout\n\t[[self cancelledLock] lock];\n\t// See if our NSOperationQueue told us to cancel\n\tif ([self isCancelled] || [self complete]) {\n\t\t[[self cancelledLock] unlock];\n\t\treturn;\n\t}\n\t\n\t[self performThrottling];\n\t\n\tif ([self shouldTimeOut]) {\t\t\t\n\t\t// Do we need to auto-retry this request?\n\t\tif ([self numberOfTimesToRetryOnTimeout] > [self retryCount]) {\n\n\t\t\t// If we are resuming a download, we may need to update the Range header to take account of data we've just downloaded\n\t\t\t[self updatePartialDownloadSize];\n\t\t\tif ([self partialDownloadSize]) {\n\t\t\t\tCFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)@\"Range\", (CFStringRef)[NSString stringWithFormat:@\"bytes=%llu-\",[self partialDownloadSize]]);\n\t\t\t}\n\t\t\t[self setRetryCount:[self retryCount]+1];\n\t\t\t[self unscheduleReadStream];\n\t\t\t[[self cancelledLock] unlock];\n\t\t\t[self startRequest];\n\t\t\treturn;\n\t\t}\n\t\t[self failWithError:ASIRequestTimedOutError];\n\t\t[self cancelLoad];\n\t\t[self setComplete:YES];\n\t\t[[self cancelledLock] unlock];\n\t\treturn;\n\t}\n\n\t// readStream will be null if we aren't currently running (perhaps we're waiting for a delegate to supply credentials)\n\tif ([self readStream]) {\n\t\t\n\t\t// If we have a post body\n\t\tif ([self postLength]) {\n\t\t\n\t\t\t[self setLastBytesSent:totalBytesSent];\t\n\t\t\t\n\t\t\t// Find out how much data we've uploaded so far\n\t\t\t[self setTotalBytesSent:[[NSMakeCollectable(CFReadStreamCopyProperty((CFReadStreamRef)[self readStream], kCFStreamPropertyHTTPRequestBytesWrittenCount)) autorelease] unsignedLongLongValue]];\n\t\t\tif (totalBytesSent > lastBytesSent) {\n\t\t\t\t\n\t\t\t\t// We've uploaded more data,  reset the timeout\n\t\t\t\t[self setLastActivityTime:[NSDate date]];\n\t\t\t\t[ASIHTTPRequest incrementBandwidthUsedInLastSecond:(unsigned long)(totalBytesSent-lastBytesSent)];\t\t\n\t\t\t\t\t\t\n\t\t\t\t#if DEBUG_REQUEST_STATUS\n\t\t\t\tif ([self totalBytesSent] == [self postLength]) {\n\t\t\t\t\tASI_DEBUG_LOG(@\"[STATUS] Request %@ finished uploading data\",self);\n\t\t\t\t}\n\t\t\t\t#endif\n\t\t\t}\n\t\t}\n\t\t\t\n\t\t[self updateProgressIndicators];\n\n\t}\n\t\n\t[[self cancelledLock] unlock];\n}\n\n\n// Cancel loading and clean up. DO NOT USE THIS TO CANCEL REQUESTS - use [request cancel] instead\n- (void)cancelLoad\n{\n\t// If we're in the middle of downloading a PAC file, let's stop that first\n\tif (PACFileReadStream) {\n\t\t[PACFileReadStream setDelegate:nil];\n\t\t[PACFileReadStream close];\n\t\t[self setPACFileReadStream:nil];\n\t\t[self setPACFileData:nil];\n\t} else if (PACFileRequest) {\n\t\t[PACFileRequest setDelegate:nil];\n\t\t[PACFileRequest cancel];\n\t\t[self setPACFileRequest:nil];\n\t}\n\n    [self destroyReadStream];\n\t\n\t[[self postBodyReadStream] close];\n\t[self setPostBodyReadStream:nil];\n\t\n    if ([self rawResponseData]) {\n\t\tif (![self complete]) {\n\t\t\t[self setRawResponseData:nil];\n\t\t}\n\t// If we were downloading to a file\n\t} else if ([self temporaryFileDownloadPath]) {\n\t\t[[self fileDownloadOutputStream] close];\n\t\t[self setFileDownloadOutputStream:nil];\n\t\t\n\t\t[[self inflatedFileDownloadOutputStream] close];\n\t\t[self setInflatedFileDownloadOutputStream:nil];\n\t\t\n\t\t// If we haven't said we might want to resume, let's remove the temporary file too\n\t\tif (![self complete]) {\n\t\t\tif (![self allowResumeForFileDownloads]) {\n\t\t\t\t[self removeTemporaryDownloadFile];\n\t\t\t}\n\t\t\t[self removeTemporaryUncompressedDownloadFile];\n\t\t}\n\t}\n\t\n\t// Clean up any temporary file used to store request body for streaming\n\tif (![self authenticationNeeded] && ![self willRetryRequest] && [self didCreateTemporaryPostDataFile]) {\n\t\t[self removeTemporaryUploadFile];\n\t\t[self removeTemporaryCompressedUploadFile];\n\t\t[self setDidCreateTemporaryPostDataFile:NO];\n\t}\n}\n\n#pragma mark HEAD request\n\n// Used by ASINetworkQueue to create a HEAD request appropriate for this request with the same headers (though you can use it yourself)\n- (ASIHTTPRequest *)HEADRequest\n{\n\tASIHTTPRequest *headRequest = [[self class] requestWithURL:[self url]];\n\t\n\t// Copy the properties that make sense for a HEAD request\n\t[headRequest setRequestHeaders:[[[self requestHeaders] mutableCopy] autorelease]];\n\t[headRequest setRequestCookies:[[[self requestCookies] mutableCopy] autorelease]];\n\t[headRequest setUseCookiePersistence:[self useCookiePersistence]];\n\t[headRequest setUseKeychainPersistence:[self useKeychainPersistence]];\n\t[headRequest setUseSessionPersistence:[self useSessionPersistence]];\n\t[headRequest setAllowCompressedResponse:[self allowCompressedResponse]];\n\t[headRequest setUsername:[self username]];\n\t[headRequest setPassword:[self password]];\n\t[headRequest setDomain:[self domain]];\n\t[headRequest setProxyUsername:[self proxyUsername]];\n\t[headRequest setProxyPassword:[self proxyPassword]];\n\t[headRequest setProxyDomain:[self proxyDomain]];\n\t[headRequest setProxyHost:[self proxyHost]];\n\t[headRequest setProxyPort:[self proxyPort]];\n\t[headRequest setProxyType:[self proxyType]];\n\t[headRequest setShouldPresentAuthenticationDialog:[self shouldPresentAuthenticationDialog]];\n\t[headRequest setShouldPresentProxyAuthenticationDialog:[self shouldPresentProxyAuthenticationDialog]];\n\t[headRequest setTimeOutSeconds:[self timeOutSeconds]];\n\t[headRequest setUseHTTPVersionOne:[self useHTTPVersionOne]];\n\t[headRequest setValidatesSecureCertificate:[self validatesSecureCertificate]];\n    [headRequest setClientCertificateIdentity:clientCertificateIdentity];\n\t[headRequest setClientCertificates:[[clientCertificates copy] autorelease]];\n\t[headRequest setPACurl:[self PACurl]];\n\t[headRequest setShouldPresentCredentialsBeforeChallenge:[self shouldPresentCredentialsBeforeChallenge]];\n\t[headRequest setNumberOfTimesToRetryOnTimeout:[self numberOfTimesToRetryOnTimeout]];\n\t[headRequest setShouldUseRFC2616RedirectBehaviour:[self shouldUseRFC2616RedirectBehaviour]];\n\t[headRequest setShouldAttemptPersistentConnection:[self shouldAttemptPersistentConnection]];\n\t[headRequest setPersistentConnectionTimeoutSeconds:[self persistentConnectionTimeoutSeconds]];\n\t\n\t[headRequest setMainRequest:self];\n\t[headRequest setRequestMethod:@\"HEAD\"];\n\treturn headRequest;\n}\n\n\n#pragma mark upload/download progress\n\n\n- (void)updateProgressIndicators\n{\n\t//Only update progress if this isn't a HEAD request used to preset the content-length\n\tif (![self mainRequest]) {\n\t\tif ([self showAccurateProgress] || ([self complete] && ![self updatedProgress])) {\n\t\t\t[self updateUploadProgress];\n\t\t\t[self updateDownloadProgress];\n\t\t}\n\t}\n}\n\n- (id)uploadProgressDelegate\n{\n\t[[self cancelledLock] lock];\n\tid d = [[uploadProgressDelegate retain] autorelease];\n\t[[self cancelledLock] unlock];\n\treturn d;\n}\n\n- (void)setUploadProgressDelegate:(id)newDelegate\n{\n\t[[self cancelledLock] lock];\n\tuploadProgressDelegate = newDelegate;\n\n\t#if !TARGET_OS_IPHONE\n\t// If the uploadProgressDelegate is an NSProgressIndicator, we set its MaxValue to 1.0 so we can update it as if it were a UIProgressView\n\tdouble max = 1.0;\n\t[ASIHTTPRequest performSelector:@selector(setMaxValue:) onTarget:&uploadProgressDelegate withObject:nil amount:&max callerToRetain:nil];\n\t#endif\n\t[[self cancelledLock] unlock];\n}\n\n- (id)downloadProgressDelegate\n{\n\t[[self cancelledLock] lock];\n\tid d = [[downloadProgressDelegate retain] autorelease];\n\t[[self cancelledLock] unlock];\n\treturn d;\n}\n\n- (void)setDownloadProgressDelegate:(id)newDelegate\n{\n\t[[self cancelledLock] lock];\n\tdownloadProgressDelegate = newDelegate;\n\n\t#if !TARGET_OS_IPHONE\n\t// If the downloadProgressDelegate is an NSProgressIndicator, we set its MaxValue to 1.0 so we can update it as if it were a UIProgressView\n\tdouble max = 1.0;\n\t[ASIHTTPRequest performSelector:@selector(setMaxValue:) onTarget:&downloadProgressDelegate withObject:nil amount:&max callerToRetain:nil];\t\n\t#endif\n\t[[self cancelledLock] unlock];\n}\n\n\n- (void)updateDownloadProgress\n{\n\t// We won't update download progress until we've examined the headers, since we might need to authenticate\n\tif (![self responseHeaders] || [self needsRedirect] || !([self contentLength] || [self complete])) {\n\t\treturn;\n\t}\n\t\t\n\tunsigned long long bytesReadSoFar = [self totalBytesRead]+[self partialDownloadSize];\n\tunsigned long long value = 0;\n\t\n\tif ([self showAccurateProgress] && [self contentLength]) {\n\t\tvalue = bytesReadSoFar-[self lastBytesRead];\n\t\tif (value == 0) {\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tvalue = 1;\n\t\t[self setUpdatedProgress:YES];\n\t}\n\tif (!value) {\n\t\treturn;\n\t}\n\n\t[ASIHTTPRequest performSelector:@selector(request:didReceiveBytes:) onTarget:&queue withObject:self amount:&value callerToRetain:self];\n\t[ASIHTTPRequest performSelector:@selector(request:didReceiveBytes:) onTarget:&downloadProgressDelegate withObject:self amount:&value callerToRetain:self];\n\n\t[ASIHTTPRequest updateProgressIndicator:&downloadProgressDelegate withProgress:[self totalBytesRead]+[self partialDownloadSize] ofTotal:[self contentLength]+[self partialDownloadSize]];\n\n\t#if NS_BLOCKS_AVAILABLE\n    if (bytesReceivedBlock) {\n\t\tunsigned long long totalSize = [self contentLength] + [self partialDownloadSize];\n\t\t[self performBlockOnMainThread:^{ if (bytesReceivedBlock) { bytesReceivedBlock(value, totalSize); }}];\n    }\n\t#endif\n\t[self setLastBytesRead:bytesReadSoFar];\n}\n\n- (void)updateUploadProgress\n{\n\tif ([self isCancelled] || [self totalBytesSent] == 0) {\n\t\treturn;\n\t}\n\t\n\t// If this is the first time we've written to the buffer, totalBytesSent will be the size of the buffer (currently seems to be 128KB on both Leopard and iPhone 2.2.1, 32KB on iPhone 3.0)\n\t// If request body is less than the buffer size, totalBytesSent will be the total size of the request body\n\t// We will remove this from any progress display, as kCFStreamPropertyHTTPRequestBytesWrittenCount does not tell us how much data has actually be written\n\tif ([self uploadBufferSize] == 0 && [self totalBytesSent] != [self postLength]) {\n\t\t[self setUploadBufferSize:[self totalBytesSent]];\n\t\t[self incrementUploadSizeBy:-[self uploadBufferSize]];\n\t}\n\t\n\tunsigned long long value = 0;\n\t\n\tif ([self showAccurateProgress]) {\n\t\tif ([self totalBytesSent] == [self postLength] || [self lastBytesSent] > 0) {\n\t\t\tvalue = [self totalBytesSent]-[self lastBytesSent];\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tvalue = 1;\n\t\t[self setUpdatedProgress:YES];\n\t}\n\t\n\tif (!value) {\n\t\treturn;\n\t}\n\t\n\t[ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&queue withObject:self amount:&value callerToRetain:self];\n\t[ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&uploadProgressDelegate withObject:self amount:&value callerToRetain:self];\n\t[ASIHTTPRequest updateProgressIndicator:&uploadProgressDelegate withProgress:[self totalBytesSent]-[self uploadBufferSize] ofTotal:[self postLength]-[self uploadBufferSize]];\n\n\t#if NS_BLOCKS_AVAILABLE\n    if(bytesSentBlock){\n\t\tunsigned long long totalSize = [self postLength];\n\t\t[self performBlockOnMainThread:^{ if (bytesSentBlock) { bytesSentBlock(value, totalSize); }}];\n\t}\n\t#endif\n}\n\n\n- (void)incrementDownloadSizeBy:(long long)length\n{\n\t[ASIHTTPRequest performSelector:@selector(request:incrementDownloadSizeBy:) onTarget:&queue withObject:self amount:&length callerToRetain:self];\n\t[ASIHTTPRequest performSelector:@selector(request:incrementDownloadSizeBy:) onTarget:&downloadProgressDelegate withObject:self amount:&length callerToRetain:self];\n\n\t#if NS_BLOCKS_AVAILABLE\n    if(downloadSizeIncrementedBlock){\n\t\t[self performBlockOnMainThread:^{ if (downloadSizeIncrementedBlock) { downloadSizeIncrementedBlock(length); }}];\n    }\n\t#endif\n}\n\n- (void)incrementUploadSizeBy:(long long)length\n{\n\t[ASIHTTPRequest performSelector:@selector(request:incrementUploadSizeBy:) onTarget:&queue withObject:self amount:&length callerToRetain:self];\n\t[ASIHTTPRequest performSelector:@selector(request:incrementUploadSizeBy:) onTarget:&uploadProgressDelegate withObject:self amount:&length callerToRetain:self];\n\n\t#if NS_BLOCKS_AVAILABLE\n    if(uploadSizeIncrementedBlock) {\n\t\t[self performBlockOnMainThread:^{ if (uploadSizeIncrementedBlock) { uploadSizeIncrementedBlock(length); }}];\n    }\n\t#endif\n}\n\n\n-(void)removeUploadProgressSoFar\n{\n\tlong long progressToRemove = -[self totalBytesSent];\n\t[ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&queue withObject:self amount:&progressToRemove callerToRetain:self];\n\t[ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&uploadProgressDelegate withObject:self amount:&progressToRemove callerToRetain:self];\n\t[ASIHTTPRequest updateProgressIndicator:&uploadProgressDelegate withProgress:0 ofTotal:[self postLength]];\n\n\t#if NS_BLOCKS_AVAILABLE\n    if(bytesSentBlock){\n\t\tunsigned long long totalSize = [self postLength];\n\t\t[self performBlockOnMainThread:^{  if (bytesSentBlock) { bytesSentBlock(progressToRemove, totalSize); }}];\n\t}\n\t#endif\n}\n\n#if NS_BLOCKS_AVAILABLE\n- (void)performBlockOnMainThread:(ASIBasicBlock)block\n{\n\t[self performSelectorOnMainThread:@selector(callBlock:) withObject:[[block copy] autorelease] waitUntilDone:[NSThread isMainThread]];\n}\n\n- (void)callBlock:(ASIBasicBlock)block\n{\n\tblock();\n}\n#endif\n\n\n+ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount callerToRetain:(id)callerToRetain\n{\n\tif ([*target respondsToSelector:selector]) {\n\t\tNSMethodSignature *signature = nil;\n\t\tsignature = [*target methodSignatureForSelector:selector];\n\t\tNSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];\n\n\t\t[invocation setSelector:selector];\n\t\t\n\t\tint argumentNumber = 2;\n\t\t\n\t\t// If we got an object parameter, we pass a pointer to the object pointer\n\t\tif (object) {\n\t\t\t[invocation setArgument:&object atIndex:argumentNumber];\n\t\t\targumentNumber++;\n\t\t}\n\t\t\n\t\t// For the amount we'll just pass the pointer directly so NSInvocation will call the method using the number itself rather than a pointer to it\n\t\tif (amount) {\n\t\t\t[invocation setArgument:amount atIndex:argumentNumber];\n\t\t}\n\n        SEL callback = @selector(performInvocation:onTarget:releasingObject:);\n        NSMethodSignature *cbSignature = [ASIHTTPRequest methodSignatureForSelector:callback];\n        NSInvocation *cbInvocation = [NSInvocation invocationWithMethodSignature:cbSignature];\n        [cbInvocation setSelector:callback];\n        [cbInvocation setTarget:self];\n        [cbInvocation setArgument:&invocation atIndex:2];\n        [cbInvocation setArgument:&target atIndex:3];\n\t\tif (callerToRetain) {\n\t\t\t[cbInvocation setArgument:&callerToRetain atIndex:4];\n\t\t}\n\n\t\tCFRetain(invocation);\n\n\t\t// Used to pass in a request that we must retain until after the call\n\t\t// We're using CFRetain rather than [callerToRetain retain] so things to avoid earthquakes when using garbage collection\n\t\tif (callerToRetain) {\n\t\t\tCFRetain(callerToRetain);\n\t\t}\n        [cbInvocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:[NSThread isMainThread]];\n    }\n}\n\n+ (void)performInvocation:(NSInvocation *)invocation onTarget:(id *)target releasingObject:(id)objectToRelease\n{\n    if (*target && [*target respondsToSelector:[invocation selector]]) {\n        [invocation invokeWithTarget:*target];\n    }\n\tCFRelease(invocation);\n\tif (objectToRelease) {\n\t\tCFRelease(objectToRelease);\n\t}\n}\n\t\n\t\n+ (void)updateProgressIndicator:(id *)indicator withProgress:(unsigned long long)progress ofTotal:(unsigned long long)total\n{\n\t#if TARGET_OS_IPHONE\n\t\t// Cocoa Touch: UIProgressView\n\t\tSEL selector = @selector(setProgress:);\n\t\tfloat progressAmount = (float)((progress*1.0)/(total*1.0));\n\t\t\n\t#else\n\t\t// Cocoa: NSProgressIndicator\n\t\tdouble progressAmount = progressAmount = (progress*1.0)/(total*1.0);\n\t\tSEL selector = @selector(setDoubleValue:);\n\t#endif\n\t\n\tif (![*indicator respondsToSelector:selector]) {\n\t\treturn;\n\t}\n\t\n\t[progressLock lock];\n\t[ASIHTTPRequest performSelector:selector onTarget:indicator withObject:nil amount:&progressAmount callerToRetain:nil];\n\t[progressLock unlock];\n}\n\n\n#pragma mark talking to delegates / calling blocks\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)requestStarted\n{\n\tif ([self error] || [self mainRequest]) {\n\t\treturn;\n\t}\n\tif (delegate && [delegate respondsToSelector:didStartSelector]) {\n\t\t[delegate performSelector:didStartSelector withObject:self];\n\t}\n\t#if NS_BLOCKS_AVAILABLE\n\tif(startedBlock){\n\t\tstartedBlock();\n\t}\n\t#endif\n\tif (queue && [queue respondsToSelector:@selector(requestStarted:)]) {\n\t\t[queue performSelector:@selector(requestStarted:) withObject:self];\n\t}\n}\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)requestRedirected\n{\n\tif ([self error] || [self mainRequest]) {\n\t\treturn;\n\t}\n\n\tif([[self delegate] respondsToSelector:@selector(requestRedirected:)]){\n\t\t[[self delegate] performSelector:@selector(requestRedirected:) withObject:self];\n\t}\n\n\t#if NS_BLOCKS_AVAILABLE\n\tif(requestRedirectedBlock){\n\t\trequestRedirectedBlock();\n\t}\n\t#endif\n}\n\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)requestReceivedResponseHeaders:(NSMutableDictionary *)newResponseHeaders\n{\n\tif ([self error] || [self mainRequest]) {\n\t\treturn;\n\t}\n\n\tif (delegate && [delegate respondsToSelector:didReceiveResponseHeadersSelector]) {\n\t\t[delegate performSelector:didReceiveResponseHeadersSelector withObject:self withObject:newResponseHeaders];\n\t}\n\n\t#if NS_BLOCKS_AVAILABLE\n\tif(headersReceivedBlock){\n\t\theadersReceivedBlock(newResponseHeaders);\n    }\n\t#endif\n\n\tif (queue && [queue respondsToSelector:@selector(request:didReceiveResponseHeaders:)]) {\n\t\t[queue performSelector:@selector(request:didReceiveResponseHeaders:) withObject:self withObject:newResponseHeaders];\n\t}\n}\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)requestWillRedirectToURL:(NSURL *)newURL\n{\n\tif ([self error] || [self mainRequest]) {\n\t\treturn;\n\t}\n\tif (delegate && [delegate respondsToSelector:willRedirectSelector]) {\n\t\t[delegate performSelector:willRedirectSelector withObject:self withObject:newURL];\n\t}\n\tif (queue && [queue respondsToSelector:@selector(request:willRedirectToURL:)]) {\n\t\t[queue performSelector:@selector(request:willRedirectToURL:) withObject:self withObject:newURL];\n\t}\n}\n\n// Subclasses might override this method to process the result in the same thread\n// If you do this, don't forget to call [super requestFinished] to let the queue / delegate know we're done\n- (void)requestFinished\n{\n#if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING\n\tASI_DEBUG_LOG(@\"[STATUS] Request finished: %@\",self);\n#endif\n\tif ([self error] || [self mainRequest]) {\n\t\treturn;\n\t}\n\tif ([self isPACFileRequest]) {\n\t\t[self reportFinished];\n\t} else {\n\t\t[self performSelectorOnMainThread:@selector(reportFinished) withObject:nil waitUntilDone:[NSThread isMainThread]];\n\t}\n}\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)reportFinished\n{\n\tif (delegate && [delegate respondsToSelector:didFinishSelector]) {\n\t\t[delegate performSelector:didFinishSelector withObject:self];\n\t}\n\n\t#if NS_BLOCKS_AVAILABLE\n\tif(completionBlock){\n\t\tcompletionBlock();\n\t}\n\t#endif\n\n\tif (queue && [queue respondsToSelector:@selector(requestFinished:)]) {\n\t\t[queue performSelector:@selector(requestFinished:) withObject:self];\n\t}\n}\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)reportFailure\n{\n\tif (delegate && [delegate respondsToSelector:didFailSelector]) {\n\t\t[delegate performSelector:didFailSelector withObject:self];\n\t}\n\n\t#if NS_BLOCKS_AVAILABLE\n    if(failureBlock){\n        failureBlock();\n    }\n\t#endif\n\n\tif (queue && [queue respondsToSelector:@selector(requestFailed:)]) {\n\t\t[queue performSelector:@selector(requestFailed:) withObject:self];\n\t}\n}\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)passOnReceivedData:(NSData *)data\n{\n\tif (delegate && [delegate respondsToSelector:didReceiveDataSelector]) {\n\t\t[delegate performSelector:didReceiveDataSelector withObject:self withObject:data];\n\t}\n\n\t#if NS_BLOCKS_AVAILABLE\n\tif (dataReceivedBlock) {\n\t\tdataReceivedBlock(data);\n\t}\n\t#endif\n}\n\n// Subclasses might override this method to perform error handling in the same thread\n// If you do this, don't forget to call [super failWithError:] to let the queue / delegate know we're done\n- (void)failWithError:(NSError *)theError\n{\n#if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING\n\tASI_DEBUG_LOG(@\"[STATUS] Request %@: %@\",self,(theError == ASIRequestCancelledError ? @\"Cancelled\" : @\"Failed\"));\n#endif\n\t[self setComplete:YES];\n\t\n\t// Invalidate the current connection so subsequent requests don't attempt to reuse it\n\tif (theError && [theError code] != ASIAuthenticationErrorType && [theError code] != ASITooMuchRedirectionErrorType) {\n\t\t[connectionsLock lock];\n\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\tASI_DEBUG_LOG(@\"[CONNECTION] Request #%@ failed and will invalidate connection #%@\",[self requestID],[[self connectionInfo] objectForKey:@\"id\"]);\n\t\t#endif\n\t\t[[self connectionInfo] removeObjectForKey:@\"request\"];\n\t\t[persistentConnectionsPool removeObject:[self connectionInfo]];\n\t\t[connectionsLock unlock];\n\t\t[self destroyReadStream];\n\t}\n\tif ([self connectionCanBeReused]) {\n\t\t[[self connectionInfo] setObject:[NSDate dateWithTimeIntervalSinceNow:[self persistentConnectionTimeoutSeconds]] forKey:@\"expires\"];\n\t}\n\t\n    if ([self isCancelled] || [self error]) {\n\t\treturn;\n\t}\n\t\n\t// If we have cached data, use it and ignore the error when using ASIFallbackToCacheIfLoadFailsCachePolicy\n\tif ([self downloadCache] && ([self cachePolicy] & ASIFallbackToCacheIfLoadFailsCachePolicy)) {\n\t\tif ([[self downloadCache] canUseCachedDataForRequest:self]) {\n\t\t\t[self useDataFromCache];\n\t\t\treturn;\n\t\t}\n\t}\n\t\n\t\n\t[self setError:theError];\n\t\n\tASIHTTPRequest *failedRequest = self;\n\t\n\t// If this is a HEAD request created by an ASINetworkQueue or compatible queue delegate, make the main request fail\n\tif ([self mainRequest]) {\n\t\tfailedRequest = [self mainRequest];\n\t\t[failedRequest setError:theError];\n\t}\n\n\tif ([self isPACFileRequest]) {\n\t\t[failedRequest reportFailure];\n\t} else {\n\t\t[failedRequest performSelectorOnMainThread:@selector(reportFailure) withObject:nil waitUntilDone:[NSThread isMainThread]];\n\t}\n\t\n    if (!inProgress)\n    {\n        // if we're not in progress, we can't notify the queue we've finished (doing so can cause a crash later on)\n        // \"markAsFinished\" will be at the start of main() when we are started\n        return;\n    }\n\t[self markAsFinished];\n}\n\n#pragma mark parsing HTTP response headers\n\n- (void)readResponseHeaders\n{\n\t[self setAuthenticationNeeded:ASINoAuthenticationNeededYet];\n\n\tCFHTTPMessageRef message = (CFHTTPMessageRef)CFReadStreamCopyProperty((CFReadStreamRef)[self readStream], kCFStreamPropertyHTTPResponseHeader);\n\tif (!message) {\n\t\treturn;\n\t}\n\t\n\t// Make sure we've received all the headers\n\tif (!CFHTTPMessageIsHeaderComplete(message)) {\n\t\tCFRelease(message);\n\t\treturn;\n\t}\n\n\t#if DEBUG_REQUEST_STATUS\n\tif ([self totalBytesSent] == [self postLength]) {\n\t\tASI_DEBUG_LOG(@\"[STATUS] Request %@ received response headers\",self);\n\t}\n\t#endif\t\t\n\n\t[self setResponseHeaders:[NSMakeCollectable(CFHTTPMessageCopyAllHeaderFields(message)) autorelease]];\n\t[self setResponseStatusCode:(int)CFHTTPMessageGetResponseStatusCode(message)];\n\t[self setResponseStatusMessage:[NSMakeCollectable(CFHTTPMessageCopyResponseStatusLine(message)) autorelease]];\n\n\tif ([self downloadCache] && ([[self downloadCache] canUseCachedDataForRequest:self])) {\n\n\t\t// Update the expiry date\n\t\t[[self downloadCache] updateExpiryForRequest:self maxAge:[self secondsToCache]];\n\n\t\t// Read the response from the cache\n\t\t[self useDataFromCache];\n\n\t\tCFRelease(message);\n\t\treturn;\n\t}\n\n\t// Is the server response a challenge for credentials?\n\tif ([self responseStatusCode] == 401) {\n\t\t[self setAuthenticationNeeded:ASIHTTPAuthenticationNeeded];\n\t} else if ([self responseStatusCode] == 407) {\n\t\t[self setAuthenticationNeeded:ASIProxyAuthenticationNeeded];\n\t} else {\n\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tif ([self authenticationScheme]) {\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ has passed %@ authentication\",self,[self authenticationScheme]);\n\t\t}\n\t\t#endif\n\t}\n\t\t\n\t// Authentication succeeded, or no authentication was required\n\tif (![self authenticationNeeded]) {\n\n\t\t// Did we get here without an authentication challenge? (which can happen when shouldPresentCredentialsBeforeChallenge is YES and basic auth was successful)\n\t\tif (!requestAuthentication && [[self authenticationScheme] isEqualToString:(NSString *)kCFHTTPAuthenticationSchemeBasic] && [self username] && [self password] && [self useSessionPersistence]) {\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ passed BASIC authentication, and will save credentials in the session store for future use\",self);\n\t\t\t#endif\n\t\t\t\n\t\t\tNSMutableDictionary *newCredentials = [NSMutableDictionary dictionaryWithCapacity:2];\n\t\t\t[newCredentials setObject:[self username] forKey:(NSString *)kCFHTTPAuthenticationUsername];\n\t\t\t[newCredentials setObject:[self password] forKey:(NSString *)kCFHTTPAuthenticationPassword];\n\t\t\t\n\t\t\t// Store the credentials in the session \n\t\t\tNSMutableDictionary *sessionCredentials = [NSMutableDictionary dictionary];\n\t\t\t[sessionCredentials setObject:newCredentials forKey:@\"Credentials\"];\n\t\t\t[sessionCredentials setObject:[self url] forKey:@\"URL\"];\n\t\t\t[sessionCredentials setObject:(NSString *)kCFHTTPAuthenticationSchemeBasic forKey:@\"AuthenticationScheme\"];\n\t\t\t[[self class] storeAuthenticationCredentialsInSessionStore:sessionCredentials];\n\t\t}\n\t}\n\n\t// Read response textEncoding\n\t[self parseStringEncodingFromHeaders];\n\n\t// Handle cookies\n\tNSArray *newCookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[self responseHeaders] forURL:[self url]];\n\t[self setResponseCookies:newCookies];\n\t\n\tif ([self useCookiePersistence]) {\n\t\t\n\t\t// Store cookies in global persistent store\n\t\t[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:newCookies forURL:[self url] mainDocumentURL:nil];\n\t\t\n\t\t// We also keep any cookies in the sessionCookies array, so that we have a reference to them if we need to remove them later\n\t\tNSHTTPCookie *cookie;\n\t\tfor (cookie in newCookies) {\n\t\t\t[ASIHTTPRequest addSessionCookie:cookie];\n\t\t}\n\t}\n\t\n\t// Do we need to redirect?\n\tif (![self willRedirect]) {\n\t\t// See if we got a Content-length header\n\t\tNSString *cLength = [responseHeaders valueForKey:@\"Content-Length\"];\n\t\tASIHTTPRequest *theRequest = self;\n\t\tif ([self mainRequest]) {\n\t\t\ttheRequest = [self mainRequest];\n\t\t}\n\n\t\tif (cLength) {\n\t\t\tunsigned long long length = strtoull([cLength UTF8String], NULL, 0);\n\n\t\t\t// Workaround for Apache HEAD requests for dynamically generated content returning the wrong Content-Length when using gzip\n\t\t\tif ([self mainRequest] && [self allowCompressedResponse] && length == 20 && [self showAccurateProgress] && [self shouldResetDownloadProgress]) {\n\t\t\t\t[[self mainRequest] setShowAccurateProgress:NO];\n\t\t\t\t[[self mainRequest] incrementDownloadSizeBy:1];\n\n\t\t\t} else {\n\t\t\t\t[theRequest setContentLength:length];\n\t\t\t\tif ([self showAccurateProgress] && [self shouldResetDownloadProgress]) {\n\t\t\t\t\t[theRequest incrementDownloadSizeBy:[theRequest contentLength]+[theRequest partialDownloadSize]];\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else if ([self showAccurateProgress] && [self shouldResetDownloadProgress]) {\n\t\t\t[theRequest setShowAccurateProgress:NO];\n\t\t\t[theRequest incrementDownloadSizeBy:1];\n\t\t}\n\t}\n\n\t// Handle connection persistence\n\tif ([self shouldAttemptPersistentConnection]) {\n\t\t\n\t\tNSString *connectionHeader = [[[self responseHeaders] objectForKey:@\"Connection\"] lowercaseString];\n\n\t\tNSString *httpVersion = [NSMakeCollectable(CFHTTPMessageCopyVersion(message)) autorelease];\n\t\t\n\t\t// Don't re-use the connection if the server is HTTP 1.0 and didn't send Connection: Keep-Alive\n\t\tif (![httpVersion isEqualToString:(NSString *)kCFHTTPVersion1_0] || [connectionHeader isEqualToString:@\"keep-alive\"]) {\n\n\t\t\t// See if server explicitly told us to close the connection\n\t\t\tif (![connectionHeader isEqualToString:@\"close\"]) {\n\t\t\t\t\n\t\t\t\tNSString *keepAliveHeader = [[self responseHeaders] objectForKey:@\"Keep-Alive\"];\n\t\t\t\t\n\t\t\t\t// If we got a keep alive header, we'll reuse the connection for as long as the server tells us\n\t\t\t\tif (keepAliveHeader) { \n\t\t\t\t\tint timeout = 0;\n\t\t\t\t\tint max = 0;\n\t\t\t\t\tNSScanner *scanner = [NSScanner scannerWithString:keepAliveHeader];\n\t\t\t\t\t[scanner scanString:@\"timeout=\" intoString:NULL];\n\t\t\t\t\t[scanner scanInt:&timeout];\n\t\t\t\t\t[scanner scanUpToString:@\"max=\" intoString:NULL];\n\t\t\t\t\t[scanner scanString:@\"max=\" intoString:NULL];\n\t\t\t\t\t[scanner scanInt:&max];\n\t\t\t\t\tif (max > 5) {\n\t\t\t\t\t\t[self setConnectionCanBeReused:YES];\n\t\t\t\t\t\t[self setPersistentConnectionTimeoutSeconds:timeout];\n\t\t\t\t\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\t\t\t\t\t\tASI_DEBUG_LOG(@\"[CONNECTION] Got a keep-alive header, will keep this connection open for %f seconds\", [self persistentConnectionTimeoutSeconds]);\n\t\t\t\t\t\t#endif\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Otherwise, we'll assume we can keep this connection open\n\t\t\t\t} else {\n\t\t\t\t\t[self setConnectionCanBeReused:YES];\n\t\t\t\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\t\t\t\t\tASI_DEBUG_LOG(@\"[CONNECTION] Got no keep-alive header, will keep this connection open for %f seconds\", [self persistentConnectionTimeoutSeconds]);\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCFRelease(message);\n\t[self performSelectorOnMainThread:@selector(requestReceivedResponseHeaders:) withObject:[[[self responseHeaders] copy] autorelease] waitUntilDone:[NSThread isMainThread]];\n}\n\n- (BOOL)willRedirect\n{\n\t// Do we need to redirect?\n\tif (![self shouldRedirect] || ![responseHeaders valueForKey:@\"Location\"]) {\n\t\treturn NO;\n\t}\n\n\t// Note that ASIHTTPRequest does not currently support 305 Use Proxy\n\tint responseCode = [self responseStatusCode];\n\tif (responseCode != 301 && responseCode != 302 && responseCode != 303 && responseCode != 307) {\n\t\treturn NO;\n\t}\n\n\t[self performSelectorOnMainThread:@selector(requestRedirected) withObject:nil waitUntilDone:[NSThread isMainThread]];\n\n\t// By default, we redirect 301 and 302 response codes as GET requests\n\t// According to RFC 2616 this is wrong, but this is what most browsers do, so it's probably what you're expecting to happen\n\t// See also:\n\t// http://allseeing-i.lighthouseapp.com/projects/27881/tickets/27-302-redirection-issue\n\n\tif (responseCode != 307 && (![self shouldUseRFC2616RedirectBehaviour] || responseCode == 303)) {\n\t\t[self setRequestMethod:@\"GET\"];\n\t\t[self setPostBody:nil];\n\t\t[self setPostLength:0];\n\n\t\t// Perhaps there are other headers we should be preserving, but it's hard to know what we need to keep and what to throw away.\n\t\tNSString *userAgentHeader = [[self requestHeaders] objectForKey:@\"User-Agent\"];\n\t\tNSString *acceptHeader = [[self requestHeaders] objectForKey:@\"Accept\"];\n\t\t[self setRequestHeaders:nil];\n\t\tif (userAgentHeader) {\n\t\t\t[self addRequestHeader:@\"User-Agent\" value:userAgentHeader];\n\t\t}\n\t\tif (acceptHeader) {\n\t\t\t[self addRequestHeader:@\"Accept\" value:acceptHeader];\n\t\t}\n\t\t[self setHaveBuiltRequestHeaders:NO];\n\n\t} else {\n\t\t// Force rebuild the cookie header incase we got some new cookies from this request\n\t\t// All other request headers will remain as they are for 301 / 302 redirects\n\t\t[self applyCookieHeader];\n\t}\n\n\t// Force the redirected request to rebuild the request headers (if not a 303, it will re-use old ones, and add any new ones)\n\t[self setRedirectURL:[[NSURL URLWithString:[responseHeaders valueForKey:@\"Location\"] relativeToURL:[self url]] absoluteURL]];\n\t[self setNeedsRedirect:YES];\n\n\t// Clear the request cookies\n\t// This means manually added cookies will not be added to the redirect request - only those stored in the global persistent store\n\t// But, this is probably the safest option - we might be redirecting to a different domain\n\t[self setRequestCookies:[NSMutableArray array]];\n\n\t#if DEBUG_REQUEST_STATUS\n\tASI_DEBUG_LOG(@\"[STATUS] Request will redirect (code: %i): %@\",responseCode,self);\n\t#endif\n\n\treturn YES;\n}\n\n- (void)parseStringEncodingFromHeaders\n{\n\t// Handle response text encoding\n\tNSStringEncoding charset = 0;\n\tNSString *mimeType = nil;\n\t[[self class] parseMimeType:&mimeType andResponseEncoding:&charset fromContentType:[[self responseHeaders] valueForKey:@\"Content-Type\"]];\n\tif (charset != 0) {\n\t\t[self setResponseEncoding:charset];\n\t} else {\n\t\t[self setResponseEncoding:[self defaultResponseEncoding]];\n\t}\n}\n\n#pragma mark http authentication\n\n- (void)saveProxyCredentialsToKeychain:(NSDictionary *)newCredentials\n{\n\tNSURLCredential *authenticationCredentials = [NSURLCredential credentialWithUser:[newCredentials objectForKey:(NSString *)kCFHTTPAuthenticationUsername] password:[newCredentials objectForKey:(NSString *)kCFHTTPAuthenticationPassword] persistence:NSURLCredentialPersistencePermanent];\n\tif (authenticationCredentials) {\n\t\t[ASIHTTPRequest saveCredentials:authenticationCredentials forProxy:[self proxyHost] port:[self proxyPort] realm:[self proxyAuthenticationRealm]];\n\t}\t\n}\n\n\n- (void)saveCredentialsToKeychain:(NSDictionary *)newCredentials\n{\n\tNSURLCredential *authenticationCredentials = [NSURLCredential credentialWithUser:[newCredentials objectForKey:(NSString *)kCFHTTPAuthenticationUsername] password:[newCredentials objectForKey:(NSString *)kCFHTTPAuthenticationPassword] persistence:NSURLCredentialPersistencePermanent];\n\t\n\tif (authenticationCredentials) {\n\t\t[ASIHTTPRequest saveCredentials:authenticationCredentials forHost:[[self url] host] port:[[[self url] port] intValue] protocol:[[self url] scheme] realm:[self authenticationRealm]];\n\t}\t\n}\n\n- (BOOL)applyProxyCredentials:(NSDictionary *)newCredentials\n{\n\t[self setProxyAuthenticationRetryCount:[self proxyAuthenticationRetryCount]+1];\n\t\n\tif (newCredentials && proxyAuthentication && request) {\n\n\t\t// Apply whatever credentials we've built up to the old request\n\t\tif (CFHTTPMessageApplyCredentialDictionary(request, proxyAuthentication, (CFMutableDictionaryRef)newCredentials, NULL)) {\n\t\t\t\n\t\t\t//If we have credentials and they're ok, let's save them to the keychain\n\t\t\tif (useKeychainPersistence) {\n\t\t\t\t[self saveProxyCredentialsToKeychain:newCredentials];\n\t\t\t}\n\t\t\tif (useSessionPersistence) {\n\t\t\t\tNSMutableDictionary *sessionProxyCredentials = [NSMutableDictionary dictionary];\n\t\t\t\t[sessionProxyCredentials setObject:(id)proxyAuthentication forKey:@\"Authentication\"];\n\t\t\t\t[sessionProxyCredentials setObject:newCredentials forKey:@\"Credentials\"];\n\t\t\t\t[sessionProxyCredentials setObject:[self proxyHost] forKey:@\"Host\"];\n\t\t\t\t[sessionProxyCredentials setObject:[NSNumber numberWithInt:[self proxyPort]] forKey:@\"Port\"];\n\t\t\t\t[sessionProxyCredentials setObject:[self proxyAuthenticationScheme] forKey:@\"AuthenticationScheme\"];\n\t\t\t\t[[self class] storeProxyAuthenticationCredentialsInSessionStore:sessionProxyCredentials];\n\t\t\t}\n\t\t\t[self setProxyCredentials:newCredentials];\n\t\t\treturn YES;\n\t\t} else {\n\t\t\t[[self class] removeProxyAuthenticationCredentialsFromSessionStore:newCredentials];\n\t\t}\n\t}\n\treturn NO;\n}\n\n- (BOOL)applyCredentials:(NSDictionary *)newCredentials\n{\n\t[self setAuthenticationRetryCount:[self authenticationRetryCount]+1];\n\t\n\tif (newCredentials && requestAuthentication && request) {\n\t\t// Apply whatever credentials we've built up to the old request\n\t\tif (CFHTTPMessageApplyCredentialDictionary(request, requestAuthentication, (CFMutableDictionaryRef)newCredentials, NULL)) {\n\t\t\t\n\t\t\t//If we have credentials and they're ok, let's save them to the keychain\n\t\t\tif (useKeychainPersistence) {\n\t\t\t\t[self saveCredentialsToKeychain:newCredentials];\n\t\t\t}\n\t\t\tif (useSessionPersistence) {\n\t\t\t\t\n\t\t\t\tNSMutableDictionary *sessionCredentials = [NSMutableDictionary dictionary];\n\t\t\t\t[sessionCredentials setObject:(id)requestAuthentication forKey:@\"Authentication\"];\n\t\t\t\t[sessionCredentials setObject:newCredentials forKey:@\"Credentials\"];\n\t\t\t\t[sessionCredentials setObject:[self url] forKey:@\"URL\"];\n\t\t\t\t[sessionCredentials setObject:[self authenticationScheme] forKey:@\"AuthenticationScheme\"];\n\t\t\t\tif ([self authenticationRealm]) {\n\t\t\t\t\t[sessionCredentials setObject:[self authenticationRealm] forKey:@\"AuthenticationRealm\"];\n\t\t\t\t}\n\t\t\t\t[[self class] storeAuthenticationCredentialsInSessionStore:sessionCredentials];\n\n\t\t\t}\n\t\t\t[self setRequestCredentials:newCredentials];\n\t\t\treturn YES;\n\t\t} else {\n\t\t\t[[self class] removeAuthenticationCredentialsFromSessionStore:newCredentials];\n\t\t}\n\t}\n\treturn NO;\n}\n\n- (NSMutableDictionary *)findProxyCredentials\n{\n\tNSMutableDictionary *newCredentials = [[[NSMutableDictionary alloc] init] autorelease];\n\t\n\tNSString *user = nil;\n\tNSString *pass = nil;\n\t\n\tASIHTTPRequest *theRequest = [self mainRequest];\n\t// If this is a HEAD request generated by an ASINetworkQueue, we'll try to use the details from the main request\n\tif ([theRequest proxyUsername] && [theRequest proxyPassword]) {\n\t\tuser = [theRequest proxyUsername];\n\t\tpass = [theRequest proxyPassword];\n\t\t\n\t// Let's try to use the ones set in this object\n\t} else if ([self proxyUsername] && [self proxyPassword]) {\n\t\tuser = [self proxyUsername];\n\t\tpass = [self proxyPassword];\n\t}\n\n\t// When we connect to a website using NTLM via a proxy, we will use the main credentials\n\tif ((!user || !pass) && [self proxyAuthenticationScheme] == (NSString *)kCFHTTPAuthenticationSchemeNTLM) {\n\t\tuser = [self username];\n\t\tpass = [self password];\n\t}\n\n\n\t\n\t// Ok, that didn't work, let's try the keychain\n\t// For authenticating proxies, we'll look in the keychain regardless of the value of useKeychainPersistence\n\tif ((!user || !pass)) {\n\t\tNSURLCredential *authenticationCredentials = [ASIHTTPRequest savedCredentialsForProxy:[self proxyHost] port:[self proxyPort] protocol:[[self url] scheme] realm:[self proxyAuthenticationRealm]];\n\t\tif (authenticationCredentials) {\n\t\t\tuser = [authenticationCredentials user];\n\t\t\tpass = [authenticationCredentials password];\n\t\t}\n\t\t\n\t}\n\n\t// Handle NTLM, which requires a domain to be set too\n\tif (CFHTTPAuthenticationRequiresAccountDomain(proxyAuthentication)) {\n\n\t\tNSString *ntlmDomain = [self proxyDomain];\n\n\t\t// If we have no domain yet\n\t\tif (!ntlmDomain || [ntlmDomain length] == 0) {\n\n\t\t\t// Let's try to extract it from the username\n\t\t\tNSArray* ntlmComponents = [user componentsSeparatedByString:@\"\\\\\"];\n\t\t\tif ([ntlmComponents count] == 2) {\n\t\t\t\tntlmDomain = [ntlmComponents objectAtIndex:0];\n\t\t\t\tuser = [ntlmComponents objectAtIndex:1];\n\n\t\t\t// If we are connecting to a website using NTLM, but we are connecting via a proxy, the string we need may be in the domain property\n\t\t\t} else {\n\t\t\t\tntlmDomain = [self domain];\n\t\t\t}\n\t\t\tif (!ntlmDomain) {\n\t\t\t\tntlmDomain = @\"\";\n\t\t\t}\n\t\t}\n\t\t[newCredentials setObject:ntlmDomain forKey:(NSString *)kCFHTTPAuthenticationAccountDomain];\n\t}\n\n\n\t// If we have a username and password, let's apply them to the request and continue\n\tif (user && pass) {\n\t\t[newCredentials setObject:user forKey:(NSString *)kCFHTTPAuthenticationUsername];\n\t\t[newCredentials setObject:pass forKey:(NSString *)kCFHTTPAuthenticationPassword];\n\t\treturn newCredentials;\n\t}\n\treturn nil;\n}\n\n\n- (NSMutableDictionary *)findCredentials\n{\n\tNSMutableDictionary *newCredentials = [[[NSMutableDictionary alloc] init] autorelease];\n\n\t// First, let's look at the url to see if the username and password were included\n\tNSString *user = [[self url] user];\n\tNSString *pass = [[self url] password];\n\n\tif (user && pass) {\n\n\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will use credentials set on its url\",self);\n\t\t#endif\n\n\t} else {\n\t\t\n\t\t// If this is a HEAD request generated by an ASINetworkQueue, we'll try to use the details from the main request\n\t\tif ([self mainRequest] && [[self mainRequest] username] && [[self mainRequest] password]) {\n\t\t\tuser = [[self mainRequest] username];\n\t\t\tpass = [[self mainRequest] password];\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will use credentials from its parent request\",self);\n\t\t\t#endif\n\n\t\t// Let's try to use the ones set in this object\n\t\t} else if ([self username] && [self password]) {\n\t\t\tuser = [self username];\n\t\t\tpass = [self password];\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will use username and password properties as credentials\",self);\n\t\t\t#endif\n\t\t}\t\t\n\t}\n\t\n\t// Ok, that didn't work, let's try the keychain\n\tif ((!user || !pass) && useKeychainPersistence) {\n\t\tNSURLCredential *authenticationCredentials = [ASIHTTPRequest savedCredentialsForHost:[[self url] host] port:[[[self url] port] intValue] protocol:[[self url] scheme] realm:[self authenticationRealm]];\n\t\tif (authenticationCredentials) {\n\t\t\tuser = [authenticationCredentials user];\n\t\t\tpass = [authenticationCredentials password];\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tif (user && pass) {\n\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will use credentials from the keychain\",self);\n\t\t\t}\n\t\t\t#endif\n\t\t}\n\t}\n\n\t// Handle NTLM, which requires a domain to be set too\n\tif (CFHTTPAuthenticationRequiresAccountDomain(requestAuthentication)) {\n\n\t\tNSString *ntlmDomain = [self domain];\n\n\t\t// If we have no domain yet, let's try to extract it from the username\n\t\tif (!ntlmDomain || [ntlmDomain length] == 0) {\n\t\t\tntlmDomain = @\"\";\n\t\t\tNSArray* ntlmComponents = [user componentsSeparatedByString:@\"\\\\\"];\n\t\t\tif ([ntlmComponents count] == 2) {\n\t\t\t\tntlmDomain = [ntlmComponents objectAtIndex:0];\n\t\t\t\tuser = [ntlmComponents objectAtIndex:1];\n\t\t\t}\n\t\t}\n\t\t[newCredentials setObject:ntlmDomain forKey:(NSString *)kCFHTTPAuthenticationAccountDomain];\n\t}\n\n\t// If we have a username and password, let's apply them to the request and continue\n\tif (user && pass) {\n\t\t[newCredentials setObject:user forKey:(NSString *)kCFHTTPAuthenticationUsername];\n\t\t[newCredentials setObject:pass forKey:(NSString *)kCFHTTPAuthenticationPassword];\n\t\treturn newCredentials;\n\t}\n\treturn nil;\n}\n\n// Called by delegate or authentication dialog to resume loading once authentication info has been populated\n- (void)retryUsingSuppliedCredentials\n{\n\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ received credentials from its delegate or an ASIAuthenticationDialog, will retry\",self);\n\t#endif\n\t//If the url was changed by the delegate, our CFHTTPMessageRef will be NULL and we'll go back to the start\n\tif (!request) {\n\t\t[self performSelector:@selector(main) onThread:[[self class] threadForRequest:self] withObject:nil waitUntilDone:NO];\n\t\treturn;\n\t}\n\t[self performSelector:@selector(attemptToApplyCredentialsAndResume) onThread:[[self class] threadForRequest:self] withObject:nil waitUntilDone:NO];\n}\n\n// Called by delegate or authentication dialog to cancel authentication\n- (void)cancelAuthentication\n{\n\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ had authentication cancelled by its delegate or an ASIAuthenticationDialog\",self);\n\t#endif\n\t[self performSelector:@selector(failAuthentication) onThread:[[self class] threadForRequest:self] withObject:nil waitUntilDone:NO];\n}\n\n- (void)failAuthentication\n{\n\t[self failWithError:ASIAuthenticationError];\n}\n\n- (BOOL)showProxyAuthenticationDialog\n{\n\tif ([self isSynchronous]) {\n\t\treturn NO;\n\t}\n\n\t// Mac authentication dialog coming soon!\n\t#if TARGET_OS_IPHONE\n\tif ([self shouldPresentProxyAuthenticationDialog]) {\n\t\t[ASIAuthenticationDialog performSelectorOnMainThread:@selector(presentAuthenticationDialogForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];\n\t\treturn YES;\n\t}\n\treturn NO;\n\t#else\n\treturn NO;\n\t#endif\n}\n\n\n- (BOOL)willAskDelegateForProxyCredentials\n{\n\tif ([self isSynchronous]) {\n\t\treturn NO;\n\t}\n\n\t// If we have a delegate, we'll see if it can handle proxyAuthenticationNeededForRequest:.\n\t// Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate\n\tid authenticationDelegate = [self delegate];\n\tif (!authenticationDelegate) {\n\t\tauthenticationDelegate = [self queue];\n\t}\n\t\n\tBOOL delegateOrBlockWillHandleAuthentication = NO;\n\n\tif ([authenticationDelegate respondsToSelector:@selector(proxyAuthenticationNeededForRequest:)]) {\n\t\tdelegateOrBlockWillHandleAuthentication = YES;\n\t}\n\n\t#if NS_BLOCKS_AVAILABLE\n\tif(proxyAuthenticationNeededBlock){\n\t\tdelegateOrBlockWillHandleAuthentication = YES;\n\t}\n\t#endif\n\n\tif (delegateOrBlockWillHandleAuthentication) {\n\t\t[self performSelectorOnMainThread:@selector(askDelegateForProxyCredentials) withObject:nil waitUntilDone:NO];\n\t}\n\t\n\treturn delegateOrBlockWillHandleAuthentication;\n}\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)askDelegateForProxyCredentials\n{\n\tid authenticationDelegate = [self delegate];\n\tif (!authenticationDelegate) {\n\t\tauthenticationDelegate = [self queue];\n\t}\n\tif ([authenticationDelegate respondsToSelector:@selector(proxyAuthenticationNeededForRequest:)]) {\n\t\t[authenticationDelegate performSelector:@selector(proxyAuthenticationNeededForRequest:) withObject:self];\n\t\treturn;\n\t}\n\t#if NS_BLOCKS_AVAILABLE\n\tif(proxyAuthenticationNeededBlock){\n\t\tproxyAuthenticationNeededBlock();\n\t}\n\t#endif\n}\n\n\n- (BOOL)willAskDelegateForCredentials\n{\n\tif ([self isSynchronous]) {\n\t\treturn NO;\n\t}\n\n\t// If we have a delegate, we'll see if it can handle proxyAuthenticationNeededForRequest:.\n\t// Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate\n\tid authenticationDelegate = [self delegate];\n\tif (!authenticationDelegate) {\n\t\tauthenticationDelegate = [self queue];\n\t}\n\n\tBOOL delegateOrBlockWillHandleAuthentication = NO;\n\n\tif ([authenticationDelegate respondsToSelector:@selector(authenticationNeededForRequest:)]) {\n\t\tdelegateOrBlockWillHandleAuthentication = YES;\n\t}\n\n\t#if NS_BLOCKS_AVAILABLE\n\tif (authenticationNeededBlock) {\n\t\tdelegateOrBlockWillHandleAuthentication = YES;\n\t}\n\t#endif\n\n\tif (delegateOrBlockWillHandleAuthentication) {\n\t\t[self performSelectorOnMainThread:@selector(askDelegateForCredentials) withObject:nil waitUntilDone:NO];\n\t}\n\treturn delegateOrBlockWillHandleAuthentication;\n}\n\n/* ALWAYS CALLED ON MAIN THREAD! */\n- (void)askDelegateForCredentials\n{\n\tid authenticationDelegate = [self delegate];\n\tif (!authenticationDelegate) {\n\t\tauthenticationDelegate = [self queue];\n\t}\n\t\n\tif ([authenticationDelegate respondsToSelector:@selector(authenticationNeededForRequest:)]) {\n\t\t[authenticationDelegate performSelector:@selector(authenticationNeededForRequest:) withObject:self];\n\t\treturn;\n\t}\n\t\n\t#if NS_BLOCKS_AVAILABLE\n\tif (authenticationNeededBlock) {\n\t\tauthenticationNeededBlock();\n\t}\n\t#endif\t\n}\n\n- (void)attemptToApplyProxyCredentialsAndResume\n{\n\t\n\tif ([self error] || [self isCancelled]) {\n\t\treturn;\n\t}\n\t\n\t// Read authentication data\n\tif (!proxyAuthentication) {\n\t\tCFHTTPMessageRef responseHeader = (CFHTTPMessageRef) CFReadStreamCopyProperty((CFReadStreamRef)[self readStream],kCFStreamPropertyHTTPResponseHeader);\n\t\tproxyAuthentication = CFHTTPAuthenticationCreateFromResponse(NULL, responseHeader);\n\t\tCFRelease(responseHeader);\n\t\t[self setProxyAuthenticationScheme:[NSMakeCollectable(CFHTTPAuthenticationCopyMethod(proxyAuthentication)) autorelease]];\n\t}\n\t\n\t// If we haven't got a CFHTTPAuthenticationRef by now, something is badly wrong, so we'll have to give up\n\tif (!proxyAuthentication) {\n\t\t[self cancelLoad];\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Failed to get authentication object from response headers\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n\t}\n\t\n\t// Get the authentication realm\n\t[self setProxyAuthenticationRealm:nil];\n\tif (!CFHTTPAuthenticationRequiresAccountDomain(proxyAuthentication)) {\n\t\t[self setProxyAuthenticationRealm:[NSMakeCollectable(CFHTTPAuthenticationCopyRealm(proxyAuthentication)) autorelease]];\n\t}\n\t\n\t// See if authentication is valid\n\tCFStreamError err;\t\t\n\tif (!CFHTTPAuthenticationIsValid(proxyAuthentication, &err)) {\n\t\t\n\t\tCFRelease(proxyAuthentication);\n\t\tproxyAuthentication = NULL;\n\t\t\n\t\t// check for bad credentials, so we can give the delegate a chance to replace them\n\t\tif (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName || err.error == kCFStreamErrorHTTPAuthenticationBadPassword)) {\n\t\t\t\n\t\t\t// Prevent more than one request from asking for credentials at once\n\t\t\t[delegateAuthenticationLock lock];\n\t\t\t\n\t\t\t// We know the credentials we just presented are bad, we should remove them from the session store too\n\t\t\t[[self class] removeProxyAuthenticationCredentialsFromSessionStore:proxyCredentials];\n\t\t\t[self setProxyCredentials:nil];\n\t\t\t\n\t\t\t\n\t\t\t// If the user cancelled authentication via a dialog presented by another request, our queue may have cancelled us\n\t\t\tif ([self error] || [self isCancelled]) {\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\t// Now we've acquired the lock, it may be that the session contains credentials we can re-use for this request\n\t\t\tif ([self useSessionPersistence]) {\n\t\t\t\tNSDictionary *credentials = [self findSessionProxyAuthenticationCredentials];\n\t\t\t\tif (credentials && [self applyProxyCredentials:[credentials objectForKey:@\"Credentials\"]]) {\n\t\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t\t[self startRequest];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t[self setLastActivityTime:nil];\n\t\t\t\n\t\t\tif ([self willAskDelegateForProxyCredentials]) {\n\t\t\t\t[self attemptToApplyProxyCredentialsAndResume];\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ([self showProxyAuthenticationDialog]) {\n\t\t\t\t[self attemptToApplyProxyCredentialsAndResume];\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t}\n\t\t[self cancelLoad];\n\t\t[self failWithError:ASIAuthenticationError];\n\t\treturn;\n\t}\n\n\t[self cancelLoad];\n\t\n\tif (proxyCredentials) {\n\t\t\n\t\t// We use startRequest rather than starting all over again in load request because NTLM requires we reuse the request\n\t\tif ((([self proxyAuthenticationScheme] != (NSString *)kCFHTTPAuthenticationSchemeNTLM) || [self proxyAuthenticationRetryCount] < 2) && [self applyProxyCredentials:proxyCredentials]) {\n\t\t\t[self startRequest];\n\t\t\t\n\t\t// We've failed NTLM authentication twice, we should assume our credentials are wrong\n\t\t} else if ([self proxyAuthenticationScheme] == (NSString *)kCFHTTPAuthenticationSchemeNTLM && [self proxyAuthenticationRetryCount] == 2) {\n\t\t\t[self failWithError:ASIAuthenticationError];\n\t\t\t\n\t\t// Something went wrong, we'll have to give up\n\t\t} else {\n\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Failed to apply proxy credentials to request\",NSLocalizedDescriptionKey,nil]]];\n\t\t}\n\t\t\n\t// Are a user name & password needed?\n\t}  else if (CFHTTPAuthenticationRequiresUserNameAndPassword(proxyAuthentication)) {\n\t\t\n\t\t// Prevent more than one request from asking for credentials at once\n\t\t[delegateAuthenticationLock lock];\n\t\t\n\t\t// If the user cancelled authentication via a dialog presented by another request, our queue may have cancelled us\n\t\tif ([self error] || [self isCancelled]) {\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// Now we've acquired the lock, it may be that the session contains credentials we can re-use for this request\n\t\tif ([self useSessionPersistence]) {\n\t\t\tNSDictionary *credentials = [self findSessionProxyAuthenticationCredentials];\n\t\t\tif (credentials && [self applyProxyCredentials:[credentials objectForKey:@\"Credentials\"]]) {\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t[self startRequest];\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t\n\t\tNSMutableDictionary *newCredentials = [self findProxyCredentials];\n\t\t\n\t\t//If we have some credentials to use let's apply them to the request and continue\n\t\tif (newCredentials) {\n\t\t\t\n\t\t\tif ([self applyProxyCredentials:newCredentials]) {\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t[self startRequest];\n\t\t\t} else {\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Failed to apply proxy credentials to request\",NSLocalizedDescriptionKey,nil]]];\n\t\t\t}\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif ([self willAskDelegateForProxyCredentials]) {\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif ([self showProxyAuthenticationDialog]) {\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t\treturn;\n\t\t}\n\t\t[delegateAuthenticationLock unlock];\n\t\t\n\t\t// The delegate isn't interested and we aren't showing the authentication dialog, we'll have to give up\n\t\t[self failWithError:ASIAuthenticationError];\n\t\treturn;\n\t}\n\t\n}\n\n- (BOOL)showAuthenticationDialog\n{\n\tif ([self isSynchronous]) {\n\t\treturn NO;\n\t}\n\t// Mac authentication dialog coming soon!\n\t#if TARGET_OS_IPHONE\n\tif ([self shouldPresentAuthenticationDialog]) {\n\t\t[ASIAuthenticationDialog performSelectorOnMainThread:@selector(presentAuthenticationDialogForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];\n\t\treturn YES;\n\t}\n\treturn NO;\n\t#else\n\treturn NO;\n\t#endif\n}\n\n- (void)attemptToApplyCredentialsAndResume\n{\n\tif ([self error] || [self isCancelled]) {\n\t\treturn;\n\t}\n\t\n\t// Do we actually need to authenticate with a proxy?\n\tif ([self authenticationNeeded] == ASIProxyAuthenticationNeeded) {\n\t\t[self attemptToApplyProxyCredentialsAndResume];\n\t\treturn;\n\t}\n\t\n\t// Read authentication data\n\tif (!requestAuthentication) {\n\t\tCFHTTPMessageRef responseHeader = (CFHTTPMessageRef) CFReadStreamCopyProperty((CFReadStreamRef)[self readStream],kCFStreamPropertyHTTPResponseHeader);\n\t\trequestAuthentication = CFHTTPAuthenticationCreateFromResponse(NULL, responseHeader);\n\t\tCFRelease(responseHeader);\n\t\t[self setAuthenticationScheme:[NSMakeCollectable(CFHTTPAuthenticationCopyMethod(requestAuthentication)) autorelease]];\n\t}\n\t\n\tif (!requestAuthentication) {\n\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ failed to read authentication information from response headers\",self);\n\t\t#endif\n\n\t\t[self cancelLoad];\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Failed to get authentication object from response headers\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n\t}\n\t\n\t// Get the authentication realm\n\t[self setAuthenticationRealm:nil];\n\tif (!CFHTTPAuthenticationRequiresAccountDomain(requestAuthentication)) {\n\t\t[self setAuthenticationRealm:[NSMakeCollectable(CFHTTPAuthenticationCopyRealm(requestAuthentication)) autorelease]];\n\t}\n\t\n\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tNSString *realm = [self authenticationRealm];\n\t\tif (realm) {\n\t\t\trealm = [NSString stringWithFormat:@\" (Realm: %@)\",realm];\n\t\t} else {\n\t\t\trealm = @\"\";\n\t\t}\n\t\tif ([self authenticationScheme] != (NSString *)kCFHTTPAuthenticationSchemeNTLM || [self authenticationRetryCount] == 0) {\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ received 401 challenge and must authenticate using %@%@\",self,[self authenticationScheme],realm);\n\t\t} else {\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ NTLM handshake step %i\",self,[self authenticationRetryCount]+1);\n\t\t}\n\t#endif\n\n\t// See if authentication is valid\n\tCFStreamError err;\t\t\n\tif (!CFHTTPAuthenticationIsValid(requestAuthentication, &err)) {\n\t\t\n\t\tCFRelease(requestAuthentication);\n\t\trequestAuthentication = NULL;\n\t\t\n\t\t// check for bad credentials, so we can give the delegate a chance to replace them\n\t\tif (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName || err.error == kCFStreamErrorHTTPAuthenticationBadPassword)) {\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ had bad credentials, will remove them from the session store if they are cached\",self);\n\t\t\t#endif\n\n\t\t\t// Prevent more than one request from asking for credentials at once\n\t\t\t[delegateAuthenticationLock lock];\n\t\t\t\n\t\t\t// We know the credentials we just presented are bad, we should remove them from the session store too\n\t\t\t[[self class] removeAuthenticationCredentialsFromSessionStore:requestCredentials];\n\t\t\t[self setRequestCredentials:nil];\n\t\t\t\n\t\t\t// If the user cancelled authentication via a dialog presented by another request, our queue may have cancelled us\n\t\t\tif ([self error] || [self isCancelled]) {\n\n\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ failed or was cancelled while waiting to access credentials\",self);\n\t\t\t\t#endif\n\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Now we've acquired the lock, it may be that the session contains credentials we can re-use for this request\n\t\t\tif ([self useSessionPersistence]) {\n\t\t\t\tNSDictionary *credentials = [self findSessionAuthenticationCredentials];\n\t\t\t\tif (credentials && [self applyCredentials:[credentials objectForKey:@\"Credentials\"]]) {\n\n\t\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will reuse cached credentials from the session (%@)\",self,[credentials objectForKey:@\"AuthenticationScheme\"]);\n\t\t\t\t\t#endif\n\n\t\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t\t[self startRequest];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t[self setLastActivityTime:nil];\n\t\t\t\n\t\t\tif ([self willAskDelegateForCredentials]) {\n\n\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will ask its delegate for credentials to use\",self);\n\t\t\t\t#endif\n\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ([self showAuthenticationDialog]) {\n\n\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will ask ASIAuthenticationDialog for credentials\",self);\n\t\t\t\t#endif\n\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t}\n\n\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ has no credentials to present and must give up\",self);\n\t\t#endif\n\n\t\t[self cancelLoad];\n\t\t[self failWithError:ASIAuthenticationError];\n\t\treturn;\n\t}\n\t\n\t[self cancelLoad];\n\t\n\tif (requestCredentials) {\n\t\t\n\t\tif ((([self authenticationScheme] != (NSString *)kCFHTTPAuthenticationSchemeNTLM) || [self authenticationRetryCount] < 2) && [self applyCredentials:requestCredentials]) {\n\t\t\t[self startRequest];\n\t\t\t\n\t\t\t// We've failed NTLM authentication twice, we should assume our credentials are wrong\n\t\t} else if ([self authenticationScheme] == (NSString *)kCFHTTPAuthenticationSchemeNTLM && [self authenticationRetryCount ] == 2) {\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ has failed NTLM authentication\",self);\n\t\t\t#endif\n\n\t\t\t[self failWithError:ASIAuthenticationError];\n\t\t\t\n\t\t} else {\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ had credentials and they were not marked as bad, but we got a 401 all the same.\",self);\n\t\t\t#endif\n\n\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Failed to apply credentials to request\",NSLocalizedDescriptionKey,nil]]];\n\t\t}\n\t\t\n\t\t// Are a user name & password needed?\n\t}  else if (CFHTTPAuthenticationRequiresUserNameAndPassword(requestAuthentication)) {\n\t\t\n\t\t// Prevent more than one request from asking for credentials at once\n\t\t[delegateAuthenticationLock lock];\n\t\t\n\t\t// If the user cancelled authentication via a dialog presented by another request, our queue may have cancelled us\n\t\tif ([self error] || [self isCancelled]) {\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ failed or was cancelled while waiting to access credentials\",self);\n\t\t\t#endif\n\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// Now we've acquired the lock, it may be that the session contains credentials we can re-use for this request\n\t\tif ([self useSessionPersistence]) {\n\t\t\tNSDictionary *credentials = [self findSessionAuthenticationCredentials];\n\t\t\tif (credentials && [self applyCredentials:[credentials objectForKey:@\"Credentials\"]]) {\n\n\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will reuse cached credentials from the session (%@)\",self,[credentials objectForKey:@\"AuthenticationScheme\"]);\n\t\t\t\t#endif\n\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t[self startRequest];\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t\n\n\t\tNSMutableDictionary *newCredentials = [self findCredentials];\n\t\t\n\t\t//If we have some credentials to use let's apply them to the request and continue\n\t\tif (newCredentials) {\n\t\t\t\n\t\t\tif ([self applyCredentials:newCredentials]) {\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t[self startRequest];\n\t\t\t} else {\n\t\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ failed to apply credentials\",self);\n\t\t\t\t#endif\n\t\t\t\t[delegateAuthenticationLock unlock];\n\t\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Failed to apply credentials to request\",NSLocalizedDescriptionKey,nil]]];\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif ([self willAskDelegateForCredentials]) {\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will ask its delegate for credentials to use\",self);\n\t\t\t#endif\n\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t\treturn;\n\t\t}\n\t\tif ([self showAuthenticationDialog]) {\n\n\t\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ will ask ASIAuthenticationDialog for credentials\",self);\n\t\t\t#endif\n\n\t\t\t[delegateAuthenticationLock unlock];\n\t\t\treturn;\n\t\t}\n\n\t\t#if DEBUG_HTTP_AUTHENTICATION\n\t\tASI_DEBUG_LOG(@\"[AUTH] Request %@ has no credentials to present and must give up\",self);\n\t\t#endif\n\t\t[delegateAuthenticationLock unlock];\n\t\t[self failWithError:ASIAuthenticationError];\n\t\treturn;\n\t}\n\t\n}\n\n- (void)addBasicAuthenticationHeaderWithUsername:(NSString *)theUsername andPassword:(NSString *)thePassword\n{\n\t[self addRequestHeader:@\"Authorization\" value:[NSString stringWithFormat:@\"Basic %@\",[ASIHTTPRequest base64forData:[[NSString stringWithFormat:@\"%@:%@\",theUsername,thePassword] dataUsingEncoding:NSUTF8StringEncoding]]]];\t\n\t[self setAuthenticationScheme:(NSString *)kCFHTTPAuthenticationSchemeBasic];\n\n}\n\n\n#pragma mark stream status handlers\n\n- (void)handleNetworkEvent:(CFStreamEventType)type\n{\t\n\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\n\n\t[[self cancelledLock] lock];\n\t\n\tif ([self complete] || [self isCancelled]) {\n\t\t[[self cancelledLock] unlock];\n\t\t[pool drain];\n\t\treturn;\n\t}\n\n\tCFRetain(self);\n\n    // Dispatch the stream events.\n    switch (type) {\n        case kCFStreamEventHasBytesAvailable:\n            [self handleBytesAvailable];\n            break;\n            \n        case kCFStreamEventEndEncountered:\n            [self handleStreamComplete];\n            break;\n            \n        case kCFStreamEventErrorOccurred:\n            [self handleStreamError];\n            break;\n            \n        default:\n            break;\n    }\n\t\n\t[self performThrottling];\n\t\n\t[[self cancelledLock] unlock];\n\t\n\tif ([self downloadComplete] && [self needsRedirect]) {\n\t\tif (![self willAskDelegateToConfirmRedirect]) {\n\t\t\t[self performRedirect];\n\t\t}\n\t} else if ([self downloadComplete] && [self authenticationNeeded]) {\n\t\t[self attemptToApplyCredentialsAndResume];\n\t}\n\n\tCFRelease(self);\n\t[pool drain];\n}\n\n- (BOOL)willAskDelegateToConfirmRedirect\n{\n\t// We must lock to ensure delegate / queue aren't changed while we check them\n\t[[self cancelledLock] lock];\n\n\t// Here we perform an initial check to see if either the delegate or the queue wants to be asked about the redirect, because if not we should redirect straight away\n\t// We will check again on the main thread later\n\tBOOL needToAskDelegateAboutRedirect = (([self delegate] && [[self delegate] respondsToSelector:[self willRedirectSelector]]) || ([self queue] && [[self queue] respondsToSelector:@selector(request:willRedirectToURL:)]));\n\n\t[[self cancelledLock] unlock];\n\n\t// Either the delegate or the queue's delegate is interested in being told when we are about to redirect\n\tif (needToAskDelegateAboutRedirect) {\n\t\tNSURL *newURL = [[[self redirectURL] copy] autorelease];\n\t\t[self setRedirectURL:nil];\n\t\t[self performSelectorOnMainThread:@selector(requestWillRedirectToURL:) withObject:newURL waitUntilDone:[NSThread isMainThread]];\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n- (void)handleBytesAvailable\n{\n\tif (![self responseHeaders]) {\n\t\t[self readResponseHeaders];\n\t}\n\t\n\t// If we've cancelled the load part way through (for example, after deciding to use a cached version)\n\tif ([self complete]) {\n\t\treturn;\n\t}\n\t\n\t// In certain (presumably very rare) circumstances, handleBytesAvailable seems to be called when there isn't actually any data available\n\t// We'll check that there is actually data available to prevent blocking on CFReadStreamRead()\n\t// So far, I've only seen this in the stress tests, so it might never happen in real-world situations.\n\tif (!CFReadStreamHasBytesAvailable((CFReadStreamRef)[self readStream])) {\n\t\treturn;\n\t}\n\n\tlong long bufferSize = 16384;\n\tif (contentLength > 262144) {\n\t\tbufferSize = 262144;\n\t} else if (contentLength > 65536) {\n\t\tbufferSize = 65536;\n\t}\n\t\n\t// Reduce the buffer size if we're receiving data too quickly when bandwidth throttling is active\n\t// This just augments the throttling done in measureBandwidthUsage to reduce the amount we go over the limit\n\t\n\tif ([[self class] isBandwidthThrottled]) {\n\t\t[bandwidthThrottlingLock lock];\n\t\tif (maxBandwidthPerSecond > 0) {\n\t\t\tlong long maxiumumSize  = (long long)maxBandwidthPerSecond-(long long)bandwidthUsedInLastSecond;\n\t\t\tif (maxiumumSize < 0) {\n\t\t\t\t// We aren't supposed to read any more data right now, but we'll read a single byte anyway so the CFNetwork's buffer isn't full\n\t\t\t\tbufferSize = 1;\n\t\t\t} else if (maxiumumSize/4 < bufferSize) {\n\t\t\t\t// We were going to fetch more data that we should be allowed, so we'll reduce the size of our read\n\t\t\t\tbufferSize = maxiumumSize/4;\n\t\t\t}\n\t\t}\n\t\tif (bufferSize < 1) {\n\t\t\tbufferSize = 1;\n\t\t}\n\t\t[bandwidthThrottlingLock unlock];\n\t}\n\t\n\t\n    UInt8 buffer[bufferSize];\n    NSInteger bytesRead = [[self readStream] read:buffer maxLength:sizeof(buffer)];\n\n    // Less than zero is an error\n    if (bytesRead < 0) {\n        [self handleStreamError];\n\t\t\n\t// If zero bytes were read, wait for the EOF to come.\n    } else if (bytesRead) {\n\n\t\t// If we are inflating the response on the fly\n\t\tNSData *inflatedData = nil;\n\t\tif ([self isResponseCompressed] && ![self shouldWaitToInflateCompressedResponses]) {\n\t\t\tif (![self dataDecompressor]) {\n\t\t\t\t[self setDataDecompressor:[ASIDataDecompressor decompressor]];\n\t\t\t}\n\t\t\tNSError *err = nil;\n\t\t\tinflatedData = [[self dataDecompressor] uncompressBytes:buffer length:bytesRead error:&err];\n\t\t\tif (err) {\n\t\t\t\t[self failWithError:err];\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t\n\t\t[self setTotalBytesRead:[self totalBytesRead]+bytesRead];\n\t\t[self setLastActivityTime:[NSDate date]];\n\n\t\t// For bandwidth measurement / throttling\n\t\t[ASIHTTPRequest incrementBandwidthUsedInLastSecond:bytesRead];\n\t\t\n\t\t// If we need to redirect, and have automatic redirect on, and might be resuming a download, let's do nothing with the content\n\t\tif ([self needsRedirect] && [self shouldRedirect] && [self allowResumeForFileDownloads]) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tBOOL dataWillBeHandledExternally = NO;\n\t\tif ([[self delegate] respondsToSelector:[self didReceiveDataSelector]]) {\n\t\t\tdataWillBeHandledExternally = YES;\n\t\t}\n\t\t#if NS_BLOCKS_AVAILABLE\n\t\tif (dataReceivedBlock) {\n\t\t\tdataWillBeHandledExternally = YES;\n\t\t}\n\t\t#endif\n\t\t// Does the delegate want to handle the data manually?\n\t\tif (dataWillBeHandledExternally) {\n\n\t\t\tNSData *data = nil;\n\t\t\tif ([self isResponseCompressed] && ![self shouldWaitToInflateCompressedResponses]) {\n\t\t\t\tdata = inflatedData;\n\t\t\t} else {\n\t\t\t\tdata = [NSData dataWithBytes:buffer length:bytesRead];\n\t\t\t}\n\t\t\t[self performSelectorOnMainThread:@selector(passOnReceivedData:) withObject:data waitUntilDone:[NSThread isMainThread]];\n\t\t\t\n\t\t// Are we downloading to a file?\n\t\t} else if ([self downloadDestinationPath]) {\n\t\t\tBOOL append = NO;\n\t\t\tif (![self fileDownloadOutputStream]) {\n\t\t\t\tif (![self temporaryFileDownloadPath]) {\n\t\t\t\t\t[self setTemporaryFileDownloadPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]];\n\t\t\t\t} else if ([self allowResumeForFileDownloads] && [[self requestHeaders] objectForKey:@\"Range\"]) {\n\t\t\t\t\tif ([[self responseHeaders] objectForKey:@\"Content-Range\"]) {\n\t\t\t\t\t\tappend = YES;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t[self incrementDownloadSizeBy:-[self partialDownloadSize]];\n\t\t\t\t\t\t[self setPartialDownloadSize:0];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t[self setFileDownloadOutputStream:[[[NSOutputStream alloc] initToFileAtPath:[self temporaryFileDownloadPath] append:append] autorelease]];\n\t\t\t\t[[self fileDownloadOutputStream] open];\n\n\t\t\t}\n\t\t\t[[self fileDownloadOutputStream] write:buffer maxLength:bytesRead];\n\n\t\t\tif ([self isResponseCompressed] && ![self shouldWaitToInflateCompressedResponses]) {\n\t\t\t\t\n\t\t\t\tif (![self inflatedFileDownloadOutputStream]) {\n\t\t\t\t\tif (![self temporaryUncompressedDataDownloadPath]) {\n\t\t\t\t\t\t[self setTemporaryUncompressedDataDownloadPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]];\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t[self setInflatedFileDownloadOutputStream:[[[NSOutputStream alloc] initToFileAtPath:[self temporaryUncompressedDataDownloadPath] append:append] autorelease]];\n\t\t\t\t\t[[self inflatedFileDownloadOutputStream] open];\n\t\t\t\t}\n\n\t\t\t\t[[self inflatedFileDownloadOutputStream] write:[inflatedData bytes] maxLength:[inflatedData length]];\n\t\t\t}\n\n\t\t\t\n\t\t//Otherwise, let's add the data to our in-memory store\n\t\t} else {\n\t\t\tif ([self isResponseCompressed] && ![self shouldWaitToInflateCompressedResponses]) {\n\t\t\t\t[rawResponseData appendData:inflatedData];\n\t\t\t} else {\n\t\t\t\t[rawResponseData appendBytes:buffer length:bytesRead];\n\t\t\t}\n\t\t}\n    }\n}\n\n- (void)handleStreamComplete\n{\t\n\n#if DEBUG_REQUEST_STATUS\n\tASI_DEBUG_LOG(@\"[STATUS] Request %@ finished downloading data (%qu bytes)\",self, [self totalBytesRead]);\n#endif\n\t[self setStatusTimer:nil];\n\t[self setDownloadComplete:YES];\n\t\n\tif (![self responseHeaders]) {\n\t\t[self readResponseHeaders];\n\t}\n\n\t[progressLock lock];\t\n\t// Find out how much data we've uploaded so far\n\t[self setLastBytesSent:totalBytesSent];\t\n\t[self setTotalBytesSent:[[NSMakeCollectable(CFReadStreamCopyProperty((CFReadStreamRef)[self readStream], kCFStreamPropertyHTTPRequestBytesWrittenCount)) autorelease] unsignedLongLongValue]];\n\t[self setComplete:YES];\n\tif (![self contentLength]) {\n\t\t[self setContentLength:[self totalBytesRead]];\n\t}\n\t[self updateProgressIndicators];\n\n\t\n\t[[self postBodyReadStream] close];\n\t[self setPostBodyReadStream:nil];\n\t\n\t[self setDataDecompressor:nil];\n\n\tNSError *fileError = nil;\n\t\n\t// Delete up the request body temporary file, if it exists\n\tif ([self didCreateTemporaryPostDataFile] && ![self authenticationNeeded]) {\n\t\t[self removeTemporaryUploadFile];\n\t\t[self removeTemporaryCompressedUploadFile];\n\t}\n\t\n\t// Close the output stream as we're done writing to the file\n\tif ([self temporaryFileDownloadPath]) {\n\t\t\n\t\t[[self fileDownloadOutputStream] close];\n\t\t[self setFileDownloadOutputStream:nil];\n\n\t\t[[self inflatedFileDownloadOutputStream] close];\n\t\t[self setInflatedFileDownloadOutputStream:nil];\n\n\t\t// If we are going to redirect and we are resuming, let's ignore this download\n\t\tif ([self shouldRedirect] && [self needsRedirect] && [self allowResumeForFileDownloads]) {\n\t\t\n\t\t} else if ([self isResponseCompressed]) {\n\t\t\t\n\t\t\t// Decompress the file directly to the destination path\n\t\t\tif ([self shouldWaitToInflateCompressedResponses]) {\n\t\t\t\t[ASIDataDecompressor uncompressDataFromFile:[self temporaryFileDownloadPath] toFile:[self downloadDestinationPath] error:&fileError];\n\n\t\t\t// Response should already have been inflated, move the temporary file to the destination path\n\t\t\t} else {\n\t\t\t\tNSError *moveError = nil;\n\t\t\t\t[[[[NSFileManager alloc] init] autorelease] moveItemAtPath:[self temporaryUncompressedDataDownloadPath] toPath:[self downloadDestinationPath] error:&moveError];\n\t\t\t\tif (moveError) {\n\t\t\t\t\tfileError = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Failed to move file from '%@' to '%@'\",[self temporaryFileDownloadPath],[self downloadDestinationPath]],NSLocalizedDescriptionKey,moveError,NSUnderlyingErrorKey,nil]];\n\t\t\t\t}\n\t\t\t\t[self setTemporaryUncompressedDataDownloadPath:nil];\n\n\t\t\t}\n\t\t\t[self removeTemporaryDownloadFile];\n\n\t\t} else {\n\t\n\t\t\t//Remove any file at the destination path\n\t\t\tNSError *moveError = nil;\n\t\t\tif (![[self class] removeFileAtPath:[self downloadDestinationPath] error:&moveError]) {\n\t\t\t\tfileError = moveError;\n\n\t\t\t}\n\n\t\t\t//Move the temporary file to the destination path\n\t\t\tif (!fileError) {\n\t\t\t\t[[[[NSFileManager alloc] init] autorelease] moveItemAtPath:[self temporaryFileDownloadPath] toPath:[self downloadDestinationPath] error:&moveError];\n\t\t\t\tif (moveError) {\n\t\t\t\t\tfileError = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Failed to move file from '%@' to '%@'\",[self temporaryFileDownloadPath],[self downloadDestinationPath]],NSLocalizedDescriptionKey,moveError,NSUnderlyingErrorKey,nil]];\n\t\t\t\t}\n\t\t\t\t[self setTemporaryFileDownloadPath:nil];\n\t\t\t}\n\t\t\t\n\t\t}\n\t}\n\t\n\t// Save to the cache\n\tif ([self downloadCache] && ![self didUseCachedResponse]) {\n\t\t[[self downloadCache] storeResponseForRequest:self maxAge:[self secondsToCache]];\n\t}\n\t\n\t[progressLock unlock];\n\n\t\n\t[connectionsLock lock];\n\tif (![self connectionCanBeReused]) {\n\t\t[self unscheduleReadStream];\n\t}\n\t#if DEBUG_PERSISTENT_CONNECTIONS\n\tif ([self requestID]) {\n\t\tASI_DEBUG_LOG(@\"[CONNECTION] Request #%@ finished using connection #%@\",[self requestID], [[self connectionInfo] objectForKey:@\"id\"]);\n\t}\n\t#endif\n\t[[self connectionInfo] removeObjectForKey:@\"request\"];\n\t[[self connectionInfo] setObject:[NSDate dateWithTimeIntervalSinceNow:[self persistentConnectionTimeoutSeconds]] forKey:@\"expires\"];\n\t[connectionsLock unlock];\n\t\n\tif (![self authenticationNeeded]) {\n\t\t[self destroyReadStream];\n\t}\n\t\n\n\tif (![self needsRedirect] && ![self authenticationNeeded] && ![self didUseCachedResponse]) {\n\t\t\n\t\tif (fileError) {\n\t\t\t[self failWithError:fileError];\n\t\t} else {\n\t\t\t[self requestFinished];\n\t\t}\n\n\t\t[self markAsFinished];\n\t\t\n\t// If request has asked delegate or ASIAuthenticationDialog for credentials\n\t} else if ([self authenticationNeeded]) {\n\t\tCFRunLoopStop(CFRunLoopGetCurrent());\n\t}\n\n}\n\n- (void)markAsFinished\n{\n\t// Autoreleased requests may well be dealloced here otherwise\n\tCFRetain(self);\n\n\t// dealloc won't be called when running with GC, so we'll clean these up now\n\tif (request) {\n\t\tCFRelease(request);\n\t\trequest = nil;\n\t}\n\tif (requestAuthentication) {\n\t\tCFRelease(requestAuthentication);\n\t\trequestAuthentication = nil;\n\t}\n\tif (proxyAuthentication) {\n\t\tCFRelease(proxyAuthentication);\n\t\tproxyAuthentication = nil;\n\t}\n\n    BOOL wasInProgress = inProgress;\n    BOOL wasFinished = finished;\n\n    if (!wasFinished)\n        [self willChangeValueForKey:@\"isFinished\"];\n    if (wasInProgress)\n        [self willChangeValueForKey:@\"isExecuting\"];\n\n\t[self setInProgress:NO];\n    finished = YES;\n\n    if (wasInProgress)\n        [self didChangeValueForKey:@\"isExecuting\"];\n    if (!wasFinished)\n        [self didChangeValueForKey:@\"isFinished\"];\n\n\tCFRunLoopStop(CFRunLoopGetCurrent());\n\n\t#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n\tif ([ASIHTTPRequest isMultitaskingSupported] && [self shouldContinueWhenAppEntersBackground]) {\n\t\tdispatch_async(dispatch_get_main_queue(), ^{\n\t\t\tif (backgroundTask != UIBackgroundTaskInvalid) {\n\t\t\t\t[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];\n\t\t\t\tbackgroundTask = UIBackgroundTaskInvalid;\n\t\t\t}\n\t\t});\n\t}\n\t#endif\n\tCFRelease(self);\n}\n\n- (void)useDataFromCache\n{\n\tNSDictionary *headers = [[self downloadCache] cachedResponseHeadersForURL:[self url]];\n\tNSString *dataPath = [[self downloadCache] pathToCachedResponseDataForURL:[self url]];\n\n\tASIHTTPRequest *theRequest = self;\n\tif ([self mainRequest]) {\n\t\ttheRequest = [self mainRequest];\n\t}\n\n\tif (headers && dataPath) {\n\n\t\t[self setResponseStatusCode:[[headers objectForKey:@\"X-ASIHTTPRequest-Response-Status-Code\"] intValue]];\n\t\t[self setDidUseCachedResponse:YES];\n\t\t[theRequest setResponseHeaders:headers];\n\n\t\tif ([theRequest downloadDestinationPath]) {\n\t\t\t[theRequest setDownloadDestinationPath:dataPath];\n\t\t} else {\n\t\t\t[theRequest setRawResponseData:[NSMutableData dataWithData:[[self downloadCache] cachedResponseDataForURL:[self url]]]];\n\t\t}\n\t\t[theRequest setContentLength:[[[self responseHeaders] objectForKey:@\"Content-Length\"] longLongValue]];\n\t\t[theRequest setTotalBytesRead:[self contentLength]];\n\n\t\t[theRequest parseStringEncodingFromHeaders];\n\n\t\t[theRequest setResponseCookies:[NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:[self url]]];\n\n\t\t// See if we need to redirect\n\t\tif ([self willRedirect]) {\n\t\t\tif (![self willAskDelegateToConfirmRedirect]) {\n\t\t\t\t[self performRedirect];\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\t[theRequest setComplete:YES];\n\t[theRequest setDownloadComplete:YES];\n\n\t// If we're pulling data from the cache without contacting the server at all, we won't have set originalURL yet\n\tif ([self redirectCount] == 0) {\n\t\t[theRequest setOriginalURL:[theRequest url]];\n\t}\n\n\t[theRequest updateProgressIndicators];\n\t[theRequest requestFinished];\n\t[theRequest markAsFinished];\t\n\tif ([self mainRequest]) {\n\t\t[self markAsFinished];\n\t}\n}\n\n- (BOOL)retryUsingNewConnection\n{\n\tif ([self retryCount] == 0) {\n\n\t\t[self setWillRetryRequest:YES];\n\t\t[self cancelLoad];\n\t\t[self setWillRetryRequest:NO];\n\n\t\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\t\tASI_DEBUG_LOG(@\"[CONNECTION] Request attempted to use connection #%@, but it has been closed - will retry with a new connection\", [[self connectionInfo] objectForKey:@\"id\"]);\n\t\t#endif\n\t\t[connectionsLock lock];\n\t\t[[self connectionInfo] removeObjectForKey:@\"request\"];\n\t\t[persistentConnectionsPool removeObject:[self connectionInfo]];\n\t\t[self setConnectionInfo:nil];\n\t\t[connectionsLock unlock];\n\t\t[self setRetryCount:[self retryCount]+1];\n\t\t[self startRequest];\n\t\treturn YES;\n\t}\n\t#if DEBUG_PERSISTENT_CONNECTIONS\n\t\tASI_DEBUG_LOG(@\"[CONNECTION] Request attempted to use connection #%@, but it has been closed - we have already retried with a new connection, so we must give up\", [[self connectionInfo] objectForKey:@\"id\"]);\n\t#endif\t\n\treturn NO;\n}\n\n- (void)handleStreamError\n\n{\n\tNSError *underlyingError = [NSMakeCollectable(CFReadStreamCopyError((CFReadStreamRef)[self readStream])) autorelease];\n\n\tif (![self error]) { // We may already have handled this error\n\t\t\n\t\t// First, check for a 'socket not connected', 'broken pipe' or 'connection lost' error\n\t\t// This may occur when we've attempted to reuse a connection that should have been closed\n\t\t// If we get this, we need to retry the request\n\t\t// We'll only do this once - if it happens again on retry, we'll give up\n\t\t// -1005 = kCFURLErrorNetworkConnectionLost - this doesn't seem to be declared on Mac OS 10.5\n\t\tif (([[underlyingError domain] isEqualToString:NSPOSIXErrorDomain] && ([underlyingError code] == ENOTCONN || [underlyingError code] == EPIPE)) \n\t\t\t|| ([[underlyingError domain] isEqualToString:(NSString *)kCFErrorDomainCFNetwork] && [underlyingError code] == -1005)) {\n\t\t\tif ([self retryUsingNewConnection]) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t\n\t\tNSString *reason = @\"A connection failure occurred\";\n\t\t\n\t\t// We'll use a custom error message for SSL errors, but you should always check underlying error if you want more details\n\t\t// For some reason SecureTransport.h doesn't seem to be available on iphone, so error codes hard-coded\n\t\t// Also, iPhone seems to handle errors differently from Mac OS X - a self-signed certificate returns a different error code on each platform, so we'll just provide a general error\n\t\tif ([[underlyingError domain] isEqualToString:NSOSStatusErrorDomain]) {\n\t\t\tif ([underlyingError code] <= -9800 && [underlyingError code] >= -9818) {\n\t\t\t\treason = [NSString stringWithFormat:@\"%@: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date)\",reason];\n\t\t\t}\n\t\t}\n\t\t[self cancelLoad];\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIConnectionFailureErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:reason,NSLocalizedDescriptionKey,underlyingError,NSUnderlyingErrorKey,nil]]];\n\t} else {\n\t\t[self cancelLoad];\n\t}\n\t[self checkRequestStatus];\n}\n\n#pragma mark managing the read stream\n\n- (void)destroyReadStream\n{\n    if ([self readStream]) {\n\t\t[self unscheduleReadStream];\n\t\tif (![self connectionCanBeReused]) {\n\t\t\t[[self readStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:[self runLoopMode]];\n\t\t\t[[self readStream] close];\n\t\t}\n\t\t[self setReadStream:nil];\n    }\t\n}\n\n- (void)scheduleReadStream\n{\n\tif ([self readStream] && ![self readStreamIsScheduled]) {\n\n\t\t[connectionsLock lock];\n\t\trunningRequestCount++;\n\t\tif (shouldUpdateNetworkActivityIndicator) {\n\t\t\t[[self class] showNetworkActivityIndicator];\n\t\t}\n\t\t[connectionsLock unlock];\n\n\t\t// Reset the timeout\n\t\t[self setLastActivityTime:[NSDate date]];\n\t\tCFStreamClientContext ctxt = {0, self, NULL, NULL, NULL};\n\t\tCFReadStreamSetClient((CFReadStreamRef)[self readStream], kNetworkEvents, ReadStreamClientCallBack, &ctxt);\n\t\t[[self readStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:[self runLoopMode]];\n\t\t[self setReadStreamIsScheduled:YES];\n\t}\n}\n\n\n- (void)unscheduleReadStream\n{\n\tif ([self readStream] && [self readStreamIsScheduled]) {\n\n\t\t[connectionsLock lock];\n\t\trunningRequestCount--;\n\t\tif (shouldUpdateNetworkActivityIndicator && runningRequestCount == 0) {\n\t\t\t// This call will wait half a second before turning off the indicator\n\t\t\t// This can prevent flicker when you have a single request finish and then immediately start another request\n\t\t\t// We run this on the main thread because we have no guarantee this thread will have a runloop in 0.5 seconds time\n\t\t\t// We don't bother the cancel this call if we start a new request, because we'll check if requests are running before we hide it\n\t\t\t[[self class] performSelectorOnMainThread:@selector(hideNetworkActivityIndicatorAfterDelay) withObject:nil waitUntilDone:[NSThread isMainThread]];\n\t\t}\n\t\t[connectionsLock unlock];\n\n\t\tCFReadStreamSetClient((CFReadStreamRef)[self readStream], kCFStreamEventNone, NULL, NULL);\n\t\t[[self readStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:[self runLoopMode]];\n\t\t[self setReadStreamIsScheduled:NO];\n\t}\n}\n\n#pragma mark cleanup\n\n- (BOOL)removeTemporaryDownloadFile\n{\n\tNSError *err = nil;\n\tif ([self temporaryFileDownloadPath]) {\n\t\tif (![[self class] removeFileAtPath:[self temporaryFileDownloadPath] error:&err]) {\n\t\t\t[self failWithError:err];\n\t\t}\n\t\t[self setTemporaryFileDownloadPath:nil];\n\t}\n\treturn (!err);\n}\n\n- (BOOL)removeTemporaryUncompressedDownloadFile\n{\n\tNSError *err = nil;\n\tif ([self temporaryUncompressedDataDownloadPath]) {\n\t\tif (![[self class] removeFileAtPath:[self temporaryUncompressedDataDownloadPath] error:&err]) {\n\t\t\t[self failWithError:err];\n\t\t}\n\t\t[self setTemporaryUncompressedDataDownloadPath:nil];\n\t}\n\treturn (!err);\n}\n\n- (BOOL)removeTemporaryUploadFile\n{\n\tNSError *err = nil;\n\tif ([self postBodyFilePath]) {\n\t\tif (![[self class] removeFileAtPath:[self postBodyFilePath] error:&err]) {\n\t\t\t[self failWithError:err];\n\t\t}\n\t\t[self setPostBodyFilePath:nil];\n\t}\n\treturn (!err);\n}\n\n- (BOOL)removeTemporaryCompressedUploadFile\n{\n\tNSError *err = nil;\n\tif ([self compressedPostBodyFilePath]) {\n\t\tif (![[self class] removeFileAtPath:[self compressedPostBodyFilePath] error:&err]) {\n\t\t\t[self failWithError:err];\n\t\t}\n\t\t[self setCompressedPostBodyFilePath:nil];\n\t}\n\treturn (!err);\n}\n\n+ (BOOL)removeFileAtPath:(NSString *)path error:(NSError **)err\n{\n\tNSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];\n\n\tif ([fileManager fileExistsAtPath:path]) {\n\t\tNSError *removeError = nil;\n\t\t[fileManager removeItemAtPath:path error:&removeError];\n\t\tif (removeError) {\n\t\t\tif (err) {\n\t\t\t\t*err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@\"Failed to delete file at path '%@'\",path],NSLocalizedDescriptionKey,removeError,NSUnderlyingErrorKey,nil]];\n\t\t\t}\n\t\t\treturn NO;\n\t\t}\n\t}\n\treturn YES;\n}\n\n#pragma mark Proxies\n\n- (BOOL)configureProxies\n{\n\t// Have details of the proxy been set on this request\n\tif (![self isPACFileRequest] && (![self proxyHost] && ![self proxyPort])) {\n\n\t\t// If not, we need to figure out what they'll be\n\t\tNSArray *proxies = nil;\n\n\t\t// Have we been given a proxy auto config file?\n\t\tif ([self PACurl]) {\n\n\t\t\t// If yes, we'll need to fetch the PAC file asynchronously, so we stop this request to wait until we have the proxy details.\n\t\t\t[self fetchPACFile];\n\t\t\treturn NO;\n\n\t\t\t// Detect proxy settings and apply them\n\t\t} else {\n\n#if TARGET_OS_IPHONE\n\t\t\tNSDictionary *proxySettings = [NSMakeCollectable(CFNetworkCopySystemProxySettings()) autorelease];\n#else\n\t\t\tNSDictionary *proxySettings = [NSMakeCollectable(SCDynamicStoreCopyProxies(NULL)) autorelease];\n#endif\n\n\t\t\tproxies = [NSMakeCollectable(CFNetworkCopyProxiesForURL((CFURLRef)[self url], (CFDictionaryRef)proxySettings)) autorelease];\n\n\t\t\t// Now check to see if the proxy settings contained a PAC url, we need to run the script to get the real list of proxies if so\n\t\t\tNSDictionary *settings = [proxies objectAtIndex:0];\n\t\t\tif ([settings objectForKey:(NSString *)kCFProxyAutoConfigurationURLKey]) {\n\t\t\t\t[self setPACurl:[settings objectForKey:(NSString *)kCFProxyAutoConfigurationURLKey]];\n\t\t\t\t[self fetchPACFile];\n\t\t\t\treturn NO;\n\t\t\t}\n\t\t}\n\n\t\tif (!proxies) {\n\t\t\t[self setReadStream:nil];\n\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Unable to obtain information on proxy servers needed for request\",NSLocalizedDescriptionKey,nil]]];\n\t\t\treturn NO;\n\t\t}\n\t\t// I don't really understand why the dictionary returned by CFNetworkCopyProxiesForURL uses different key names from CFNetworkCopySystemProxySettings/SCDynamicStoreCopyProxies\n\t\t// and why its key names are documented while those we actually need to use don't seem to be (passing the kCF* keys doesn't seem to work)\n\t\tif ([proxies count] > 0) {\n\t\t\tNSDictionary *settings = [proxies objectAtIndex:0];\n\t\t\t[self setProxyHost:[settings objectForKey:(NSString *)kCFProxyHostNameKey]];\n\t\t\t[self setProxyPort:[[settings objectForKey:(NSString *)kCFProxyPortNumberKey] intValue]];\n\t\t\t[self setProxyType:[settings objectForKey:(NSString *)kCFProxyTypeKey]];\n\t\t}\n\t}\n\treturn YES;\n}\n\n\n\n// Attempts to download a PAC (Proxy Auto-Configuration) file\n// PAC files at file://, http:// and https:// addresses are supported\n- (void)fetchPACFile\n{\n\t// For file:// urls, we'll use an async NSInputStream (ASIHTTPRequest does not support file:// urls)\n\tif ([[self PACurl] isFileURL]) {\n\t\tNSInputStream *stream = [[[NSInputStream alloc] initWithFileAtPath:[[self PACurl] path]] autorelease];\n\t\t[self setPACFileReadStream:stream];\n\t\t[stream setDelegate:(id)self];\n\t\t[stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:[self runLoopMode]];\n\t\t[stream open];\n\t\t// If it takes more than timeOutSeconds to read the PAC, we'll just give up and assume no proxies\n\t\t// We won't bother to handle cases where the first part of the PAC is read within timeOutSeconds, but the whole thing takes longer\n\t\t// Either our PAC file is in easy reach, or it's going to slow things down to the point that it's probably better requests fail\n\t\t[self performSelector:@selector(timeOutPACRead) withObject:nil afterDelay:[self timeOutSeconds]];\n\t\treturn;\n\t}\n\n\tNSString *scheme = [[[self PACurl] scheme] lowercaseString];\n\tif (![scheme isEqualToString:@\"http\"] && ![scheme isEqualToString:@\"https\"]) {\n\t\t// Don't know how to read data from this URL, we'll have to give up\n\t\t// We'll simply assume no proxies, and start the request as normal\n\t\t[self startRequest];\n\t\treturn;\n\t}\n\n\t// Create an ASIHTTPRequest to fetch the PAC file\n\tASIHTTPRequest *PACRequest = [ASIHTTPRequest requestWithURL:[self PACurl]];\n\n\t// Will prevent this request attempting to configure proxy settings for itself\n\t[PACRequest setIsPACFileRequest:YES];\n\n\t[PACRequest setTimeOutSeconds:[self timeOutSeconds]];\n\n\t// If we're a synchronous request, we'll download the PAC file synchronously\n\tif ([self isSynchronous]) {\n\t\t[PACRequest startSynchronous];\n\t\tif (![PACRequest error] && [PACRequest responseString]) {\n\t\t\t[self runPACScript:[PACRequest responseString]];\n\t\t}\n\t\t[self startRequest];\n\t\treturn;\n\t}\n\n\t[self setPACFileRequest:PACRequest];\n\n\t// Force this request to run before others in the shared queue\n\t[PACRequest setQueuePriority:NSOperationQueuePriorityHigh];\n\n\t// We'll treat failure to download the PAC file the same as success - if we were unable to fetch a PAC file, we proceed as if we have no proxy server and let this request fail itself if necessary\n\t[PACRequest setDelegate:self];\n\t[PACRequest setDidFinishSelector:@selector(finishedDownloadingPACFile:)];\n\t[PACRequest setDidFailSelector:@selector(finishedDownloadingPACFile:)];\n\t[PACRequest startAsynchronous];\n\n\t// Temporarily increase the number of operations in the shared queue to give our request a chance to run\n\t[connectionsLock lock];\n\t[sharedQueue setMaxConcurrentOperationCount:[sharedQueue maxConcurrentOperationCount]+1];\n\t[connectionsLock unlock];\n}\n\n// Called as we read the PAC file from a file:// url\n- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode\n{\n\tif (![self PACFileReadStream]) {\n\t\treturn;\n\t}\n\tif (eventCode == NSStreamEventHasBytesAvailable) {\n\n\t\tif (![self PACFileData]) {\n\t\t\t[self setPACFileData:[NSMutableData data]];\n\t\t}\n\t\t// If your PAC file is larger than 16KB, you're just being cruel.\n\t\tuint8_t buf[16384];\n\t\tNSInteger len = [(NSInputStream *)stream read:buf maxLength:16384];\n\t\tif (len) {\n\t\t\t[[self PACFileData] appendBytes:(const void *)buf length:len];\n\t\t}\n\n\t} else if (eventCode == NSStreamEventErrorOccurred || eventCode == NSStreamEventEndEncountered) {\n\n\t\t[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeOutPACRead) object:nil];\n\n\t\t[stream close];\n\t\t[stream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:[self runLoopMode]];\n\t\t[self setPACFileReadStream:nil];\n\n\t\tif (eventCode == NSStreamEventEndEncountered) {\n\t\t\t// It sounds as though we have no idea what encoding a PAC file will use\n\t\t\tstatic NSStringEncoding encodingsToTry[2] = {NSUTF8StringEncoding,NSISOLatin1StringEncoding};\n\t\t\tNSUInteger i;\n\t\t\tfor (i=0; i<2; i++) {\n\t\t\t\tNSString *pacScript =  [[[NSString alloc] initWithBytes:[[self PACFileData] bytes] length:[[self PACFileData] length] encoding:encodingsToTry[i]] autorelease];\n\t\t\t\tif (pacScript) {\n\t\t\t\t\t[self runPACScript:pacScript];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t[self setPACFileData:nil];\n\t\t[self startRequest];\n\t}\n}\n\n// Called if it takes longer than timeOutSeconds to read the whole PAC file (when reading from a file:// url)\n- (void)timeOutPACRead\n{\n\t[self stream:[self PACFileReadStream] handleEvent:NSStreamEventErrorOccurred];\n}\n\n// Runs the downloaded PAC script\n- (void)runPACScript:(NSString *)script\n{\n\tif (script) {\n\t\t// From: http://developer.apple.com/samplecode/CFProxySupportTool/listing1.html\n\t\t// Work around <rdar://problem/5530166>.  This dummy call to \n\t\t// CFNetworkCopyProxiesForURL initialise some state within CFNetwork \n\t\t// that is required by CFNetworkCopyProxiesForAutoConfigurationScript.\n\t\tCFRelease(CFNetworkCopyProxiesForURL((CFURLRef)[self url], NULL));\n\n\t\t// Obtain the list of proxies by running the autoconfiguration script\n\t\tCFErrorRef err = NULL;\n\t\tNSArray *proxies = [NSMakeCollectable(CFNetworkCopyProxiesForAutoConfigurationScript((CFStringRef)script,(CFURLRef)[self url], &err)) autorelease];\n\t\tif (!err && [proxies count] > 0) {\n\t\t\tNSDictionary *settings = [proxies objectAtIndex:0];\n\t\t\t[self setProxyHost:[settings objectForKey:(NSString *)kCFProxyHostNameKey]];\n\t\t\t[self setProxyPort:[[settings objectForKey:(NSString *)kCFProxyPortNumberKey] intValue]];\n\t\t\t[self setProxyType:[settings objectForKey:(NSString *)kCFProxyTypeKey]];\n\t\t}\n\t}\n}\n\n// Called if we successfully downloaded a PAC file from a webserver\n- (void)finishedDownloadingPACFile:(ASIHTTPRequest *)theRequest\n{\n\tif (![theRequest error] && [theRequest responseString]) {\n\t\t[self runPACScript:[theRequest responseString]];\n\t}\n\n\t// Set the shared queue's maxConcurrentOperationCount back to normal\n\t[connectionsLock lock];\n\t[sharedQueue setMaxConcurrentOperationCount:[sharedQueue maxConcurrentOperationCount]-1];\n\t[connectionsLock unlock];\n\n\t// We no longer need our PAC file request\n\t[self setPACFileRequest:nil];\n\n\t// Start the request\n\t[self startRequest];\n}\n\n\n#pragma mark persistent connections\n\n- (NSNumber *)connectionID\n{\n\treturn [[self connectionInfo] objectForKey:@\"id\"];\n}\n\n+ (void)expirePersistentConnections\n{\n\t[connectionsLock lock];\n\tNSUInteger i;\n\tfor (i=0; i<[persistentConnectionsPool count]; i++) {\n\t\tNSDictionary *existingConnection = [persistentConnectionsPool objectAtIndex:i];\n\t\tif (![existingConnection objectForKey:@\"request\"] && [[existingConnection objectForKey:@\"expires\"] timeIntervalSinceNow] <= 0) {\n#if DEBUG_PERSISTENT_CONNECTIONS\n\t\t\tASI_DEBUG_LOG(@\"[CONNECTION] Closing connection #%i because it has expired\",[[existingConnection objectForKey:@\"id\"] intValue]);\n#endif\n\t\t\tNSInputStream *stream = [existingConnection objectForKey:@\"stream\"];\n\t\t\tif (stream) {\n\t\t\t\t[stream close];\n\t\t\t}\n\t\t\t[persistentConnectionsPool removeObject:existingConnection];\n\t\t\ti--;\n\t\t}\n\t}\t\n\t[connectionsLock unlock];\n}\n\n#pragma mark NSCopying\n- (id)copyWithZone:(NSZone *)zone\n{\n\t// Don't forget - this will return a retained copy!\n\tASIHTTPRequest *newRequest = [[[self class] alloc] initWithURL:[self url]];\n\t[newRequest setDelegate:[self delegate]];\n\t[newRequest setRequestMethod:[self requestMethod]];\n\t[newRequest setPostBody:[self postBody]];\n\t[newRequest setShouldStreamPostDataFromDisk:[self shouldStreamPostDataFromDisk]];\n\t[newRequest setPostBodyFilePath:[self postBodyFilePath]];\n\t[newRequest setRequestHeaders:[[[self requestHeaders] mutableCopyWithZone:zone] autorelease]];\n\t[newRequest setRequestCookies:[[[self requestCookies] mutableCopyWithZone:zone] autorelease]];\n\t[newRequest setUseCookiePersistence:[self useCookiePersistence]];\n\t[newRequest setUseKeychainPersistence:[self useKeychainPersistence]];\n\t[newRequest setUseSessionPersistence:[self useSessionPersistence]];\n\t[newRequest setAllowCompressedResponse:[self allowCompressedResponse]];\n\t[newRequest setDownloadDestinationPath:[self downloadDestinationPath]];\n\t[newRequest setTemporaryFileDownloadPath:[self temporaryFileDownloadPath]];\n\t[newRequest setUsername:[self username]];\n\t[newRequest setPassword:[self password]];\n\t[newRequest setDomain:[self domain]];\n\t[newRequest setProxyUsername:[self proxyUsername]];\n\t[newRequest setProxyPassword:[self proxyPassword]];\n\t[newRequest setProxyDomain:[self proxyDomain]];\n\t[newRequest setProxyHost:[self proxyHost]];\n\t[newRequest setProxyPort:[self proxyPort]];\n\t[newRequest setProxyType:[self proxyType]];\n\t[newRequest setUploadProgressDelegate:[self uploadProgressDelegate]];\n\t[newRequest setDownloadProgressDelegate:[self downloadProgressDelegate]];\n\t[newRequest setShouldPresentAuthenticationDialog:[self shouldPresentAuthenticationDialog]];\n\t[newRequest setShouldPresentProxyAuthenticationDialog:[self shouldPresentProxyAuthenticationDialog]];\n\t[newRequest setPostLength:[self postLength]];\n\t[newRequest setHaveBuiltPostBody:[self haveBuiltPostBody]];\n\t[newRequest setDidStartSelector:[self didStartSelector]];\n\t[newRequest setDidFinishSelector:[self didFinishSelector]];\n\t[newRequest setDidFailSelector:[self didFailSelector]];\n\t[newRequest setTimeOutSeconds:[self timeOutSeconds]];\n\t[newRequest setShouldResetDownloadProgress:[self shouldResetDownloadProgress]];\n\t[newRequest setShouldResetUploadProgress:[self shouldResetUploadProgress]];\n\t[newRequest setShowAccurateProgress:[self showAccurateProgress]];\n\t[newRequest setDefaultResponseEncoding:[self defaultResponseEncoding]];\n\t[newRequest setAllowResumeForFileDownloads:[self allowResumeForFileDownloads]];\n\t[newRequest setUserInfo:[[[self userInfo] copyWithZone:zone] autorelease]];\n\t[newRequest setTag:[self tag]];\n\t[newRequest setUseHTTPVersionOne:[self useHTTPVersionOne]];\n\t[newRequest setShouldRedirect:[self shouldRedirect]];\n\t[newRequest setValidatesSecureCertificate:[self validatesSecureCertificate]];\n    [newRequest setClientCertificateIdentity:clientCertificateIdentity];\n\t[newRequest setClientCertificates:[[clientCertificates copy] autorelease]];\n\t[newRequest setPACurl:[self PACurl]];\n\t[newRequest setShouldPresentCredentialsBeforeChallenge:[self shouldPresentCredentialsBeforeChallenge]];\n\t[newRequest setNumberOfTimesToRetryOnTimeout:[self numberOfTimesToRetryOnTimeout]];\n\t[newRequest setShouldUseRFC2616RedirectBehaviour:[self shouldUseRFC2616RedirectBehaviour]];\n\t[newRequest setShouldAttemptPersistentConnection:[self shouldAttemptPersistentConnection]];\n\t[newRequest setPersistentConnectionTimeoutSeconds:[self persistentConnectionTimeoutSeconds]];\n    [newRequest setAuthenticationScheme:[self authenticationScheme]];\n\treturn newRequest;\n}\n\n#pragma mark default time out\n\n+ (NSTimeInterval)defaultTimeOutSeconds\n{\n\treturn defaultTimeOutSeconds;\n}\n\n+ (void)setDefaultTimeOutSeconds:(NSTimeInterval)newTimeOutSeconds\n{\n\tdefaultTimeOutSeconds = newTimeOutSeconds;\n}\n\n\n#pragma mark client certificate\n\n- (void)setClientCertificateIdentity:(SecIdentityRef)anIdentity {\n    if(clientCertificateIdentity) {\n        CFRelease(clientCertificateIdentity);\n    }\n    \n    clientCertificateIdentity = anIdentity;\n    \n\tif (clientCertificateIdentity) {\n\t\tCFRetain(clientCertificateIdentity);\n\t}\n}\n\n\n#pragma mark session credentials\n\n+ (NSMutableArray *)sessionProxyCredentialsStore\n{\n\t[sessionCredentialsLock lock];\n\tif (!sessionProxyCredentialsStore) {\n\t\tsessionProxyCredentialsStore = [[NSMutableArray alloc] init];\n\t}\n\t[sessionCredentialsLock unlock];\n\treturn sessionProxyCredentialsStore;\n}\n\n+ (NSMutableArray *)sessionCredentialsStore\n{\n\t[sessionCredentialsLock lock];\n\tif (!sessionCredentialsStore) {\n\t\tsessionCredentialsStore = [[NSMutableArray alloc] init];\n\t}\n\t[sessionCredentialsLock unlock];\n\treturn sessionCredentialsStore;\n}\n\n+ (void)storeProxyAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials\n{\n\t[sessionCredentialsLock lock];\n\t[self removeProxyAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@\"Credentials\"]];\n\t[[[self class] sessionProxyCredentialsStore] addObject:credentials];\n\t[sessionCredentialsLock unlock];\n}\n\n+ (void)storeAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials\n{\n\t[sessionCredentialsLock lock];\n\t[self removeAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@\"Credentials\"]];\n\t[[[self class] sessionCredentialsStore] addObject:credentials];\n\t[sessionCredentialsLock unlock];\n}\n\n+ (void)removeProxyAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials\n{\n\t[sessionCredentialsLock lock];\n\tNSMutableArray *sessionCredentialsList = [[self class] sessionProxyCredentialsStore];\n\tNSUInteger i;\n\tfor (i=0; i<[sessionCredentialsList count]; i++) {\n\t\tNSDictionary *theCredentials = [sessionCredentialsList objectAtIndex:i];\n\t\tif ([theCredentials objectForKey:@\"Credentials\"] == credentials) {\n\t\t\t[sessionCredentialsList removeObjectAtIndex:i];\n\t\t\t[sessionCredentialsLock unlock];\n\t\t\treturn;\n\t\t}\n\t}\n\t[sessionCredentialsLock unlock];\n}\n\n+ (void)removeAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials\n{\n\t[sessionCredentialsLock lock];\n\tNSMutableArray *sessionCredentialsList = [[self class] sessionCredentialsStore];\n\tNSUInteger i;\n\tfor (i=0; i<[sessionCredentialsList count]; i++) {\n\t\tNSDictionary *theCredentials = [sessionCredentialsList objectAtIndex:i];\n\t\tif ([theCredentials objectForKey:@\"Credentials\"] == credentials) {\n\t\t\t[sessionCredentialsList removeObjectAtIndex:i];\n\t\t\t[sessionCredentialsLock unlock];\n\t\t\treturn;\n\t\t}\n\t}\n\t[sessionCredentialsLock unlock];\n}\n\n- (NSDictionary *)findSessionProxyAuthenticationCredentials\n{\n\t[sessionCredentialsLock lock];\n\tNSMutableArray *sessionCredentialsList = [[self class] sessionProxyCredentialsStore];\n\tfor (NSDictionary *theCredentials in sessionCredentialsList) {\n\t\tif ([[theCredentials objectForKey:@\"Host\"] isEqualToString:[self proxyHost]] && [[theCredentials objectForKey:@\"Port\"] intValue] == [self proxyPort]) {\n\t\t\t[sessionCredentialsLock unlock];\n\t\t\treturn theCredentials;\n\t\t}\n\t}\n\t[sessionCredentialsLock unlock];\n\treturn nil;\n}\n\n\n- (NSDictionary *)findSessionAuthenticationCredentials\n{\n\t[sessionCredentialsLock lock];\n\tNSMutableArray *sessionCredentialsList = [[self class] sessionCredentialsStore];\n\tNSURL *requestURL = [self url];\n\n\tBOOL haveFoundExactMatch;\n\tNSDictionary *closeMatch = nil;\n\n\t// Loop through all the cached credentials we have, looking for the best match for this request\n\tfor (NSDictionary *theCredentials in sessionCredentialsList) {\n\t\t\n\t\thaveFoundExactMatch = NO;\n\t\tNSURL *cachedCredentialsURL = [theCredentials objectForKey:@\"URL\"];\n\n\t\t// Find an exact match (same url)\n\t\tif ([cachedCredentialsURL isEqual:[self url]]) {\n\t\t\thaveFoundExactMatch = YES;\n\n\t\t// This is not an exact match for the url, and we already have a close match we can use\n\t\t} else if (closeMatch) {\n\t\t\tcontinue;\n\n\t\t// Find a close match (same host, scheme and port)\n\t\t} else if ([[cachedCredentialsURL host] isEqualToString:[requestURL host]] && ([cachedCredentialsURL port] == [requestURL port] || ([requestURL port] && [[cachedCredentialsURL port] isEqualToNumber:[requestURL port]])) && [[cachedCredentialsURL scheme] isEqualToString:[requestURL scheme]]) {\n\t\t} else {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Just a sanity check to ensure we never choose credentials from a different realm. Can't really do more than that, as either this request or the stored credentials may not have a realm when the other does\n\t\tif ([self authenticationRealm] && ([theCredentials objectForKey:@\"AuthenticationRealm\"] && ![[theCredentials objectForKey:@\"AuthenticationRealm\"] isEqualToString:[self authenticationRealm]])) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// If we have a username and password set on the request, check that they are the same as the cached ones\n\t\tif ([self username] && [self password]) {\n\t\t\tNSDictionary *usernameAndPassword = [theCredentials objectForKey:@\"Credentials\"];\n\t\t\tNSString *storedUsername = [usernameAndPassword objectForKey:(NSString *)kCFHTTPAuthenticationUsername];\n\t\t\tNSString *storedPassword = [usernameAndPassword objectForKey:(NSString *)kCFHTTPAuthenticationPassword];\n\t\t\tif (![storedUsername isEqualToString:[self username]] || ![storedPassword isEqualToString:[self password]]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// If we have an exact match for the url, use those credentials\n\t\tif (haveFoundExactMatch) {\n\t\t\t[sessionCredentialsLock unlock];\n\t\t\treturn theCredentials;\n\t\t}\n\n\t\t// We have no exact match, let's remember that we have a good match for this server, and we'll use it at the end if we don't find an exact match\n\t\tcloseMatch = theCredentials;\n\t}\n\t[sessionCredentialsLock unlock];\n\n\t// Return credentials that matched on host, port and scheme, or nil if we didn't find any\n\treturn closeMatch;\n}\n\n#pragma mark keychain storage\n\n+ (void)saveCredentials:(NSURLCredential *)credentials forHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm\n{\n\tNSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:realm authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];\n\t[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credentials forProtectionSpace:protectionSpace];\n}\n\n+ (void)saveCredentials:(NSURLCredential *)credentials forProxy:(NSString *)host port:(int)port realm:(NSString *)realm\n{\n\tNSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithProxyHost:host port:port type:NSURLProtectionSpaceHTTPProxy realm:realm authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];\n\t[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credentials forProtectionSpace:protectionSpace];\n}\n\n+ (NSURLCredential *)savedCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm\n{\n\tNSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:realm authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];\n\treturn [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace];\n}\n\n+ (NSURLCredential *)savedCredentialsForProxy:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm\n{\n\tNSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithProxyHost:host port:port type:NSURLProtectionSpaceHTTPProxy realm:realm authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];\n\treturn [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace];\n}\n\n+ (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm\n{\n\tNSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:realm authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];\n\tNSURLCredential *credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace];\n\tif (credential) {\n\t\t[[NSURLCredentialStorage sharedCredentialStorage] removeCredential:credential forProtectionSpace:protectionSpace];\n\t}\n}\n\n+ (void)removeCredentialsForProxy:(NSString *)host port:(int)port realm:(NSString *)realm\n{\n\tNSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithProxyHost:host port:port type:NSURLProtectionSpaceHTTPProxy realm:realm authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];\n\tNSURLCredential *credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace];\n\tif (credential) {\n\t\t[[NSURLCredentialStorage sharedCredentialStorage] removeCredential:credential forProtectionSpace:protectionSpace];\n\t}\n}\n\n+ (NSMutableArray *)sessionCookies\n{\n\t[sessionCookiesLock lock];\n\tif (!sessionCookies) {\n\t\t[ASIHTTPRequest setSessionCookies:[NSMutableArray array]];\n\t}\n\tNSMutableArray *cookies = [[sessionCookies retain] autorelease];\n\t[sessionCookiesLock unlock];\n\treturn cookies;\n}\n\n+ (void)setSessionCookies:(NSMutableArray *)newSessionCookies\n{\n\t[sessionCookiesLock lock];\n\t// Remove existing cookies from the persistent store\n\tfor (NSHTTPCookie *cookie in sessionCookies) {\n\t\t[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];\n\t}\n\t[sessionCookies release];\n\tsessionCookies = [newSessionCookies retain];\n\t[sessionCookiesLock unlock];\n}\n\n+ (void)addSessionCookie:(NSHTTPCookie *)newCookie\n{\n\t[sessionCookiesLock lock];\n\tNSHTTPCookie *cookie;\n\tNSUInteger i;\n\tNSUInteger max = [[ASIHTTPRequest sessionCookies] count];\n\tfor (i=0; i<max; i++) {\n\t\tcookie = [[ASIHTTPRequest sessionCookies] objectAtIndex:i];\n\t\tif ([[cookie domain] isEqualToString:[newCookie domain]] && [[cookie path] isEqualToString:[newCookie path]] && [[cookie name] isEqualToString:[newCookie name]]) {\n\t\t\t[[ASIHTTPRequest sessionCookies] removeObjectAtIndex:i];\n\t\t\tbreak;\n\t\t}\n\t}\n\t[[ASIHTTPRequest sessionCookies] addObject:newCookie];\n\t[sessionCookiesLock unlock];\n}\n\n// Dump all session data (authentication and cookies)\n+ (void)clearSession\n{\n\t[sessionCredentialsLock lock];\n\t[[[self class] sessionCredentialsStore] removeAllObjects];\n\t[sessionCredentialsLock unlock];\n\t[[self class] setSessionCookies:nil];\n\t[[[self class] defaultCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];\n}\n\n#pragma mark get user agent\n\n+ (NSString *)defaultUserAgentString\n{\n\t@synchronized (self) {\n\n\t\tif (!defaultUserAgent) {\n\n\t\t\tNSBundle *bundle = [NSBundle bundleForClass:[self class]];\n\n\t\t\t// Attempt to find a name for this application\n\t\t\tNSString *appName = [bundle objectForInfoDictionaryKey:@\"CFBundleDisplayName\"];\n\t\t\tif (!appName) {\n\t\t\t\tappName = [bundle objectForInfoDictionaryKey:@\"CFBundleName\"];\n\t\t\t}\n\n\t\t\tNSData *latin1Data = [appName dataUsingEncoding:NSUTF8StringEncoding];\n\t\t\tappName = [[[NSString alloc] initWithData:latin1Data encoding:NSISOLatin1StringEncoding] autorelease];\n\n\t\t\t// If we couldn't find one, we'll give up (and ASIHTTPRequest will use the standard CFNetwork user agent)\n\t\t\tif (!appName) {\n\t\t\t\treturn nil;\n\t\t\t}\n\n\t\t\tNSString *appVersion = nil;\n\t\t\tNSString *marketingVersionNumber = [bundle objectForInfoDictionaryKey:@\"CFBundleShortVersionString\"];\n\t\t\tNSString *developmentVersionNumber = [bundle objectForInfoDictionaryKey:@\"CFBundleVersion\"];\n\t\t\tif (marketingVersionNumber && developmentVersionNumber) {\n\t\t\t\tif ([marketingVersionNumber isEqualToString:developmentVersionNumber]) {\n\t\t\t\t\tappVersion = marketingVersionNumber;\n\t\t\t\t} else {\n\t\t\t\t\tappVersion = [NSString stringWithFormat:@\"%@ rv:%@\",marketingVersionNumber,developmentVersionNumber];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tappVersion = (marketingVersionNumber ? marketingVersionNumber : developmentVersionNumber);\n\t\t\t}\n\n\t\t\tNSString *deviceName;\n\t\t\tNSString *OSName;\n\t\t\tNSString *OSVersion;\n\t\t\tNSString *locale = [[NSLocale currentLocale] localeIdentifier];\n\n\t\t\t#if TARGET_OS_IPHONE\n\t\t\t\tUIDevice *device = [UIDevice currentDevice];\n\t\t\t\tdeviceName = [device model];\n\t\t\t\tOSName = [device systemName];\n\t\t\t\tOSVersion = [device systemVersion];\n\n\t\t\t#else\n\t\t\t\tdeviceName = @\"Macintosh\";\n\t\t\t\tOSName = @\"Mac OS X\";\n\n\t\t\t\t// From http://www.cocoadev.com/index.pl?DeterminingOSVersion\n\t\t\t\t// We won't bother to check for systems prior to 10.4, since ASIHTTPRequest only works on 10.5+\n\t\t\t\tOSErr err;\n\t\t\t\tSInt32 versionMajor, versionMinor, versionBugFix;\n\t\t\t\terr = Gestalt(gestaltSystemVersionMajor, &versionMajor);\n\t\t\t\tif (err != noErr) return nil;\n\t\t\t\terr = Gestalt(gestaltSystemVersionMinor, &versionMinor);\n\t\t\t\tif (err != noErr) return nil;\n\t\t\t\terr = Gestalt(gestaltSystemVersionBugFix, &versionBugFix);\n\t\t\t\tif (err != noErr) return nil;\n\t\t\t\tOSVersion = [NSString stringWithFormat:@\"%u.%u.%u\", versionMajor, versionMinor, versionBugFix];\n\t\t\t#endif\n\n\t\t\t// Takes the form \"My Application 1.0 (Macintosh; Mac OS X 10.5.7; en_GB)\"\n\t\t\t[self setDefaultUserAgentString:[NSString stringWithFormat:@\"%@ %@ (%@; %@ %@; %@)\", appName, appVersion, deviceName, OSName, OSVersion, locale]];\t\n\t\t}\n\t\treturn [[defaultUserAgent retain] autorelease];\n\t}\n\treturn nil;\n}\n\n+ (void)setDefaultUserAgentString:(NSString *)agent\n{\n\t@synchronized (self) {\n\t\tif (defaultUserAgent == agent) {\n\t\t\treturn;\n\t\t}\n\t\t[defaultUserAgent release];\n\t\tdefaultUserAgent = [agent copy];\n\t}\n}\n\n\n#pragma mark mime-type detection\n\n+ (NSString *)mimeTypeForFileAtPath:(NSString *)path\n{\n\tif (![[[[NSFileManager alloc] init] autorelease] fileExistsAtPath:path]) {\n\t\treturn nil;\n\t}\n\t// Borrowed from http://stackoverflow.com/questions/2439020/wheres-the-iphone-mime-type-database\n\tCFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[path pathExtension], NULL);\n    CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);\n    CFRelease(UTI);\n\tif (!MIMEType) {\n\t\treturn @\"application/octet-stream\";\n\t}\n    return [NSMakeCollectable(MIMEType) autorelease];\n}\n\n#pragma mark bandwidth measurement / throttling\n\n- (void)performThrottling\n{\n\tif (![self readStream]) {\n\t\treturn;\n\t}\n\t[ASIHTTPRequest measureBandwidthUsage];\n\tif ([ASIHTTPRequest isBandwidthThrottled]) {\n\t\t[bandwidthThrottlingLock lock];\n\t\t// Handle throttling\n\t\tif (throttleWakeUpTime) {\n\t\t\tif ([throttleWakeUpTime timeIntervalSinceDate:[NSDate date]] > 0) {\n\t\t\t\tif ([self readStreamIsScheduled]) {\n\t\t\t\t\t[self unscheduleReadStream];\n\t\t\t\t\t#if DEBUG_THROTTLING\n\t\t\t\t\tASI_DEBUG_LOG(@\"[THROTTLING] Sleeping request %@ until after %@\",self,throttleWakeUpTime);\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (![self readStreamIsScheduled]) {\n\t\t\t\t\t[self scheduleReadStream];\n\t\t\t\t\t#if DEBUG_THROTTLING\n\t\t\t\t\tASI_DEBUG_LOG(@\"[THROTTLING] Waking up request %@\",self);\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\t\t} \n\t\t[bandwidthThrottlingLock unlock];\n\t\t\n\t// Bandwidth throttling must have been turned off since we last looked, let's re-schedule the stream\n\t} else if (![self readStreamIsScheduled]) {\n\t\t[self scheduleReadStream];\t\t\t\n\t}\n}\n\n+ (BOOL)isBandwidthThrottled\n{\n#if TARGET_OS_IPHONE\n\t[bandwidthThrottlingLock lock];\n\n\tBOOL throttle = isBandwidthThrottled || (!shouldThrottleBandwidthForWWANOnly && (maxBandwidthPerSecond > 0));\n\t[bandwidthThrottlingLock unlock];\n\treturn throttle;\n#else\n\t[bandwidthThrottlingLock lock];\n\tBOOL throttle = (maxBandwidthPerSecond > 0);\n\t[bandwidthThrottlingLock unlock];\n\treturn throttle;\n#endif\n}\n\n+ (unsigned long)maxBandwidthPerSecond\n{\n\t[bandwidthThrottlingLock lock];\n\tunsigned long amount = maxBandwidthPerSecond;\n\t[bandwidthThrottlingLock unlock];\n\treturn amount;\n}\n\n+ (void)setMaxBandwidthPerSecond:(unsigned long)bytes\n{\n\t[bandwidthThrottlingLock lock];\n\tmaxBandwidthPerSecond = bytes;\n\t[bandwidthThrottlingLock unlock];\n}\n\n+ (void)incrementBandwidthUsedInLastSecond:(unsigned long)bytes\n{\n\t[bandwidthThrottlingLock lock];\n\tbandwidthUsedInLastSecond += bytes;\n\t[bandwidthThrottlingLock unlock];\n}\n\n+ (void)recordBandwidthUsage\n{\n\tif (bandwidthUsedInLastSecond == 0) {\n\t\t[bandwidthUsageTracker removeAllObjects];\n\t} else {\n\t\tNSTimeInterval interval = [bandwidthMeasurementDate timeIntervalSinceNow];\n\t\twhile ((interval < 0 || [bandwidthUsageTracker count] > 5) && [bandwidthUsageTracker count] > 0) {\n\t\t\t[bandwidthUsageTracker removeObjectAtIndex:0];\n\t\t\tinterval++;\n\t\t}\n\t}\n\t#if DEBUG_THROTTLING\n\tASI_DEBUG_LOG(@\"[THROTTLING] ===Used: %u bytes of bandwidth in last measurement period===\",bandwidthUsedInLastSecond);\n\t#endif\n\t[bandwidthUsageTracker addObject:[NSNumber numberWithUnsignedLong:bandwidthUsedInLastSecond]];\n\t[bandwidthMeasurementDate release];\n\tbandwidthMeasurementDate = [[NSDate dateWithTimeIntervalSinceNow:1] retain];\n\tbandwidthUsedInLastSecond = 0;\n\t\n\tNSUInteger measurements = [bandwidthUsageTracker count];\n\tunsigned long totalBytes = 0;\n\tfor (NSNumber *bytes in bandwidthUsageTracker) {\n\t\ttotalBytes += [bytes unsignedLongValue];\n\t}\n\taverageBandwidthUsedPerSecond = totalBytes/measurements;\t\t\n}\n\n+ (unsigned long)averageBandwidthUsedPerSecond\n{\n\t[bandwidthThrottlingLock lock];\n\tunsigned long amount = \taverageBandwidthUsedPerSecond;\n\t[bandwidthThrottlingLock unlock];\n\treturn amount;\n}\n\n+ (void)measureBandwidthUsage\n{\n\t// Other requests may have to wait for this lock if we're sleeping, but this is fine, since in that case we already know they shouldn't be sending or receiving data\n\t[bandwidthThrottlingLock lock];\n\n\tif (!bandwidthMeasurementDate || [bandwidthMeasurementDate timeIntervalSinceNow] < -0) {\n\t\t[ASIHTTPRequest recordBandwidthUsage];\n\t}\n\t\n\t// Are we performing bandwidth throttling?\n\tif (\n\t#if TARGET_OS_IPHONE\n\tisBandwidthThrottled || (!shouldThrottleBandwidthForWWANOnly && (maxBandwidthPerSecond))\n\t#else\n\tmaxBandwidthPerSecond\n\t#endif\n\t) {\n\t\t// How much data can we still send or receive this second?\n\t\tlong long bytesRemaining = (long long)maxBandwidthPerSecond - (long long)bandwidthUsedInLastSecond;\n\t\t\t\n\t\t// Have we used up our allowance?\n\t\tif (bytesRemaining < 0) {\n\t\t\t\n\t\t\t// Yes, put this request to sleep until a second is up, with extra added punishment sleeping time for being very naughty (we have used more bandwidth than we were allowed)\n\t\t\tdouble extraSleepyTime = (-bytesRemaining/(maxBandwidthPerSecond*1.0));\n\t\t\t[throttleWakeUpTime release];\n\t\t\tthrottleWakeUpTime = [[NSDate alloc] initWithTimeInterval:extraSleepyTime sinceDate:bandwidthMeasurementDate];\n\t\t}\n\t}\n\t[bandwidthThrottlingLock unlock];\n}\n\t\n+ (unsigned long)maxUploadReadLength\n{\n\t[bandwidthThrottlingLock lock];\n\t\n\t// We'll split our bandwidth allowance into 4 (which is the default for an ASINetworkQueue's max concurrent operations count) to give all running requests a fighting chance of reading data this cycle\n\tlong long toRead = maxBandwidthPerSecond/4;\n\tif (maxBandwidthPerSecond > 0 && (bandwidthUsedInLastSecond + toRead > maxBandwidthPerSecond)) {\n\t\ttoRead = (long long)maxBandwidthPerSecond-(long long)bandwidthUsedInLastSecond;\n\t\tif (toRead < 0) {\n\t\t\ttoRead = 0;\n\t\t}\n\t}\n\t\n\tif (toRead == 0 || !bandwidthMeasurementDate || [bandwidthMeasurementDate timeIntervalSinceNow] < -0) {\n\t\t[throttleWakeUpTime release];\n\t\tthrottleWakeUpTime = [bandwidthMeasurementDate retain];\n\t}\n\t[bandwidthThrottlingLock unlock];\t\n\treturn (unsigned long)toRead;\n}\n\t\n\n#if TARGET_OS_IPHONE\n+ (void)setShouldThrottleBandwidthForWWAN:(BOOL)throttle\n{\n\tif (throttle) {\n\t\t[ASIHTTPRequest throttleBandwidthForWWANUsingLimit:ASIWWANBandwidthThrottleAmount];\n\t} else {\n\t\t[ASIHTTPRequest unsubscribeFromNetworkReachabilityNotifications];\n\t\t[ASIHTTPRequest setMaxBandwidthPerSecond:0];\n\t\t[bandwidthThrottlingLock lock];\n\t\tisBandwidthThrottled = NO;\n\t\tshouldThrottleBandwidthForWWANOnly = NO;\n\t\t[bandwidthThrottlingLock unlock];\n\t}\n}\n\n+ (void)throttleBandwidthForWWANUsingLimit:(unsigned long)limit\n{\t\n\t[bandwidthThrottlingLock lock];\n\tshouldThrottleBandwidthForWWANOnly = YES;\n\tmaxBandwidthPerSecond = limit;\n\t[ASIHTTPRequest registerForNetworkReachabilityNotifications];\t\n\t[bandwidthThrottlingLock unlock];\n\t[ASIHTTPRequest reachabilityChanged:nil];\n}\n\n#pragma mark reachability\n\n+ (void)registerForNetworkReachabilityNotifications\n{\n\t[[Reachability reachabilityForInternetConnection] startNotifier];\n\t[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];\n}\n\n\n+ (void)unsubscribeFromNetworkReachabilityNotifications\n{\n\t[[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];\n}\n\n+ (BOOL)isNetworkReachableViaWWAN\n{\n\treturn ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == ReachableViaWWAN);\t\n}\n\n+ (void)reachabilityChanged:(NSNotification *)note\n{\n\t[bandwidthThrottlingLock lock];\n\tisBandwidthThrottled = [ASIHTTPRequest isNetworkReachableViaWWAN];\n\t[bandwidthThrottlingLock unlock];\n}\n#endif\n\n#pragma mark queue\n\n// Returns the shared queue\n+ (NSOperationQueue *)sharedQueue\n{\n    return [[sharedQueue retain] autorelease];\n}\n\n#pragma mark cache\n\n+ (void)setDefaultCache:(id <ASICacheDelegate>)cache\n{\n\t@synchronized (self) {\n\t\t[cache retain];\n\t\t[defaultCache release];\n\t\tdefaultCache = cache;\n\t}\n}\n\n+ (id <ASICacheDelegate>)defaultCache\n{\n    @synchronized(self) {\n        return [[defaultCache retain] autorelease];\n    }\n\treturn nil;\n}\n\n\n#pragma mark network activity\n\n+ (BOOL)isNetworkInUse\n{\n\t[connectionsLock lock];\n\tBOOL inUse = (runningRequestCount > 0);\n\t[connectionsLock unlock];\n\treturn inUse;\n}\n\n+ (void)setShouldUpdateNetworkActivityIndicator:(BOOL)shouldUpdate\n{\n\t[connectionsLock lock];\n\tshouldUpdateNetworkActivityIndicator = shouldUpdate;\n\t[connectionsLock unlock];\n}\n\n+ (void)showNetworkActivityIndicator\n{\n#if TARGET_OS_IPHONE\n\t[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];\n#endif\n}\n\n+ (void)hideNetworkActivityIndicator\n{\n#if TARGET_OS_IPHONE\n\t[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];\t\n#endif\n}\n\n\n/* Always called on main thread */\n+ (void)hideNetworkActivityIndicatorAfterDelay\n{\n\t[self performSelector:@selector(hideNetworkActivityIndicatorIfNeeeded) withObject:nil afterDelay:0.5];\n}\n\n+ (void)hideNetworkActivityIndicatorIfNeeeded\n{\n\t[connectionsLock lock];\n\tif (runningRequestCount == 0) {\n\t\t[self hideNetworkActivityIndicator];\n\t}\n\t[connectionsLock unlock];\n}\n\n\n#pragma mark threading behaviour\n\n// In the default implementation, all requests run in a single background thread\n// Advanced users only: Override this method in a subclass for a different threading behaviour\n// Eg: return [NSThread mainThread] to run all requests in the main thread\n// Alternatively, you can create a thread on demand, or manage a pool of threads\n// Threads returned by this method will need to run the runloop in default mode (eg CFRunLoopRun())\n// Requests will stop the runloop when they complete\n// If you have multiple requests sharing the thread or you want to re-use the thread, you'll need to restart the runloop\n+ (NSThread *)threadForRequest:(ASIHTTPRequest *)request\n{\n\tif (networkThread == nil) {\n\t\t@synchronized(self) {\n\t\t\tif (networkThread == nil) {\n\t\t\t\tnetworkThread = [[NSThread alloc] initWithTarget:self selector:@selector(runRequests) object:nil];\n\t\t\t\t[networkThread start];\n\t\t\t}\n\t\t}\n\t}\n\treturn networkThread;\n}\n\n+ (void)runRequests\n{\n\t// Should keep the runloop from exiting\n\tCFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};\n\tCFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);\n\tCFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);\n\n    BOOL runAlways = YES; // Introduced to cheat Static Analyzer\n\twhile (runAlways) {\n\t\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\n\t\tCFRunLoopRun();\n\t\t[pool drain];\n\t}\n\n\t// Should never be called, but anyway\n\tCFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);\n\tCFRelease(source);\n}\n\n#pragma mark miscellany \n\n#if TARGET_OS_IPHONE\n+ (BOOL)isMultitaskingSupported\n{\n\tBOOL multiTaskingSupported = NO;\n\tif ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {\n\t\tmultiTaskingSupported = [(id)[UIDevice currentDevice] isMultitaskingSupported];\n\t}\n\treturn multiTaskingSupported;\n}\n#endif\n\n// From: http://www.cocoadev.com/index.pl?BaseSixtyFour\n\n+ (NSString*)base64forData:(NSData*)theData {\n\t\n\tconst uint8_t* input = (const uint8_t*)[theData bytes];\n\tNSInteger length = [theData length];\n\t\n    static char table[] = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\t\n    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];\n    uint8_t* output = (uint8_t*)data.mutableBytes;\n\t\n\tNSInteger i,i2;\n    for (i=0; i < length; i += 3) {\n        NSInteger value = 0;\n\t\tfor (i2=0; i2<3; i2++) {\n            value <<= 8;\n            if (i+i2 < length) {\n                value |= (0xFF & input[i+i2]);\n            }\n        }\n\t\t\n        NSInteger theIndex = (i / 3) * 4;\n        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];\n        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];\n        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';\n        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';\n    }\n\t\n    return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];\n}\n\n+ (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge\n{\n\tNSDictionary *responseHeaders = [request responseHeaders];\n  \n\t// If we weren't given a custom max-age, lets look for one in the response headers\n\tif (!maxAge) {\n\t\tNSString *cacheControl = [[responseHeaders objectForKey:@\"Cache-Control\"] lowercaseString];\n\t\tif (cacheControl) {\n\t\t\tNSScanner *scanner = [NSScanner scannerWithString:cacheControl];\n\t\t\t[scanner scanUpToString:@\"max-age\" intoString:NULL];\n\t\t\tif ([scanner scanString:@\"max-age\" intoString:NULL]) {\n\t\t\t\t[scanner scanString:@\"=\" intoString:NULL];\n\t\t\t\t[scanner scanDouble:&maxAge];\n\t\t\t}\n\t\t}\n\t}\n  \n\t// RFC 2612 says max-age must override any Expires header\n\tif (maxAge) {\n\t\treturn [[NSDate date] addTimeInterval:maxAge];\n\t} else {\n\t\tNSString *expires = [responseHeaders objectForKey:@\"Expires\"];\n\t\tif (expires) {\n\t\t\treturn [ASIHTTPRequest dateFromRFC1123String:expires];\n\t\t}\n\t}\n\treturn nil;\n}\n\n// Based on hints from http://stackoverflow.com/questions/1850824/parsing-a-rfc-822-date-with-nsdateformatter\n+ (NSDate *)dateFromRFC1123String:(NSString *)string\n{\n\tNSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];\n\t[formatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"] autorelease]];\n\t// Does the string include a week day?\n\tNSString *day = @\"\";\n\tif ([string rangeOfString:@\",\"].location != NSNotFound) {\n\t\tday = @\"EEE, \";\n\t}\n\t// Does the string include seconds?\n\tNSString *seconds = @\"\";\n\tif ([[string componentsSeparatedByString:@\":\"] count] == 3) {\n\t\tseconds = @\":ss\";\n\t}\n\t[formatter setDateFormat:[NSString stringWithFormat:@\"%@dd MMM yyyy HH:mm%@ z\",day,seconds]];\n\treturn [formatter dateFromString:string];\n}\n\n+ (void)parseMimeType:(NSString **)mimeType andResponseEncoding:(NSStringEncoding *)stringEncoding fromContentType:(NSString *)contentType\n{\n\tif (!contentType) {\n\t\treturn;\n\t}\n\tNSScanner *charsetScanner = [NSScanner scannerWithString: contentType];\n\tif (![charsetScanner scanUpToString:@\";\" intoString:mimeType] || [charsetScanner scanLocation] == [contentType length]) {\n\t\t*mimeType = [contentType stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];\n\t\treturn;\n\t}\n\t*mimeType = [*mimeType stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];\n\tNSString *charsetSeparator = @\"charset=\";\n\tNSString *IANAEncoding = nil;\n\n\tif ([charsetScanner scanUpToString: charsetSeparator intoString: NULL] && [charsetScanner scanLocation] < [contentType length]) {\n\t\t[charsetScanner setScanLocation: [charsetScanner scanLocation] + [charsetSeparator length]];\n\t\t[charsetScanner scanUpToString: @\";\" intoString: &IANAEncoding];\n\t}\n\n\tif (IANAEncoding) {\n\t\tCFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)IANAEncoding);\n\t\tif (cfEncoding != kCFStringEncodingInvalidId) {\n\t\t\t*stringEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);\n\t\t}\n\t}\n}\n\n#pragma mark -\n#pragma mark blocks\n#if NS_BLOCKS_AVAILABLE\n- (void)setStartedBlock:(ASIBasicBlock)aStartedBlock\n{\n\t[startedBlock release];\n\tstartedBlock = [aStartedBlock copy];\n}\n\n- (void)setHeadersReceivedBlock:(ASIHeadersBlock)aReceivedBlock\n{\n\t[headersReceivedBlock release];\n\theadersReceivedBlock = [aReceivedBlock copy];\n}\n\n- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock\n{\n\t[completionBlock release];\n\tcompletionBlock = [aCompletionBlock copy];\n}\n\n- (void)setFailedBlock:(ASIBasicBlock)aFailedBlock\n{\n\t[failureBlock release];\n\tfailureBlock = [aFailedBlock copy];\n}\n\n- (void)setBytesReceivedBlock:(ASIProgressBlock)aBytesReceivedBlock\n{\n\t[bytesReceivedBlock release];\n\tbytesReceivedBlock = [aBytesReceivedBlock copy];\n}\n\n- (void)setBytesSentBlock:(ASIProgressBlock)aBytesSentBlock\n{\n\t[bytesSentBlock release];\n\tbytesSentBlock = [aBytesSentBlock copy];\n}\n\n- (void)setDownloadSizeIncrementedBlock:(ASISizeBlock)aDownloadSizeIncrementedBlock{\n\t[downloadSizeIncrementedBlock release];\n\tdownloadSizeIncrementedBlock = [aDownloadSizeIncrementedBlock copy];\n}\n\n- (void)setUploadSizeIncrementedBlock:(ASISizeBlock)anUploadSizeIncrementedBlock\n{\n\t[uploadSizeIncrementedBlock release];\n\tuploadSizeIncrementedBlock = [anUploadSizeIncrementedBlock copy];\n}\n\n- (void)setDataReceivedBlock:(ASIDataBlock)aReceivedBlock\n{\n\t[dataReceivedBlock release];\n\tdataReceivedBlock = [aReceivedBlock copy];\n}\n\n- (void)setAuthenticationNeededBlock:(ASIBasicBlock)anAuthenticationBlock\n{\n\t[authenticationNeededBlock release];\n\tauthenticationNeededBlock = [anAuthenticationBlock copy];\n}\n- (void)setProxyAuthenticationNeededBlock:(ASIBasicBlock)aProxyAuthenticationBlock\n{\n\t[proxyAuthenticationNeededBlock release];\n\tproxyAuthenticationNeededBlock = [aProxyAuthenticationBlock copy];\n}\n- (void)setRequestRedirectedBlock:(ASIBasicBlock)aRedirectBlock\n{\n\t[requestRedirectedBlock release];\n\trequestRedirectedBlock = [aRedirectBlock copy];\n}\n#endif\n\n#pragma mark ===\n\n@synthesize username;\n@synthesize password;\n@synthesize userAgent;\n@synthesize domain;\n@synthesize proxyUsername;\n@synthesize proxyPassword;\n@synthesize proxyDomain;\n@synthesize url;\n@synthesize originalURL;\n@synthesize delegate;\n@synthesize queue;\n@synthesize uploadProgressDelegate;\n@synthesize downloadProgressDelegate;\n@synthesize useKeychainPersistence;\n@synthesize useSessionPersistence;\n@synthesize useCookiePersistence;\n@synthesize downloadDestinationPath;\n@synthesize temporaryFileDownloadPath;\n@synthesize temporaryUncompressedDataDownloadPath;\n@synthesize didStartSelector;\n@synthesize didReceiveResponseHeadersSelector;\n@synthesize willRedirectSelector;\n@synthesize didFinishSelector;\n@synthesize didFailSelector;\n@synthesize didReceiveDataSelector;\n@synthesize authenticationRealm;\n@synthesize proxyAuthenticationRealm;\n@synthesize error;\n@synthesize complete;\n@synthesize requestHeaders;\n@synthesize responseHeaders;\n@synthesize responseCookies;\n@synthesize requestCookies;\n@synthesize requestCredentials;\n@synthesize responseStatusCode;\n@synthesize rawResponseData;\n@synthesize lastActivityTime;\n@synthesize timeOutSeconds;\n@synthesize requestMethod;\n@synthesize postBody;\n@synthesize compressedPostBody;\n@synthesize contentLength;\n@synthesize partialDownloadSize;\n@synthesize postLength;\n@synthesize shouldResetDownloadProgress;\n@synthesize shouldResetUploadProgress;\n@synthesize mainRequest;\n@synthesize totalBytesRead;\n@synthesize totalBytesSent;\n@synthesize showAccurateProgress;\n@synthesize uploadBufferSize;\n@synthesize defaultResponseEncoding;\n@synthesize responseEncoding;\n@synthesize allowCompressedResponse;\n@synthesize allowResumeForFileDownloads;\n@synthesize userInfo;\n@synthesize tag;\n@synthesize postBodyFilePath;\n@synthesize compressedPostBodyFilePath;\n@synthesize postBodyWriteStream;\n@synthesize postBodyReadStream;\n@synthesize shouldStreamPostDataFromDisk;\n@synthesize didCreateTemporaryPostDataFile;\n@synthesize useHTTPVersionOne;\n@synthesize lastBytesRead;\n@synthesize lastBytesSent;\n@synthesize cancelledLock;\n@synthesize haveBuiltPostBody;\n@synthesize fileDownloadOutputStream;\n@synthesize inflatedFileDownloadOutputStream;\n@synthesize authenticationRetryCount;\n@synthesize proxyAuthenticationRetryCount;\n@synthesize updatedProgress;\n@synthesize shouldRedirect;\n@synthesize validatesSecureCertificate;\n@synthesize needsRedirect;\n@synthesize redirectCount;\n@synthesize shouldCompressRequestBody;\n@synthesize proxyCredentials;\n@synthesize proxyHost;\n@synthesize proxyPort;\n@synthesize proxyType;\n@synthesize PACurl;\n@synthesize authenticationScheme;\n@synthesize proxyAuthenticationScheme;\n@synthesize shouldPresentAuthenticationDialog;\n@synthesize shouldPresentProxyAuthenticationDialog;\n@synthesize authenticationNeeded;\n@synthesize responseStatusMessage;\n@synthesize shouldPresentCredentialsBeforeChallenge;\n@synthesize haveBuiltRequestHeaders;\n@synthesize inProgress;\n@synthesize numberOfTimesToRetryOnTimeout;\n@synthesize retryCount;\n@synthesize willRetryRequest;\n@synthesize shouldAttemptPersistentConnection;\n@synthesize persistentConnectionTimeoutSeconds;\n@synthesize connectionCanBeReused;\n@synthesize connectionInfo;\n@synthesize readStream;\n@synthesize readStreamIsScheduled;\n@synthesize shouldUseRFC2616RedirectBehaviour;\n@synthesize downloadComplete;\n@synthesize requestID;\n@synthesize runLoopMode;\n@synthesize statusTimer;\n@synthesize downloadCache;\n@synthesize cachePolicy;\n@synthesize cacheStoragePolicy;\n@synthesize didUseCachedResponse;\n@synthesize secondsToCache;\n@synthesize clientCertificates;\n@synthesize redirectURL;\n#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n@synthesize shouldContinueWhenAppEntersBackground;\n#endif\n@synthesize dataDecompressor;\n@synthesize shouldWaitToInflateCompressedResponses;\n\n@synthesize isPACFileRequest;\n@synthesize PACFileRequest;\n@synthesize PACFileReadStream;\n@synthesize PACFileData;\n\n@synthesize isSynchronous;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIHTTPRequestConfig.h",
    "content": "//\n//  ASIHTTPRequestConfig.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 14/12/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n\n// ======\n// Debug output configuration options\n// ======\n\n// If defined will use the specified function for debug logging\n// Otherwise use NSLog\n#ifndef ASI_DEBUG_LOG\n    #define ASI_DEBUG_LOG NSLog\n#endif\n\n// When set to 1 ASIHTTPRequests will print information about what a request is doing\n#ifndef DEBUG_REQUEST_STATUS\n\t#define DEBUG_REQUEST_STATUS 0\n#endif\n\n// When set to 1, ASIFormDataRequests will print information about the request body to the console\n#ifndef DEBUG_FORM_DATA_REQUEST\n\t#define DEBUG_FORM_DATA_REQUEST 0\n#endif\n\n// When set to 1, ASIHTTPRequests will print information about bandwidth throttling to the console\n#ifndef DEBUG_THROTTLING\n\t#define DEBUG_THROTTLING 0\n#endif\n\n// When set to 1, ASIHTTPRequests will print information about persistent connections to the console\n#ifndef DEBUG_PERSISTENT_CONNECTIONS\n\t#define DEBUG_PERSISTENT_CONNECTIONS 0\n#endif\n\n// When set to 1, ASIHTTPRequests will print information about HTTP authentication (Basic, Digest or NTLM) to the console\n#ifndef DEBUG_HTTP_AUTHENTICATION\n    #define DEBUG_HTTP_AUTHENTICATION 0\n#endif\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIHTTPRequestDelegate.h",
    "content": "//\n//  ASIHTTPRequestDelegate.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 13/04/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n@class ASIHTTPRequest;\n\n@protocol ASIHTTPRequestDelegate <NSObject>\n\n@optional\n\n// These are the default delegate methods for request status\n// You can use different ones by setting didStartSelector / didFinishSelector / didFailSelector\n- (void)requestStarted:(ASIHTTPRequest *)request;\n- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders;\n- (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL;\n- (void)requestFinished:(ASIHTTPRequest *)request;\n- (void)requestFailed:(ASIHTTPRequest *)request;\n- (void)requestRedirected:(ASIHTTPRequest *)request;\n\n// When a delegate implements this method, it is expected to process all incoming data itself\n// This means that responseData / responseString / downloadDestinationPath etc are ignored\n// You can have the request call a different method by setting didReceiveDataSelector\n- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;\n\n// If a delegate implements one of these, it will be asked to supply credentials when none are available\n// The delegate can then either restart the request ([request retryUsingSuppliedCredentials]) once credentials have been set\n// or cancel it ([request cancelAuthentication])\n- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;\n- (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIInputStream.h",
    "content": "//\n//  ASIInputStream.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 10/08/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@class ASIHTTPRequest;\n\n// This is a wrapper for NSInputStream that pretends to be an NSInputStream itself\n// Subclassing NSInputStream seems to be tricky, and may involve overriding undocumented methods, so we'll cheat instead.\n// It is used by ASIHTTPRequest whenever we have a request body, and handles measuring and throttling the bandwidth used for uploading\n\n@interface ASIInputStream : NSObject {\n\tNSInputStream *stream;\n\tASIHTTPRequest *request;\n}\n+ (id)inputStreamWithFileAtPath:(NSString *)path request:(ASIHTTPRequest *)request;\n+ (id)inputStreamWithData:(NSData *)data request:(ASIHTTPRequest *)request;\n\n@property (retain, nonatomic) NSInputStream *stream;\n@property (assign, nonatomic) ASIHTTPRequest *request;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIInputStream.m",
    "content": "//\n//  ASIInputStream.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 10/08/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIInputStream.h\"\n#import \"ASIHTTPRequest.h\"\n\n// Used to ensure only one request can read data at once\nstatic NSLock *readLock = nil;\n\n@implementation ASIInputStream\n\n+ (void)initialize\n{\n\tif (self == [ASIInputStream class]) {\n\t\treadLock = [[NSLock alloc] init];\n\t}\n}\n\n+ (id)inputStreamWithFileAtPath:(NSString *)path request:(ASIHTTPRequest *)theRequest\n{\n\tASIInputStream *theStream = [[[self alloc] init] autorelease];\n\t[theStream setRequest:theRequest];\n\t[theStream setStream:[NSInputStream inputStreamWithFileAtPath:path]];\n\treturn theStream;\n}\n\n+ (id)inputStreamWithData:(NSData *)data request:(ASIHTTPRequest *)theRequest\n{\n\tASIInputStream *theStream = [[[self alloc] init] autorelease];\n\t[theStream setRequest:theRequest];\n\t[theStream setStream:[NSInputStream inputStreamWithData:data]];\n\treturn theStream;\n}\n\n- (void)dealloc\n{\n\t[stream release];\n\t[super dealloc];\n}\n\n// Called when CFNetwork wants to read more of our request body\n// When throttling is on, we ask ASIHTTPRequest for the maximum amount of data we can read\n- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len\n{\n\t[readLock lock];\n\tunsigned long toRead = len;\n\tif ([ASIHTTPRequest isBandwidthThrottled]) {\n\t\ttoRead = [ASIHTTPRequest maxUploadReadLength];\n\t\tif (toRead > len) {\n\t\t\ttoRead = len;\n\t\t} else if (toRead == 0) {\n\t\t\ttoRead = 1;\n\t\t}\n\t\t[request performThrottling];\n\t}\n\t[readLock unlock];\n\tNSInteger rv = [stream read:buffer maxLength:toRead];\n\tif (rv > 0)\n\t\t[ASIHTTPRequest incrementBandwidthUsedInLastSecond:rv];\n\treturn rv;\n}\n\n/*\n * Implement NSInputStream mandatory methods to make sure they are implemented\n * (necessary for MacRuby for example) and avoid the overhead of method\n * forwarding for these common methods.\n */\n- (void)open\n{\n    [stream open];\n}\n\n- (void)close\n{\n    [stream close];\n}\n\n- (id)delegate\n{\n    return [stream delegate];\n}\n\n- (void)setDelegate:(id)delegate\n{\n    [stream setDelegate:delegate];\n}\n\n- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode\n{\n    [stream scheduleInRunLoop:aRunLoop forMode:mode];\n}\n\n- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode\n{\n    [stream removeFromRunLoop:aRunLoop forMode:mode];\n}\n\n- (id)propertyForKey:(NSString *)key\n{\n    return [stream propertyForKey:key];\n}\n\n- (BOOL)setProperty:(id)property forKey:(NSString *)key\n{\n    return [stream setProperty:property forKey:key];\n}\n\n- (NSStreamStatus)streamStatus\n{\n    return [stream streamStatus];\n}\n\n- (NSError *)streamError\n{\n    return [stream streamError];\n}\n\n// If we get asked to perform a method we don't have (probably internal ones),\n// we'll just forward the message to our stream\n\n- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector\n{\n\treturn [stream methodSignatureForSelector:aSelector];\n}\n\t \n- (void)forwardInvocation:(NSInvocation *)anInvocation\n{\n\t[anInvocation invokeWithTarget:stream];\n}\n\n@synthesize stream;\n@synthesize request;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASINetworkQueue.h",
    "content": "//\n//  ASINetworkQueue.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 07/11/2008.\n//  Copyright 2008-2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"ASIHTTPRequestDelegate.h\"\n#import \"ASIProgressDelegate.h\"\n\n@interface ASINetworkQueue : NSOperationQueue <ASIProgressDelegate, ASIHTTPRequestDelegate, NSCopying> {\n\t\n\t// Delegate will get didFail + didFinish messages (if set)\n\tid delegate;\n\n\t// Will be called when a request starts with the request as the argument\n\tSEL requestDidStartSelector;\n\t\n\t// Will be called when a request receives response headers\n\t// Should take the form request:didRecieveResponseHeaders:, where the first argument is the request, and the second the headers dictionary\n\tSEL requestDidReceiveResponseHeadersSelector;\n\t\n\t// Will be called when a request is about to redirect\n\t// Should take the form request:willRedirectToURL:, where the first argument is the request, and the second the new url\n\tSEL requestWillRedirectSelector;\n\n\t// Will be called when a request completes with the request as the argument\n\tSEL requestDidFinishSelector;\n\t\n\t// Will be called when a request fails with the request as the argument\n\tSEL requestDidFailSelector;\n\t\n\t// Will be called when the queue finishes with the queue as the argument\n\tSEL queueDidFinishSelector;\n\t\n\t// Upload progress indicator, probably an NSProgressIndicator or UIProgressView\n\tid uploadProgressDelegate;\n\t\n\t// Total amount uploaded so far for all requests in this queue\n\tunsigned long long bytesUploadedSoFar;\n\t\n\t// Total amount to be uploaded for all requests in this queue - requests add to this figure as they work out how much data they have to transmit\n\tunsigned long long totalBytesToUpload;\n\n\t// Download progress indicator, probably an NSProgressIndicator or UIProgressView\n\tid downloadProgressDelegate;\n\t\n\t// Total amount downloaded so far for all requests in this queue\n\tunsigned long long bytesDownloadedSoFar;\n\t\n\t// Total amount to be downloaded for all requests in this queue - requests add to this figure as they receive Content-Length headers\n\tunsigned long long totalBytesToDownload;\n\t\n\t// When YES, the queue will cancel all requests when a request fails. Default is YES\n\tBOOL shouldCancelAllRequestsOnFailure;\n\t\n\t//Number of real requests (excludes HEAD requests created to manage showAccurateProgress)\n\tint requestsCount;\n\t\n\t// When NO, this request will only update the progress indicator when it completes\n\t// When YES, this request will update the progress indicator according to how much data it has received so far\n\t// When YES, the queue will first perform HEAD requests for all GET requests in the queue, so it can calculate the total download size before it starts\n\t// NO means better performance, because it skips this step for GET requests, and it won't waste time updating the progress indicator until a request completes \n\t// Set to YES if the size of a requests in the queue varies greatly for much more accurate results\n\t// Default for requests in the queue is NO\n\tBOOL showAccurateProgress;\n\n\t// Storage container for additional queue information.\n\tNSDictionary *userInfo;\n\t\n}\n\n// Convenience constructor\n+ (id)queue;\n\n// Call this to reset a queue - it will cancel all operations, clear delegates, and suspend operation\n- (void)reset;\n\n// Used internally to manage HEAD requests when showAccurateProgress is YES, do not use!\n- (void)addHEADOperation:(NSOperation *)operation;\n\n// All ASINetworkQueues are paused when created so that total size can be calculated before the queue starts\n// This method will start the queue\n- (void)go;\n\n@property (assign, nonatomic, setter=setUploadProgressDelegate:) id uploadProgressDelegate;\n@property (assign, nonatomic, setter=setDownloadProgressDelegate:) id downloadProgressDelegate;\n\n@property (assign) SEL requestDidStartSelector;\n@property (assign) SEL requestDidReceiveResponseHeadersSelector;\n@property (assign) SEL requestWillRedirectSelector;\n@property (assign) SEL requestDidFinishSelector;\n@property (assign) SEL requestDidFailSelector;\n@property (assign) SEL queueDidFinishSelector;\n@property (assign) BOOL shouldCancelAllRequestsOnFailure;\n@property (assign) id delegate;\n@property (assign) BOOL showAccurateProgress;\n@property (assign, readonly) int requestsCount;\n@property (retain) NSDictionary *userInfo;\n\n@property (assign) unsigned long long bytesUploadedSoFar;\n@property (assign) unsigned long long totalBytesToUpload;\n@property (assign) unsigned long long bytesDownloadedSoFar;\n@property (assign) unsigned long long totalBytesToDownload;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASINetworkQueue.m",
    "content": "//\n//  ASINetworkQueue.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 07/11/2008.\n//  Copyright 2008-2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASINetworkQueue.h\"\n#import \"ASIHTTPRequest.h\"\n\n// Private stuff\n@interface ASINetworkQueue ()\n\t- (void)resetProgressDelegate:(id *)progressDelegate;\n\t@property (assign) int requestsCount;\n@end\n\n@implementation ASINetworkQueue\n\n- (id)init\n{\n\tself = [super init];\n\t[self setShouldCancelAllRequestsOnFailure:YES];\n\t[self setMaxConcurrentOperationCount:4];\n\t[self setSuspended:YES];\n\t\n\treturn self;\n}\n\n+ (id)queue\n{\n\treturn [[[self alloc] init] autorelease];\n}\n\n- (void)dealloc\n{\n\t//We need to clear the queue on any requests that haven't got around to cleaning up yet, as otherwise they'll try to let us know if something goes wrong, and we'll be long gone by then\n\tfor (ASIHTTPRequest *request in [self operations]) {\n\t\t[request setQueue:nil];\n\t}\n\t[userInfo release];\n\t[super dealloc];\n}\n\n- (void)setSuspended:(BOOL)suspend\n{\n\t[super setSuspended:suspend];\n}\n\n- (void)reset\n{\n\t[self cancelAllOperations];\n\t[self setDelegate:nil];\n\t[self setDownloadProgressDelegate:nil];\n\t[self setUploadProgressDelegate:nil];\n\t[self setRequestDidStartSelector:NULL];\n\t[self setRequestDidReceiveResponseHeadersSelector:NULL];\n\t[self setRequestDidFailSelector:NULL];\n\t[self setRequestDidFinishSelector:NULL];\n\t[self setQueueDidFinishSelector:NULL];\n\t[self setSuspended:YES];\n}\n\n\n- (void)go\n{\n\t[self setSuspended:NO];\n}\n\n- (void)cancelAllOperations\n{\n\t[self setBytesUploadedSoFar:0];\n\t[self setTotalBytesToUpload:0];\n\t[self setBytesDownloadedSoFar:0];\n\t[self setTotalBytesToDownload:0];\n\t[super cancelAllOperations];\n}\n\n- (void)setUploadProgressDelegate:(id)newDelegate\n{\n\tuploadProgressDelegate = newDelegate;\n\t[self resetProgressDelegate:&uploadProgressDelegate];\n\n}\n\n- (void)setDownloadProgressDelegate:(id)newDelegate\n{\n\tdownloadProgressDelegate = newDelegate;\n\t[self resetProgressDelegate:&downloadProgressDelegate];\n}\n\n- (void)resetProgressDelegate:(id *)progressDelegate\n{\n#if !TARGET_OS_IPHONE\n\t// If the uploadProgressDelegate is an NSProgressIndicator, we set its MaxValue to 1.0 so we can treat it similarly to UIProgressViews\n\tSEL selector = @selector(setMaxValue:);\n\tif ([*progressDelegate respondsToSelector:selector]) {\n\t\tdouble max = 1.0;\n\t\t[ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&max callerToRetain:nil];\n\t}\n\tselector = @selector(setDoubleValue:);\n\tif ([*progressDelegate respondsToSelector:selector]) {\n\t\tdouble value = 0.0;\n\t\t[ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value callerToRetain:nil];\n\t}\n#else\n\tSEL selector = @selector(setProgress:);\n\tif ([*progressDelegate respondsToSelector:selector]) {\n\t\tfloat value = 0.0f;\n\t\t[ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value callerToRetain:nil];\n\t}\n#endif\n}\n\n- (void)addHEADOperation:(NSOperation *)operation\n{\n\tif ([operation isKindOfClass:[ASIHTTPRequest class]]) {\n\t\t\n\t\tASIHTTPRequest *request = (ASIHTTPRequest *)operation;\n\t\t[request setRequestMethod:@\"HEAD\"];\n\t\t[request setQueuePriority:10];\n\t\t[request setShowAccurateProgress:YES];\n\t\t[request setQueue:self];\n\t\t\n\t\t// Important - we are calling NSOperation's add method - we don't want to add this as a normal request!\n\t\t[super addOperation:request];\n\t}\n}\n\n// Only add ASIHTTPRequests to this queue!!\n- (void)addOperation:(NSOperation *)operation\n{\n\tif (![operation isKindOfClass:[ASIHTTPRequest class]]) {\n\t\t[NSException raise:@\"AttemptToAddInvalidRequest\" format:@\"Attempted to add an object that was not an ASIHTTPRequest to an ASINetworkQueue\"];\n\t}\n\t\t\n\t[self setRequestsCount:[self requestsCount]+1];\n\t\n\tASIHTTPRequest *request = (ASIHTTPRequest *)operation;\n\t\n\tif ([self showAccurateProgress]) {\n\t\t\n\t\t// Force the request to build its body (this may change requestMethod)\n\t\t[request buildPostBody];\n\t\t\n\t\t// If this is a GET request and we want accurate progress, perform a HEAD request first to get the content-length\n\t\t// We'll only do this before the queue is started\n\t\t// If requests are added after the queue is started they will probably move the overall progress backwards anyway, so there's no value performing the HEAD requests first\n\t\t// Instead, they'll update the total progress if and when they receive a content-length header\n\t\tif ([[request requestMethod] isEqualToString:@\"GET\"]) {\n\t\t\tif ([self isSuspended]) {\n\t\t\t\tASIHTTPRequest *HEADRequest = [request HEADRequest];\n\t\t\t\t[self addHEADOperation:HEADRequest];\n\t\t\t\t[request addDependency:HEADRequest];\n\t\t\t\tif ([request shouldResetDownloadProgress]) {\n\t\t\t\t\t[self resetProgressDelegate:&downloadProgressDelegate];\n\t\t\t\t\t[request setShouldResetDownloadProgress:NO];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t[request buildPostBody];\n\t\t[self request:nil incrementUploadSizeBy:[request postLength]];\n\n\n\t} else {\n\t\t[self request:nil incrementDownloadSizeBy:1];\n\t\t[self request:nil incrementUploadSizeBy:1];\n\t}\n\t// Tell the request not to increment the upload size when it starts, as we've already added its length\n\tif ([request shouldResetUploadProgress]) {\n\t\t[self resetProgressDelegate:&uploadProgressDelegate];\n\t\t[request setShouldResetUploadProgress:NO];\n\t}\n\t\n\t[request setShowAccurateProgress:[self showAccurateProgress]];\n\t\n\t[request setQueue:self];\n\t[super addOperation:request];\n\n}\n\n- (void)requestStarted:(ASIHTTPRequest *)request\n{\n\tif ([self requestDidStartSelector]) {\n\t\t[[self delegate] performSelector:[self requestDidStartSelector] withObject:request];\n\t}\n}\n\n- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders\n{\n\tif ([self requestDidReceiveResponseHeadersSelector]) {\n\t\t[[self delegate] performSelector:[self requestDidReceiveResponseHeadersSelector] withObject:request withObject:responseHeaders];\n\t}\n}\n\n- (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL\n{\n\tif ([self requestWillRedirectSelector]) {\n\t\t[[self delegate] performSelector:[self requestWillRedirectSelector] withObject:request withObject:newURL];\n\t}\n}\n\n- (void)requestFinished:(ASIHTTPRequest *)request\n{\n\t[self setRequestsCount:[self requestsCount]-1];\n\tif ([self requestDidFinishSelector]) {\n\t\t[[self delegate] performSelector:[self requestDidFinishSelector] withObject:request];\n\t}\n\tif ([self requestsCount] == 0) {\n\t\tif ([self queueDidFinishSelector]) {\n\t\t\t[[self delegate] performSelector:[self queueDidFinishSelector] withObject:self];\n\t\t}\n\t}\n}\n\n- (void)requestFailed:(ASIHTTPRequest *)request\n{\n\t[self setRequestsCount:[self requestsCount]-1];\n\tif ([self requestDidFailSelector]) {\n\t\t[[self delegate] performSelector:[self requestDidFailSelector] withObject:request];\n\t}\n\tif ([self requestsCount] == 0) {\n\t\tif ([self queueDidFinishSelector]) {\n\t\t\t[[self delegate] performSelector:[self queueDidFinishSelector] withObject:self];\n\t\t}\n\t}\n\tif ([self shouldCancelAllRequestsOnFailure] && [self requestsCount] > 0) {\n\t\t[self cancelAllOperations];\n\t}\n\t\n}\n\n\n- (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes\n{\n\t[self setBytesDownloadedSoFar:[self bytesDownloadedSoFar]+bytes];\n\tif ([self downloadProgressDelegate]) {\n\t\t[ASIHTTPRequest updateProgressIndicator:&downloadProgressDelegate withProgress:[self bytesDownloadedSoFar] ofTotal:[self totalBytesToDownload]];\n\t}\n}\n\n- (void)request:(ASIHTTPRequest *)request didSendBytes:(long long)bytes\n{\n\t[self setBytesUploadedSoFar:[self bytesUploadedSoFar]+bytes];\n\tif ([self uploadProgressDelegate]) {\n\t\t[ASIHTTPRequest updateProgressIndicator:&uploadProgressDelegate withProgress:[self bytesUploadedSoFar] ofTotal:[self totalBytesToUpload]];\n\t}\n}\n\n- (void)request:(ASIHTTPRequest *)request incrementDownloadSizeBy:(long long)newLength\n{\n\t[self setTotalBytesToDownload:[self totalBytesToDownload]+newLength];\n}\n\n- (void)request:(ASIHTTPRequest *)request incrementUploadSizeBy:(long long)newLength\n{\n\t[self setTotalBytesToUpload:[self totalBytesToUpload]+newLength];\n}\n\n\n// Since this queue takes over as the delegate for all requests it contains, it should forward authorisation requests to its own delegate\n- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request\n{\n\tif ([[self delegate] respondsToSelector:@selector(authenticationNeededForRequest:)]) {\n\t\t[[self delegate] performSelector:@selector(authenticationNeededForRequest:) withObject:request];\n\t}\n}\n\n- (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request\n{\n\tif ([[self delegate] respondsToSelector:@selector(proxyAuthenticationNeededForRequest:)]) {\n\t\t[[self delegate] performSelector:@selector(proxyAuthenticationNeededForRequest:) withObject:request];\n\t}\n}\n\n\n- (BOOL)respondsToSelector:(SEL)selector\n{\n\t// We handle certain methods differently because whether our delegate implements them or not can affect how the request should behave\n\n\t// If the delegate implements this, the request will stop to wait for credentials\n\tif (selector == @selector(authenticationNeededForRequest:)) {\n\t\tif ([[self delegate] respondsToSelector:@selector(authenticationNeededForRequest:)]) {\n\t\t\treturn YES;\n\t\t}\n\t\treturn NO;\n\n\t// If the delegate implements this, the request will to wait for credentials\n\t} else if (selector == @selector(proxyAuthenticationNeededForRequest:)) {\n\t\tif ([[self delegate] respondsToSelector:@selector(proxyAuthenticationNeededForRequest:)]) {\n\t\t\treturn YES;\n\t\t}\n\t\treturn NO;\n\n\t// If the delegate implements requestWillRedirectSelector, the request will stop to allow the delegate to change the url\n\t} else if (selector == @selector(request:willRedirectToURL:)) {\n\t\tif ([self requestWillRedirectSelector] && [[self delegate] respondsToSelector:[self requestWillRedirectSelector]]) {\n\t\t\treturn YES;\n\t\t}\n\t\treturn NO;\n\t}\n\treturn [super respondsToSelector:selector];\n}\n\n#pragma mark NSCopying\n\n- (id)copyWithZone:(NSZone *)zone\n{\n\tASINetworkQueue *newQueue = [[[self class] alloc] init];\n\t[newQueue setDelegate:[self delegate]];\n\t[newQueue setRequestDidStartSelector:[self requestDidStartSelector]];\n\t[newQueue setRequestWillRedirectSelector:[self requestWillRedirectSelector]];\n\t[newQueue setRequestDidReceiveResponseHeadersSelector:[self requestDidReceiveResponseHeadersSelector]];\n\t[newQueue setRequestDidFinishSelector:[self requestDidFinishSelector]];\n\t[newQueue setRequestDidFailSelector:[self requestDidFailSelector]];\n\t[newQueue setQueueDidFinishSelector:[self queueDidFinishSelector]];\n\t[newQueue setUploadProgressDelegate:[self uploadProgressDelegate]];\n\t[newQueue setDownloadProgressDelegate:[self downloadProgressDelegate]];\n\t[newQueue setShouldCancelAllRequestsOnFailure:[self shouldCancelAllRequestsOnFailure]];\n\t[newQueue setShowAccurateProgress:[self showAccurateProgress]];\n\t[newQueue setUserInfo:[[[self userInfo] copyWithZone:zone] autorelease]];\n\treturn newQueue;\n}\n\n\n@synthesize requestsCount;\n@synthesize bytesUploadedSoFar;\n@synthesize totalBytesToUpload;\n@synthesize bytesDownloadedSoFar;\n@synthesize totalBytesToDownload;\n@synthesize shouldCancelAllRequestsOnFailure;\n@synthesize uploadProgressDelegate;\n@synthesize downloadProgressDelegate;\n@synthesize requestDidStartSelector;\n@synthesize requestDidReceiveResponseHeadersSelector;\n@synthesize requestWillRedirectSelector;\n@synthesize requestDidFinishSelector;\n@synthesize requestDidFailSelector;\n@synthesize queueDidFinishSelector;\n@synthesize delegate;\n@synthesize showAccurateProgress;\n@synthesize userInfo;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIProgressDelegate.h",
    "content": "//\n//  ASIProgressDelegate.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 13/04/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n@class ASIHTTPRequest;\n\n@protocol ASIProgressDelegate <NSObject>\n\n@optional\n\n// These methods are used to update UIProgressViews (iPhone OS) or NSProgressIndicators (Mac OS X)\n// If you are using a custom progress delegate, you may find it easier to implement didReceiveBytes / didSendBytes instead\n#if TARGET_OS_IPHONE\n- (void)setProgress:(float)newProgress;\n#else\n- (void)setDoubleValue:(double)newProgress;\n- (void)setMaxValue:(double)newMax;\n#endif\n\n// Called when the request receives some data - bytes is the length of that data\n- (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes;\n\n// Called when the request sends some data\n// The first 32KB (128KB on older platforms) of data sent is not included in this amount because of limitations with the CFNetwork API\n// bytes may be less than zero if a request needs to remove upload progress (probably because the request needs to run again)\n- (void)request:(ASIHTTPRequest *)request didSendBytes:(long long)bytes;\n\n// Called when a request needs to change the length of the content to download\n- (void)request:(ASIHTTPRequest *)request incrementDownloadSizeBy:(long long)newLength;\n\n// Called when a request needs to change the length of the content to upload\n// newLength may be less than zero when a request needs to remove the size of the internal buffer from progress tracking\n- (void)request:(ASIHTTPRequest *)request incrementUploadSizeBy:(long long)newLength;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIWebPageRequest/ASIWebPageRequest.h",
    "content": "//\n//  ASIWebPageRequest.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 29/06/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n//  This is an EXPERIMENTAL class - use at your own risk!\n//  It is strongly recommend to set a downloadDestinationPath when using ASIWebPageRequest\n//  Also, performance will be better if your ASIWebPageRequest has a downloadCache setup\n//  Known issue: You cannot use startSychronous with an ASIWebPageRequest\n\n#import \"ASIHTTPRequest.h\"\n\n@class ASINetworkQueue;\n\n// Used internally for storing what type of data we got from the server\ntypedef enum _ASIWebContentType {\n    ASINotParsedWebContentType = 0,\n    ASIHTMLWebContentType = 1,\n    ASICSSWebContentType = 2\n} ASIWebContentType;\n\n// These correspond with the urlReplacementMode property of ASIWebPageRequest\ntypedef enum _ASIURLReplacementMode {\n\n\t// Don't modify html or css content at all\n    ASIDontModifyURLs = 0,\n\n\t// Replace external resources urls (images, stylesheets etc) with data uris, so their content is embdedded directly in the html/css\n    ASIReplaceExternalResourcesWithData = 1,\n\n\t// Replace external resource urls with the url of locally cached content\n\t// You must set the baseURL of a WebView / UIWebView to a file url pointing at the downloadDestinationPath of the main ASIWebPageRequest if you want to display your content\n    // See the Mac or iPhone example projects for a demonstration of how to do this\n\t// The hrefs of all hyperlinks are changed to use absolute urls when using this mode\n\tASIReplaceExternalResourcesWithLocalURLs = 2\n} ASIURLReplacementMode;\n\n\n\n@interface ASIWebPageRequest : ASIHTTPRequest {\n\n\t// Each ASIWebPageRequest for an HTML or CSS file creates its own internal queue to download external resources\n\tASINetworkQueue *externalResourceQueue;\n\n\t// This dictionary stores a list of external resources to download, along with their content-type data or a path to the data\n\tNSMutableDictionary *resourceList;\n\n\t// Used internally for parsing HTML (with libxml)\n\tstruct _xmlDoc *doc;\n\n\t// If the response is an HTML or CSS file, this will be set so the content can be correctly parsed when it has finished fetching external resources\n\tASIWebContentType webContentType;\n\n\t// Stores a reference to the ASIWebPageRequest that created this request\n\t// Note that a parentRequest can also have a parent request because ASIWebPageRequests parse their contents to look for external resources recursively\n\t// For example, a request for an image can be created by a request for a stylesheet which was created by a request for a web page\n\tASIWebPageRequest *parentRequest;\n\n\t// Controls what ASIWebPageRequest does with external resources. See the notes above for more.\n\tASIURLReplacementMode urlReplacementMode;\n\n\t// When set to NO, loading will stop when an external resource fails to load. Defaults to YES\n\tBOOL shouldIgnoreExternalResourceErrors;\n}\n\n// Will return a data URI that contains a base64 version of the content at this url\n// This is used when replacing urls in the html and css with actual data\n// If you subclass ASIWebPageRequest, you can override this function to return different content or a url pointing at another location\n- (NSString *)contentForExternalURL:(NSString *)theURL;\n\n// Returns the location that a downloaded external resource's content will be stored in\n- (NSString *)cachePathForRequest:(ASIWebPageRequest *)theRequest;\n\n\n@property (retain, nonatomic) ASIWebPageRequest *parentRequest;\n@property (assign, nonatomic) ASIURLReplacementMode urlReplacementMode;\n@property (assign, nonatomic) BOOL shouldIgnoreExternalResourceErrors;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/ASIWebPageRequest/ASIWebPageRequest.m",
    "content": "//\n//  ASIWebPageRequest.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 29/06/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n//  This is an EXPERIMENTAL class - use at your own risk!\n\n#import \"ASIWebPageRequest.h\"\n#import \"ASINetworkQueue.h\"\n#import <CommonCrypto/CommonHMAC.h>\n#import <libxml/HTMLparser.h>\n#import <libxml/xmlsave.h>\n#import <libxml/xpath.h>\n#import <libxml/xpathInternals.h>\n\n// An xPath query that controls the external resources ASIWebPageRequest will fetch\n// By default, it will fetch stylesheets, javascript files, images, frames, iframes, and html 5 video / audio\nstatic xmlChar *xpathExpr = (xmlChar *)\"//link/@href|//a/@href|//script/@src|//img/@src|//frame/@src|//iframe/@src|//style|//*/@style|//source/@src|//video/@poster|//audio/@src\";\n\nstatic NSLock *xmlParsingLock = nil;\nstatic NSMutableArray *requestsUsingXMLParser = nil;\n\n@interface ASIWebPageRequest ()\n- (void)readResourceURLs;\n- (void)updateResourceURLs;\n- (void)parseAsHTML;\n- (void)parseAsCSS;\n- (void)addURLToFetch:(NSString *)newURL;\n+ (NSArray *)CSSURLsFromString:(NSString *)string;\n- (NSString *)relativePathTo:(NSString *)destinationPath fromPath:(NSString *)sourcePath;\n\n- (void)finishedFetchingExternalResources:(ASINetworkQueue *)queue;\n- (void)externalResourceFetchSucceeded:(ASIHTTPRequest *)externalResourceRequest;\n- (void)externalResourceFetchFailed:(ASIHTTPRequest *)externalResourceRequest;\n\n@property (retain, nonatomic) ASINetworkQueue *externalResourceQueue;\n@property (retain, nonatomic) NSMutableDictionary *resourceList;\n@end\n\n@implementation ASIWebPageRequest\n\n+ (void)initialize\n{\n\tif (self == [ASIWebPageRequest class]) {\n\t\txmlParsingLock = [[NSLock alloc] init];\n\t\trequestsUsingXMLParser = [[NSMutableArray alloc] init];\n\t}\n}\n\n- (id)initWithURL:(NSURL *)newURL\n{\n\tself = [super initWithURL:newURL];\n\t[self setShouldIgnoreExternalResourceErrors:YES];\n\treturn self;\n}\n\n- (void)dealloc\n{\n\t[externalResourceQueue cancelAllOperations];\n\t[externalResourceQueue release];\n\t[resourceList release];\n\t[parentRequest release];\n\t[super dealloc];\n}\n\n// This is a bit of a hack\n// The role of this method in normal ASIHTTPRequests is to tell the queue we are done with the request, and perform some cleanup\n// We override it to stop that happening, and instead do that work in the bottom of finishedFetchingExternalResources:\n- (void)markAsFinished\n{\n\tif ([self error]) {\n\t\t[super markAsFinished];\n\t}\n}\n\n// This method is normally responsible for telling delegates we are done, but it happens to be the most convenient place to parse the responses\n// Again, we call the super implementation in finishedFetchingExternalResources:, or here if this download was not an HTML or CSS file\n- (void)requestFinished\n{\n\tcomplete = NO;\n\tif ([self mainRequest] || [self didUseCachedResponse]) {\n\t\t[super requestFinished];\n\t\t[super markAsFinished];\n\t\treturn;\n\t}\n\twebContentType = ASINotParsedWebContentType;\n\tNSString *contentType = [[[self responseHeaders] objectForKey:@\"Content-Type\"] lowercaseString];\n\tcontentType = [[contentType componentsSeparatedByString:@\";\"] objectAtIndex:0];\n\tif ([contentType isEqualToString:@\"text/html\"] || [contentType isEqualToString:@\"text/xhtml\"] || [contentType isEqualToString:@\"text/xhtml+xml\"] || [contentType isEqualToString:@\"application/xhtml+xml\"]) {\n\t\t[self parseAsHTML];\n\t\treturn;\n\t} else if ([contentType isEqualToString:@\"text/css\"]) {\n\t\t[self parseAsCSS];\n\t\treturn;\n\t}\n\t[super requestFinished];\n\t[super markAsFinished];\n}\n\n- (void)parseAsCSS\n{\n\twebContentType = ASICSSWebContentType;\n\n\tNSString *responseCSS = nil;\n\tNSError *err = nil;\n\tif ([self downloadDestinationPath]) {\n\t\tresponseCSS = [NSString stringWithContentsOfFile:[self downloadDestinationPath] encoding:[self responseEncoding] error:&err];\n\t} else {\n\t\tresponseCSS = [self responseString];\n\t}\n\tif (err) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:100 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Unable to read HTML string from response\",NSLocalizedDescriptionKey,err,NSUnderlyingErrorKey,nil]]];\n\t\treturn;\n\t} else if (!responseCSS) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:100 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Unable to read HTML string from response\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n\t}\n\tNSArray *urls = [[self class] CSSURLsFromString:responseCSS];\n\n\t[self setResourceList:[NSMutableDictionary dictionary]];\n\n\tfor (NSString *theURL in urls) {\n\t\t[self addURLToFetch:theURL];\n\t}\n\tif (![[self resourceList] count]) {\n\t\t[super requestFinished];\n\t\t[super markAsFinished];\n\t\treturn;\n\t}\n\n\t// Create a new request for every item in the queue\n\t[[self externalResourceQueue] cancelAllOperations];\n\t[self setExternalResourceQueue:[ASINetworkQueue queue]];\n\t[[self externalResourceQueue] setDelegate:self];\n\t[[self externalResourceQueue] setShouldCancelAllRequestsOnFailure:[self shouldIgnoreExternalResourceErrors]];\n\t[[self externalResourceQueue] setShowAccurateProgress:[self showAccurateProgress]];\n\t[[self externalResourceQueue] setQueueDidFinishSelector:@selector(finishedFetchingExternalResources:)];\n\t[[self externalResourceQueue] setRequestDidFinishSelector:@selector(externalResourceFetchSucceeded:)];\n\t[[self externalResourceQueue] setRequestDidFailSelector:@selector(externalResourceFetchFailed:)];\n\tfor (NSString *theURL in [[self resourceList] keyEnumerator]) {\n\t\tASIWebPageRequest *externalResourceRequest = [ASIWebPageRequest requestWithURL:[NSURL URLWithString:theURL relativeToURL:[self url]]];\n\t\t[externalResourceRequest setRequestHeaders:[self requestHeaders]];\n\t\t[externalResourceRequest setDownloadCache:[self downloadCache]];\n\t\t[externalResourceRequest setCachePolicy:[self cachePolicy]];\n\t\t[externalResourceRequest setCacheStoragePolicy:[self cacheStoragePolicy]];\n\t\t[externalResourceRequest setUserInfo:[NSDictionary dictionaryWithObject:theURL forKey:@\"Path\"]];\n\t\t[externalResourceRequest setParentRequest:self];\n\t\t[externalResourceRequest setUrlReplacementMode:[self urlReplacementMode]];\n\t\t[externalResourceRequest setShouldResetDownloadProgress:NO];\n\t\t[externalResourceRequest setDelegate:self];\n\t\t[externalResourceRequest setUploadProgressDelegate:self];\n\t\t[externalResourceRequest setDownloadProgressDelegate:self];\n\t\tif ([self downloadDestinationPath]) {\n\t\t\t[externalResourceRequest setDownloadDestinationPath:[self cachePathForRequest:externalResourceRequest]];\n\t\t}\n\t\t[[self externalResourceQueue] addOperation:externalResourceRequest];\n\t}\n\t[[self externalResourceQueue] go];\n}\n\n- (const char *)encodingName\n{\n\txmlCharEncoding encoding = XML_CHAR_ENCODING_NONE;\n\tswitch ([self responseEncoding])\n\t{\n\t\tcase NSASCIIStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_ASCII;\n\t\t\tbreak;\n\t\tcase NSJapaneseEUCStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_EUC_JP;\n\t\t\tbreak;\n\t\tcase NSUTF8StringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_UTF8;\n\t\t\tbreak;\n\t\tcase NSISOLatin1StringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_8859_1;\n\t\t\tbreak;\n\t\tcase NSShiftJISStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_SHIFT_JIS;\n\t\t\tbreak;\n\t\tcase NSISOLatin2StringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_8859_2;\n\t\t\tbreak;\n\t\tcase NSISO2022JPStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_2022_JP;\n\t\t\tbreak;\n\t\tcase NSUTF16BigEndianStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_UTF16BE;\n\t\t\tbreak;\n\t\tcase NSUTF16LittleEndianStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_UTF16LE;\n\t\t\tbreak;\n\t\tcase NSUTF32BigEndianStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_UCS4BE;\n\t\t\tbreak;\n\t\tcase NSUTF32LittleEndianStringEncoding:\n\t\t\tencoding = XML_CHAR_ENCODING_UCS4LE;\n\t\t\tbreak;\n\t\tcase NSNEXTSTEPStringEncoding:\n\t\tcase NSSymbolStringEncoding:\n\t\tcase NSNonLossyASCIIStringEncoding:\n\t\tcase NSUnicodeStringEncoding:\n\t\tcase NSMacOSRomanStringEncoding:\n\t\tcase NSUTF32StringEncoding:\n\t\tdefault:\n\t\t\tencoding = XML_CHAR_ENCODING_ERROR;\n\t\t\tbreak;\n\t}\n\treturn xmlGetCharEncodingName(encoding);\n}\n\n- (void)parseAsHTML\n{\n\twebContentType = ASIHTMLWebContentType;\n\n\t// Only allow parsing of a single document at a time\n\t[xmlParsingLock lock];\n\n\tif (![requestsUsingXMLParser count]) {\n\t\txmlInitParser();\n\t}\n\t[requestsUsingXMLParser addObject:self];\n\n\n    /* Load XML document */\n\tif ([self downloadDestinationPath]) {\n\t\tdoc = htmlReadFile([[self downloadDestinationPath] cStringUsingEncoding:NSUTF8StringEncoding], [self encodingName], HTML_PARSE_NONET | HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);\n\t} else {\n\t\tNSData *data = [self responseData];\n\t\tdoc = htmlReadMemory([data bytes], (int)[data length], \"\", [self encodingName], HTML_PARSE_NONET | HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);\n\t}\n    if (doc == NULL) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Error: unable to parse reponse XML\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n    }\n\t\n\t[self setResourceList:[NSMutableDictionary dictionary]];\n\n    // Populate the list of URLS to download\n    [self readResourceURLs];\n\n\tif ([self error] || ![[self resourceList] count]) {\n\t\t[requestsUsingXMLParser removeObject:self];\n\t\txmlFreeDoc(doc);\n\t\tdoc = NULL;\n\t}\n\n\t[xmlParsingLock unlock];\n\n\tif ([self error]) {\n\t\treturn;\n\t} else if (![[self resourceList] count]) {\n\t\t[super requestFinished];\n\t\t[super markAsFinished];\n\t\treturn;\n\t}\n\t\n\t// Create a new request for every item in the queue\n\t[[self externalResourceQueue] cancelAllOperations];\n\t[self setExternalResourceQueue:[ASINetworkQueue queue]];\n\t[[self externalResourceQueue] setDelegate:self];\n\t[[self externalResourceQueue] setShouldCancelAllRequestsOnFailure:[self shouldIgnoreExternalResourceErrors]];\n\t[[self externalResourceQueue] setShowAccurateProgress:[self showAccurateProgress]];\n\t[[self externalResourceQueue] setQueueDidFinishSelector:@selector(finishedFetchingExternalResources:)];\n\t[[self externalResourceQueue] setRequestDidFinishSelector:@selector(externalResourceFetchSucceeded:)];\n\t[[self externalResourceQueue] setRequestDidFailSelector:@selector(externalResourceFetchFailed:)];\n\tfor (NSString *theURL in [[self resourceList] keyEnumerator]) {\n\t\tASIWebPageRequest *externalResourceRequest = [ASIWebPageRequest requestWithURL:[NSURL URLWithString:theURL relativeToURL:[self url]]];\n\t\t[externalResourceRequest setRequestHeaders:[self requestHeaders]];\n\t\t[externalResourceRequest setDownloadCache:[self downloadCache]];\n\t\t[externalResourceRequest setCachePolicy:[self cachePolicy]];\n\t\t[externalResourceRequest setCacheStoragePolicy:[self cacheStoragePolicy]];\n\t\t[externalResourceRequest setUserInfo:[NSDictionary dictionaryWithObject:theURL forKey:@\"Path\"]];\n\t\t[externalResourceRequest setParentRequest:self];\n\t\t[externalResourceRequest setUrlReplacementMode:[self urlReplacementMode]];\n\t\t[externalResourceRequest setShouldResetDownloadProgress:NO];\n\t\t[externalResourceRequest setDelegate:self];\n\t\t[externalResourceRequest setUploadProgressDelegate:self];\n\t\t[externalResourceRequest setDownloadProgressDelegate:self];\n\t\tif ([self downloadDestinationPath]) {\n\t\t\t[externalResourceRequest setDownloadDestinationPath:[self cachePathForRequest:externalResourceRequest]];\n\t\t}\n\t\t[[self externalResourceQueue] addOperation:externalResourceRequest];\n\t}\n\t[[self externalResourceQueue] go];\n}\n\n- (void)externalResourceFetchSucceeded:(ASIHTTPRequest *)externalResourceRequest\n{\n\tNSString *originalPath = [[externalResourceRequest userInfo] objectForKey:@\"Path\"];\n\tNSMutableDictionary *requestResponse = [[self resourceList] objectForKey:originalPath];\n\tNSString *contentType = [[externalResourceRequest responseHeaders] objectForKey:@\"Content-Type\"];\n\tif (!contentType) {\n\t\tcontentType = @\"application/octet-stream\";\n\t}\n\t[requestResponse setObject:contentType forKey:@\"ContentType\"];\n\tif ([self downloadDestinationPath]) {\n\t\t[requestResponse setObject:[externalResourceRequest downloadDestinationPath] forKey:@\"DataPath\"];\n\t} else {\n\t\tNSData *data = [externalResourceRequest responseData];\n\t\tif (data) {\n\t\t\t[requestResponse setObject:data forKey:@\"Data\"];\n\t\t}\n\t}\n}\n\n- (void)externalResourceFetchFailed:(ASIHTTPRequest *)externalResourceRequest\n{\n\tif ([[self externalResourceQueue] shouldCancelAllRequestsOnFailure]) {\n\t\t[self failWithError:[externalResourceRequest error]];\n\t}\n}\n\n- (void)finishedFetchingExternalResources:(ASINetworkQueue *)queue\n{\n\tif ([self urlReplacementMode] != ASIDontModifyURLs) {\n\t\tif (webContentType == ASICSSWebContentType) {\n\t\t\tNSMutableString *parsedResponse;\n\t\t\tNSError *err = nil;\n\t\t\tif ([self downloadDestinationPath]) {\n\t\t\t\tparsedResponse = [NSMutableString stringWithContentsOfFile:[self downloadDestinationPath] encoding:[self responseEncoding] error:&err];\n\t\t\t} else {\n\t\t\t\tparsedResponse = [[[self responseString] mutableCopy] autorelease];\n\t\t\t}\n\t\t\tif (err) {\n\t\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Error: unable to read response CSS from disk\",NSLocalizedDescriptionKey,nil]]];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (![self error]) {\n\t\t\t\tfor (NSString *resource in [[self resourceList] keyEnumerator]) {\n\t\t\t\t\tif ([parsedResponse rangeOfString:resource].location != NSNotFound) {\n\t\t\t\t\t\tNSString *newURL = [self contentForExternalURL:resource];\n\t\t\t\t\t\tif (newURL) {\n\t\t\t\t\t\t\t[parsedResponse replaceOccurrencesOfString:resource withString:newURL options:0 range:NSMakeRange(0, [parsedResponse length])];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ([self downloadDestinationPath]) {\n\t\t\t\t[parsedResponse writeToFile:[self downloadDestinationPath] atomically:NO encoding:[self responseEncoding] error:&err];\n\t\t\t\tif (err) {\n\t\t\t\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Error: unable to write response CSS to disk\",NSLocalizedDescriptionKey,nil]]];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t[self setRawResponseData:(id)[parsedResponse dataUsingEncoding:[self responseEncoding]]];\n\t\t\t}\n\t\t} else {\n\t\t\t[xmlParsingLock lock];\n\n\t\t\t[self updateResourceURLs];\n\n\t\t\tif (![self error]) {\n\n\t\t\t\t// We'll use the xmlsave API so we can strip the xml declaration\n\t\t\t\txmlSaveCtxtPtr saveContext;\n\n\t\t\t\tif ([self downloadDestinationPath]) {\n\n\t\t\t\t\t// Truncate the file first\n\t\t\t\t\t[[[[NSFileManager alloc] init] autorelease] createFileAtPath:[self downloadDestinationPath] contents:nil attributes:nil];\n\n\t\t\t\t\tsaveContext = xmlSaveToFd([[NSFileHandle fileHandleForWritingAtPath:[self downloadDestinationPath]] fileDescriptor],NULL,2); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5\n\t\t\t\t\txmlSaveDoc(saveContext, doc);\n\t\t\t\t\txmlSaveClose(saveContext);\n\n\t\t\t\t} else {\n\t#if TARGET_OS_MAC && MAC_OS_X_VERSION_MAX_ALLOWED <= __MAC_10_5\n\t\t\t\t\t// xmlSaveToBuffer() is not implemented in the 10.5 version of libxml\n\t\t\t\t\tNSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];\n\t\t\t\t\t[[[[NSFileManager alloc] init] autorelease] createFileAtPath:tempPath contents:nil attributes:nil];\n\t\t\t\t\tsaveContext = xmlSaveToFd([[NSFileHandle fileHandleForWritingAtPath:tempPath] fileDescriptor],NULL,2); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5\n\t\t\t\t\txmlSaveDoc(saveContext, doc);\n\t\t\t\t\txmlSaveClose(saveContext);\n\t\t\t\t\t[self setRawResponseData:[NSMutableData dataWithContentsOfFile:tempPath]];\n\t#else\n\t\t\t\t\txmlBufferPtr buffer = xmlBufferCreate();\n\t\t\t\t\tsaveContext = xmlSaveToBuffer(buffer,NULL,2); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5\n\t\t\t\t\txmlSaveDoc(saveContext, doc);\n\t\t\t\t\txmlSaveClose(saveContext);\n\t\t\t\t\t[self setRawResponseData:[[[NSMutableData alloc] initWithBytes:buffer->content length:buffer->use] autorelease]];\n\t\t\t\t\txmlBufferFree(buffer);\n\t#endif\n\t\t\t\t}\n\n\t\t\t\t// Strip the content encoding if the original response was gzipped\n\t\t\t\tif ([self isResponseCompressed]) {\n\t\t\t\t\tNSMutableDictionary *headers = [[[self responseHeaders] mutableCopy] autorelease];\n\t\t\t\t\t[headers removeObjectForKey:@\"Content-Encoding\"];\n\t\t\t\t\t[self setResponseHeaders:headers];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\txmlFreeDoc(doc);\n\t\t\tdoc = nil;\n\n\t\t\t[requestsUsingXMLParser removeObject:self];\n\t\t\tif (![requestsUsingXMLParser count]) {\n\t\t\t\txmlCleanupParser();\n\t\t\t}\n\t\t\t[xmlParsingLock unlock];\n\t\t}\n\t}\n\tif (![self parentRequest]) {\n\t\t[[self class] updateProgressIndicator:&downloadProgressDelegate withProgress:contentLength ofTotal:contentLength];\n\t}\n\n\tNSMutableDictionary *newHeaders = [[[self responseHeaders] mutableCopy] autorelease];\n\t[newHeaders removeObjectForKey:@\"Content-Encoding\"];\n\t[self setResponseHeaders:newHeaders];\n\n\t// Write the parsed content back to the cache\n\tif ([self urlReplacementMode] != ASIDontModifyURLs) {\n\t\t[[self downloadCache] storeResponseForRequest:self maxAge:[self secondsToCache]];\n\t}\n\n\t[super requestFinished];\n\t[super markAsFinished];\n}\n\n- (void)readResourceURLs\n{\n\t// Create xpath evaluation context\n    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);\n    if(xpathCtx == NULL) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Error: unable to create new XPath context\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n    }\n\n    // Evaluate xpath expression\n    xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);\n    if(xpathObj == NULL) {\n        xmlXPathFreeContext(xpathCtx); \n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Error: unable to evaluate XPath expression!\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n    }\n\t\n\t// Now loop through our matches\n\txmlNodeSetPtr nodes = xpathObj->nodesetval;\n\n    int size = (nodes) ? nodes->nodeNr : 0;\n\tint i;\n    for(i = size - 1; i >= 0; i--) {\n\t\tassert(nodes->nodeTab[i]);\n\t\tNSString *parentName  = [NSString stringWithCString:(char *)nodes->nodeTab[i]->parent->name encoding:[self responseEncoding]];\n\t\tNSString *nodeName = [NSString stringWithCString:(char *)nodes->nodeTab[i]->name encoding:[self responseEncoding]];\n\n\t\txmlChar *nodeValue = xmlNodeGetContent(nodes->nodeTab[i]);\n\t\tNSString *value = [NSString stringWithCString:(char *)nodeValue encoding:[self responseEncoding]];\n\t\txmlFree(nodeValue);\n\n\t\t// Our xpath query matched all <link> elements, but we're only interested in stylesheets\n\t\t// We do the work here rather than in the xPath query because the query is case-sensitive, and we want to match on 'stylesheet', 'StyleSHEEt' etc\n\t\tif ([[parentName lowercaseString] isEqualToString:@\"link\"]) {\n\t\t\txmlChar *relAttribute = xmlGetNoNsProp(nodes->nodeTab[i]->parent,(xmlChar *)\"rel\");\n\t\t\tif (relAttribute) {\n\t\t\t\tNSString *rel = [NSString stringWithCString:(char *)relAttribute encoding:[self responseEncoding]];\n\t\t\t\txmlFree(relAttribute);\n\t\t\t\tif ([[rel lowercaseString] isEqualToString:@\"stylesheet\"]) {\n\t\t\t\t\t[self addURLToFetch:value];\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Parse the content of <style> tags and style attributes to find external image urls or external css files\n\t\t} else if ([[nodeName lowercaseString] isEqualToString:@\"style\"]) {\n\t\t\tNSArray *externalResources = [[self class] CSSURLsFromString:value];\n\t\t\tfor (NSString *theURL in externalResources) {\n\t\t\t\t[self addURLToFetch:theURL];\n\t\t\t}\n\n\t\t// Parse the content of <source src=\"\"> tags (HTML 5 audio + video)\n\t\t// We explictly disable the download of files with .webm, .ogv and .ogg extensions, since it's highly likely they won't be useful to us\n\t\t} else if ([[parentName lowercaseString] isEqualToString:@\"source\"] || [[parentName lowercaseString] isEqualToString:@\"audio\"]) {\n\t\t\tNSString *fileExtension = [[value pathExtension] lowercaseString];\n\t\t\tif (![fileExtension isEqualToString:@\"ogg\"] && ![fileExtension isEqualToString:@\"ogv\"] && ![fileExtension isEqualToString:@\"webm\"]) {\n\t\t\t\t[self addURLToFetch:value];\n\t\t\t}\n\n\t\t// For all other elements matched by our xpath query (except hyperlinks), add the content as an external url to fetch\n\t\t} else if (![[parentName lowercaseString] isEqualToString:@\"a\"]) {\n\t\t\t[self addURLToFetch:value];\n\t\t}\n\t\tif (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) {\n\t\t\tnodes->nodeTab[i] = NULL;\n\t\t}\n    }\n\t\n\txmlXPathFreeObject(xpathObj);\n    xmlXPathFreeContext(xpathCtx); \n}\n\n- (void)addURLToFetch:(NSString *)newURL\n{\n\t// Get rid of any surrounding whitespace\n\tnewURL = [newURL stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n\t// Don't attempt to fetch data URIs\n\tif ([newURL length] > 4) {\n\t\tif (![[[newURL substringToIndex:5] lowercaseString] isEqualToString:@\"data:\"]) {\n\t\t\tNSURL *theURL = [NSURL URLWithString:newURL relativeToURL:[self url]];\n\t\t\tif (theURL) {\n\t\t\t\tif (![[self resourceList] objectForKey:newURL]) {\n\t\t\t\t\t[[self resourceList] setObject:[NSMutableDictionary dictionary] forKey:newURL];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n- (void)updateResourceURLs\n{\n\t// Create xpath evaluation context\n\txmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);\n\tif(xpathCtx == NULL) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Error: unable to create new XPath context\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n\t}\n\n \t// Evaluate xpath expression\n\txmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);\n\tif(xpathObj == NULL) {\n\t\txmlXPathFreeContext(xpathCtx);\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Error: unable to evaluate XPath expression!\",NSLocalizedDescriptionKey,nil]]];\n\t\treturn;\n\t}\n\n\t// Loop through all the matches, replacing urls where nescessary\n\txmlNodeSetPtr nodes = xpathObj->nodesetval;\n\tint size = (nodes) ? nodes->nodeNr : 0;\n\tint i;\n\tfor(i = size - 1; i >= 0; i--) {\n\t\tassert(nodes->nodeTab[i]);\n\t\tNSString *parentName  = [NSString stringWithCString:(char *)nodes->nodeTab[i]->parent->name encoding:[self responseEncoding]];\n\t\tNSString *nodeName  = [NSString stringWithCString:(char *)nodes->nodeTab[i]->name encoding:[self responseEncoding]];\n\n\t\txmlChar *nodeValue = xmlNodeGetContent(nodes->nodeTab[i]);\n\t\tNSString *value = [NSString stringWithCString:(char *)nodeValue encoding:[self responseEncoding]];\n\t\txmlFree(nodeValue);\n\n\t\t// Replace external urls in <style> tags or in style attributes\n\t\tif ([[nodeName lowercaseString] isEqualToString:@\"style\"]) {\n\t\t\tNSArray *externalResources = [[self class] CSSURLsFromString:value];\n\t\t\tfor (NSString *theURL in externalResources) {\n\t\t\t\tif ([value rangeOfString:theURL].location != NSNotFound) {\n\t\t\t\t\tNSString *newURL = [self contentForExternalURL:theURL];\n\t\t\t\t\tif (newURL) {\n\t\t\t\t\t\tvalue = [value stringByReplacingOccurrencesOfString:theURL withString:newURL];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\txmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[value cStringUsingEncoding:[self responseEncoding]]);\n\n\t\t// Replace relative hyperlinks with absolute ones, since we will need to set a local baseURL when loading this in a web view\n\t\t} else if ([self urlReplacementMode] == ASIReplaceExternalResourcesWithLocalURLs && [[parentName lowercaseString] isEqualToString:@\"a\"]) {\n\t\t\tNSString *newURL = [[NSURL URLWithString:value relativeToURL:[self url]] absoluteString];\n\t\t\tif (newURL) {\n\t\t\t\txmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[newURL cStringUsingEncoding:[self responseEncoding]]);\n\t\t\t}\n\n\t\t// Replace all other external resource urls\n\t\t} else {\n\t\t\tNSString *newURL = [self contentForExternalURL:value];\n\t\t\tif (newURL) {\n\t\t\t\txmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[newURL cStringUsingEncoding:[self responseEncoding]]);\n\t\t\t}\n\t\t}\n\n\t\tif (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) {\n\t\t\tnodes->nodeTab[i] = NULL;\n\t\t}\n\t}\n\txmlXPathFreeObject(xpathObj);\n\txmlXPathFreeContext(xpathCtx);\n}\n\n// The three methods below are responsible for forwarding delegate methods we want to handle to the parent request's approdiate delegate\n// Certain delegate methods are ignored (eg setProgress: / setDoubleValue: / setMaxValue:)\n- (BOOL)respondsToSelector:(SEL)selector\n{\n\tif ([self parentRequest]) {\n\t\treturn [[self parentRequest] respondsToSelector:selector];\n\t}\n\t//Ok, now check for selectors we want to pass on to the delegate\n\tif (selector == @selector(requestStarted:) || selector == @selector(request:didReceiveResponseHeaders:) || selector == @selector(request:willRedirectToURL:) || selector == @selector(requestFinished:) || selector == @selector(requestFailed:) || selector == @selector(request:didReceiveData:) || selector == @selector(authenticationNeededForRequest:) || selector == @selector(proxyAuthenticationNeededForRequest:)) {\n\t\treturn [delegate respondsToSelector:selector];\n\t} else if (selector == @selector(request:didReceiveBytes:) || selector == @selector(request:incrementDownloadSizeBy:)) {\n\t\treturn [downloadProgressDelegate respondsToSelector:selector];\n\t} else if (selector == @selector(request:didSendBytes:)  || selector == @selector(request:incrementUploadSizeBy:)) {\n\t\treturn [uploadProgressDelegate respondsToSelector:selector];\n\t}\n\treturn [super respondsToSelector:selector];\n}\n\n- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector\n{\n\tif ([self parentRequest]) {\n\t\treturn [[self parentRequest] methodSignatureForSelector:selector];\n\t}\n\tif (selector == @selector(requestStarted:) || selector == @selector(request:didReceiveResponseHeaders:) || selector == @selector(request:willRedirectToURL:) || selector == @selector(requestFinished:) || selector == @selector(requestFailed:) || selector == @selector(request:didReceiveData:) || selector == @selector(authenticationNeededForRequest:) || selector == @selector(proxyAuthenticationNeededForRequest:)) {\n\t\treturn [(id)delegate methodSignatureForSelector:selector];\n\t} else if (selector == @selector(request:didReceiveBytes:) || selector == @selector(request:incrementDownloadSizeBy:)) {\n\t\treturn [(id)downloadProgressDelegate methodSignatureForSelector:selector];\n\t} else if (selector == @selector(request:didSendBytes:)  || selector == @selector(request:incrementUploadSizeBy:)) {\n\t\treturn [(id)uploadProgressDelegate methodSignatureForSelector:selector];\n\t}\n\treturn nil;\n}\n\n- (void)forwardInvocation:(NSInvocation *)anInvocation\n{\n\tif ([self parentRequest]) {\n\t\treturn [[self parentRequest] forwardInvocation:anInvocation];\n\t}\n\tSEL selector = [anInvocation selector];\n\tif (selector == @selector(requestStarted:) || selector == @selector(request:didReceiveResponseHeaders:) || selector == @selector(request:willRedirectToURL:) || selector == @selector(requestFinished:) || selector == @selector(requestFailed:) || selector == @selector(request:didReceiveData:) || selector == @selector(authenticationNeededForRequest:) || selector == @selector(proxyAuthenticationNeededForRequest:)) {\n\t\t[anInvocation invokeWithTarget:delegate];\n\t} else if (selector == @selector(request:didReceiveBytes:) || selector == @selector(request:incrementDownloadSizeBy:)) {\n\t\t[anInvocation invokeWithTarget:downloadProgressDelegate];\n\t} else if (selector == @selector(request:didSendBytes:)  || selector == @selector(request:incrementUploadSizeBy:)) {\n\t\t[anInvocation invokeWithTarget:uploadProgressDelegate];\n\t}\n}\n\n// A quick and dirty way to build a list of external resource urls from a css string\n+ (NSArray *)CSSURLsFromString:(NSString *)string\n{\n\tNSMutableArray *urls = [NSMutableArray array];\n\tNSScanner *scanner = [NSScanner scannerWithString:string];\n\t[scanner setCaseSensitive:NO];\n\twhile (1) {\n\t\tNSString *theURL = nil;\n\t\t[scanner scanUpToString:@\"url(\" intoString:NULL];\n\t\t[scanner scanString:@\"url(\" intoString:NULL];\n\t\t[scanner scanUpToString:@\")\" intoString:&theURL];\n\t\tif (!theURL) {\n\t\t\tbreak;\n\t\t}\n\t\t// Remove any quotes or whitespace around the url\n\t\ttheURL = [theURL stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n\t\ttheURL = [theURL stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@\"\\\"'\"]];\n\t\ttheURL = [theURL stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n\t\t[urls addObject:theURL];\n\t}\n\treturn urls;\n}\n\n// Returns a relative file path from sourcePath to destinationPath (eg ../../foo/bar.txt)\n- (NSString *)relativePathTo:(NSString *)destinationPath fromPath:(NSString *)sourcePath\n{\n\tNSArray *sourcePathComponents = [sourcePath pathComponents];\n\tNSArray *destinationPathComponents = [destinationPath pathComponents];\n\tNSUInteger i;\n\tNSString *newPath = @\"\";\n\tNSString *sourcePathComponent, *destinationPathComponent;\n\tfor (i=0; i<[sourcePathComponents count]; i++) {\n\t\tsourcePathComponent = [sourcePathComponents objectAtIndex:i];\n\t\tif ([destinationPathComponents count] > i) {\n\t\t\tdestinationPathComponent = [destinationPathComponents objectAtIndex:i];\n\t\t\tif (![sourcePathComponent isEqualToString:destinationPathComponent]) {\n\t\t\t\tNSUInteger i2;\n\t\t\t\tfor (i2=i+1; i2<[sourcePathComponents count]; i2++) {\n\t\t\t\t\tnewPath = [newPath stringByAppendingPathComponent:@\"..\"];\n\t\t\t\t}\n\t\t\t\tnewPath = [newPath stringByAppendingPathComponent:destinationPathComponent];\n\t\t\t\tfor (i2=i+1; i2<[destinationPathComponents count]; i2++) {\n\t\t\t\t\tnewPath = [newPath stringByAppendingPathComponent:[destinationPathComponents objectAtIndex:i2]];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn newPath;\n}\n\n- (NSString *)contentForExternalURL:(NSString *)theURL\n{\n\tif ([self urlReplacementMode] == ASIReplaceExternalResourcesWithLocalURLs) {\n\t\tNSString *resourcePath = [[resourceList objectForKey:theURL] objectForKey:@\"DataPath\"];\n\t\treturn [self relativePathTo:resourcePath fromPath:[self downloadDestinationPath]];\n\t}\n\tNSData *data;\n\tif ([[resourceList objectForKey:theURL] objectForKey:@\"DataPath\"]) {\n\t\tdata = [NSData dataWithContentsOfFile:[[resourceList objectForKey:theURL] objectForKey:@\"DataPath\"]];\n\t} else {\n\t\tdata = [[resourceList objectForKey:theURL] objectForKey:@\"Data\"];\n\t}\n\tNSString *contentType = [[resourceList objectForKey:theURL] objectForKey:@\"ContentType\"];\n\tif (data && contentType) {\n\t\tNSString *dataURI = [NSString stringWithFormat:@\"data:%@;base64,\",contentType];\n\t\tdataURI = [dataURI stringByAppendingString:[ASIHTTPRequest base64forData:data]];\n\t\treturn dataURI;\n\t}\n\treturn nil;\n}\n\n- (NSString *)cachePathForRequest:(ASIWebPageRequest *)theRequest\n{\n\t// If we're using a download cache (and its a good idea to do so when using ASIWebPageRequest), ask it for the location to store this file\n\t// This ends up being quite efficient, as we download directly to the cache\n\tif ([self downloadCache]) {\n\t\treturn [[self downloadCache] pathToStoreCachedResponseDataForRequest:theRequest];\n\n\t// This is a fallback for when we don't have a download cache - we store the external resource in a file in the temporary directory\n\t} else {\n\t\t// Borrowed from: http://stackoverflow.com/questions/652300/using-md5-hash-on-a-string-in-cocoa\n\t\tconst char *cStr = [[[theRequest url] absoluteString] UTF8String];\n\t\tunsigned char result[16];\n\t\tCC_MD5(cStr, (CC_LONG)strlen(cStr), result);\n\t\tNSString *md5 = [NSString stringWithFormat:@\"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\",result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],result[8], result[9], result[10], result[11],result[12], result[13], result[14], result[15]]; \t\n\t\treturn [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:[md5 stringByAppendingPathExtension:@\"html\"]];\n\t}\n}\n\n\n@synthesize externalResourceQueue;\n@synthesize resourceList;\n@synthesize parentRequest;\n@synthesize urlReplacementMode;\n@synthesize shouldIgnoreExternalResourceErrors;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesCDNRequest.h",
    "content": "//\n//  ASICloudFilesCDNRequest.h\n//\n//  Created by Michael Mayo on 1/6/10.\n//\n\n#import \"ASICloudFilesRequest.h\"\n\n@class ASICloudFilesContainerXMLParserDelegate;\n\n@interface ASICloudFilesCDNRequest : ASICloudFilesRequest {\n\tNSString *accountName;\n\tNSString *containerName;\n\tASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;\n\t\n}\n\n@property (retain) NSString *accountName;\n@property (retain) NSString *containerName;\n@property (retain) ASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;\n\n\n// HEAD /<api version>/<account>/<container>\n// Response:\n// X-CDN-Enabled: True\n// X-CDN-URI: http://cdn.cloudfiles.mosso.com/c1234\n// X-CDN-SSL-URI: https://cdn.ssl.cloudfiles.mosso.com/c1234\n// X-CDN-TTL: 86400\n+ (id)containerInfoRequest:(NSString *)containerName;\n- (BOOL)cdnEnabled;\n- (NSString *)cdnURI;\n- (NSString *)cdnSSLURI;\n- (NSUInteger)cdnTTL;\n\n\n// GET /<api version>/<account>\n// limit, marker, format, enabled_only=true\n+ (id)listRequest;\n+ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker enabledOnly:(BOOL)enabledOnly;\n- (NSArray *)containers;\n\n\n// PUT /<api version>/<account>/<container>\n// PUT operations against a Container are used to CDN-enable that Container.\n// Include an HTTP header of X-TTL to specify a custom TTL.\n+ (id)putRequestWithContainer:(NSString *)containerName;\n+ (id)putRequestWithContainer:(NSString *)containerName ttl:(NSUInteger)ttl;\n// returns: - (NSString *)cdnURI;\n\n// POST /<api version>/<account>/<container>\n// POST operations against a CDN-enabled Container are used to adjust CDN attributes.\n// The POST operation can be used to set a new TTL cache expiration or to enable/disable public sharing over the CDN.\n// X-TTL: 86400\n// X-CDN-Enabled: True\n+ (id)postRequestWithContainer:(NSString *)containerName;\n+ (id)postRequestWithContainer:(NSString *)containerName cdnEnabled:(BOOL)cdnEnabled ttl:(NSUInteger)ttl;\n// returns: - (NSString *)cdnURI;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesCDNRequest.m",
    "content": "//\n//  ASICloudFilesCDNRequest.m\n//\n//  Created by Michael Mayo on 1/6/10.\n//\n\n#import \"ASICloudFilesCDNRequest.h\"\n#import \"ASICloudFilesContainerXMLParserDelegate.h\"\n\n\n@implementation ASICloudFilesCDNRequest\n\n@synthesize accountName, containerName, xmlParserDelegate;\n\n+ (id)cdnRequestWithMethod:(NSString *)method query:(NSString *)query {\n\tNSString *urlString = [NSString stringWithFormat:@\"%@%@\", [ASICloudFilesRequest cdnManagementURL], query];\n\tASICloudFilesCDNRequest *request = [[[ASICloudFilesCDNRequest alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];\n\t[request setRequestMethod:method];\n\t[request addRequestHeader:@\"X-Auth-Token\" value:[ASICloudFilesRequest authToken]];\n\treturn request;\n}\n\n+ (id)cdnRequestWithMethod:(NSString *)method containerName:(NSString *)containerName {\n\tNSString *urlString = [NSString stringWithFormat:@\"%@/%@\", [ASICloudFilesRequest cdnManagementURL], containerName];\n\tASICloudFilesCDNRequest *request = [[[ASICloudFilesCDNRequest alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];\n\t[request setRequestMethod:method];\n\t[request addRequestHeader:@\"X-Auth-Token\" value:[ASICloudFilesRequest authToken]];\n\trequest.containerName = containerName;\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark HEAD - Container Info\n\n+ (id)containerInfoRequest:(NSString *)containerName {\n\tASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@\"HEAD\" containerName:containerName];\n\treturn request;\n}\n\n- (BOOL)cdnEnabled {\n    NSNumber *enabled = [[self responseHeaders] objectForKey:@\"X-CDN-Enabled\"];\n    if (!enabled) {\n        enabled = [[self responseHeaders] objectForKey:@\"X-Cdn-Enabled\"];\n    }\n\treturn [enabled boolValue];\n}\n\n- (NSString *)cdnURI {\n\tNSString *uri = [[self responseHeaders] objectForKey:@\"X-CDN-URI\"];\n    if (!uri) {\n        uri = [[self responseHeaders] objectForKey:@\"X-Cdn-Uri\"];\n    }\n    return uri;\n}\n\n- (NSString *)cdnSSLURI {\n    NSString *uri = [[self responseHeaders] objectForKey:@\"X-CDN-SSL-URI\"];\n    if (!uri) {\n        uri = [[self responseHeaders] objectForKey:@\"X-Cdn-Ssl-Uri\"];\n    }\n\treturn uri;\n}\n\n- (NSUInteger)cdnTTL {\n    NSNumber *ttl = [[self responseHeaders] objectForKey:@\"X-TTL\"];\n    if (!ttl) {\n        ttl = [[self responseHeaders] objectForKey:@\"X-Ttl\"];\n    }\n    return [ttl intValue];\n}\n\n#pragma mark -\n#pragma mark GET - CDN Container Lists\n\n+ (id)listRequest {\n\tASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@\"GET\" query:@\"?format=xml\"];\n\treturn request;\n}\n\n+ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker enabledOnly:(BOOL)enabledOnly  {\n\tNSString *query = @\"?format=xml\";\n\t\n\tif (limit > 0) {\n\t\tquery = [query stringByAppendingString:[NSString stringWithFormat:@\"&limit=%i\", limit]];\n\t}\n\t\n\tif (marker) {\n\t\tquery = [query stringByAppendingString:[NSString stringWithFormat:@\"&marker=%@\", marker]];\n\t}\n\t\n\tif (limit > 0) {\n\t\tquery = [query stringByAppendingString:[NSString stringWithFormat:@\"&limit=%i\", limit]];\n\t}\n\t\n\tASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@\"GET\" query:query];\n\treturn request;\n}\n\n- (NSArray *)containers {\n\tif (xmlParserDelegate.containerObjects) {\n\t\treturn xmlParserDelegate.containerObjects;\n\t}\n\t\n\tNSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];\n\tif (xmlParserDelegate == nil) {\n\t\txmlParserDelegate = [[ASICloudFilesContainerXMLParserDelegate alloc] init];\n\t}\n\t\n\t[parser setDelegate:xmlParserDelegate];\n\t[parser setShouldProcessNamespaces:NO];\n\t[parser setShouldReportNamespacePrefixes:NO];\n\t[parser setShouldResolveExternalEntities:NO];\n\t[parser parse];\n\t\n\treturn xmlParserDelegate.containerObjects;\n}\n\n#pragma mark -\n#pragma mark PUT - CDN Enable Container\n\n// PUT /<api version>/<account>/<container>\n// PUT operations against a Container are used to CDN-enable that Container.\n// Include an HTTP header of X-TTL to specify a custom TTL.\n+ (id)putRequestWithContainer:(NSString *)containerName {\n\tASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@\"PUT\" containerName:containerName];\n\treturn request;\n}\n\n+ (id)putRequestWithContainer:(NSString *)containerName ttl:(NSUInteger)ttl {\n\tASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@\"PUT\" containerName:containerName];\t\n\t[request addRequestHeader:@\"X-Ttl\" value:[NSString stringWithFormat:@\"%i\", ttl]];\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark POST - Adjust CDN Attributes\n\n// POST /<api version>/<account>/<container>\n// POST operations against a CDN-enabled Container are used to adjust CDN attributes.\n// The POST operation can be used to set a new TTL cache expiration or to enable/disable public sharing over the CDN.\n// X-TTL: 86400\n// X-CDN-Enabled: True\n+ (id)postRequestWithContainer:(NSString *)containerName {\n\tASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@\"POST\" containerName:containerName];\n\treturn request;\n}\n\n+ (id)postRequestWithContainer:(NSString *)containerName cdnEnabled:(BOOL)cdnEnabled ttl:(NSUInteger)ttl {\n\tASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest cdnRequestWithMethod:@\"POST\" containerName:containerName];\n\tif (ttl > 0) {\n\t\t[request addRequestHeader:@\"X-Ttl\" value:[NSString stringWithFormat:@\"%i\", ttl]];\n\t}\n\t[request addRequestHeader:@\"X-CDN-Enabled\" value:cdnEnabled ? @\"True\" : @\"False\"];\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark Memory Management\n\n-(void)dealloc {\n\t[accountName release];\n\t[containerName release];\n\t[xmlParserDelegate release];\n\t[super dealloc];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesContainer.h",
    "content": "//\n//  ASICloudFilesContainer.h\n//\n//  Created by Michael Mayo on 1/7/10.\n//\n\n#import <Foundation/Foundation.h>\n\n\n@interface ASICloudFilesContainer : NSObject {\n\t\n\t// regular container attributes\n\tNSString *name;\n\tNSUInteger count;\n\tNSUInteger bytes;\n\t\n\t// CDN container attributes\n\tBOOL cdnEnabled;\n\tNSUInteger ttl;\n\tNSString *cdnURL;\n\tBOOL logRetention;\n\tNSString *referrerACL;\n\tNSString *useragentACL;\n}\n\n+ (id)container;\n\n// regular container attributes\n@property (retain) NSString *name;\n@property (assign) NSUInteger count;\n@property (assign) NSUInteger bytes;\n\n// CDN container attributes\n@property (assign) BOOL cdnEnabled;\n@property (assign) NSUInteger ttl;\n@property (retain) NSString *cdnURL;\n@property (assign) BOOL logRetention;\n@property (retain) NSString *referrerACL;\n@property (retain) NSString *useragentACL;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesContainer.m",
    "content": "//\n//  ASICloudFilesContainer.m\n//\n//  Created by Michael Mayo on 1/7/10.\n//\n\n#import \"ASICloudFilesContainer.h\"\n\n\n@implementation ASICloudFilesContainer\n\n// regular container attributes\n@synthesize name, count, bytes;\n\n// CDN container attributes\n@synthesize cdnEnabled, ttl, cdnURL, logRetention, referrerACL, useragentACL;\n\n+ (id)container {\n\tASICloudFilesContainer *container = [[[self alloc] init] autorelease];\n\treturn container;\n}\n\n-(void) dealloc {\n\t[name release];\n\t[cdnURL release];\n\t[referrerACL release];\n\t[useragentACL release];\n\t[super dealloc];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesContainerRequest.h",
    "content": "//\n//  ASICloudFilesContainerRequest.h\n//\n//  Created by Michael Mayo on 1/6/10.\n//\n\n#import \"ASICloudFilesRequest.h\"\n\n@class ASICloudFilesContainer, ASICloudFilesContainerXMLParserDelegate;\n\n@interface ASICloudFilesContainerRequest : ASICloudFilesRequest {\n\t\n\t// Internally used while parsing the response\n\tNSString *currentContent;\n\tNSString *currentElement;\n\tASICloudFilesContainer *currentObject;\n\tASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;\n}\n\n@property (retain) NSString *currentElement;\n@property (retain) NSString *currentContent;\n@property (retain) ASICloudFilesContainer *currentObject;\n@property (retain) ASICloudFilesContainerXMLParserDelegate *xmlParserDelegate;\n\n// HEAD /<api version>/<account>\n// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.\n+ (id)accountInfoRequest;\n- (NSUInteger)containerCount;\n- (NSUInteger)bytesUsed;\n\n// GET /<api version>/<account>/<container>\n// Create a request to list all containers\n+ (id)listRequest;\n+ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker;\n- (NSArray *)containers;\n\n// PUT /<api version>/<account>/<container>\n+ (id)createContainerRequest:(NSString *)containerName;\n\n// DELETE /<api version>/<account>/<container>\n+ (id)deleteContainerRequest:(NSString *)containerName;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesContainerRequest.m",
    "content": "//\n//  ASICloudFilesContainerRequest.m\n//\n//  Created by Michael Mayo on 1/6/10.\n//\n\n#import \"ASICloudFilesContainerRequest.h\"\n#import \"ASICloudFilesContainer.h\"\n#import \"ASICloudFilesContainerXMLParserDelegate.h\"\n\n\n@implementation ASICloudFilesContainerRequest\n\n@synthesize currentElement, currentContent, currentObject;\n@synthesize xmlParserDelegate;\n\n#pragma mark -\n#pragma mark Constructors\n\n+ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName queryString:(NSString *)queryString {\n\tNSString *urlString;\n\tif (containerName == nil) {\n\t\turlString = [NSString stringWithFormat:@\"%@%@\", [ASICloudFilesRequest storageURL], queryString];\n\t} else {\n\t\turlString = [NSString stringWithFormat:@\"%@/%@%@\", [ASICloudFilesRequest storageURL], containerName, queryString];\n\t}\n\n\tASICloudFilesContainerRequest *request = [[[ASICloudFilesContainerRequest alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];\n\t[request setRequestMethod:method];\n\t[request addRequestHeader:@\"X-Auth-Token\" value:[ASICloudFilesRequest authToken]];\n\treturn request;\n}\n\n+ (id)storageRequestWithMethod:(NSString *)method queryString:(NSString *)queryString {\n\treturn [ASICloudFilesContainerRequest storageRequestWithMethod:method containerName:nil queryString:queryString];\n}\n\n+ (id)storageRequestWithMethod:(NSString *)method {\n\treturn [ASICloudFilesContainerRequest storageRequestWithMethod:method queryString:@\"\"];\n}\n\n#pragma mark -\n#pragma mark HEAD - Retrieve Container Count and Total Bytes Used\n\n// HEAD /<api version>/<account>\n// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.\n+ (id)accountInfoRequest {\n\tASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@\"HEAD\"];\n\treturn request;\n}\n\n- (NSUInteger)containerCount {\n\treturn [[[self responseHeaders] objectForKey:@\"X-Account-Container-Count\"] intValue];\n}\n\n- (NSUInteger)bytesUsed {\n\treturn [[[self responseHeaders] objectForKey:@\"X-Account-Bytes-Used\"] intValue];\n}\n\n#pragma mark -\n#pragma mark GET - Retrieve Container List\n\n+ (id)listRequestWithLimit:(NSUInteger)limit marker:(NSString *)marker {\n\tNSString *queryString = @\"?format=xml\";\n\t\n\tif (limit > 0) {\n\t\tqueryString = [queryString stringByAppendingString:[NSString stringWithFormat:@\"&limit=%i\", limit]];\n\t}\n\t\n\tif (marker != nil) {\n\t\tqueryString = [queryString stringByAppendingString:[NSString stringWithFormat:@\"&marker=%@\", marker]];\n\t}\n\t\n\tASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@\"GET\" queryString:queryString];\n\treturn request;\n}\n\n// GET /<api version>/<account>/<container>\n// Create a request to list all containers\n+ (id)listRequest {\n\tASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@\"GET\" \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tqueryString:@\"?format=xml\"];\n\treturn request;\n}\n\n- (NSArray *)containers {\n\tif (xmlParserDelegate.containerObjects) {\n\t\treturn xmlParserDelegate.containerObjects;\n\t}\n\t\n\tNSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];\n\tif (xmlParserDelegate == nil) {\n\t\txmlParserDelegate = [[ASICloudFilesContainerXMLParserDelegate alloc] init];\n\t}\n\t\n\t[parser setDelegate:xmlParserDelegate];\n\t[parser setShouldProcessNamespaces:NO];\n\t[parser setShouldReportNamespacePrefixes:NO];\n\t[parser setShouldResolveExternalEntities:NO];\n\t[parser parse];\n\t\n\treturn xmlParserDelegate.containerObjects;\n}\n\n#pragma mark -\n#pragma mark PUT - Create Container\n\n// PUT /<api version>/<account>/<container>\n+ (id)createContainerRequest:(NSString *)containerName {\n\tASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@\"PUT\" containerName:containerName queryString:@\"\"];\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark DELETE - Delete Container\n\n// DELETE /<api version>/<account>/<container>\n+ (id)deleteContainerRequest:(NSString *)containerName {\n\tASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@\"DELETE\" containerName:containerName queryString:@\"\"];\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark Memory Management\n\n- (void)dealloc {\n\t[currentElement release];\n\t[currentContent release];\n\t[currentObject release];\n\t[xmlParserDelegate release];\n\t[super dealloc];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesContainerXMLParserDelegate.h",
    "content": "//\n//  ASICloudFilesContainerXMLParserDelegate.h\n//\n//  Created by Michael Mayo on 1/10/10.\n//\n\n#import \"ASICloudFilesRequest.h\"\n\n#if !TARGET_OS_IPHONE || (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_4_0)\n#import \"ASINSXMLParserCompat.h\"\n#endif\n\n@class ASICloudFilesContainer;\n\n@interface ASICloudFilesContainerXMLParserDelegate : NSObject <NSXMLParserDelegate> {\n\t\t\n\tNSMutableArray *containerObjects;\n\n\t// Internally used while parsing the response\n\tNSString *currentContent;\n\tNSString *currentElement;\n\tASICloudFilesContainer *currentObject;\n}\n\n@property (retain) NSMutableArray *containerObjects;\n\n@property (retain) NSString *currentElement;\n@property (retain) NSString *currentContent;\n@property (retain) ASICloudFilesContainer *currentObject;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesContainerXMLParserDelegate.m",
    "content": "//\n//  ASICloudFilesContainerXMLParserDelegate.m\n//\n//  Created by Michael Mayo on 1/10/10.\n//\n\n#import \"ASICloudFilesContainerXMLParserDelegate.h\"\n#import \"ASICloudFilesContainer.h\"\n\n\n@implementation ASICloudFilesContainerXMLParserDelegate\n\n@synthesize containerObjects, currentElement, currentContent, currentObject;\n\n#pragma mark -\n#pragma mark XML Parser Delegate\n\n- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {\n\t[self setCurrentElement:elementName];\n\t\n\tif ([elementName isEqualToString:@\"container\"]) {\n\t\t[self setCurrentObject:[ASICloudFilesContainer container]];\n\t}\n\t[self setCurrentContent:@\"\"];\n}\n\n- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {\n\n\tif ([elementName isEqualToString:@\"name\"]) {\n\t\t[self currentObject].name = [self currentContent];\n\t} else if ([elementName isEqualToString:@\"count\"]) {\n\t\t[self currentObject].count = [[self currentContent] intValue];\n\t} else if ([elementName isEqualToString:@\"bytes\"]) {\n\t\t[self currentObject].bytes = [[self currentContent] intValue];\n\t} else if ([elementName isEqualToString:@\"cdn_enabled\"]) {\n\t\t[self currentObject].cdnEnabled = [[self currentObject] isEqual:@\"True\"];\n\t} else if ([elementName isEqualToString:@\"ttl\"]) {\n\t\t[self currentObject].ttl = [[self currentContent] intValue];\n\t} else if ([elementName isEqualToString:@\"cdn_url\"]) {\n\t\t[self currentObject].cdnURL = [self currentContent];\n\t} else if ([elementName isEqualToString:@\"log_retention\"]) {\n\t\t[self currentObject].logRetention = [[self currentObject] isEqual:@\"True\"];\n\t} else if ([elementName isEqualToString:@\"referrer_acl\"]) {\n\t\t[self currentObject].referrerACL = [self currentContent];\n\t} else if ([elementName isEqualToString:@\"useragent_acl\"]) {\n\t\t[self currentObject].useragentACL = [self currentContent];\n\t} else if ([elementName isEqualToString:@\"container\"]) {\n\t\t// we're done with this container.  time to move on to the next\n\t\tif (containerObjects == nil) {\n\t\t\tcontainerObjects = [[NSMutableArray alloc] init];\n\t\t}\n\t\t[containerObjects addObject:currentObject];\n\t\t[self setCurrentObject:nil];\n\t}\n}\n\n- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {\n\t[self setCurrentContent:[[self currentContent] stringByAppendingString:string]];\n}\n\n#pragma mark -\n#pragma mark Memory Management\n\n- (void)dealloc {\n\t[containerObjects release];\n\t[currentElement release];\n\t[currentContent release];\n\t[currentObject release];\n\t[super dealloc];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesObject.h",
    "content": "//\n//  ASICloudFilesObject.h\n//\n//  Created by Michael Mayo on 1/7/10.\n//\n\n#import <Foundation/Foundation.h>\n\n\n@interface ASICloudFilesObject : NSObject {\n\tNSString *name;\n\tNSString *hash;\n\tNSUInteger bytes;\n\tNSString *contentType;\n\tNSDate *lastModified;\n\tNSData *data;\n\tNSMutableDictionary *metadata;\n}\n\n@property (retain) NSString *name;\n@property (retain) NSString *hash;\n@property (assign) NSUInteger bytes;\n@property (retain) NSString *contentType;\n@property (retain) NSDate *lastModified;\n@property (retain) NSData *data;\t\n@property (retain) NSMutableDictionary *metadata;\n\n+ (id)object;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesObject.m",
    "content": "//\n//  ASICloudFilesObject.m\n//\n//  Created by Michael Mayo on 1/7/10.\n//\n\n#import \"ASICloudFilesObject.h\"\n\n\n@implementation ASICloudFilesObject\n\n@synthesize name, hash, bytes, contentType, lastModified, data, metadata;\n\n+ (id)object {\n\tASICloudFilesObject *object = [[[self alloc] init] autorelease];\n\treturn object;\n}\n\n-(void)dealloc {\n\t[name release];\n\t[hash release];\n\t[contentType release];\n\t[lastModified release];\n\t[data release];\n\t[metadata release];\n\t[super dealloc];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesObjectRequest.h",
    "content": "//\n//  ASICloudFilesObjectRequest.h\n//\n//  Created by Michael Mayo on 1/6/10.\n//\n\n#import \"ASICloudFilesRequest.h\"\n\n#if !TARGET_OS_IPHONE || (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_4_0)\n#import \"ASINSXMLParserCompat.h\"\n#endif\n\n@class ASICloudFilesObject;\n\n@interface ASICloudFilesObjectRequest : ASICloudFilesRequest <NSXMLParserDelegate> {\n\n\t\n\tNSString *accountName;\n\tNSString *containerName;\n\t\n\t// Internally used while parsing the response\n\tNSString *currentContent;\n\tNSString *currentElement;\n\tASICloudFilesObject *currentObject;\n\tNSMutableArray *objects;\n\t\n}\n\n@property (retain) NSString *accountName;\n@property (retain) NSString *containerName;\n@property (retain) NSString *currentElement;\n@property (retain) NSString *currentContent;\n@property (retain) ASICloudFilesObject *currentObject;\n\n\n// HEAD /<api version>/<account>/<container>\n// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.\n+ (id)containerInfoRequest:(NSString *)containerName;\n- (NSUInteger)containerObjectCount;\n- (NSUInteger)containerBytesUsed;\n\n// HEAD /<api version>/<account>/<container>/<object>\n// to get metadata\n+ (id)objectInfoRequest:(NSString *)containerName objectPath:(NSString *)objectPath;\n- (NSArray *)objects;\n\n+ (id)listRequestWithContainer:(NSString *)containerName;\n+ (id)listRequestWithContainer:(NSString *)containerName limit:(NSUInteger)limit marker:(NSString *)marker prefix:(NSString *)prefix path:(NSString *)path;\n\n// Conditional GET headers: If-Match • If-None-Match • If-Modified-Since • If-Unmodified-Since\n// HTTP Range header: “Range: bytes=0-5” •\t“Range: bytes=-5” •\t“Range: bytes=32-“\n+ (id)getObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath;\n- (ASICloudFilesObject *)object;\n\n// PUT /<api version>/<account>/<container>/<object>\n// PUT operations are used to write, or overwrite, an Object's metadata and content.\n// The Object can be created with custom metadata via HTTP headers identified with the “X-Object-Meta-” prefix.\n+ (id)putObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object;\n+ (id)putObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath contentType:(NSString *)contentType objectData:(NSData *)objectData metadata:(NSDictionary *)metadata etag:(NSString *)etag;\n+ (id)putObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath contentType:(NSString *)contentType file:(NSString *)filePath metadata:(NSDictionary *)metadata etag:(NSString *)etag;\n\n// POST /<api version>/<account>/<container>/<object>\n// POST operations against an Object name are used to set and overwrite arbitrary key/value metadata. You cannot use the POST operation to change any of the Object's other headers such as Content-Type, ETag, etc. It is not used to upload storage Objects (see PUT).\n// A POST request will delete all existing metadata added with a previous PUT/POST.\n+ (id)postObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object;\n+ (id)postObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath metadata:(NSDictionary *)metadata;\n\n// DELETE /<api version>/<account>/<container>/<object>\n+ (id)deleteObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesObjectRequest.m",
    "content": "//\n//  ASICloudFilesObjectRequest.m\n//\n//  Created by Michael Mayo on 1/6/10.\n//\n\n#import \"ASICloudFilesObjectRequest.h\"\n#import \"ASICloudFilesObject.h\"\n\n\n@implementation ASICloudFilesObjectRequest\n\n@synthesize currentElement, currentContent, currentObject;\n@synthesize accountName, containerName;\n\n#pragma mark -\n#pragma mark Constructors\n\n+ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName {\n\tNSString *urlString = [NSString stringWithFormat:@\"%@/%@\", [ASICloudFilesRequest storageURL], containerName];\n\tASICloudFilesObjectRequest *request = [[[ASICloudFilesObjectRequest alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];\n\t[request setRequestMethod:method];\n\t[request addRequestHeader:@\"X-Auth-Token\" value:[ASICloudFilesRequest authToken]];\n\trequest.containerName = containerName;\n\treturn request;\n}\n\n+ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName queryString:(NSString *)queryString {\n\tNSString *urlString = [NSString stringWithFormat:@\"%@/%@%@\", [ASICloudFilesRequest storageURL], containerName, queryString];\n\tASICloudFilesObjectRequest *request = [[[ASICloudFilesObjectRequest alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];\n\t[request setRequestMethod:method];\n\t[request addRequestHeader:@\"X-Auth-Token\" value:[ASICloudFilesRequest authToken]];\n\trequest.containerName = containerName;\n\treturn request;\n}\n\n+ (id)storageRequestWithMethod:(NSString *)method containerName:(NSString *)containerName objectPath:(NSString *)objectPath {\n\tNSString *urlString = [NSString stringWithFormat:@\"%@/%@/%@\", [ASICloudFilesRequest storageURL], containerName, objectPath];\n\tASICloudFilesObjectRequest *request = [[[ASICloudFilesObjectRequest alloc] initWithURL:[NSURL URLWithString:urlString]] autorelease];\n\t[request setRequestMethod:method];\n\t[request addRequestHeader:@\"X-Auth-Token\" value:[ASICloudFilesRequest authToken]];\n\trequest.containerName = containerName;\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark HEAD - Container Info\n\n+ (id)containerInfoRequest:(NSString *)containerName {\n\tASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@\"HEAD\" containerName:containerName];\n\treturn request;\n}\n\n- (NSUInteger)containerObjectCount {\n\treturn [[[self responseHeaders] objectForKey:@\"X-Container-Object-Count\"] intValue];\n}\n\n- (NSUInteger)containerBytesUsed {\n\treturn [[[self responseHeaders] objectForKey:@\"X-Container-Bytes-Used\"] intValue];\n}\n\n#pragma mark -\n#pragma mark HEAD - Object Info\n\n+ (id)objectInfoRequest:(NSString *)containerName objectPath:(NSString *)objectPath {\n\tASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@\"HEAD\" containerName:containerName objectPath:objectPath];\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark GET - List Objects\n\n+ (NSString *)queryStringWithContainer:(NSString *)container limit:(NSUInteger)limit marker:(NSString *)marker prefix:(NSString *)prefix path:(NSString *)path {\n\tNSString *queryString = @\"?format=xml\";\n\t\n\tif (limit && limit > 0) {\n\t\tqueryString = [queryString stringByAppendingString:[NSString stringWithFormat:@\"&limit=%i\", limit]];\n\t}\n\tif (marker) {\n\t\tqueryString = [queryString stringByAppendingString:[NSString stringWithFormat:@\"&marker=%@\", [marker stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];\n\t}\n\tif (path) {\n\t\tqueryString = [queryString stringByAppendingString:[NSString stringWithFormat:@\"&path=%@\", [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];\n\t}\n\t\n\treturn queryString;\n}\n\n+ (id)listRequestWithContainer:(NSString *)containerName limit:(NSUInteger)limit marker:(NSString *)marker prefix:(NSString *)prefix path:(NSString *)path {\n\tNSString *queryString = [ASICloudFilesObjectRequest queryStringWithContainer:containerName limit:limit marker:marker prefix:prefix path:path];\n\tASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@\"GET\" containerName:containerName queryString:queryString];\n\treturn request;\n}\n\n+ (id)listRequestWithContainer:(NSString *)containerName {\n\treturn [ASICloudFilesObjectRequest listRequestWithContainer:containerName limit:0 marker:nil prefix:nil path:nil];\n}\n\n- (NSArray *)objects {\n\tif (objects) {\n\t\treturn objects;\n\t}\n\tobjects = [[[NSMutableArray alloc] init] autorelease];\n\t\n\tNSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];\n\t[parser setDelegate:self];\n\t[parser setShouldProcessNamespaces:NO];\n\t[parser setShouldReportNamespacePrefixes:NO];\n\t[parser setShouldResolveExternalEntities:NO];\n\t[parser parse];\n\treturn objects;\n}\n\n#pragma mark -\n#pragma mark GET - Retrieve Object\n\n+ (id)getObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath {\n\treturn [ASICloudFilesObjectRequest storageRequestWithMethod:@\"GET\" containerName:containerName objectPath:objectPath];\n}\n\n- (ASICloudFilesObject *)object {\n\tASICloudFilesObject *object = [ASICloudFilesObject object];\n\t\n\tNSString *path = [self url].path;\n\tNSRange range = [path rangeOfString:self.containerName];\n\tpath = [path substringFromIndex:range.location + range.length + 1];\n\t\n\tobject.name = path;\n\tobject.hash = [[self responseHeaders] objectForKey:@\"ETag\"];\n\tobject.bytes = [[[self responseHeaders] objectForKey:@\"Content-Length\"] intValue];\n\tobject.contentType = [[self responseHeaders] objectForKey:@\"Content-Type\"];\n\tobject.lastModified = [[self responseHeaders] objectForKey:@\"Last-Modified\"];\n\tobject.metadata = [NSMutableDictionary dictionary];\n\t\n\tfor (NSString *key in [[self responseHeaders] keyEnumerator]) {\n\t\tNSRange metaRange = [key rangeOfString:@\"X-Object-Meta-\"];\n\t\tif (metaRange.location == 0) {\n\t\t\t[object.metadata setObject:[[self responseHeaders] objectForKey:key] forKey:[key substringFromIndex:metaRange.length]];\n\t\t}\n\t}\n\t\n\tobject.data = [self responseData];\n\t\n\treturn object;\n}\n\n#pragma mark -\n#pragma mark PUT - Upload Object\n\n+ (id)putObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object {\n\treturn [self putObjectRequestWithContainer:containerName objectPath:object.name contentType:object.contentType objectData:object.data metadata:object.metadata etag:nil];\n}\n\n+ (id)putObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath contentType:(NSString *)contentType objectData:(NSData *)objectData metadata:(NSDictionary *)metadata etag:(NSString *)etag {\n\t\n\tASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@\"PUT\" containerName:containerName objectPath:objectPath];\n\t[request addRequestHeader:@\"Content-Type\" value:contentType];\n\n\t// add metadata to headers\n\tif (metadata) {\n\t\tfor (NSString *key in [metadata keyEnumerator]) {\n\t\t\t[request addRequestHeader:[NSString stringWithFormat:@\"X-Object-Meta-%@\", key] value:[metadata objectForKey:key]];\n\t\t}\n\t}\t\n\t\n\t[request appendPostData:objectData];\t\n\treturn request;\n}\n\n+ (id)putObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath contentType:(NSString *)contentType file:(NSString *)filePath metadata:(NSDictionary *)metadata etag:(NSString *)etag\n{\n\tASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@\"PUT\" containerName:containerName objectPath:objectPath];\n\t[request addRequestHeader:@\"Content-Type\" value:contentType];\n\t\n\t// add metadata to headers\n\tif (metadata) {\n\t\tfor (NSString *key in [metadata keyEnumerator]) {\n\t\t\t[request addRequestHeader:[NSString stringWithFormat:@\"X-Object-Meta-%@\", key] value:[metadata objectForKey:key]];\n\t\t}\n\t}\t\n\t\n\t[request setShouldStreamPostDataFromDisk:YES];\n\t[request setPostBodyFilePath:filePath];\n\treturn request;\t\n}\n\n#pragma mark -\n#pragma mark POST - Set Object Metadata\n\n+ (id)postObjectRequestWithContainer:(NSString *)containerName object:(ASICloudFilesObject *)object {\n\treturn [self postObjectRequestWithContainer:containerName objectPath:object.name metadata:object.metadata];\n}\n\n+ (id)postObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath metadata:(NSDictionary *)metadata {\n\tASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@\"POST\" containerName:containerName objectPath:objectPath];\n\t\n\t// add metadata to headers\n\tif (metadata) {\n\t\tfor (NSString *key in [metadata keyEnumerator]) {\n\t\t\t[request addRequestHeader:[NSString stringWithFormat:@\"X-Object-Meta-%@\", key] value:[metadata objectForKey:key]];\n\t\t}\n\t}\t\n\t\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark DELETE - Delete Object\n\n+ (id)deleteObjectRequestWithContainer:(NSString *)containerName objectPath:(NSString *)objectPath {\n\tASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest storageRequestWithMethod:@\"DELETE\" containerName:containerName objectPath:objectPath];\n\treturn request;\n}\n\n#pragma mark -\n#pragma mark XML Parser Delegate\n\n- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {\n\t[self setCurrentElement:elementName];\n\t\n\tif ([elementName isEqualToString:@\"object\"]) {\n\t\t[self setCurrentObject:[ASICloudFilesObject object]];\n\t}\n\t[self setCurrentContent:@\"\"];\n}\n\n- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {\n\tif ([elementName isEqualToString:@\"name\"]) {\n\t\t[self currentObject].name = [self currentContent];\n\t} else if ([elementName isEqualToString:@\"hash\"]) {\n\t\t[self currentObject].hash = [self currentContent];\n\t} else if ([elementName isEqualToString:@\"bytes\"]) {\n\t\t[self currentObject].bytes = [[self currentContent] intValue];\n\t} else if ([elementName isEqualToString:@\"content_type\"]) {\n\t\t[self currentObject].contentType = [self currentContent];\n\t} else if ([elementName isEqualToString:@\"last_modified\"]) {\n\t\t[self currentObject].lastModified = [self dateFromString:[self currentContent]];\n\t} else if ([elementName isEqualToString:@\"object\"]) {\n\t\t// we're done with this object.  time to move on to the next\n\t\t[objects addObject:currentObject];\n\t\t[self setCurrentObject:nil];\n\t}\n}\n\n- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {\n\t[self setCurrentContent:[[self currentContent] stringByAppendingString:string]];\n}\n\n#pragma mark -\n#pragma mark Memory Management\n\n- (void)dealloc {\n\t[currentElement release];\n\t[currentContent release];\n\t[currentObject release];\n\t[accountName release];\n\t[containerName release];\n\t[super dealloc];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesRequest.h",
    "content": "//\n//  ASICloudFilesRequest.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Michael Mayo on 22/12/09.  \n//  mike.mayo@rackspace.com or mike@overhrd.com\n//  twitter.com/greenisus\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n// A class for accessing data stored on the Rackspace Cloud Files Service\n// http://www.rackspacecloud.com/cloud_hosting_products/files\n// \n// Cloud Files Developer Guide:\n// http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf\n\n#import <Foundation/Foundation.h>\n#import \"ASIHTTPRequest.h\"\n\n\n@interface ASICloudFilesRequest : ASIHTTPRequest {\n}\n\n+ (NSString *)storageURL;\n+ (NSString *)cdnManagementURL;\n+ (NSString *)authToken;\n\n#pragma mark Rackspace Cloud Authentication\n\n+ (id)authenticationRequest;\n+ (NSError *)authenticate;\n+ (NSString *)username;\n+ (void)setUsername:(NSString *)username;\n+ (NSString *)apiKey;\n+ (void)setApiKey:(NSString *)apiKey;\n\n// helper to parse dates in the format returned by Cloud Files\n-(NSDate *)dateFromString:(NSString *)dateString;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/CloudFiles/ASICloudFilesRequest.m",
    "content": "//\n//  ASICloudFilesRequest.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Michael Mayo on 22/12/09.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n// A class for accessing data stored on Rackspace's Cloud Files Service\n// http://www.rackspacecloud.com/cloud_hosting_products/files\n// \n// Cloud Files Developer Guide:\n// http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf\n\n#import \"ASICloudFilesRequest.h\"\n\nstatic NSString *username = nil;\nstatic NSString *apiKey = nil;\nstatic NSString *authToken = nil;\nstatic NSString *storageURL = nil;\nstatic NSString *cdnManagementURL = nil;\nstatic NSString *rackspaceCloudAuthURL = @\"https://auth.api.rackspacecloud.com/v1.0\";\n\nstatic NSRecursiveLock *accessDetailsLock = nil;\n\n@implementation ASICloudFilesRequest\n\n+ (void)initialize\n{\n\tif (self == [ASICloudFilesRequest class]) {\n\t\taccessDetailsLock = [[NSRecursiveLock alloc] init];\n\t}\n}\n\n#pragma mark -\n#pragma mark Attributes and Service URLs\n\n+ (NSString *)authToken {\n\treturn authToken;\n}\n\n+ (NSString *)storageURL {\n\treturn storageURL;\n}\n\n+ (NSString *)cdnManagementURL {\n\treturn cdnManagementURL;\n}\n\n#pragma mark -\n#pragma mark Authentication\n\n+ (id)authenticationRequest\n{\n\t[accessDetailsLock lock];\n\tASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:rackspaceCloudAuthURL]] autorelease];\n\t[request addRequestHeader:@\"X-Auth-User\" value:username];\n\t[request addRequestHeader:@\"X-Auth-Key\" value:apiKey];\n\t[accessDetailsLock unlock];\n\treturn request;\n}\n\n+ (NSError *)authenticate\n{\n\t[accessDetailsLock lock];\n\tASIHTTPRequest *request = [ASICloudFilesRequest authenticationRequest];\n\t[request startSynchronous];\n\t\n\tif (![request error]) {\n\t\tNSDictionary *responseHeaders = [request responseHeaders];\n\t\tauthToken = [responseHeaders objectForKey:@\"X-Auth-Token\"];\n\t\tstorageURL = [responseHeaders objectForKey:@\"X-Storage-Url\"];\n\t\tcdnManagementURL = [responseHeaders objectForKey:@\"X-CDN-Management-Url\"];\n        \n        // there is a bug in the Cloud Files API for some older accounts that causes\n        // the CDN URL to come back in a slightly different header\n        if (!cdnManagementURL) {\n            cdnManagementURL = [responseHeaders objectForKey:@\"X-Cdn-Management-Url\"];\n        }\n\t}\n\t[accessDetailsLock unlock];\n\treturn [request error];\n}\n\n+ (NSString *)username\n{\n\treturn username;\n}\n\n+ (void)setUsername:(NSString *)newUsername\n{\n\t[accessDetailsLock lock];\n\t[username release];\n\tusername = [newUsername retain];\n\t[accessDetailsLock unlock];\n}\n\n+ (NSString *)apiKey {\n\treturn apiKey;\n}\n\n+ (void)setApiKey:(NSString *)newApiKey\n{\n\t[accessDetailsLock lock];\n\t[apiKey release];\n\tapiKey = [newApiKey retain];\n\t[accessDetailsLock unlock];\n}\n\n#pragma mark -\n#pragma mark Date Parser\n\n-(NSDate *)dateFromString:(NSString *)dateString\n{\n\t// We store our date formatter in the calling thread's dictionary\n\t// NSDateFormatter is not thread-safe, this approach ensures each formatter is only used on a single thread\n\t// This formatter can be reused many times in parsing a single response, so it would be expensive to keep creating new date formatters\n\tNSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];\n\tNSDateFormatter *dateFormatter = [threadDict objectForKey:@\"ASICloudFilesResponseDateFormatter\"];\n\tif (dateFormatter == nil) {\n\t\tdateFormatter = [[[NSDateFormatter alloc] init] autorelease];\n\t\t[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"] autorelease]];\n\t\t// example: 2009-11-04T19:46:20.192723\n\t\t[dateFormatter setDateFormat:@\"yyyy-MM-dd'T'H:mm:ss.SSSSSS\"];\n\t\t[threadDict setObject:dateFormatter forKey:@\"ASICloudFilesResponseDateFormatter\"];\n\t}\n\treturn [dateFormatter dateFromString:dateString];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASINSXMLParserCompat.h",
    "content": "//\n//  ASINSXMLParserCompat.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//  This file exists to prevent warnings about the NSXMLParserDelegate protocol when building S3 or Cloud Files stuff\n//\n//  Created by Ben Copsey on 17/06/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n\n#if (!TARGET_OS_IPHONE  && __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_6) || (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED <= __IPHONE_4_0)\n@protocol NSXMLParserDelegate\n\n@optional\n- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;\n- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;\n\n@end\n#endif\n\n\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3Bucket.h",
    "content": "//\n//  ASIS3Bucket.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n//  Instances of this class represent buckets stored on S3\n//  ASIS3ServiceRequests return an array of ASIS3Buckets when you perform a service GET query\n//  You'll probably never need to create instances of ASIS3Bucket yourself\n\n#import <Foundation/Foundation.h>\n\n\n@interface ASIS3Bucket : NSObject {\n\t\n\t// The name of this bucket (will be unique throughout S3)\n\tNSString *name;\n\t\n\t// The date this bucket was created\n\tNSDate *creationDate;\n\t\n\t// Information about the owner of this bucket\n\tNSString *ownerID;\n\tNSString *ownerName;\n}\n\n+ (id)bucketWithOwnerID:(NSString *)ownerID ownerName:(NSString *)ownerName;\n\n@property (retain) NSString *name;\n@property (retain) NSDate *creationDate;\n@property (retain) NSString *ownerID;\n@property (retain) NSString *ownerName;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3Bucket.m",
    "content": "//\n//  ASIS3Bucket.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIS3Bucket.h\"\n\n\n@implementation ASIS3Bucket\n\n+ (id)bucketWithOwnerID:(NSString *)anOwnerID ownerName:(NSString *)anOwnerName\n{\n\tASIS3Bucket *bucket = [[[self alloc] init] autorelease];\n\t[bucket setOwnerID:anOwnerID];\n\t[bucket setOwnerName:anOwnerName];\n\treturn bucket;\n}\n\n- (void)dealloc\n{\n\t[name release];\n\t[creationDate release];\n\t[ownerID release];\n\t[ownerName release];\n\t[super dealloc];\n}\n\n- (NSString *)description\n{\n\treturn [NSString stringWithFormat:@\"Name: %@ creationDate: %@ ownerID: %@ ownerName: %@\",[self name],[self creationDate],[self ownerID],[self ownerName]];\n}\n\n@synthesize name;\n@synthesize creationDate;\n@synthesize ownerID;\n@synthesize ownerName;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3BucketObject.h",
    "content": "//\n//  ASIS3BucketObject.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 13/07/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n//  Instances of this class represent objects stored in a bucket on S3\n//  ASIS3BucketRequests return an array of ASIS3BucketObjects when you perform a list query\n\n#import <Foundation/Foundation.h>\n@class ASIS3ObjectRequest;\n\n@interface ASIS3BucketObject : NSObject <NSCopying> {\n\t\n\t// The bucket this object belongs to\n\tNSString *bucket;\n\t\n\t// The key (path) of this object in the bucket\n\tNSString *key;\n\t\n\t// When this object was last modified\n\tNSDate *lastModified;\n\t\n\t// The ETag for this object's content\n\tNSString *ETag;\n\t\n\t// The size in bytes of this object\n\tunsigned long long size;\n\t\n\t// Info about the owner\n\tNSString *ownerID;\n\tNSString *ownerName;\n}\n\n+ (id)objectWithBucket:(NSString *)bucket;\n\n// Returns a request that will fetch this object when run\n- (ASIS3ObjectRequest *)GETRequest;\n\n// Returns a request that will replace this object with the contents of the file at filePath when run\n- (ASIS3ObjectRequest *)PUTRequestWithFile:(NSString *)filePath;\n\n// Returns a request that will delete this object when run\n- (ASIS3ObjectRequest *)DELETERequest;\n\n@property (retain) NSString *bucket;\n@property (retain) NSString *key;\n@property (retain) NSDate *lastModified;\n@property (retain) NSString *ETag;\n@property (assign) unsigned long long size;\n@property (retain) NSString *ownerID;\n@property (retain) NSString *ownerName;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3BucketObject.m",
    "content": "//\n//  ASIS3BucketObject.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 13/07/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIS3BucketObject.h\"\n#import \"ASIS3ObjectRequest.h\"\n\n@implementation ASIS3BucketObject\n\n+ (id)objectWithBucket:(NSString *)theBucket\n{\n\tASIS3BucketObject *object = [[[self alloc] init] autorelease];\n\t[object setBucket:theBucket];\n\treturn object;\n}\n\n- (void)dealloc\n{\n\t[bucket release];\n\t[key release];\n\t[lastModified release];\n\t[ETag release];\n\t[ownerID release];\n\t[ownerName release];\n\t[super dealloc];\n}\n\n- (ASIS3ObjectRequest *)GETRequest\n{\n\treturn [ASIS3ObjectRequest requestWithBucket:[self bucket] key:[self key]];\n}\n\n- (ASIS3ObjectRequest *)PUTRequestWithFile:(NSString *)filePath\n{\n\treturn [ASIS3ObjectRequest PUTRequestForFile:filePath withBucket:[self bucket] key:[self key]];\n}\n\n- (ASIS3ObjectRequest *)DELETERequest\n{\n\tASIS3ObjectRequest *request = [ASIS3ObjectRequest requestWithBucket:[self bucket] key:[self key]];\n\t[request setRequestMethod:@\"DELETE\"];\n\treturn request;\n}\n\n- (NSString *)description\n{\n\treturn [NSString stringWithFormat:@\"Key: %@ lastModified: %@ ETag: %@ size: %llu ownerID: %@ ownerName: %@\",[self key],[self lastModified],[self ETag],[self size],[self ownerID],[self ownerName]];\n}\n\n- (id)copyWithZone:(NSZone *)zone\n{\n\tASIS3BucketObject *newBucketObject = [[[self class] alloc] init];\n\t[newBucketObject setBucket:[self bucket]];\n\t[newBucketObject setKey:[self key]];\n\t[newBucketObject setLastModified:[self lastModified]];\n\t[newBucketObject setETag:[self ETag]];\n\t[newBucketObject setSize:[self size]];\n\t[newBucketObject setOwnerID:[self ownerID]];\n\t[newBucketObject setOwnerName:[self ownerName]];\n\treturn newBucketObject;\n}\n\n@synthesize bucket;\n@synthesize key;\n@synthesize lastModified;\n@synthesize ETag;\n@synthesize size;\n@synthesize ownerID;\n@synthesize ownerName;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3BucketRequest.h",
    "content": "//\n//  ASIS3BucketRequest.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n//  Use this class to create buckets, fetch a list of their contents, and delete buckets\n\n#import <Foundation/Foundation.h>\n#import \"ASIS3Request.h\"\n\n@class ASIS3BucketObject;\n\n@interface ASIS3BucketRequest : ASIS3Request {\n\t\n\t// Name of the bucket to talk to\n\tNSString *bucket;\n\t\n\t// A parameter passed to S3 in the query string to tell it to return specialised information\n\t// Consult the S3 REST API documentation for more info\n\tNSString *subResource;\n\t\n\t// Options for filtering GET requests\n\t// See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html\n\tNSString *prefix;\n\tNSString *marker;\n\tint maxResultCount;\n\tNSString *delimiter;\n\t\n\t// Internally used while parsing the response\n\tASIS3BucketObject *currentObject;\n\t\n\t// Returns an array of ASIS3BucketObjects created from the XML response\n\tNSMutableArray *objects;\t\n\t\n\t// Will be populated with a list of 'folders' when a delimiter is set\n\tNSMutableArray *commonPrefixes;\n\t\n\t// Will be true if this request did not return all the results matching the query (use maxResultCount to configure the number of results to return)\n\tBOOL isTruncated;\n}\n\n// Fetch a bucket\n+ (id)requestWithBucket:(NSString *)bucket;\n\n// Create a bucket request, passing a parameter in the query string\n// You'll need to parse the response XML yourself\n// Examples:\n// Fetch ACL:\n// ASIS3BucketRequest *request = [ASIS3BucketRequest requestWithBucket:@\"mybucket\" parameter:@\"acl\"];\n// Fetch Location:\n// ASIS3BucketRequest *request = [ASIS3BucketRequest requestWithBucket:@\"mybucket\" parameter:@\"location\"];\n// See the S3 REST API docs for more information about the parameters you can pass\n+ (id)requestWithBucket:(NSString *)bucket subResource:(NSString *)subResource;\n\n// Use for creating new buckets\n+ (id)PUTRequestWithBucket:(NSString *)bucket;\n\n// Use for deleting buckets - they must be empty for this to succeed\n+ (id)DELETERequestWithBucket:(NSString *)bucket;\n\n@property (retain, nonatomic) NSString *bucket;\n@property (retain, nonatomic) NSString *subResource;\n@property (retain, nonatomic) NSString *prefix;\n@property (retain, nonatomic) NSString *marker;\n@property (assign, nonatomic) int maxResultCount;\n@property (retain, nonatomic) NSString *delimiter;\n@property (retain, readonly) NSMutableArray *objects;\n@property (retain, readonly) NSMutableArray *commonPrefixes;\n@property (assign, readonly) BOOL isTruncated;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3BucketRequest.m",
    "content": "//\n//  ASIS3BucketRequest.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIS3BucketRequest.h\"\n#import \"ASIS3BucketObject.h\"\n\n\n// Private stuff\n@interface ASIS3BucketRequest ()\n@property (retain, nonatomic) ASIS3BucketObject *currentObject;\n@property (retain) NSMutableArray *objects;\n@property (retain) NSMutableArray *commonPrefixes;\n@property (assign) BOOL isTruncated;\n@end\n\n@implementation ASIS3BucketRequest\n\n- (id)initWithURL:(NSURL *)newURL\n{\n\tself = [super initWithURL:newURL];\n\t[self setObjects:[[[NSMutableArray alloc] init] autorelease]];\n\t[self setCommonPrefixes:[[[NSMutableArray alloc] init] autorelease]];\n\treturn self;\n}\n\n+ (id)requestWithBucket:(NSString *)theBucket\n{\n\tASIS3BucketRequest *request = [[[self alloc] initWithURL:nil] autorelease];\n\t[request setBucket:theBucket];\n\treturn request;\n}\n\n+ (id)requestWithBucket:(NSString *)theBucket subResource:(NSString *)theSubResource\n{\n\tASIS3BucketRequest *request = [[[self alloc] initWithURL:nil] autorelease];\n\t[request setBucket:theBucket];\n\t[request setSubResource:theSubResource];\n\treturn request;\n}\n\n+ (id)PUTRequestWithBucket:(NSString *)theBucket\n{\n\tASIS3BucketRequest *request = [self requestWithBucket:theBucket];\n\t[request setRequestMethod:@\"PUT\"];\n\treturn request;\n}\n\n\n+ (id)DELETERequestWithBucket:(NSString *)theBucket\n{\n\tASIS3BucketRequest *request = [self requestWithBucket:theBucket];\n\t[request setRequestMethod:@\"DELETE\"];\n\treturn request;\n}\n\n- (void)dealloc\n{\n\t[currentObject release];\n\t[objects release];\n\t[commonPrefixes release];\n\t[prefix release];\n\t[marker release];\n\t[delimiter release];\n\t[subResource release];\n\t[bucket release];\n\t[super dealloc];\n}\n\n- (NSString *)canonicalizedResource\n{\n\tif ([self subResource]) {\n\t\treturn [NSString stringWithFormat:@\"/%@/?%@\",[self bucket],[self subResource]];\n\t} \n\treturn [NSString stringWithFormat:@\"/%@/\",[self bucket]];\n}\n\n- (void)buildURL\n{\n\tNSString *baseURL;\n\tif ([self subResource]) {\n\t\tbaseURL = [NSString stringWithFormat:@\"%@://%@.%@/?%@\",[self requestScheme],[self bucket],[[self class] S3Host],[self subResource]];\n\t} else {\n\t\tbaseURL = [NSString stringWithFormat:@\"%@://%@.%@\",[self requestScheme],[self bucket],[[self class] S3Host]];\n\t}\n\tNSMutableArray *queryParts = [[[NSMutableArray alloc] init] autorelease];\n\tif ([self prefix]) {\n\t\t[queryParts addObject:[NSString stringWithFormat:@\"prefix=%@\",[[self prefix] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];\n\t}\n\tif ([self marker]) {\n\t\t[queryParts addObject:[NSString stringWithFormat:@\"marker=%@\",[[self marker] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];\n\t}\n\tif ([self delimiter]) {\n\t\t[queryParts addObject:[NSString stringWithFormat:@\"delimiter=%@\",[[self delimiter] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];\n\t}\n\tif ([self maxResultCount] > 0) {\n\t\t[queryParts addObject:[NSString stringWithFormat:@\"max-keys=%hi\",[self maxResultCount]]];\n\t}\n\tif ([queryParts count]) {\n\t\tNSString* template = @\"%@?%@\";\n\t\tif ([[self subResource] length] > 0) {\n\t\t\ttemplate = @\"%@&%@\";\n\t\t}\n\t\t[self setURL:[NSURL URLWithString:[NSString stringWithFormat:template,baseURL,[queryParts componentsJoinedByString:@\"&\"]]]];\n\t} else {\n\t\t[self setURL:[NSURL URLWithString:baseURL]];\n\n\t}\n}\n\n- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict\n{\n\tif ([elementName isEqualToString:@\"Contents\"]) {\n\t\t[self setCurrentObject:[ASIS3BucketObject objectWithBucket:[self bucket]]];\n\t}\n\t[super parser:parser didStartElement:elementName namespaceURI:namespaceURI qualifiedName:qName attributes:attributeDict];\n}\n\n- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName\n{\n\tif ([elementName isEqualToString:@\"Contents\"]) {\n\t\t[objects addObject:currentObject];\n\t\t[self setCurrentObject:nil];\n\t} else if ([elementName isEqualToString:@\"Key\"]) {\n\t\t[[self currentObject] setKey:[self currentXMLElementContent]];\n\t} else if ([elementName isEqualToString:@\"LastModified\"]) {\n\t\t[[self currentObject] setLastModified:[[ASIS3Request S3ResponseDateFormatter] dateFromString:[self currentXMLElementContent]]];\n\t} else if ([elementName isEqualToString:@\"ETag\"]) {\n\t\t[[self currentObject] setETag:[self currentXMLElementContent]];\n\t} else if ([elementName isEqualToString:@\"Size\"]) {\n\t\t[[self currentObject] setSize:(unsigned long long)[[self currentXMLElementContent] longLongValue]];\n\t} else if ([elementName isEqualToString:@\"ID\"]) {\n\t\t[[self currentObject] setOwnerID:[self currentXMLElementContent]];\n\t} else if ([elementName isEqualToString:@\"DisplayName\"]) {\n\t\t[[self currentObject] setOwnerName:[self currentXMLElementContent]];\n\t} else if ([elementName isEqualToString:@\"Prefix\"] && [[self currentXMLElementStack] count] > 2 && [[[self currentXMLElementStack] objectAtIndex:[[self currentXMLElementStack] count]-2] isEqualToString:@\"CommonPrefixes\"]) {\n\t\t[[self commonPrefixes] addObject:[self currentXMLElementContent]];\n\t} else if ([elementName isEqualToString:@\"IsTruncated\"]) {\n\t\t[self setIsTruncated:[[self currentXMLElementContent] isEqualToString:@\"true\"]];\n\t} else {\n\t\t// Let ASIS3Request look for error messages\n\t\t[super parser:parser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName];\n\t}\n}\n\n#pragma mark NSCopying\n\n- (id)copyWithZone:(NSZone *)zone\n{\n\tASIS3BucketRequest *newRequest = [super copyWithZone:zone];\n\t[newRequest setBucket:[self bucket]];\n\t[newRequest setSubResource:[self subResource]];\n\t[newRequest setPrefix:[self prefix]];\n\t[newRequest setMarker:[self marker]];\n\t[newRequest setMaxResultCount:[self maxResultCount]];\n\t[newRequest setDelimiter:[self delimiter]];\n\treturn newRequest;\n}\n\n@synthesize bucket;\n@synthesize subResource;\n@synthesize currentObject;\n@synthesize objects;\n@synthesize commonPrefixes;\n@synthesize prefix;\n@synthesize marker;\n@synthesize maxResultCount;\n@synthesize delimiter;\n@synthesize isTruncated;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3ObjectRequest.h",
    "content": "//\n//  ASIS3ObjectRequest.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n//  Use an ASIS3ObjectRequest to fetch, upload, copy and delete objects on Amazon S3\n\n#import <Foundation/Foundation.h>\n#import \"ASIS3Request.h\"\n\n// Constants for storage class\nextern NSString *const ASIS3StorageClassStandard;\nextern NSString *const ASIS3StorageClassReducedRedundancy;\n\n@interface ASIS3ObjectRequest : ASIS3Request {\n\n\t// Name of the bucket to talk to\n\tNSString *bucket;\n\t\n\t// Key of the resource you want to access on S3\n\tNSString *key;\n\t\n\t// The bucket + path of the object to be copied (used with COPYRequestFromBucket:path:toBucket:path:)\n\tNSString *sourceBucket;\n\tNSString *sourceKey;\n\t\n\t// The mime type of the content for PUT requests\n\t// Set this if having the correct mime type returned to you when you GET the data is important (eg it will be served by a web-server)\n\t// Can be autodetected when PUTing a file from disk, will default to 'application/octet-stream' when PUTing data\n\tNSString *mimeType;\n\t\n\t// Set this to specify you want to work with a particular subresource (eg an acl for that resource)\n\t// See requestWithBucket:key:subResource:, below.\n\tNSString* subResource;\n\n\t// The storage class to be used for PUT requests\n\t// Set this to ASIS3StorageClassReducedRedundancy to save money on storage, at (presumably) a slightly higher risk you will lose the data\n\t// If this is not set, no x-amz-storage-class header will be sent to S3, and their default will be used\n\tNSString *storageClass;\n}\n\n// Create a request, building an appropriate url\n+ (id)requestWithBucket:(NSString *)bucket key:(NSString *)key;\n\n// Create a request for an object, passing a parameter in the query string\n// You'll need to parse the response XML yourself\n// Examples:\n// Fetch ACL:\n// ASIS3ObjectRequest *request = [ASIS3ObjectRequest requestWithBucket:@\"mybucket\" key:@\"my-key\" parameter:@\"acl\"];\n// Get object torret:\n// ASIS3ObjectRequest *request = [ASIS3ObjectRequest requestWithBucket:@\"mybucket\" key:@\"my-key\" parameter:@\"torrent\"];\n// See the S3 REST API docs for more information about the parameters you can pass\n+ (id)requestWithBucket:(NSString *)bucket key:(NSString *)key subResource:(NSString *)subResource;\n\n// Create a PUT request using the file at filePath as the body\n+ (id)PUTRequestForFile:(NSString *)filePath withBucket:(NSString *)bucket key:(NSString *)key;\n\n// Create a PUT request using the supplied NSData as the body (set the mime-type manually with setMimeType: if necessary)\n+ (id)PUTRequestForData:(NSData *)data withBucket:(NSString *)bucket key:(NSString *)key;\n\n// Create a DELETE request for the object at path\n+ (id)DELETERequestWithBucket:(NSString *)bucket key:(NSString *)key;\n\n// Create a PUT request to copy an object from one location to another\n// Clang will complain because it thinks this method should return an object with +1 retain :(\n+ (id)COPYRequestFromBucket:(NSString *)sourceBucket key:(NSString *)sourceKey toBucket:(NSString *)bucket key:(NSString *)key;\n\n// Creates a HEAD request for the object at path\n+ (id)HEADRequestWithBucket:(NSString *)bucket key:(NSString *)key;\n\n@property (retain, nonatomic) NSString *bucket;\n@property (retain, nonatomic) NSString *key;\n@property (retain, nonatomic) NSString *sourceBucket;\n@property (retain, nonatomic) NSString *sourceKey;\n@property (retain, nonatomic) NSString *mimeType;\n@property (retain, nonatomic) NSString *subResource;\n@property (retain, nonatomic) NSString *storageClass;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3ObjectRequest.m",
    "content": "//\n//  ASIS3ObjectRequest.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIS3ObjectRequest.h\"\n\nNSString *const ASIS3StorageClassStandard = @\"STANDARD\";\nNSString *const ASIS3StorageClassReducedRedundancy = @\"REDUCED_REDUNDANCY\";\n\n@implementation ASIS3ObjectRequest\n\n- (ASIHTTPRequest *)HEADRequest\n{\n\tASIS3ObjectRequest *headRequest = (ASIS3ObjectRequest *)[super HEADRequest];\n\t[headRequest setKey:[self key]];\n\t[headRequest setBucket:[self bucket]];\n\treturn headRequest;\n}\n\n+ (id)requestWithBucket:(NSString *)theBucket key:(NSString *)theKey\n{\n\tASIS3ObjectRequest *newRequest = [[[self alloc] initWithURL:nil] autorelease];\n\t[newRequest setBucket:theBucket];\n\t[newRequest setKey:theKey];\n\treturn newRequest;\n}\n\n+ (id)requestWithBucket:(NSString *)theBucket key:(NSString *)theKey subResource:(NSString *)theSubResource\n{\n\tASIS3ObjectRequest *newRequest = [[[self alloc] initWithURL:nil] autorelease];\n\t[newRequest setSubResource:theSubResource];\n\t[newRequest setBucket:theBucket];\n\t[newRequest setKey:theKey];\n\treturn newRequest;\n}\n\n+ (id)PUTRequestForData:(NSData *)data withBucket:(NSString *)theBucket key:(NSString *)theKey\n{\n\tASIS3ObjectRequest *newRequest = [self requestWithBucket:theBucket key:theKey];\n\t[newRequest appendPostData:data];\n\t[newRequest setRequestMethod:@\"PUT\"];\n\treturn newRequest;\n}\n\n+ (id)PUTRequestForFile:(NSString *)filePath withBucket:(NSString *)theBucket key:(NSString *)theKey\n{\n\tASIS3ObjectRequest *newRequest = [self requestWithBucket:theBucket key:theKey];\n\t[newRequest setPostBodyFilePath:filePath];\n\t[newRequest setShouldStreamPostDataFromDisk:YES];\n\t[newRequest setRequestMethod:@\"PUT\"];\n\t[newRequest setMimeType:[ASIHTTPRequest mimeTypeForFileAtPath:filePath]];\n\treturn newRequest;\n}\n\n+ (id)DELETERequestWithBucket:(NSString *)theBucket key:(NSString *)theKey\n{\n\tASIS3ObjectRequest *newRequest = [self requestWithBucket:theBucket key:theKey];\n\t[newRequest setRequestMethod:@\"DELETE\"];\n\treturn newRequest;\n}\n\n+ (id)COPYRequestFromBucket:(NSString *)theSourceBucket key:(NSString *)theSourceKey toBucket:(NSString *)theBucket key:(NSString *)theKey\n{\n\tASIS3ObjectRequest *newRequest = [self requestWithBucket:theBucket key:theKey];\n\t[newRequest setRequestMethod:@\"PUT\"];\n\t[newRequest setSourceBucket:theSourceBucket];\n\t[newRequest setSourceKey:theSourceKey];\n\treturn newRequest;\n}\n\n+ (id)HEADRequestWithBucket:(NSString *)theBucket key:(NSString *)theKey\n{\n\tASIS3ObjectRequest *newRequest = [self requestWithBucket:theBucket key:theKey];\n\t[newRequest setRequestMethod:@\"HEAD\"];\n\treturn newRequest;\n}\n\n- (id)copyWithZone:(NSZone *)zone\n{\n\tASIS3ObjectRequest *newRequest = [super copyWithZone:zone];\n\t[newRequest setBucket:[self bucket]];\n\t[newRequest setKey:[self key]];\n\t[newRequest setSourceBucket:[self sourceBucket]];\n\t[newRequest setSourceKey:[self sourceKey]];\n\t[newRequest setMimeType:[self mimeType]];\n\t[newRequest setSubResource:[self subResource]];\n\t[newRequest setStorageClass:[self storageClass]];\n\treturn newRequest;\n}\n\n- (void)dealloc\n{\n\t[bucket release];\n\t[key release];\n\t[mimeType release];\n\t[sourceKey release];\n\t[sourceBucket release];\n\t[subResource release];\n\t[storageClass release];\n\t[super dealloc];\n}\n\n- (void)buildURL\n{\n\tif ([self subResource]) {\n\t\t[self setURL:[NSURL URLWithString:[NSString stringWithFormat:@\"%@://%@.%@%@?%@\",[self requestScheme],[self bucket],[[self class] S3Host],[ASIS3Request stringByURLEncodingForS3Path:[self key]],[self subResource]]]];\n\t} else {\n\t\t[self setURL:[NSURL URLWithString:[NSString stringWithFormat:@\"%@://%@.%@%@\",[self requestScheme],[self bucket],[[self class] S3Host],[ASIS3Request stringByURLEncodingForS3Path:[self key]]]]];\n\t}\n}\n\n- (NSString *)mimeType\n{\n\tif (mimeType) {\n\t\treturn mimeType;\n\t} else if ([self postBodyFilePath]) {\n\t\treturn [ASIHTTPRequest mimeTypeForFileAtPath:[self postBodyFilePath]];\n\t} else {\n\t\treturn @\"application/octet-stream\";\n\t}\n}\n\n- (NSString *)canonicalizedResource\n{\n\tif ([[self subResource] length] > 0) {\n\t\treturn [NSString stringWithFormat:@\"/%@%@?%@\",[self bucket],[ASIS3Request stringByURLEncodingForS3Path:[self key]], [self subResource]];\n\t}\n\treturn [NSString stringWithFormat:@\"/%@%@\",[self bucket],[ASIS3Request stringByURLEncodingForS3Path:[self key]]];\n}\n\n- (NSMutableDictionary *)S3Headers\n{\n\tNSMutableDictionary *headers = [super S3Headers];\n\tif ([self sourceKey]) {\n\t\tNSString *path = [ASIS3Request stringByURLEncodingForS3Path:[self sourceKey]];\n\t\t[headers setObject:[[self sourceBucket] stringByAppendingString:path] forKey:@\"x-amz-copy-source\"];\n\t}\n\tif ([self storageClass]) {\n\t\t[headers setObject:[self storageClass] forKey:@\"x-amz-storage-class\"];\n\t}\n\treturn headers;\n}\n\n- (NSString *)stringToSignForHeaders:(NSString *)canonicalizedAmzHeaders resource:(NSString *)canonicalizedResource\n{\n\tif ([[self requestMethod] isEqualToString:@\"PUT\"] && ![self sourceKey]) {\n\t\t[self addRequestHeader:@\"Content-Type\" value:[self mimeType]];\n\t\treturn [NSString stringWithFormat:@\"PUT\\n\\n%@\\n%@\\n%@%@\",[self mimeType],dateString,canonicalizedAmzHeaders,canonicalizedResource];\n\t} \n\treturn [super stringToSignForHeaders:canonicalizedAmzHeaders resource:canonicalizedResource];\n}\n\n@synthesize bucket;\n@synthesize key;\n@synthesize sourceBucket;\n@synthesize sourceKey;\n@synthesize mimeType;\n@synthesize subResource;\n@synthesize storageClass;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3Request.h",
    "content": "//\n//  ASIS3Request.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 30/06/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n// A class for accessing data stored on Amazon's Simple Storage Service (http://aws.amazon.com/s3/) using the REST API\n// While you can use this class directly, the included subclasses make typical operations easier\n\n#import <Foundation/Foundation.h>\n#import \"ASIHTTPRequest.h\"\n\n#if !TARGET_OS_IPHONE || (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_4_0)\n#import \"ASINSXMLParserCompat.h\"\n#endif\n\n// See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAccessPolicy.html for what these mean\nextern NSString *const ASIS3AccessPolicyPrivate; // This is the default in S3 when no access policy header is provided\nextern NSString *const ASIS3AccessPolicyPublicRead;\nextern NSString *const ASIS3AccessPolicyPublicReadWrite;\nextern NSString *const ASIS3AccessPolicyAuthenticatedRead;\nextern NSString *const ASIS3AccessPolicyBucketOwnerRead;\nextern NSString *const ASIS3AccessPolicyBucketOwnerFullControl;\n\n// Constants for requestScheme - defaults is ASIS3RequestSchemeHTTP\nextern NSString *const ASIS3RequestSchemeHTTP;\nextern NSString *const ASIS3RequestSchemeHTTPS;\n\n\n\ntypedef enum _ASIS3ErrorType {\n    ASIS3ResponseParsingFailedType = 1,\n    ASIS3ResponseErrorType = 2\n} ASIS3ErrorType;\n\n\n\n@interface ASIS3Request : ASIHTTPRequest <NSCopying, NSXMLParserDelegate> {\n\t\n\t// Your S3 access key. Set it on the request, or set it globally using [ASIS3Request setSharedAccessKey:]\n\tNSString *accessKey;\n\t\n\t// Your S3 secret access key. Set it on the request, or set it globally using [ASIS3Request setSharedSecretAccessKey:]\n\tNSString *secretAccessKey;\n\t\n\t// Set to ASIS3RequestSchemeHTTPS to send your requests via HTTPS (default is ASIS3RequestSchemeHTTP)\n\tNSString *requestScheme;\n\n\t// The string that will be used in the HTTP date header. Generally you'll want to ignore this and let the class add the current date for you, but the accessor is used by the tests\n\tNSString *dateString;\n\n\t// The access policy to use when PUTting a file (see the string constants at the top ASIS3Request.h for details on what the possible options are)\n\tNSString *accessPolicy;\n\n\t// Internally used while parsing errors\n\tNSString *currentXMLElementContent;\n\tNSMutableArray *currentXMLElementStack;\n}\n\n// Uses the supplied date to create a Date header string\n- (void)setDate:(NSDate *)date;\n\n// Will return a dictionary of the 'amz-' headers that wil be sent to S3\n// Override in subclasses to add new ones\t\n- (NSMutableDictionary *)S3Headers;\n\t\n// Returns the string that will used to create a signature for this request\n// Is overridden in ASIS3ObjectRequest\n- (NSString *)stringToSignForHeaders:(NSString *)canonicalizedAmzHeaders resource:(NSString *)canonicalizedResource;\n\n// Parses the response to work out if S3 returned an error\t\n- (void)parseResponseXML;\n\n#pragma mark shared access keys\n\n// Get and set the global access key, this will be used for all requests the access key hasn't been set for\n+ (NSString *)sharedAccessKey;\n+ (void)setSharedAccessKey:(NSString *)newAccessKey;\n+ (NSString *)sharedSecretAccessKey;\n+ (void)setSharedSecretAccessKey:(NSString *)newAccessKey;\n\n# pragma mark helpers\n\t\n// Returns a date formatter than can be used to parse a date from S3\n+ (NSDateFormatter*)S3ResponseDateFormatter;\n\t\n// Returns a date formatter than can be used to send a date header to S3\n+ (NSDateFormatter*)S3RequestDateFormatter;\n\n\n// URL-encodes an S3 key so it can be used in a url\n// You shouldn't normally need to use this yourself\n+ (NSString *)stringByURLEncodingForS3Path:(NSString *)key;\n\n// Returns a string for the hostname used for S3 requests. You shouldn't ever need to change this.\n+ (NSString *)S3Host;\n\n// This is called automatically before the request starts to build the request URL (if one has not been manually set already)\n- (void)buildURL;\n\n@property (retain) NSString *dateString;\n@property (retain) NSString *accessKey;\n@property (retain) NSString *secretAccessKey;\n@property (retain) NSString *accessPolicy;\n@property (retain) NSString *currentXMLElementContent;\n@property (retain) NSMutableArray *currentXMLElementStack;\n@property (retain) NSString *requestScheme;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3Request.m",
    "content": "//\n//  ASIS3Request.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 30/06/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIS3Request.h\"\n#import <CommonCrypto/CommonHMAC.h>\n\nNSString *const ASIS3AccessPolicyPrivate = @\"private\";\nNSString *const ASIS3AccessPolicyPublicRead = @\"public-read\";\nNSString *const ASIS3AccessPolicyPublicReadWrite = @\"public-read-write\";\nNSString *const ASIS3AccessPolicyAuthenticatedRead = @\"authenticated-read\";\nNSString *const ASIS3AccessPolicyBucketOwnerRead = @\"bucket-owner-read\";\nNSString *const ASIS3AccessPolicyBucketOwnerFullControl = @\"bucket-owner-full-control\";\n\nNSString *const ASIS3RequestSchemeHTTP = @\"http\";\nNSString *const ASIS3RequestSchemeHTTPS = @\"https\";\n\nstatic NSString *sharedAccessKey = nil;\nstatic NSString *sharedSecretAccessKey = nil;\n\n// Private stuff\n@interface ASIS3Request ()\n\t+ (NSData *)HMACSHA1withKey:(NSString *)key forString:(NSString *)string;\n@end\n\n@implementation ASIS3Request\n\n- (id)initWithURL:(NSURL *)newURL\n{\n\tself = [super initWithURL:newURL];\n\t// After a bit of experimentation/guesswork, this number seems to reduce the chance of a 'RequestTimeout' error\n\t[self setPersistentConnectionTimeoutSeconds:20];\n\t[self setRequestScheme:ASIS3RequestSchemeHTTP];\n\treturn self;\n}\n\n\n- (void)dealloc\n{\n\t[currentXMLElementContent release];\n\t[currentXMLElementStack release];\n\t[dateString release];\n\t[accessKey release];\n\t[secretAccessKey release];\n\t[accessPolicy release];\n\t[requestScheme release];\n\t[super dealloc];\n}\n\n\n- (void)setDate:(NSDate *)date\n{\n\t[self setDateString:[[ASIS3Request S3RequestDateFormatter] stringFromDate:date]];\t\n}\n\n- (ASIHTTPRequest *)HEADRequest\n{\n\tASIS3Request *headRequest = (ASIS3Request *)[super HEADRequest];\n\t[headRequest setAccessKey:[self accessKey]];\n\t[headRequest setSecretAccessKey:[self secretAccessKey]];\n\treturn headRequest;\n}\n\n- (NSMutableDictionary *)S3Headers\n{\n\tNSMutableDictionary *headers = [NSMutableDictionary dictionary];\n\tif ([self accessPolicy]) {\n\t\t[headers setObject:[self accessPolicy] forKey:@\"x-amz-acl\"];\n\t}\n\treturn headers;\n}\n\n- (void)main\n{\n\tif (![self url]) {\n\t\t[self buildURL];\n\t}\n\t[super main];\n}\n\n- (NSString *)canonicalizedResource\n{\n\treturn @\"/\";\n}\n\n- (NSString *)stringToSignForHeaders:(NSString *)canonicalizedAmzHeaders resource:(NSString *)canonicalizedResource\n{\n\treturn [NSString stringWithFormat:@\"%@\\n\\n\\n%@\\n%@%@\",[self requestMethod],[self dateString],canonicalizedAmzHeaders,canonicalizedResource];\n}\n\n- (void)buildRequestHeaders\n{\n\tif (![self url]) {\n\t\t[self buildURL];\n\t}\n\t[super buildRequestHeaders];\n\n\t// If an access key / secret access key haven't been set for this request, let's use the shared keys\n\tif (![self accessKey]) {\n\t\t[self setAccessKey:[ASIS3Request sharedAccessKey]];\n\t}\n\tif (![self secretAccessKey]) {\n\t\t[self setSecretAccessKey:[ASIS3Request sharedSecretAccessKey]];\n\t}\n\t// If a date string hasn't been set, we'll create one from the current time\n\tif (![self dateString]) {\n\t\t[self setDate:[NSDate date]];\n\t}\n\t[self addRequestHeader:@\"Date\" value:[self dateString]];\n\t\n\t// Ensure our formatted string doesn't use '(null)' for the empty path\n\tNSString *canonicalizedResource = [self canonicalizedResource];\n\t\n\t// Add a header for the access policy if one was set, otherwise we won't add one (and S3 will default to private)\n\tNSMutableDictionary *amzHeaders = [self S3Headers];\n\tNSString *canonicalizedAmzHeaders = @\"\";\n\tfor (NSString *header in [amzHeaders keysSortedByValueUsingSelector:@selector(compare:)]) {\n\t\tcanonicalizedAmzHeaders = [NSString stringWithFormat:@\"%@%@:%@\\n\",canonicalizedAmzHeaders,[header lowercaseString],[amzHeaders objectForKey:header]];\n\t\t[self addRequestHeader:header value:[amzHeaders objectForKey:header]];\n\t}\n\t\n\t// Jump through hoops while eating hot food\n\tNSString *stringToSign = [self stringToSignForHeaders:canonicalizedAmzHeaders resource:canonicalizedResource];\n\tNSString *signature = [ASIHTTPRequest base64forData:[ASIS3Request HMACSHA1withKey:[self secretAccessKey] forString:stringToSign]];\n\tNSString *authorizationString = [NSString stringWithFormat:@\"AWS %@:%@\",[self accessKey],signature];\n\t[self addRequestHeader:@\"Authorization\" value:authorizationString];\n\t\n\t\n}\n\n- (void)requestFinished\n{\n\tif ([[[self responseHeaders] objectForKey:@\"Content-Type\"] isEqualToString:@\"application/xml\"]) {\n\t\t[self parseResponseXML];\n\t}\n\tif (![self error]) {\n\t\t[super requestFinished];\n\t}\n}\n\n#pragma mark Error XML parsing\n\n- (void)parseResponseXML\n{\n\tNSData* xmlData = [self responseData];\n\tif (![xmlData length]) {\n\t\treturn;\n\t}\n\tNSXMLParser *parser = [[[NSXMLParser alloc] initWithData:xmlData] autorelease];\n\t[self setCurrentXMLElementStack:[NSMutableArray array]];\n\t[parser setDelegate:self];\n\t[parser setShouldProcessNamespaces:NO];\n\t[parser setShouldReportNamespacePrefixes:NO];\n\t[parser setShouldResolveExternalEntities:NO];\n\t[parser parse];\n\n}\n\n- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError\n{\n\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIS3ResponseParsingFailedType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@\"Parsing the resposnse failed\",NSLocalizedDescriptionKey,parseError,NSUnderlyingErrorKey,nil]]];\n}\n\n- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict\n{\n\t[self setCurrentXMLElementContent:@\"\"];\n\t[[self currentXMLElementStack] addObject:elementName];\n}\n\n- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName\n{\n\t[[self currentXMLElementStack] removeLastObject];\n\tif ([elementName isEqualToString:@\"Message\"]) {\n\t\t[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIS3ResponseErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self currentXMLElementContent],NSLocalizedDescriptionKey,nil]]];\n\t// Handle S3 connection expiry errors\n\t} else if ([elementName isEqualToString:@\"Code\"]) {\n\t\tif ([[self currentXMLElementContent] isEqualToString:@\"RequestTimeout\"]) {\n\t\t\tif ([self retryUsingNewConnection]) {\n\t\t\t\t[parser abortParsing];\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\n- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string\n{\n\t[self setCurrentXMLElementContent:[[self currentXMLElementContent] stringByAppendingString:string]];\n}\n\n- (id)copyWithZone:(NSZone *)zone\n{\n\tASIS3Request *newRequest = [super copyWithZone:zone];\n\t[newRequest setAccessKey:[self accessKey]];\n\t[newRequest setSecretAccessKey:[self secretAccessKey]];\n\t[newRequest setRequestScheme:[self requestScheme]];\n\t[newRequest setAccessPolicy:[self accessPolicy]];\n\treturn newRequest;\n}\n\n\n#pragma mark Shared access keys\n\n+ (NSString *)sharedAccessKey\n{\n\treturn sharedAccessKey;\n}\n\n+ (void)setSharedAccessKey:(NSString *)newAccessKey\n{\n\t[sharedAccessKey release];\n\tsharedAccessKey = [newAccessKey retain];\n}\n\n+ (NSString *)sharedSecretAccessKey\n{\n\treturn sharedSecretAccessKey;\n}\n\n+ (void)setSharedSecretAccessKey:(NSString *)newAccessKey\n{\n\t[sharedSecretAccessKey release];\n\tsharedSecretAccessKey = [newAccessKey retain];\n}\n\n\n#pragma mark helpers\n\n+ (NSString *)stringByURLEncodingForS3Path:(NSString *)key\n{\n\tif (!key) {\n\t\treturn @\"/\";\n\t}\n\tNSString *path = [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)key, NULL, CFSTR(\":?#[]@!$ &'()*+,;=\\\"<>%{}|\\\\^~`\"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) autorelease];\n\tif (![[path substringWithRange:NSMakeRange(0, 1)] isEqualToString:@\"/\"]) {\n\t\tpath = [@\"/\" stringByAppendingString:path];\n\t}\n\treturn path;\n}\n\n// Thanks to Tom Andersen for pointing out the threading issues and providing this code!\n+ (NSDateFormatter*)S3ResponseDateFormatter\n{\n\t// We store our date formatter in the calling thread's dictionary\n\t// NSDateFormatter is not thread-safe, this approach ensures each formatter is only used on a single thread\n\t// This formatter can be reused 1000 times in parsing a single response, so it would be expensive to keep creating new date formatters\n\tNSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];\n\tNSDateFormatter *dateFormatter = [threadDict objectForKey:@\"ASIS3ResponseDateFormatter\"];\n\tif (dateFormatter == nil) {\n\t\tdateFormatter = [[[NSDateFormatter alloc] init] autorelease];\n\t\t[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"] autorelease]];\n\t\t[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@\"UTC\"]];\n\t\t[dateFormatter setDateFormat:@\"yyyy-MM-dd'T'HH:mm:ss'.000Z'\"];\n\t\t[threadDict setObject:dateFormatter forKey:@\"ASIS3ResponseDateFormatter\"];\n\t}\n\treturn dateFormatter;\n}\n\n+ (NSDateFormatter*)S3RequestDateFormatter\n{\n\tNSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];\n\tNSDateFormatter *dateFormatter = [threadDict objectForKey:@\"ASIS3RequestHeaderDateFormatter\"];\n\tif (dateFormatter == nil) {\n\t\tdateFormatter = [[[NSDateFormatter alloc] init] autorelease];\n\t\t// Prevent problems with dates generated by other locales (tip from: http://rel.me/t/date/)\n\t\t[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@\"en_US_POSIX\"] autorelease]];\n\t\t[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@\"UTC\"]];\n\t\t[dateFormatter setDateFormat:@\"EEE, d MMM yyyy HH:mm:ss Z\"];\n\t\t[threadDict setObject:dateFormatter forKey:@\"ASIS3RequestHeaderDateFormatter\"];\n\t}\n\treturn dateFormatter;\n\t\n}\n\n// From: http://stackoverflow.com/questions/476455/is-there-a-library-for-iphone-to-work-with-hmac-sha-1-encoding\n\n+ (NSData *)HMACSHA1withKey:(NSString *)key forString:(NSString *)string\n{\n\tNSData *clearTextData = [string dataUsingEncoding:NSUTF8StringEncoding];\n\tNSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];\n\t\n\tuint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};\n\t\n\tCCHmacContext hmacContext;\n\tCCHmacInit(&hmacContext, kCCHmacAlgSHA1, keyData.bytes, keyData.length);\n\tCCHmacUpdate(&hmacContext, clearTextData.bytes, clearTextData.length);\n\tCCHmacFinal(&hmacContext, digest);\n\t\n\treturn [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];\n}\n\n+ (NSString *)S3Host\n{\n\treturn @\"s3.amazonaws.com\";\n}\n\n- (void)buildURL\n{\n}\n\n@synthesize dateString;\n@synthesize accessKey;\n@synthesize secretAccessKey;\n@synthesize currentXMLElementContent;\n@synthesize currentXMLElementStack;\n@synthesize accessPolicy;\n@synthesize requestScheme;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3ServiceRequest.h",
    "content": "//\n//  ASIS3ServiceRequest.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n//  Create an ASIS3ServiceRequest to obtain a list of your buckets\n\n#import <Foundation/Foundation.h>\n#import \"ASIS3Request.h\"\n\n@class ASIS3Bucket;\n\n@interface ASIS3ServiceRequest : ASIS3Request {\n\t\n\t// Internally used while parsing the response\n\tASIS3Bucket *currentBucket;\n\tNSString *ownerName;\n\tNSString *ownerID;\n\t\n\t// A list of the buckets stored on S3 for this account\n\tNSMutableArray *buckets;\n}\n\n// Perform a GET request on the S3 service\n// This will fetch a list of the buckets attached to the S3 account\n+ (id)serviceRequest;\n\n@property (retain, readonly) NSMutableArray *buckets;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/ASIHTTPRequest/S3/ASIS3ServiceRequest.m",
    "content": "//\n//  ASIS3ServiceRequest.m\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 16/03/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import \"ASIS3ServiceRequest.h\"\n#import \"ASIS3Bucket.h\"\n\n// Private stuff\n@interface ASIS3ServiceRequest ()\n@property (retain) NSMutableArray *buckets;\n@property (retain, nonatomic) ASIS3Bucket *currentBucket;\n@property (retain, nonatomic) NSString *ownerID;\n@property (retain, nonatomic) NSString *ownerName;\n@end\n\n@implementation ASIS3ServiceRequest\n\n+ (id)serviceRequest\n{\n\tASIS3ServiceRequest *request = [[[self alloc] initWithURL:nil] autorelease];\n\treturn request;\n}\n\n- (id)initWithURL:(NSURL *)newURL\n{\n\tself = [super initWithURL:newURL];\n\t[self setBuckets:[[[NSMutableArray alloc] init] autorelease]];\n\treturn self;\n}\n\n- (void)dealloc\n{\n\t[buckets release];\n\t[currentBucket release];\n\t[ownerID release];\n\t[ownerName release];\n\t[super dealloc];\n}\n\n- (void)buildURL\n{\n\t[self setURL:[NSURL URLWithString:[NSString stringWithFormat:@\"%@://%@\",[self requestScheme],[[self class] S3Host]]]];\n}\n\n- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict\n{\n\tif ([elementName isEqualToString:@\"Bucket\"]) {\n\t\t[self setCurrentBucket:[ASIS3Bucket bucketWithOwnerID:[self ownerID] ownerName:[self ownerName]]];\n\t}\n\t[super parser:parser didStartElement:elementName namespaceURI:namespaceURI qualifiedName:qName attributes:attributeDict];\n}\n\n- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName\n{\n\tif ([elementName isEqualToString:@\"Bucket\"]) {\n\t\t[[self buckets] addObject:[self currentBucket]];\n\t\t[self setCurrentBucket:nil];\n\t} else if ([elementName isEqualToString:@\"Name\"]) {\n\t\t[[self currentBucket] setName:[self currentXMLElementContent]];\n\t} else if ([elementName isEqualToString:@\"CreationDate\"]) {\n\t\t[[self currentBucket] setCreationDate:[[ASIS3Request S3ResponseDateFormatter] dateFromString:[self currentXMLElementContent]]];\n\t} else if ([elementName isEqualToString:@\"ID\"]) {\n\t\t[self setOwnerID:[self currentXMLElementContent]];\n\t} else if ([elementName isEqualToString:@\"DisplayName\"]) {\n\t\t[self setOwnerName:[self currentXMLElementContent]];\n\t} else {\n\t\t// Let ASIS3Request look for error messages\n\t\t[super parser:parser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName];\n\t}\n}\n\n@synthesize buckets;\n@synthesize currentBucket;\n@synthesize ownerID;\n@synthesize ownerName;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/Base64/NSData+Base64.h",
    "content": "//\n//  NSData+Base64.h\n//  base64\n//\n//  Created by Matt Gallagher on 2009/06/03.\n//  Copyright 2009 Matt Gallagher. All rights reserved.\n//\n//  This software is provided 'as-is', without any express or implied\n//  warranty. In no event will the authors be held liable for any damages\n//  arising from the use of this software. Permission is granted to anyone to\n//  use this software for any purpose, including commercial applications, and to\n//  alter it and redistribute it freely, subject to the following restrictions:\n//\n//  1. The origin of this software must not be misrepresented; you must not\n//     claim that you wrote the original software. If you use this software\n//     in a product, an acknowledgment in the product documentation would be\n//     appreciated but is not required.\n//  2. Altered source versions must be plainly marked as such, and must not be\n//     misrepresented as being the original software.\n//  3. This notice may not be removed or altered from any source\n//     distribution.\n//\n\n#import <Foundation/Foundation.h>\n\nvoid *NewBase64Decode(\n\tconst char *inputBuffer,\n\tsize_t length,\n\tsize_t *outputLength);\n\nchar *NewBase64Encode(\n\tconst void *inputBuffer,\n\tsize_t length,\n\tbool separateLines,\n\tsize_t *outputLength);\n\n@interface NSData (Base64)\n\n+ (NSData *)dataFromBase64String:(NSString *)aString;\n- (NSString *)base64EncodedString;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/Base64/NSData+Base64.m",
    "content": "//\n//  NSData+Base64.m\n//  base64\n//\n//  Created by Matt Gallagher on 2009/06/03.\n//  Copyright 2009 Matt Gallagher. All rights reserved.\n//\n//  This software is provided 'as-is', without any express or implied\n//  warranty. In no event will the authors be held liable for any damages\n//  arising from the use of this software. Permission is granted to anyone to\n//  use this software for any purpose, including commercial applications, and to\n//  alter it and redistribute it freely, subject to the following restrictions:\n//\n//  1. The origin of this software must not be misrepresented; you must not\n//     claim that you wrote the original software. If you use this software\n//     in a product, an acknowledgment in the product documentation would be\n//     appreciated but is not required.\n//  2. Altered source versions must be plainly marked as such, and must not be\n//     misrepresented as being the original software.\n//  3. This notice may not be removed or altered from any source\n//     distribution.\n//\n\n#import \"NSData+Base64.h\"\n\n//\n// Mapping from 6 bit pattern to ASCII character.\n//\nstatic unsigned char base64EncodeLookup[65] =\n\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n//\n// Definition for \"masked-out\" areas of the base64DecodeLookup mapping\n//\n#define xx 65\n\n//\n// Mapping from ASCII character to 6 bit pattern.\n//\nstatic unsigned char base64DecodeLookup[256] =\n{\n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63, \n    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, \n    xx,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, \n    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx, \n    xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, \n    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, \n};\n\n//\n// Fundamental sizes of the binary and base64 encode/decode units in bytes\n//\n#define BINARY_UNIT_SIZE 3\n#define BASE64_UNIT_SIZE 4\n\n//\n// NewBase64Decode\n//\n// Decodes the base64 ASCII string in the inputBuffer to a newly malloced\n// output buffer.\n//\n//  inputBuffer - the source ASCII string for the decode\n//\tlength - the length of the string or -1 (to specify strlen should be used)\n//\toutputLength - if not-NULL, on output will contain the decoded length\n//\n// returns the decoded buffer. Must be free'd by caller. Length is given by\n//\toutputLength.\n//\nvoid *NewBase64Decode(\n\tconst char *inputBuffer,\n\tsize_t length,\n\tsize_t *outputLength)\n{\n\tif (length == -1)\n\t{\n\t\tlength = strlen(inputBuffer);\n\t}\n\t\n\tsize_t outputBufferSize =\n\t\t((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;\n\tunsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize);\n\t\n\tsize_t i = 0;\n\tsize_t j = 0;\n\twhile (i < length)\n\t{\n\t\t//\n\t\t// Accumulate 4 valid characters (ignore everything else)\n\t\t//\n\t\tunsigned char accumulated[BASE64_UNIT_SIZE];\n\t\tsize_t accumulateIndex = 0;\n\t\twhile (i < length)\n\t\t{\n\t\t\tunsigned char decode = base64DecodeLookup[inputBuffer[i++]];\n\t\t\tif (decode != xx)\n\t\t\t{\n\t\t\t\taccumulated[accumulateIndex] = decode;\n\t\t\t\taccumulateIndex++;\n\t\t\t\t\n\t\t\t\tif (accumulateIndex == BASE64_UNIT_SIZE)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t//\n\t\t// Store the 6 bits from each of the 4 characters as 3 bytes\n\t\t//\n\t\t// (Uses improved bounds checking suggested by Alexandre Colucci)\n\t\t//\n\t\tif(accumulateIndex >= 2)  \n\t\t\toutputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);  \n\t\tif(accumulateIndex >= 3)  \n\t\t\toutputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);  \n\t\tif(accumulateIndex >= 4)  \n\t\t\toutputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];\n\t\tj += accumulateIndex - 1;\n\t}\n\t\n\tif (outputLength)\n\t{\n\t\t*outputLength = j;\n\t}\n\treturn outputBuffer;\n}\n\n//\n// NewBase64Encode\n//\n// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced\n// output buffer.\n//\n//  inputBuffer - the source data for the encode\n//\tlength - the length of the input in bytes\n//  separateLines - if zero, no CR/LF characters will be added. Otherwise\n//\t\ta CR/LF pair will be added every 64 encoded chars.\n//\toutputLength - if not-NULL, on output will contain the encoded length\n//\t\t(not including terminating 0 char)\n//\n// returns the encoded buffer. Must be free'd by caller. Length is given by\n//\toutputLength.\n//\nchar *NewBase64Encode(\n\tconst void *buffer,\n\tsize_t length,\n\tbool separateLines,\n\tsize_t *outputLength)\n{\n\tconst unsigned char *inputBuffer = (const unsigned char *)buffer;\n\t\n\t#define MAX_NUM_PADDING_CHARS 2\n\t#define OUTPUT_LINE_LENGTH 64\n\t#define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)\n\t#define CR_LF_SIZE 2\n\t\n\t//\n\t// Byte accurate calculation of final buffer size\n\t//\n\tsize_t outputBufferSize =\n\t\t\t((length / BINARY_UNIT_SIZE)\n\t\t\t\t+ ((length % BINARY_UNIT_SIZE) ? 1 : 0))\n\t\t\t\t\t* BASE64_UNIT_SIZE;\n\tif (separateLines)\n\t{\n\t\toutputBufferSize +=\n\t\t\t(outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;\n\t}\n\t\n\t//\n\t// Include space for a terminating zero\n\t//\n\toutputBufferSize += 1;\n\n\t//\n\t// Allocate the output buffer\n\t//\n\tchar *outputBuffer = (char *)malloc(outputBufferSize);\n\tif (!outputBuffer)\n\t{\n\t\treturn NULL;\n\t}\n\n\tsize_t i = 0;\n\tsize_t j = 0;\n\tconst size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;\n\tsize_t lineEnd = lineLength;\n\t\n\twhile (true)\n\t{\n\t\tif (lineEnd > length)\n\t\t{\n\t\t\tlineEnd = length;\n\t\t}\n\n\t\tfor (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE)\n\t\t{\n\t\t\t//\n\t\t\t// Inner loop: turn 48 bytes into 64 base64 characters\n\t\t\t//\n\t\t\toutputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];\n\t\t\toutputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)\n\t\t\t\t| ((inputBuffer[i + 1] & 0xF0) >> 4)];\n\t\t\toutputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)\n\t\t\t\t| ((inputBuffer[i + 2] & 0xC0) >> 6)];\n\t\t\toutputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];\n\t\t}\n\t\t\n\t\tif (lineEnd == length)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\t//\n\t\t// Add the newline\n\t\t//\n\t\toutputBuffer[j++] = '\\r';\n\t\toutputBuffer[j++] = '\\n';\n\t\tlineEnd += lineLength;\n\t}\n\t\n\tif (i + 1 < length)\n\t{\n\t\t//\n\t\t// Handle the single '=' case\n\t\t//\n\t\toutputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];\n\t\toutputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)\n\t\t\t| ((inputBuffer[i + 1] & 0xF0) >> 4)];\n\t\toutputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];\n\t\toutputBuffer[j++] =\t'=';\n\t}\n\telse if (i < length)\n\t{\n\t\t//\n\t\t// Handle the double '=' case\n\t\t//\n\t\toutputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];\n\t\toutputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];\n\t\toutputBuffer[j++] = '=';\n\t\toutputBuffer[j++] = '=';\n\t}\n\toutputBuffer[j] = 0;\n\t\n\t//\n\t// Set the output length and return the buffer\n\t//\n\tif (outputLength)\n\t{\n\t\t*outputLength = j;\n\t}\n\treturn outputBuffer;\n}\n\n@implementation NSData (Base64)\n\n//\n// dataFromBase64String:\n//\n// Creates an NSData object containing the base64 decoded representation of\n// the base64 string 'aString'\n//\n// Parameters:\n//    aString - the base64 string to decode\n//\n// returns the autoreleased NSData representation of the base64 string\n//\n+ (NSData *)dataFromBase64String:(NSString *)aString\n{\n\tNSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];\n\tsize_t outputLength;\n\tvoid *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength);\n\tNSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];\n\tfree(outputBuffer);\n\treturn result;\n}\n\n//\n// base64EncodedString\n//\n// Creates an NSString object that contains the base 64 encoding of the\n// receiver's data. Lines are broken at 64 characters long.\n//\n// returns an autoreleased NSString being the base 64 representation of the\n//\treceiver.\n//\n- (NSString *)base64EncodedString\n{\n\tsize_t outputLength = 0;\n\tchar *outputBuffer =\n\t\tNewBase64Encode([self bytes], [self length], true, &outputLength);\n\t\n\tNSString *result = [[[NSString alloc]initWithBytes:outputBuffer\n                                                length:outputLength\n                                              encoding:NSASCIIStringEncoding]\n                        autorelease];\n\tfree(outputBuffer);\n\treturn result;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/JSON.h",
    "content": "//\n//  JSON.h\n//  SBJson\n//\n//  Created by Stig Brautaset on 01/06/2011.\n//  Copyright 2011 Stig Brautaset. All rights reserved.\n//\n\n#warning The JSON.h header is deprecated, and will disappear in a future release. Please change to include SBJson.h instead.\n#include \"SBJson.h\""
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/NSObject+SBJson.h",
    "content": "/*\n Copyright (C) 2009 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n#pragma mark JSON Writing\n\n/// Adds JSON generation to NSObject\n@interface NSObject (NSObject_SBJsonWriting)\n\n/**\n @brief Encodes the receiver into a JSON string\n \n Although defined as a category on NSObject it is only defined for NSArray and NSDictionary.\n \n @return the receiver encoded in JSON, or nil on error.\n \n @see @ref objc2json\n */\n- (NSString *)JSONRepresentation;\n\n@end\n\n\n#pragma mark JSON Parsing\n\n/// Adds JSON parsing methods to NSString\n@interface NSString (NSString_SBJsonParsing)\n\n/**\n @brief Decodes the receiver's JSON text\n \n @return the NSDictionary or NSArray represented by the receiver, or nil on error.\n \n @see @ref json2objc\n */\n- (id)JSONValue;\n\n@end\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/NSObject+SBJson.m",
    "content": "/*\n Copyright (C) 2009 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"NSObject+SBJson.h\"\n#import \"SBJsonWriter.h\"\n#import \"SBJsonParser.h\"\n\n@implementation NSObject (NSObject_SBJsonWriting)\n\n- (NSString *)JSONRepresentation {\n    SBJsonWriter *writer = [[[SBJsonWriter alloc] init] autorelease];    \n    NSString *json = [writer stringWithObject:self];\n    if (!json)\n        NSLog(@\"-JSONRepresentation failed. Error is: %@\", writer.error);\n    return json;\n}\n\n@end\n\n\n\n@implementation NSString (NSString_SBJsonParsing)\n\n- (id)JSONValue {\n    SBJsonParser *parser = [[[SBJsonParser alloc] init] autorelease];\n    id repr = [parser objectWithString:self];\n    if (!repr)\n        NSLog(@\"-JSONValue failed. Error is: %@\", parser.error);\n    return repr;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJson.h",
    "content": "/*\n Copyright (C) 2009-2011 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/**\n @page json2objc JSON to Objective-C\n \n JSON is mapped to Objective-C types in the following way:\n \n @li null    -> NSNull\n @li string  -> NSString\n @li array   -> NSMutableArray\n @li object  -> NSMutableDictionary\n @li true    -> NSNumber's -numberWithBool:YES\n @li false   -> NSNumber's -numberWithBool:NO\n @li integer up to 19 digits -> NSNumber's -numberWithLongLong:\n @li all other numbers       -> NSDecimalNumber\n \n Since Objective-C doesn't have a dedicated class for boolean values,\n these turns into NSNumber instances. However, since these are\n initialised with the -initWithBool: method they round-trip back to JSON\n properly. In other words, they won't silently suddenly become 0 or 1;\n they'll be represented as 'true' and 'false' again.\n \n As an optimisation integers up to 19 digits in length (the max length\n for signed long long integers) turn into NSNumber instances, while\n complex ones turn into NSDecimalNumber instances. We can thus avoid any\n loss of precision as JSON allows ridiculously large numbers.\n\n @page objc2json Objective-C to JSON\n \n Objective-C types are mapped to JSON types in the following way:\n \n @li NSNull        -> null\n @li NSString      -> string\n @li NSArray       -> array\n @li NSDictionary  -> object\n @li NSNumber's -initWithBool:YES -> true\n @li NSNumber's -initWithBool:NO  -> false\n @li NSNumber      -> number\n \n @note In JSON the keys of an object must be strings. NSDictionary\n keys need not be, but attempting to convert an NSDictionary with\n non-string keys into JSON will throw an exception.\n \n NSNumber instances created with the -numberWithBool: method are\n converted into the JSON boolean \"true\" and \"false\" values, and vice\n versa. Any other NSNumber instances are converted to a JSON number the\n way you would expect.\n\n */\n\n#import \"SBJsonParser.h\"\n#import \"SBJsonWriter.h\"\n#import \"SBJsonStreamParser.h\"\n#import \"SBJsonStreamParserAdapter.h\"\n#import \"SBJsonStreamWriter.h\"\n#import \"NSObject+SBJson.h\"\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonParser.h",
    "content": "/*\n Copyright (C) 2009 Stig Brautaset. All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n/**\n @brief Parse JSON Strings and NSData objects\n\n This uses SBJsonStreamParser internally.\n\n @see @ref objc2json\n\n */\n\n@interface SBJsonParser : NSObject {\n\n@private\n\tNSString *error;\n    NSUInteger depth, maxDepth;\n\n}\n\n/**\n @brief The maximum recursing depth.\n\n Defaults to 32. If the input is nested deeper than this the input will be deemed to be\n malicious and the parser returns nil, signalling an error. (\"Nested too deep\".) You can\n turn off this security feature by setting the maxDepth value to 0.\n */\n@property NSUInteger maxDepth;\n\n/**\n @brief Description of parse error\n\n This method returns the trace of the last method that failed.\n You need to check the return value of the call you're making to figure out\n if the call actually failed, before you know call this method.\n\n @return A string describing the error encountered, or nil if no error occured.\n\n */\n@property(copy) NSString *error;\n\n/**\n @brief Return the object represented by the given NSData object.\n\n The data *must* be UTF8 encoded.\n \n @param data An NSData containing UTF8 encoded data to parse.\n @return The NSArray or NSDictionary represented by the object, or nil if an error occured.\n\n */\n- (id)objectWithData:(NSData*)data;\n\n/**\n @brief Return the object represented by the given string\n\n This method converts its input to an NSData object containing UTF8 and calls -objectWithData: with it.\n\n @return The NSArray or NSDictionary represented by the object, or nil if an error occured.\n */\n- (id)objectWithString:(NSString *)repr;\n\n/**\n @brief Return the object represented by the given string\n\n This method calls objectWithString: internally. If an error occurs, and if @p error\n is not nil, it creates an NSError object and returns this through its second argument.\n\n @param jsonText the json string to parse\n @param error pointer to an NSError object to populate on error\n\n @return The NSArray or NSDictionary represented by the object, or nil if an error occured.\n */\n\n- (id)objectWithString:(NSString*)jsonText\n                 error:(NSError**)error;\n\n@end\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonParser.m",
    "content": "/*\n Copyright (C) 2009,2010 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonParser.h\"\n#import \"SBJsonStreamParser.h\"\n#import \"SBJsonStreamParserAdapter.h\"\n#import \"SBJsonStreamParserAccumulator.h\"\n\n@implementation SBJsonParser\n\n@synthesize maxDepth;\n@synthesize error;\n\n- (id)init {\n    self = [super init];\n    if (self)\n        self.maxDepth = 32u;\n    return self;\n}\n\n- (void)dealloc {\n    [error release];\n    [super dealloc];\n}\n\n#pragma mark Methods\n\n- (id)objectWithData:(NSData *)data {\n\n    if (!data) {\n        self.error = @\"Input was 'nil'\";\n        return nil;\n    }\n\n\tSBJsonStreamParserAccumulator *accumulator = [[[SBJsonStreamParserAccumulator alloc] init] autorelease];\n    \n    SBJsonStreamParserAdapter *adapter = [[[SBJsonStreamParserAdapter alloc] init] autorelease];\n    adapter.delegate = accumulator;\n\t\n\tSBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];\n\tparser.maxDepth = self.maxDepth;\n\tparser.delegate = adapter;\n\t\n\tswitch ([parser parse:data]) {\n\t\tcase SBJsonStreamParserComplete:\n            return accumulator.value;\n\t\t\tbreak;\n\t\t\t\n\t\tcase SBJsonStreamParserWaitingForData:\n\t\t    self.error = @\"Unexpected end of input\";\n\t\t\tbreak;\n\n\t\tcase SBJsonStreamParserError:\n\t\t    self.error = parser.error;\n\t\t\tbreak;\n\t}\n\t\n\treturn nil;\n}\n\n- (id)objectWithString:(NSString *)repr {\n\treturn [self objectWithData:[repr dataUsingEncoding:NSUTF8StringEncoding]];\n}\n\n- (id)objectWithString:(NSString*)repr error:(NSError**)error_ {\n\tid tmp = [self objectWithString:repr];\n    if (tmp)\n        return tmp;\n    \n    if (error_) {\n\t\tNSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:error, NSLocalizedDescriptionKey, nil];\n        *error_ = [NSError errorWithDomain:@\"org.brautaset.SBJsonParser.ErrorDomain\" code:0 userInfo:ui];\n\t}\n\t\n    return nil;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParser.h",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n  \n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n \n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n@class SBJsonTokeniser;\n@class SBJsonStreamParser;\n@class SBJsonStreamParserState;\n\ntypedef enum {\n\tSBJsonStreamParserComplete,\n\tSBJsonStreamParserWaitingForData,\n\tSBJsonStreamParserError,\n} SBJsonStreamParserStatus;\n\n\n/**\n @brief Delegate for interacting directly with the stream parser\n \n You will most likely find it much more convenient to implement the\n SBJsonStreamParserAdapterDelegate protocol instead.\n */\n@protocol SBJsonStreamParserDelegate\n\n/// Called when object start is found\n- (void)parserFoundObjectStart:(SBJsonStreamParser*)parser;\n\n/// Called when object key is found\n- (void)parser:(SBJsonStreamParser*)parser foundObjectKey:(NSString*)key;\n\n/// Called when object end is found\n- (void)parserFoundObjectEnd:(SBJsonStreamParser*)parser;\n\n/// Called when array start is found\n- (void)parserFoundArrayStart:(SBJsonStreamParser*)parser;\n\n/// Called when array end is found\n- (void)parserFoundArrayEnd:(SBJsonStreamParser*)parser;\n\n/// Called when a boolean value is found\n- (void)parser:(SBJsonStreamParser*)parser foundBoolean:(BOOL)x;\n\n/// Called when a null value is found\n- (void)parserFoundNull:(SBJsonStreamParser*)parser;\n\n/// Called when a number is found\n- (void)parser:(SBJsonStreamParser*)parser foundNumber:(NSNumber*)num;\n\n/// Called when a string is found\n- (void)parser:(SBJsonStreamParser*)parser foundString:(NSString*)string;\n\n@end\n\n\n/**\n @brief Parse a stream of JSON data.\n \n Using this class directly you can reduce the apparent latency for each\n download/parse cycle of documents over a slow connection. You can start\n parsing *and return chunks of the parsed document* before the entire\n document is downloaded.\n \n Using this class is also useful to parse huge documents on disk\n bit by bit so you don't have to keep them all in memory. \n \n @see SBJsonStreamParserAdapter for more information.\n \n @see @ref objc2json\n \n */\n@interface SBJsonStreamParser : NSObject {\n@private\n\tBOOL supportMultipleDocuments;\n\tid<SBJsonStreamParserDelegate> delegate;\n\tSBJsonTokeniser *tokeniser;\n    NSMutableArray *stateStack;\n\t__weak SBJsonStreamParserState *state;\n\tNSUInteger maxDepth;\n\tNSString *error;\n}\n\n@property (nonatomic, assign) __weak SBJsonStreamParserState *state; // Private\n@property (nonatomic, readonly, retain) NSMutableArray *stateStack; // Private\n\n/**\n @brief Expect multiple documents separated by whitespace\n\n Normally the @p -parse: method returns SBJsonStreamParserComplete when it's found a complete JSON document.\n Attempting to parse any more data at that point is considered an error. (\"Garbage after JSON\".)\n \n If you set this property to true the parser will never return SBJsonStreamParserComplete. Rather,\n once an object is completed it will expect another object to immediately follow, separated\n only by (optional) whitespace.\n\n @see The TweetStream app in the Examples\n */\n@property BOOL supportMultipleDocuments;\n\n/**\n @brief Delegate to receive messages\n\n The object set here receives a series of messages as the parser breaks down the JSON stream\n into valid tokens.\n\n @note\n Usually this should be an instance of SBJsonStreamParserAdapter, but you can\n substitute your own implementation of the SBJsonStreamParserDelegate protocol if you need to. \n */\n@property (assign) id<SBJsonStreamParserDelegate> delegate;\n\n/**\n @brief The max parse depth\n \n If the input is nested deeper than this the parser will halt parsing and return an error.\n\n Defaults to 32. \n */\n@property NSUInteger maxDepth;\n\n/// Holds the error after SBJsonStreamParserError was returned\n@property (copy) NSString *error;\n\n/**\n @brief Parse some JSON\n \n The JSON is assumed to be UTF8 encoded. This can be a full JSON document, or a part of one.\n\n @param data An NSData object containing the next chunk of JSON\n\n @return \n @li SBJsonStreamParserComplete if a full document was found\n @li SBJsonStreamParserWaitingForData if a partial document was found and more data is required to complete it\n @li SBJsonStreamParserError if an error occured. (See the error property for details in this case.)\n \n */\n- (SBJsonStreamParserStatus)parse:(NSData*)data;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParser.m",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n\n Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n\n Neither the name of the the author nor the names of its contributors\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamParser.h\"\n#import \"SBJsonTokeniser.h\"\n#import \"SBJsonStreamParserState.h\"\n#import <limits.h>\n\n@implementation SBJsonStreamParser\n\n@synthesize supportMultipleDocuments;\n@synthesize error;\n@synthesize delegate;\n@synthesize maxDepth;\n@synthesize state;\n@synthesize stateStack;\n\n#pragma mark Housekeeping\n\n- (id)init {\n\tself = [super init];\n\tif (self) {\n\t\tmaxDepth = 32u;\n        stateStack = [[NSMutableArray alloc] initWithCapacity:maxDepth];\n        state = [SBJsonStreamParserStateStart sharedInstance];\n\t\ttokeniser = [[SBJsonTokeniser alloc] init];\n\t}\n\treturn self;\n}\n\n- (void)dealloc {\n\tself.error = nil;\n    self.state = nil;\n\t[stateStack release];\n\t[tokeniser release];\n\t[super dealloc];\n}\n\n#pragma mark Methods\n\n- (NSString*)tokenName:(sbjson_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson_token_array_start:\n\t\t\treturn @\"start of array\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_array_end:\n\t\t\treturn @\"end of array\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_number:\n\t\t\treturn @\"number\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_string:\n\t\t\treturn @\"string\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_true:\n\t\tcase sbjson_token_false:\n\t\t\treturn @\"boolean\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_null:\n\t\t\treturn @\"null\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_keyval_separator:\n\t\t\treturn @\"key-value separator\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_separator:\n\t\t\treturn @\"value separator\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_object_start:\n\t\t\treturn @\"start of object\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_object_end:\n\t\t\treturn @\"end of object\";\n\t\t\tbreak;\n\n\t\tcase sbjson_token_eof:\n\t\tcase sbjson_token_error:\n\t\t\tbreak;\n\t}\n\tNSAssert(NO, @\"Should not get here\");\n\treturn @\"<aaiiie!>\";\n}\n\n- (void)maxDepthError {\n    self.error = [NSString stringWithFormat:@\"Input depth exceeds max depth of %lu\", maxDepth];\n    self.state = [SBJsonStreamParserStateError sharedInstance];\n}\n\n- (void)handleObjectStart {\n\tif (stateStack.count >= maxDepth) {\n        [self maxDepthError];\n        return;\n\t}\n\n    [delegate parserFoundObjectStart:self];\n    [stateStack addObject:state];\n    self.state = [SBJsonStreamParserStateObjectStart sharedInstance];\n}\n\n- (void)handleArrayStart {\n\tif (stateStack.count >= maxDepth) {\n        [self maxDepthError];\n        return;\n    }\n\t\n\t[delegate parserFoundArrayStart:self];\n    [stateStack addObject:state];\n    self.state = [SBJsonStreamParserStateArrayStart sharedInstance];\n}\n\n- (SBJsonStreamParserStatus)parse:(NSData *)data_ {\n\t[tokeniser appendData:data_];\n\n\n\tfor (;;) {\n\n        if ([state isKindOfClass:[SBJsonStreamParserStateError class]])\n            return SBJsonStreamParserError;\n\n        NSObject *token;\n\t\tsbjson_token_t tok = [tokeniser getToken:&token];\n\t\tswitch (tok) {\n\t\t\tcase sbjson_token_eof:\n                return [state parserShouldReturn:self];\n\t\t\t\tbreak;\n\n\t\t\tcase sbjson_token_error:\n\t\t\t\tself.state = [SBJsonStreamParserStateError sharedInstance];\n\t\t\t\tself.error = tokeniser.error;\n\t\t\t\treturn SBJsonStreamParserError;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tif (![state parser:self shouldAcceptToken:tok]) {\n\t\t\t\t\tNSString *tokenName = [self tokenName:tok];\n\t\t\t\t\tNSString *stateName = [state name];\n\n\t\t\t\t\tself.error = [NSString stringWithFormat:@\"Token '%@' not expected %@\", tokenName, stateName];\n\t\t\t\t\tself.state = [SBJsonStreamParserStateError sharedInstance];\n\t\t\t\t\treturn SBJsonStreamParserError;\n\t\t\t\t}\n\n\t\t\t\tswitch (tok) {\n\t\t\t\t\tcase sbjson_token_object_start:\n\t\t\t\t\t\t[self handleObjectStart];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_object_end:\n                        self.state = [stateStack lastObject];\n                        [stateStack removeLastObject];\n                        [state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\t[delegate parserFoundObjectEnd:self];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_array_start:\n\t\t\t\t\t\t[self handleArrayStart];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_array_end:\n                        self.state = [stateStack lastObject];\n                        [stateStack removeLastObject];\n                        [state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\t[delegate parserFoundArrayEnd:self];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_separator:\n\t\t\t\t\tcase sbjson_token_keyval_separator:\n\t\t\t\t\t\t[state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_true:\n\t\t\t\t\t\t[delegate parser:self foundBoolean:YES];\n\t\t\t\t\t\t[state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_false:\n\t\t\t\t\t\t[delegate parser:self foundBoolean:NO];\n\t\t\t\t\t\t[state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_null:\n\t\t\t\t\t\t[delegate parserFoundNull:self];\n\t\t\t\t\t\t[state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_number:\n                        [delegate parser:self foundNumber:(NSNumber*)token];\n\t\t\t\t\t\t[state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase sbjson_token_string:\n                        if ([state needKey])\n                            [delegate parser:self foundObjectKey:(NSString*)token];\n                        else\n                            [delegate parser:self foundString:(NSString*)token];\n\t\t\t\t\t\t[state parser:self shouldTransitionTo:tok];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn SBJsonStreamParserComplete;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParserAccumulator.h",
    "content": "/*\n Copyright (C) 2011 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n#import \"SBJsonStreamParserAdapter.h\"\n\n@interface SBJsonStreamParserAccumulator : NSObject <SBJsonStreamParserAdapterDelegate> {\n@private\n    id value;    \n}\n\n@property (readonly, copy) id value;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParserAccumulator.m",
    "content": "/*\n Copyright (C) 2011 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamParserAccumulator.h\"\n\n@implementation SBJsonStreamParserAccumulator\n\n@synthesize value;\n\n- (void)dealloc {\n    [value release];\n    [super dealloc];\n}\n\n#pragma mark SBJsonStreamParserAdapterDelegate\n\n- (void)parser:(SBJsonStreamParser*)parser foundArray:(NSArray *)array {\n\tvalue = [array retain];\n}\n\n- (void)parser:(SBJsonStreamParser*)parser foundObject:(NSDictionary *)dict {\n\tvalue = [dict retain];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParserAdapter.h",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n  \n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n \n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n#import \"SBJsonStreamParser.h\"\n\ntypedef enum {\n\tSBJsonStreamParserAdapterNone,\n\tSBJsonStreamParserAdapterArray,\n\tSBJsonStreamParserAdapterObject,\n} SBJsonStreamParserAdapterType;\n\n/**\n @brief Delegate for getting objects & arrays from the stream parser adapter\n \n @see The TweetStream example project.\n */\n@protocol SBJsonStreamParserAdapterDelegate\n\n/**\n @brief Called if a JSON array is found\n \n This method is called if a JSON array is found.\n \n */\n- (void)parser:(SBJsonStreamParser*)parser foundArray:(NSArray*)array;\n\n/**\n @brief Called when a JSON object is found\n\n This method is called if a JSON object is found.\n */\n- (void)parser:(SBJsonStreamParser*)parser foundObject:(NSDictionary*)dict;\n\n@end\n\n/**\n @brief SBJsonStreamParserDelegate protocol adapter\n \n Rather than implementing the SBJsonStreamParserDelegate protocol yourself you will\n most likely find it much more convenient to use an instance of this class and\n implement the SBJsonStreamParserAdapterDelegate protocol instead.\n \n Normally you would only get one call from either the -parser:foundArray: or\n -parser:foundObject: method. However, if your inputs contains multiple JSON\n documents and you set the parser's -supportMultipleDocuments property to YES\n you will get one call for each full method.\n \n @code\n SBJsonStreamParserAdapter *adapter = [[[SBJsonStreamParserAdapter alloc] init] autorelease];\n adapter.delegate = self;\n \n SBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];\n parser.delegate = adapter;\n parser.supportMultipleDocuments = YES;\n\n // Note that this input contains multiple top-level JSON documents\n NSData *json = [@\"[]{}[]{}\" dataWithEncoding:NSUTF8StringEncoding]; \n [parser parse:data];\n @endcode\n \n In the above example @p self will have the following sequence of methods called on it:\n \n @li -parser:foundArray:\n @li -parser:foundObject:\n @li -parser:foundArray:\n @li -parser:foundObject:\n\n Often you won't have control over the input you're parsing, so can't make use of\n this feature. But, all is not lost: this class will let you get the same effect by \n allowing you to skip one or more of the outer enclosing objects. Thus, the next\n example results in the same sequence of -parser:foundArray: / -parser:foundObject:\n being called on your delegate.\n \n @code\n SBJsonStreamParserAdapter *adapter = [[[SBJsonStreamParserAdapter alloc] init] autorelease];\n adapter.delegate = self;\n adapter.levelsToSkip = 1;\n \n SBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];\n parser.delegate = adapter;\n \n // Note that this input contains A SINGLE top-level document\n NSData *json = [@\"[[],{},[],{}]\" dataWithEncoding:NSUTF8StringEncoding]; \n [parser parse:data];\n @endcode\n \n*/\n@interface SBJsonStreamParserAdapter : NSObject <SBJsonStreamParserDelegate> {\n@private\n\tid<SBJsonStreamParserAdapterDelegate> delegate;\n\tNSUInteger levelsToSkip, depth;\n\t__weak NSMutableArray *array;\n\t__weak NSMutableDictionary *dict;\n\tNSMutableArray *keyStack;\n\tNSMutableArray *stack;\n\t\n\tSBJsonStreamParserAdapterType currentType;\n}\n\n/**\n @brief How many levels to skip\n \n This is useful for parsing huge JSON documents, or documents coming in over a very slow link.\n \n If you set this to N it will skip the outer N levels and call the -parser:foundArray:\n or -parser:foundObject: methods for each of the inner objects, as appropriate.\n \n @see The StreamParserIntegrationTest.m file for examples\n*/\n@property NSUInteger levelsToSkip;\n\n/**\n @brief Your delegate object\n Set this to the object you want to receive the SBJsonStreamParserAdapterDelegate messages.\n */\n@property (assign) id<SBJsonStreamParserAdapterDelegate> delegate;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParserAdapter.m",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n  \n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n \n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamParserAdapter.h\"\n\n@interface SBJsonStreamParserAdapter ()\n\n- (void)pop;\n- (void)parser:(SBJsonStreamParser*)parser found:(id)obj;\n\n@end\n\n\n\n@implementation SBJsonStreamParserAdapter\n\n@synthesize delegate;\n@synthesize levelsToSkip;\n\n#pragma mark Housekeeping\n\n- (id)init {\n\tself = [super init];\n\tif (self) {\n\t\tkeyStack = [[NSMutableArray alloc] initWithCapacity:32];\n\t\tstack = [[NSMutableArray alloc] initWithCapacity:32];\n\t\t\n\t\tcurrentType = SBJsonStreamParserAdapterNone;\n\t}\n\treturn self;\n}\t\n\n- (void)dealloc {\n\t[keyStack release];\n\t[stack release];\n\t[super dealloc];\n}\n\n#pragma mark Private methods\n\n- (void)pop {\n\t[stack removeLastObject];\n\tarray = nil;\n\tdict = nil;\n\tcurrentType = SBJsonStreamParserAdapterNone;\n\t\n\tid value = [stack lastObject];\n\t\n\tif ([value isKindOfClass:[NSArray class]]) {\n\t\tarray = value;\n\t\tcurrentType = SBJsonStreamParserAdapterArray;\n\t} else if ([value isKindOfClass:[NSDictionary class]]) {\n\t\tdict = value;\n\t\tcurrentType = SBJsonStreamParserAdapterObject;\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser found:(id)obj {\n\tNSParameterAssert(obj);\n\t\n\tswitch (currentType) {\n\t\tcase SBJsonStreamParserAdapterArray:\n\t\t\t[array addObject:obj];\n\t\t\tbreak;\n\n\t\tcase SBJsonStreamParserAdapterObject:\n\t\t\tNSParameterAssert(keyStack.count);\n\t\t\t[dict setObject:obj forKey:[keyStack lastObject]];\n\t\t\t[keyStack removeLastObject];\n\t\t\tbreak;\n\t\t\t\n\t\tcase SBJsonStreamParserAdapterNone:\n\t\t\tif ([obj isKindOfClass:[NSArray class]]) {\n\t\t\t\t[delegate parser:parser foundArray:obj];\n\t\t\t} else {\n\t\t\t\t[delegate parser:parser foundObject:obj];\n\t\t\t}\t\t\t\t\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n\n#pragma mark Delegate methods\n\n- (void)parserFoundObjectStart:(SBJsonStreamParser*)parser {\n\tif (++depth > levelsToSkip) {\n\t\tdict = [[NSMutableDictionary new] autorelease];\n\t\t[stack addObject:dict];\n\t\tcurrentType = SBJsonStreamParserAdapterObject;\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser foundObjectKey:(NSString*)key_ {\n\t[keyStack addObject:key_];\n}\n\n- (void)parserFoundObjectEnd:(SBJsonStreamParser*)parser {\n\tif (depth-- > levelsToSkip) {\n\t\tid value = [dict retain];\n\t\t[self pop];\n\t\t[self parser:parser found:value];\n\t\t[value release];\n\t}\n}\n\n- (void)parserFoundArrayStart:(SBJsonStreamParser*)parser {\n\tif (++depth > levelsToSkip) {\n\t\tarray = [[NSMutableArray new] autorelease];\n\t\t[stack addObject:array];\n\t\tcurrentType = SBJsonStreamParserAdapterArray;\n\t}\n}\n\n- (void)parserFoundArrayEnd:(SBJsonStreamParser*)parser {\n\tif (depth-- > levelsToSkip) {\n\t\tid value = [array retain];\n\t\t[self pop];\n\t\t[self parser:parser found:value];\n\t\t[value release];\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser foundBoolean:(BOOL)x {\n\t[self parser:parser found:[NSNumber numberWithBool:x]];\n}\n\n- (void)parserFoundNull:(SBJsonStreamParser*)parser {\n\t[self parser:parser found:[NSNull null]];\n}\n\n- (void)parser:(SBJsonStreamParser*)parser foundNumber:(NSNumber*)num {\n\t[self parser:parser found:num];\n}\n\n- (void)parser:(SBJsonStreamParser*)parser foundString:(NSString*)string {\n\t[self parser:parser found:string];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParserState.h",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n  \n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n \n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n#import \"SBJsonTokeniser.h\"\n#import \"SBJsonStreamParser.h\"\n\n@interface SBJsonStreamParserState : NSObject\n+ (id)sharedInstance;\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token;\n- (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser;\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok;\n- (BOOL)needKey;\n\n- (NSString*)name;\n\n@end\n\n@interface SBJsonStreamParserStateStart : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateComplete : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateError : SBJsonStreamParserState\n@end\n\n\n@interface SBJsonStreamParserStateObjectStart : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateObjectGotKey : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateObjectSeparator : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateObjectGotValue : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateObjectNeedKey : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateArrayStart : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateArrayGotValue : SBJsonStreamParserState\n@end\n\n@interface SBJsonStreamParserStateArrayNeedValue : SBJsonStreamParserState\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamParserState.m",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n\n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n\n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamParserState.h\"\n#import \"SBJsonStreamParser.h\"\n\n#define SINGLETON \\\n+ (id)sharedInstance { \\\n    static id state; \\\n    if (!state) state = [[self alloc] init]; \\\n    return state; \\\n}\n\n@implementation SBJsonStreamParserState\n\n+ (id)sharedInstance { return nil; }\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\treturn NO;\n}\n\n- (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser {\n\treturn SBJsonStreamParserWaitingForData;\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {}\n\n- (BOOL)needKey {\n\treturn NO;\n}\n\n- (NSString*)name {\n\treturn @\"<aaiie!>\";\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateStart\n\nSINGLETON\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\treturn token == sbjson_token_array_start || token == sbjson_token_object_start;\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\n\tSBJsonStreamParserState *state = nil;\n\tswitch (tok) {\n\t\tcase sbjson_token_array_start:\n\t\t\tstate = [SBJsonStreamParserStateArrayStart sharedInstance];\n\t\t\tbreak;\n\n\t\tcase sbjson_token_object_start:\n\t\t\tstate = [SBJsonStreamParserStateObjectStart sharedInstance];\n\t\t\tbreak;\n\n\t\tcase sbjson_token_array_end:\n\t\tcase sbjson_token_object_end:\n\t\t\tif (parser.supportMultipleDocuments)\n\t\t\t\tstate = parser.state;\n\t\t\telse\n\t\t\t\tstate = [SBJsonStreamParserStateComplete sharedInstance];\n\t\t\tbreak;\n\n\t\tcase sbjson_token_eof:\n\t\t\treturn;\n\n\t\tdefault:\n\t\t\tstate = [SBJsonStreamParserStateError sharedInstance];\n\t\t\tbreak;\n\t}\n\n\n\tparser.state = state;\n}\n\n- (NSString*)name { return @\"before outer-most array or object\"; }\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateComplete\n\nSINGLETON\n\n- (NSString*)name { return @\"after outer-most array or object\"; }\n\n- (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser {\n\treturn SBJsonStreamParserComplete;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateError\n\nSINGLETON\n\n- (NSString*)name { return @\"in error\"; }\n\n- (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser {\n\treturn SBJsonStreamParserError;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateObjectStart\n\nSINGLETON\n\n- (NSString*)name { return @\"at beginning of object\"; }\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson_token_object_end:\n\t\tcase sbjson_token_string:\n\t\t\treturn YES;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn NO;\n\t\t\tbreak;\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tparser.state = [SBJsonStreamParserStateObjectGotKey sharedInstance];\n}\n\n- (BOOL)needKey {\n\treturn YES;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateObjectGotKey\n\nSINGLETON\n\n- (NSString*)name { return @\"after object key\"; }\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\treturn token == sbjson_token_keyval_separator;\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tparser.state = [SBJsonStreamParserStateObjectSeparator sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateObjectSeparator\n\nSINGLETON\n\n- (NSString*)name { return @\"as object value\"; }\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson_token_object_start:\n\t\tcase sbjson_token_array_start:\n\t\tcase sbjson_token_true:\n\t\tcase sbjson_token_false:\n\t\tcase sbjson_token_null:\n\t\tcase sbjson_token_number:\n\t\tcase sbjson_token_string:\n\t\t\treturn YES;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn NO;\n\t\t\tbreak;\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tparser.state = [SBJsonStreamParserStateObjectGotValue sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateObjectGotValue\n\nSINGLETON\n\n- (NSString*)name { return @\"after object value\"; }\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson_token_object_end:\n\t\tcase sbjson_token_separator:\n\t\t\treturn YES;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn NO;\n\t\t\tbreak;\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tparser.state = [SBJsonStreamParserStateObjectNeedKey sharedInstance];\n}\n\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateObjectNeedKey\n\nSINGLETON\n\n- (NSString*)name { return @\"in place of object key\"; }\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n    return sbjson_token_string == token;\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tparser.state = [SBJsonStreamParserStateObjectGotKey sharedInstance];\n}\n\n- (BOOL)needKey {\n\treturn YES;\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateArrayStart\n\nSINGLETON\n\n- (NSString*)name { return @\"at array start\"; }\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson_token_object_end:\n\t\tcase sbjson_token_keyval_separator:\n\t\tcase sbjson_token_separator:\n\t\t\treturn NO;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn YES;\n\t\t\tbreak;\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tparser.state = [SBJsonStreamParserStateArrayGotValue sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateArrayGotValue\n\nSINGLETON\n\n- (NSString*)name { return @\"after array value\"; }\n\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\treturn token == sbjson_token_array_end || token == sbjson_token_separator;\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tif (tok == sbjson_token_separator)\n\t\tparser.state = [SBJsonStreamParserStateArrayNeedValue sharedInstance];\n}\n\n@end\n\n#pragma mark -\n\n@implementation SBJsonStreamParserStateArrayNeedValue\n\nSINGLETON\n\n- (NSString*)name { return @\"as array value\"; }\n\n\n- (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token {\n\tswitch (token) {\n\t\tcase sbjson_token_array_end:\n\t\tcase sbjson_token_keyval_separator:\n\t\tcase sbjson_token_object_end:\n\t\tcase sbjson_token_separator:\n\t\t\treturn NO;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn YES;\n\t\t\tbreak;\n\t}\n}\n\n- (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {\n\tparser.state = [SBJsonStreamParserStateArrayGotValue sharedInstance];\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamWriter.h",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n  \n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n \n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n/// Enable JSON writing for non-native objects\n@interface NSObject (SBProxyForJson)\n\n/**\n @brief Allows generation of JSON for otherwise unsupported classes.\n \n If you have a custom class that you want to create a JSON representation\n for you can implement this method in your class. It should return a\n representation of your object defined in terms of objects that can be\n translated into JSON. For example, a Person object might implement it like this:\n \n @code\n - (id)proxyForJson {\n\treturn [NSDictionary dictionaryWithObjectsAndKeys:\n\tname, @\"name\",\n\tphone, @\"phone\",\n\temail, @\"email\",\n\tnil];\n }\n @endcode\n \n */\n- (id)proxyForJson;\n\n@end\n\n@class SBJsonStreamWriter;\n\n@protocol SBJsonStreamWriterDelegate\n\n- (void)writer:(SBJsonStreamWriter*)writer appendBytes:(const void *)bytes length:(NSUInteger)length;\n\n@end\n\n@class SBJsonStreamWriterState;\n\n/**\n @brief The Stream Writer class.\n \n Accepts a stream of messages and writes JSON of these to its delegate object.\n \n This class provides a range of high-, mid- and low-level methods. You can mix\n and match calls to these. For example, you may want to call -writeArrayOpen\n to start an array and then repeatedly call -writeObject: with various objects\n before finishing off with a -writeArrayClose call.\n  \n @see @ref json2objc\n\n */\n\n@interface SBJsonStreamWriter : NSObject {\n@private\n\tNSString *error;\n    NSMutableArray *stateStack;\n    __weak SBJsonStreamWriterState *state;\n    id<SBJsonStreamWriterDelegate> delegate;\n\tNSUInteger maxDepth;\n    BOOL sortKeys, humanReadable;\n}\n\n@property (nonatomic, assign) __weak SBJsonStreamWriterState *state; // Internal\n@property (nonatomic, readonly, retain) NSMutableArray *stateStack; // Internal \n\n/**\n @brief delegate to receive JSON output\n Delegate that will receive messages with output.\n */\n@property (assign) id<SBJsonStreamWriterDelegate> delegate;\n\n/**\n @brief The maximum recursing depth.\n \n Defaults to 512. If the input is nested deeper than this the input will be deemed to be\n malicious and the parser returns nil, signalling an error. (\"Nested too deep\".) You can\n turn off this security feature by setting the maxDepth value to 0.\n */\n@property NSUInteger maxDepth;\n\n/**\n @brief Whether we are generating human-readable (multiline) JSON.\n \n Set whether or not to generate human-readable JSON. The default is NO, which produces\n JSON without any whitespace between tokens. If set to YES, generates human-readable\n JSON with linebreaks after each array value and dictionary key/value pair, indented two\n spaces per nesting level.\n */\n@property BOOL humanReadable;\n\n/**\n @brief Whether or not to sort the dictionary keys in the output.\n \n If this is set to YES, the dictionary keys in the JSON output will be in sorted order.\n (This is useful if you need to compare two structures, for example.) The default is NO.\n */\n@property BOOL sortKeys;\n\n/// Contains the error description after an error has occured.\n@property (copy) NSString *error;\n\n/** \n Write an NSDictionary to the JSON stream.\n @return YES if successful, or NO on failure\n */\n- (BOOL)writeObject:(NSDictionary*)dict;\n\n/**\n Write an NSArray to the JSON stream.\n @return YES if successful, or NO on failure\n */\n- (BOOL)writeArray:(NSArray *)array;\n\n/** \n Start writing an Object to the stream\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeObjectOpen;\n\n/**\n Close the current object being written\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeObjectClose;\n\n/** Start writing an Array to the stream\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeArrayOpen;\n\n/** Close the current Array being written\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeArrayClose;\n\n/** Write a null to the stream\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeNull;\n\n/** Write a boolean to the stream\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeBool:(BOOL)x;\n\n/** Write a Number to the stream\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeNumber:(NSNumber*)n;\n\n/** Write a String to the stream\n @return YES if successful, or NO on failure\n*/\n- (BOOL)writeString:(NSString*)s;\n\n@end\n\n@interface SBJsonStreamWriter (Private)\n- (BOOL)writeValue:(id)v;\n- (void)appendBytes:(const void *)bytes length:(NSUInteger)length;\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamWriter.m",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n\n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n\n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamWriter.h\"\n#import \"SBJsonStreamWriterState.h\"\n\nstatic NSDecimalNumber *kNotANumber;\nstatic id kStaticStringCache;\n\n\n@implementation SBJsonStreamWriter\n\n@synthesize error;\n@synthesize maxDepth;\n@synthesize state;\n@synthesize stateStack;\n@synthesize humanReadable;\n@synthesize sortKeys;\n\n+ (void)initialize {\n\tkNotANumber = [NSDecimalNumber notANumber];\n    \n    Class cacheClass = NSClassFromString(@\"NSCache\");\n    if (cacheClass) {\n        NSLog(@\"%s NSCache supported\", __FUNCTION__);\n        kStaticStringCache = [[cacheClass alloc] init];\n    }else {\n        NSLog(@\"%s NSCache not supported\", __FUNCTION__);\n    }\n\n    \n}\n\n#pragma mark Housekeeping\n\n@synthesize delegate;\n\n- (id)init {\n\tself = [super init];\n\tif (self) {\n\t\tmaxDepth = 32u;\n        stateStack = [[NSMutableArray alloc] initWithCapacity:maxDepth];\n        state = [SBJsonStreamWriterStateStart sharedInstance];\n    }\n\treturn self;\n}\n\n- (void)dealloc {\n\tself.error = nil;\n    self.state = nil;\n    [stateStack release];\n\t[super dealloc];\n}\n\n#pragma mark Methods\n\n- (void)appendBytes:(const void *)bytes length:(NSUInteger)length {\n    [delegate writer:self appendBytes:bytes length:length];\n}\n\n- (BOOL)writeObject:(NSDictionary *)dict {\n\tif (![self writeObjectOpen])\n\t\treturn NO;\n\n\tNSArray *keys = [dict allKeys];\n\tif (sortKeys)\n\t\tkeys = [keys sortedArrayUsingSelector:@selector(compare:)];\n\n\tfor (id k in keys) {\n\t\tif (![k isKindOfClass:[NSString class]]) {\n\t\t\tself.error = [NSString stringWithFormat:@\"JSON object key must be string: %@\", k];\n\t\t\treturn NO;\n\t\t}\n\n\t\tif (![self writeString:k])\n\t\t\treturn NO;\n\t\tif (![self writeValue:[dict objectForKey:k]])\n\t\t\treturn NO;\n\t}\n\n\treturn [self writeObjectClose];\n}\n\n- (BOOL)writeArray:(NSArray*)array {\n\tif (![self writeArrayOpen])\n\t\treturn NO;\n\tfor (id v in array)\n\t\tif (![self writeValue:v])\n\t\t\treturn NO;\n\treturn [self writeArrayClose];\n}\n\n\n- (BOOL)writeObjectOpen {\n\tif ([state isInvalidState:self]) return NO;\n\tif ([state expectingKey:self]) return NO;\n\t[state appendSeparator:self];\n\tif (humanReadable && stateStack.count) [state appendWhitespace:self];\n\n    [stateStack addObject:state];\n    self.state = [SBJsonStreamWriterStateObjectStart sharedInstance];\n\n\tif (maxDepth && stateStack.count > maxDepth) {\n\t\tself.error = @\"Nested too deep\";\n\t\treturn NO;\n\t}\n\n\t[delegate writer:self appendBytes:\"{\" length:1];\n\treturn YES;\n}\n\n- (BOOL)writeObjectClose {\n\tif ([state isInvalidState:self]) return NO;\n\n    SBJsonStreamWriterState *prev = state;\n\n    self.state = [stateStack lastObject];\n    [stateStack removeLastObject];\n\n\tif (humanReadable) [prev appendWhitespace:self];\n\t[delegate writer:self appendBytes:\"}\" length:1];\n\n\t[state transitionState:self];\n\treturn YES;\n}\n\n- (BOOL)writeArrayOpen {\n\tif ([state isInvalidState:self]) return NO;\n\tif ([state expectingKey:self]) return NO;\n\t[state appendSeparator:self];\n\tif (humanReadable && stateStack.count) [state appendWhitespace:self];\n\n    [stateStack addObject:state];\n\tself.state = [SBJsonStreamWriterStateArrayStart sharedInstance];\n\n\tif (maxDepth && stateStack.count > maxDepth) {\n\t\tself.error = @\"Nested too deep\";\n\t\treturn NO;\n\t}\n\n\t[delegate writer:self appendBytes:\"[\" length:1];\n\treturn YES;\n}\n\n- (BOOL)writeArrayClose {\n\tif ([state isInvalidState:self]) return NO;\n\tif ([state expectingKey:self]) return NO;\n\n    SBJsonStreamWriterState *prev = state;\n\n    self.state = [stateStack lastObject];\n    [stateStack removeLastObject];\n\n\tif (humanReadable) [prev appendWhitespace:self];\n\t[delegate writer:self appendBytes:\"]\" length:1];\n\n\t[state transitionState:self];\n\treturn YES;\n}\n\n- (BOOL)writeNull {\n\tif ([state isInvalidState:self]) return NO;\n\tif ([state expectingKey:self]) return NO;\n\t[state appendSeparator:self];\n\tif (humanReadable) [state appendWhitespace:self];\n\n\t[delegate writer:self appendBytes:\"null\" length:4];\n\t[state transitionState:self];\n\treturn YES;\n}\n\n- (BOOL)writeBool:(BOOL)x {\n\tif ([state isInvalidState:self]) return NO;\n\tif ([state expectingKey:self]) return NO;\n\t[state appendSeparator:self];\n\tif (humanReadable) [state appendWhitespace:self];\n\n\tif (x)\n\t\t[delegate writer:self appendBytes:\"true\" length:4];\n\telse\n\t\t[delegate writer:self appendBytes:\"false\" length:5];\n\t[state transitionState:self];\n\treturn YES;\n}\n\n\n- (BOOL)writeValue:(id)o {\n\tif ([o isKindOfClass:[NSDictionary class]]) {\n\t\treturn [self writeObject:o];\n\n\t} else if ([o isKindOfClass:[NSArray class]]) {\n\t\treturn [self writeArray:o];\n\n\t} else if ([o isKindOfClass:[NSString class]]) {\n\t\t[self writeString:o];\n\t\treturn YES;\n\n\t} else if ([o isKindOfClass:[NSNumber class]]) {\n\t\treturn [self writeNumber:o];\n\n\t} else if ([o isKindOfClass:[NSNull class]]) {\n\t\treturn [self writeNull];\n\n\t} else if ([o respondsToSelector:@selector(proxyForJson)]) {\n\t\treturn [self writeValue:[o proxyForJson]];\n\n\t}\n\n\tself.error = [NSString stringWithFormat:@\"JSON serialisation not supported for %@\", [o class]];\n\treturn NO;\n}\n\nstatic const char *strForChar(int c) {\n\tswitch (c) {\n\t\tcase 0: return \"\\\\u0000\"; break;\n\t\tcase 1: return \"\\\\u0001\"; break;\n\t\tcase 2: return \"\\\\u0002\"; break;\n\t\tcase 3: return \"\\\\u0003\"; break;\n\t\tcase 4: return \"\\\\u0004\"; break;\n\t\tcase 5: return \"\\\\u0005\"; break;\n\t\tcase 6: return \"\\\\u0006\"; break;\n\t\tcase 7: return \"\\\\u0007\"; break;\n\t\tcase 8: return \"\\\\b\"; break;\n\t\tcase 9: return \"\\\\t\"; break;\n\t\tcase 10: return \"\\\\n\"; break;\n\t\tcase 11: return \"\\\\u000b\"; break;\n\t\tcase 12: return \"\\\\f\"; break;\n\t\tcase 13: return \"\\\\r\"; break;\n\t\tcase 14: return \"\\\\u000e\"; break;\n\t\tcase 15: return \"\\\\u000f\"; break;\n\t\tcase 16: return \"\\\\u0010\"; break;\n\t\tcase 17: return \"\\\\u0011\"; break;\n\t\tcase 18: return \"\\\\u0012\"; break;\n\t\tcase 19: return \"\\\\u0013\"; break;\n\t\tcase 20: return \"\\\\u0014\"; break;\n\t\tcase 21: return \"\\\\u0015\"; break;\n\t\tcase 22: return \"\\\\u0016\"; break;\n\t\tcase 23: return \"\\\\u0017\"; break;\n\t\tcase 24: return \"\\\\u0018\"; break;\n\t\tcase 25: return \"\\\\u0019\"; break;\n\t\tcase 26: return \"\\\\u001a\"; break;\n\t\tcase 27: return \"\\\\u001b\"; break;\n\t\tcase 28: return \"\\\\u001c\"; break;\n\t\tcase 29: return \"\\\\u001d\"; break;\n\t\tcase 30: return \"\\\\u001e\"; break;\n\t\tcase 31: return \"\\\\u001f\"; break;\n\t\tcase 34: return \"\\\\\\\"\"; break;\n\t\tcase 92: return \"\\\\\\\\\"; break;\n\t}\n\tNSLog(@\"FUTFUTFUT: -->'%c'<---\", c);\n\treturn \"FUTFUTFUT\";\n}\n\n- (BOOL)writeString:(NSString*)string {\n\tif ([state isInvalidState:self]) return NO;\n\t[state appendSeparator:self];\n\tif (humanReadable) [state appendWhitespace:self];\n\n\tNSMutableData *buf = [kStaticStringCache objectForKey:string];\n\tif (!buf) {\n\n        NSUInteger len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];\n        const char *utf8 = [string UTF8String];\n        NSUInteger written = 0, i = 0;\n\n        buf = [NSMutableData dataWithCapacity:len * 1.1f];\n        [buf appendBytes:\"\\\"\" length:1];\n\n        for (i = 0; i < len; i++) {\n            int c = utf8[i];\n            BOOL isControlChar = c >= 0 && c < 32;\n            if (isControlChar || c == '\"' || c == '\\\\') {\n                if (i - written)\n                    [buf appendBytes:utf8 + written length:i - written];\n                written = i + 1;\n\n                const char *t = strForChar(c);\n                [buf appendBytes:t length:strlen(t)];\n            }\n        }\n\n        if (i - written)\n            [buf appendBytes:utf8 + written length:i - written];\n\n        [buf appendBytes:\"\\\"\" length:1];\n        [kStaticStringCache setObject:buf forKey:string];\n    }\n\n\t[delegate writer:self appendBytes:[buf bytes] length:[buf length]];\n\t[state transitionState:self];\n\treturn YES;\n}\n\n- (BOOL)writeNumber:(NSNumber*)number {\n\tif ((CFBooleanRef)number == kCFBooleanTrue || (CFBooleanRef)number == kCFBooleanFalse)\n\t\treturn [self writeBool:[number boolValue]];\n\n\tif ([state isInvalidState:self]) return NO;\n\tif ([state expectingKey:self]) return NO;\n\t[state appendSeparator:self];\n\tif (humanReadable) [state appendWhitespace:self];\n\n\tif ((CFNumberRef)number == kCFNumberPositiveInfinity) {\n\t\tself.error = @\"+Infinity is not a valid number in JSON\";\n\t\treturn NO;\n\n\t} else if ((CFNumberRef)number == kCFNumberNegativeInfinity) {\n\t\tself.error = @\"-Infinity is not a valid number in JSON\";\n\t\treturn NO;\n\n\t} else if ((CFNumberRef)number == kCFNumberNaN) {\n\t\tself.error = @\"NaN is not a valid number in JSON\";\n\t\treturn NO;\n\n\t} else if (number == kNotANumber) {\n\t\tself.error = @\"NaN is not a valid number in JSON\";\n\t\treturn NO;\n\t}\n\n\tconst char *objcType = [number objCType];\n\tchar num[128];\n\tsize_t len;\n\n\tswitch (objcType[0]) {\n\t\tcase 'c': case 'i': case 's': case 'l': case 'q':\n\t\t\tlen = snprintf(num, sizeof num, \"%lld\", [number longLongValue]);\n\t\t\tbreak;\n\t\tcase 'C': case 'I': case 'S': case 'L': case 'Q':\n\t\t\tlen = snprintf(num, sizeof num, \"%llu\", [number unsignedLongLongValue]);\n\t\t\tbreak;\n\t\tcase 'f': case 'd': default:\n\t\t\tif ([number isKindOfClass:[NSDecimalNumber class]]) {\n\t\t\t\tchar const *utf8 = [[number stringValue] UTF8String];\n\t\t\t\t[delegate writer:self appendBytes:utf8 length: strlen(utf8)];\n\t\t\t\t[state transitionState:self];\n\t\t\t\treturn YES;\n\t\t\t}\n\t\t\tlen = snprintf(num, sizeof num, \"%.17g\", [number doubleValue]);\n\t\t\tbreak;\n\t}\n\t[delegate writer:self appendBytes:num length: len];\n\t[state transitionState:self];\n\treturn YES;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamWriterAccumulator.h",
    "content": "/*\n Copyright (C) 2011 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamWriter.h\"\n\n@interface SBJsonStreamWriterAccumulator : NSObject <SBJsonStreamWriterDelegate> {\n@private\n    NSMutableData *data;\n}\n\n@property (readonly, copy) NSData* data;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamWriterAccumulator.m",
    "content": "/*\n Copyright (C) 2011 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamWriterAccumulator.h\"\n\n\n@implementation SBJsonStreamWriterAccumulator\n\n@synthesize data;\n\n- (id)init {\n    self = [super init];\n    if (self) {\n        data = [[NSMutableData alloc] initWithCapacity:8096u];\n    }\n    return self;\n}\n\n- (void)dealloc {\n    [data release];\n    [super dealloc];\n}\n\n#pragma mark SBJsonStreamWriterDelegate\n\n- (void)writer:(SBJsonStreamWriter *)writer appendBytes:(const void *)bytes length:(NSUInteger)length {\n    [data appendBytes:bytes length:length];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamWriterState.h",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n  \n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n \n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n@class SBJsonStreamWriter;\n\n@interface SBJsonStreamWriterState : NSObject\n+ (id)sharedInstance;\n- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer;\n- (void)appendSeparator:(SBJsonStreamWriter*)writer;\n- (BOOL)expectingKey:(SBJsonStreamWriter*)writer;\n- (void)transitionState:(SBJsonStreamWriter*)writer;\n- (void)appendWhitespace:(SBJsonStreamWriter*)writer;\n@end\n\n@interface SBJsonStreamWriterStateObjectStart : SBJsonStreamWriterState\n@end\n\n@interface SBJsonStreamWriterStateObjectKey : SBJsonStreamWriterStateObjectStart\n@end\n\n@interface SBJsonStreamWriterStateObjectValue : SBJsonStreamWriterState\n@end\n\n@interface SBJsonStreamWriterStateArrayStart : SBJsonStreamWriterState\n@end\n\n@interface SBJsonStreamWriterStateArrayValue : SBJsonStreamWriterState\n@end\n\n@interface SBJsonStreamWriterStateStart : SBJsonStreamWriterState\n@end\n\n@interface SBJsonStreamWriterStateComplete : SBJsonStreamWriterState\n@end\n\n@interface SBJsonStreamWriterStateError : SBJsonStreamWriterState\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonStreamWriterState.m",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n\n   Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n   Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n\n   Neither the name of the the author nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonStreamWriterState.h\"\n#import \"SBJsonStreamWriter.h\"\n\n#define SINGLETON \\\n+ (id)sharedInstance { \\\n    static id state; \\\n    if (!state) state = [[self alloc] init]; \\\n    return state; \\\n}\n\n\n@implementation SBJsonStreamWriterState\n+ (id)sharedInstance { return nil; }\n- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer { return NO; }\n- (void)appendSeparator:(SBJsonStreamWriter*)writer {}\n- (BOOL)expectingKey:(SBJsonStreamWriter*)writer { return NO; }\n- (void)transitionState:(SBJsonStreamWriter *)writer {}\n- (void)appendWhitespace:(SBJsonStreamWriter*)writer {\n\t[writer appendBytes:\"\\n\" length:1];\n\tfor (NSUInteger i = 0; i < writer.stateStack.count; i++)\n\t    [writer appendBytes:\"  \" length:2];\n}\n@end\n\n@implementation SBJsonStreamWriterStateObjectStart\n\nSINGLETON\n\n- (void)transitionState:(SBJsonStreamWriter *)writer {\n\twriter.state = [SBJsonStreamWriterStateObjectValue sharedInstance];\n}\n- (BOOL)expectingKey:(SBJsonStreamWriter *)writer {\n\twriter.error = @\"JSON object key must be string\";\n\treturn YES;\n}\n@end\n\n@implementation SBJsonStreamWriterStateObjectKey\n\nSINGLETON\n\n- (void)appendSeparator:(SBJsonStreamWriter *)writer {\n\t[writer appendBytes:\",\" length:1];\n}\n@end\n\n@implementation SBJsonStreamWriterStateObjectValue\n\nSINGLETON\n\n- (void)appendSeparator:(SBJsonStreamWriter *)writer {\n\t[writer appendBytes:\":\" length:1];\n}\n- (void)transitionState:(SBJsonStreamWriter *)writer {\n    writer.state = [SBJsonStreamWriterStateObjectKey sharedInstance];\n}\n- (void)appendWhitespace:(SBJsonStreamWriter *)writer {\n\t[writer appendBytes:\" \" length:1];\n}\n@end\n\n@implementation SBJsonStreamWriterStateArrayStart\n\nSINGLETON\n\n- (void)transitionState:(SBJsonStreamWriter *)writer {\n    writer.state = [SBJsonStreamWriterStateArrayValue sharedInstance];\n}\n@end\n\n@implementation SBJsonStreamWriterStateArrayValue\n\nSINGLETON\n\n- (void)appendSeparator:(SBJsonStreamWriter *)writer {\n\t[writer appendBytes:\",\" length:1];\n}\n@end\n\n@implementation SBJsonStreamWriterStateStart\n\nSINGLETON\n\n\n- (void)transitionState:(SBJsonStreamWriter *)writer {\n    writer.state = [SBJsonStreamWriterStateComplete sharedInstance];\n}\n- (void)appendSeparator:(SBJsonStreamWriter *)writer {\n}\n@end\n\n@implementation SBJsonStreamWriterStateComplete\n\nSINGLETON\n\n- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer {\n\twriter.error = @\"Stream is closed\";\n\treturn YES;\n}\n@end\n\n@implementation SBJsonStreamWriterStateError\n\nSINGLETON\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonTokeniser.h",
    "content": "/*\n Copyright (c) 2010, Stig Brautaset.\n All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n \n Neither the name of the the author nor the names of its contributors\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\ntypedef enum {\n    sbjson_token_error = -1,\n    sbjson_token_eof,\n    \n    sbjson_token_array_start,\n    sbjson_token_array_end,\n    \n    sbjson_token_object_start,\n    sbjson_token_object_end,\n\n    sbjson_token_separator,\n    sbjson_token_keyval_separator,\n    \n    sbjson_token_number,\n    sbjson_token_string,\n    sbjson_token_true,\n    sbjson_token_false,\n    sbjson_token_null,\n    \n} sbjson_token_t;\n\n@class SBJsonUTF8Stream;\n\n@interface SBJsonTokeniser : NSObject {\n@private\n    SBJsonUTF8Stream *_stream;\n    NSString *_error;\n}\n\n@property (copy) NSString *error;\n\n- (void)appendData:(NSData*)data_;\n\n- (sbjson_token_t)getToken:(NSObject**)token;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonTokeniser.m",
    "content": "/*\n Copyright (c) 2010-2011, Stig Brautaset. All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n\n Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n\n Neither the name of the the author nor the names of its contributors\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonTokeniser.h\"\n#import \"SBJsonUTF8Stream.h\"\n\n#define SBStringIsIllegalSurrogateHighCharacter(x) (((x) >= 0xd800) && ((x) <= 0xdfff))\n\n\n@implementation SBJsonTokeniser\n\n@synthesize error = _error;\n\n- (id)init {\n    self = [super init];\n    if (self) {\n        _stream = [[SBJsonUTF8Stream alloc] init];\n\n    }\n\n    return self;\n}\n\n- (void)dealloc {\n    [_stream release];\n    [super dealloc];\n}\n\n- (void)appendData:(NSData *)data_ {\n    [_stream appendData:data_];\n}\n\n\n- (sbjson_token_t)match:(const char *)pattern length:(NSUInteger)len retval:(sbjson_token_t)token {\n    if (![_stream haveRemainingCharacters:len])\n        return sbjson_token_eof;\n\n    if ([_stream skipCharacters:pattern length:len])\n        return token;\n\n    self.error = [NSString stringWithFormat:@\"Expected '%s' after initial '%.1s'\", pattern, pattern];\n    return sbjson_token_error;\n}\n\n- (BOOL)decodeEscape:(unichar)ch into:(unichar*)decoded {\n    switch (ch) {\n        case '\\\\':\n        case '/':\n        case '\"':\n            *decoded = ch;\n            break;\n\n        case 'b':\n            *decoded = '\\b';\n            break;\n\n        case 'n':\n            *decoded = '\\n';\n            break;\n\n        case 'r':\n            *decoded = '\\r';\n            break;\n\n        case 't':\n            *decoded = '\\t';\n            break;\n\n        case 'f':\n            *decoded = '\\f';\n            break;\n\n        default:\n            self.error = @\"Illegal escape character\";\n            return NO;\n            break;\n    }\n    return YES;\n}\n\n- (BOOL)decodeHexQuad:(unichar*)quad {\n    unichar c, tmp = 0;\n\n    for (int i = 0; i < 4; i++) {\n        (void)[_stream getNextUnichar:&c];\n        tmp *= 16;\n        switch (c) {\n            case '0' ... '9':\n                tmp += c - '0';\n                break;\n\n            case 'a' ... 'f':\n                tmp += 10 + c - 'a';\n                break;\n\n            case 'A' ... 'F':\n                tmp += 10 + c - 'A';\n                break;\n\n            default:\n                return NO;\n        }\n    }\n    *quad = tmp;\n    return YES;\n}\n\n- (sbjson_token_t)getStringToken:(NSObject**)token {\n    NSMutableString *acc = nil;\n\n    for (;;) {\n        [_stream skip];\n        \n        unichar ch;\n        {\n            NSMutableString *string = nil;\n            if (![_stream getSimpleString:&string])\n                return sbjson_token_eof;\n            \n            if (!string) {\n                self.error = @\"Broken Unicode encoding\";\n                return sbjson_token_error;\n            }\n                \n        \n            if (![_stream getUnichar:&ch])\n                return sbjson_token_eof;\n\n            if (acc) {\n                [acc appendString:string];\n            \n            } else if (ch == '\"') {\n                *token = string;\n                [_stream skip];\n                return sbjson_token_string;\n\n            } else {\n                acc = [[string mutableCopy] autorelease];\n            }\n        }\n        \n        switch (ch) {\n            case 0 ... 0x1F:\n                self.error = [NSString stringWithFormat:@\"Unescaped control character [0x%0.2X]\", (int)ch];\n                return sbjson_token_error;\n                break;\n\n            case '\"':\n                *token = acc;\n                [_stream skip];\n                return sbjson_token_string;\n                break;\n\n            case '\\\\':\n                if (![_stream getNextUnichar:&ch])\n                    return sbjson_token_eof;\n\n                if (ch == 'u') {\n                    if (![_stream haveRemainingCharacters:5])\n                        return sbjson_token_eof;\n\n                    unichar hi;\n                    if (![self decodeHexQuad:&hi]) {\n                        self.error = @\"Invalid hex quad\";\n                        return sbjson_token_error;\n                    }\n\n                    if (CFStringIsSurrogateHighCharacter(hi)) {\n                        unichar lo;\n\n                        if (![_stream haveRemainingCharacters:6])\n                            return sbjson_token_eof;\n\n                        (void)[_stream getNextUnichar:&ch];\n                        (void)[_stream getNextUnichar:&lo];\n                        if (ch != '\\\\' || lo != 'u' || ![self decodeHexQuad:&lo]) {\n                            self.error = @\"Missing low character in surrogate pair\";\n                            return sbjson_token_error;\n                        }\n\n                        if (!CFStringIsSurrogateLowCharacter(lo)) {\n                            self.error = @\"Invalid low character in surrogate pair\";\n                            return sbjson_token_error;\n                        }\n\n                        unichar pair[2] = {hi, lo};\n                        CFStringAppendCharacters((CFMutableStringRef)acc, pair, 2);\n                    } else if (SBStringIsIllegalSurrogateHighCharacter(hi)) {\n                        self.error = @\"Invalid high character in surrogate pair\";\n                        return sbjson_token_error;\n                    } else {\n                        CFStringAppendCharacters((CFMutableStringRef)acc, &hi, 1);\n                    }\n\n\n                } else {\n                    unichar decoded;\n                    if (![self decodeEscape:ch into:&decoded])\n                        return sbjson_token_error;\n                    CFStringAppendCharacters((CFMutableStringRef)acc, &decoded, 1);\n                }\n\n                break;\n\n            default: {\n                self.error = [NSString stringWithFormat:@\"Invalid UTF-8: '%x'\", (int)ch];\n                return sbjson_token_error;\n                break;\n            }\n        }\n    }\n    return sbjson_token_eof;\n}\n\n- (sbjson_token_t)getNumberToken:(NSObject**)token {\n\n    NSUInteger numberStart = _stream.index;\n    NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];\n\n    unichar ch;\n    if (![_stream getUnichar:&ch])\n        return sbjson_token_eof;\n\n    BOOL isNegative = NO;\n    if (ch == '-') {\n        isNegative = YES;\n        if (![_stream getNextUnichar:&ch])\n            return sbjson_token_eof;\n    }\n\n    if (ch == '0') {\n        if (![_stream getNextUnichar:&ch])\n            return sbjson_token_eof;\n\n        if ([digits characterIsMember:ch]) {\n            self.error = @\"Leading zero is illegal in number\";\n            return sbjson_token_error;\n        }\n    }\n\n    unsigned long long mantissa = 0;\n    int mantissa_length = 0;\n\n    while ([digits characterIsMember:ch]) {\n        mantissa *= 10;\n        mantissa += (ch - '0');\n        mantissa_length++;\n\n        if (![_stream getNextUnichar:&ch])\n            return sbjson_token_eof;\n    }\n\n    short exponent = 0;\n    BOOL isFloat = NO;\n\n    if (ch == '.') {\n        isFloat = YES;\n        if (![_stream getNextUnichar:&ch])\n            return sbjson_token_eof;\n\n        while ([digits characterIsMember:ch]) {\n            mantissa *= 10;\n            mantissa += (ch - '0');\n            mantissa_length++;\n            exponent--;\n\n            if (![_stream getNextUnichar:&ch])\n                return sbjson_token_eof;\n        }\n\n        if (!exponent) {\n            self.error = @\"No digits after decimal point\";\n            return sbjson_token_error;\n        }\n    }\n\n    BOOL hasExponent = NO;\n    if (ch == 'e' || ch == 'E') {\n        hasExponent = YES;\n\n        if (![_stream getNextUnichar:&ch])\n            return sbjson_token_eof;\n\n        BOOL expIsNegative = NO;\n        if (ch == '-') {\n            expIsNegative = YES;\n            if (![_stream getNextUnichar:&ch])\n                return sbjson_token_eof;\n\n        } else if (ch == '+') {\n            if (![_stream getNextUnichar:&ch])\n                return sbjson_token_eof;\n        }\n\n        short exp = 0;\n        short exp_length = 0;\n        while ([digits characterIsMember:ch]) {\n            exp *= 10;\n            exp += (ch - '0');\n            exp_length++;\n\n            if (![_stream getNextUnichar:&ch])\n                return sbjson_token_eof;\n        }\n\n        if (exp_length == 0) {\n            self.error = @\"No digits in exponent\";\n            return sbjson_token_error;\n        }\n\n        if (expIsNegative)\n            exponent -= exp;\n        else\n            exponent += exp;\n    }\n\n    if (!mantissa_length && isNegative) {\n        self.error = @\"No digits after initial minus\";\n        return sbjson_token_error;\n\n    } else if (mantissa_length >= 19) {\n        \n        NSString *number = [_stream stringWithRange:NSMakeRange(numberStart, _stream.index - numberStart)];\n        *token = [NSDecimalNumber decimalNumberWithString:number];\n\n    } else if (!isFloat && !hasExponent) {\n        if (!isNegative)\n            *token = [NSNumber numberWithUnsignedLongLong:mantissa];\n        else\n            *token = [NSNumber numberWithLongLong:-mantissa];\n    } else {\n        *token = [NSDecimalNumber decimalNumberWithMantissa:mantissa\n                                                   exponent:exponent\n                                                 isNegative:isNegative];\n    }\n\n    return sbjson_token_number;\n}\n\n- (sbjson_token_t)getToken:(NSObject **)token {\n\n    [_stream skipWhitespace];\n\n    unichar ch;\n    if (![_stream getUnichar:&ch])\n        return sbjson_token_eof;\n\n    NSUInteger oldIndexLocation = _stream.index;\n    sbjson_token_t tok;\n\n    switch (ch) {\n        case '[':\n            tok = sbjson_token_array_start;\n            [_stream skip];\n            break;\n\n        case ']':\n            tok = sbjson_token_array_end;\n            [_stream skip];\n            break;\n\n        case '{':\n            tok = sbjson_token_object_start;\n            [_stream skip];\n            break;\n\n        case ':':\n            tok = sbjson_token_keyval_separator;\n            [_stream skip];\n            break;\n\n        case '}':\n            tok = sbjson_token_object_end;\n            [_stream skip];\n            break;\n\n        case ',':\n            tok = sbjson_token_separator;\n            [_stream skip];\n            break;\n\n        case 'n':\n            tok = [self match:\"null\" length:4 retval:sbjson_token_null];\n            break;\n\n        case 't':\n            tok = [self match:\"true\" length:4 retval:sbjson_token_true];\n            break;\n\n        case 'f':\n            tok = [self match:\"false\" length:5 retval:sbjson_token_false];\n            break;\n\n        case '\"':\n            tok = [self getStringToken:token];\n            break;\n\n        case '0' ... '9':\n        case '-':\n            tok = [self getNumberToken:token];\n            break;\n\n        case '+':\n            self.error = @\"Leading + is illegal in number\";\n            tok = sbjson_token_error;\n            break;\n\n        default:\n            self.error = [NSString stringWithFormat:@\"Illegal start of token [%c]\", ch];\n            tok = sbjson_token_error;\n            break;\n    }\n\n    if (tok == sbjson_token_eof) {\n        // We ran out of bytes in the middle of a token.\n        // We don't know how to restart in mid-flight, so\n        // rewind to the start of the token for next attempt.\n        // Hopefully we'll have more data then.\n        _stream.index = oldIndexLocation;\n    }\n\n    return tok;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonUTF8Stream.h",
    "content": "/*\n Copyright (c) 2011, Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n \n Neither the name of the the author nor the names of its contributors\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n\n@interface SBJsonUTF8Stream : NSObject {\n@private\n    const char *_bytes;\n    NSMutableData *_data;\n    NSUInteger _length;\n    NSUInteger _index;\n}\n\n@property (assign) NSUInteger index;\n\n- (void)appendData:(NSData*)data_;\n\n- (BOOL)haveRemainingCharacters:(NSUInteger)chars;\n\n- (void)skip;\n- (void)skipWhitespace;\n- (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len;\n\n- (BOOL)getUnichar:(unichar*)ch;\n- (BOOL)getNextUnichar:(unichar*)ch;\n- (BOOL)getSimpleString:(NSString**)string;\n\n- (NSString*)stringWithRange:(NSRange)range;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonUTF8Stream.m",
    "content": "/*\n Copyright (c) 2011, Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n \n Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n \n Neither the name of the the author nor the names of its contributors\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonUTF8Stream.h\"\n\n\n@implementation SBJsonUTF8Stream\n\n@synthesize index = _index;\n\n- (id)init {\n    self = [super init];\n    if (self) {\n        _data = [[NSMutableData alloc] initWithCapacity:4096u];\n    }\n    return self;\n}\n\n- (void)dealloc {\n    [_data release];\n    [super dealloc];\n}\n\n- (void)appendData:(NSData *)data_ {\n    \n    if (_index) {\n        // Discard data we've already parsed\n\t\t[_data replaceBytesInRange:NSMakeRange(0, _index) withBytes:\"\" length:0];\n        \n        // Reset index to point to current position\n\t\t_index = 0;\n\t}\n    \n    [_data appendData:data_];\n    \n    // This is an optimisation. \n    _bytes = [_data bytes];\n    _length = [_data length];\n}\n\n\n- (BOOL)getUnichar:(unichar*)ch {\n    if (_index < _length) {\n        *ch = (unichar)_bytes[_index];\n        return YES;\n    }\n    return NO;\n}\n\n- (BOOL)getNextUnichar:(unichar*)ch {\n    if (++_index < _length) {\n        *ch = (unichar)_bytes[_index];\n        return YES;\n    }\n    return NO;\n}\n\n- (BOOL)getSimpleString:(NSString **)string {\n    NSUInteger start = _index;\n    while (_index < _length) {\n        switch (_bytes[_index]) {\n            case '\"':\n            case '\\\\':\n            case 0 ... 0x1f:\n                *string = [[[NSString alloc] initWithBytes:(_bytes + start) length:(_index - start) encoding:NSUTF8StringEncoding] autorelease];\n                return YES;\n                break;\n            default:\n                _index++;\n                break;\n        }\n    }\n    return NO;\n}\n\n- (void)skip {\n    _index++;\n}\n\n- (void)skipWhitespace {\n    while (_index < _length) {\n        switch (_bytes[_index]) {\n            case ' ':\n            case '\\t':\n            case '\\r':\n            case '\\n':\n                _index++;\n                break;\n            default:\n                return;\n                break;\n        }\n    }\n}\n\n- (BOOL)haveRemainingCharacters:(NSUInteger)chars {\n    return [_data length] - _index >= chars;\n}\n\n- (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len {\n    const void *bytes = [_data bytes] + _index;\n    if (!memcmp(bytes, chars, len)) {\n        _index += len;\n        return YES;\n    }\n    return NO;\n}\n\n- (NSString*)stringWithRange:(NSRange)range {\n    return [[[NSString alloc] initWithBytes:_bytes + range.location length:range.length encoding:NSUTF8StringEncoding] autorelease];\n    \n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonWriter.h",
    "content": "/*\n Copyright (C) 2009 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import <Foundation/Foundation.h>\n\n/**\n @brief The JSON writer class.\n \n This uses SBJsonStreamWriter internally.\n \n @see @ref json2objc\n */\n\n@interface SBJsonWriter : NSObject {\n@private\n    NSString *error;\n    NSUInteger maxDepth;\n    BOOL sortKeys, humanReadable;\n}\n\n/**\n @brief The maximum recursing depth.\n \n Defaults to 32. If the input is nested deeper than this the input will be deemed to be\n malicious and the parser returns nil, signalling an error. (\"Nested too deep\".) You can\n turn off this security feature by setting the maxDepth value to 0.\n */\n@property NSUInteger maxDepth;\n\n/**\n @brief Return an error trace, or nil if there was no errors.\n \n Note that this method returns the trace of the last method that failed.\n You need to check the return value of the call you're making to figure out\n if the call actually failed, before you know call this method.\n */\n@property (readonly, copy) NSString *error;\n\n/**\n @brief Whether we are generating human-readable (multiline) JSON.\n \n Set whether or not to generate human-readable JSON. The default is NO, which produces\n JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable\n JSON with linebreaks after each array value and dictionary key/value pair, indented two\n spaces per nesting level.\n */\n@property BOOL humanReadable;\n\n/**\n @brief Whether or not to sort the dictionary keys in the output.\n \n If this is set to YES, the dictionary keys in the JSON output will be in sorted order.\n (This is useful if you need to compare two structures, for example.) The default is NO.\n */\n@property BOOL sortKeys;\n\n/**\n @brief Return JSON representation for the given object.\n \n Returns a string containing JSON representation of the passed in value, or nil on error.\n If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error.\n \n @param value any instance that can be represented as JSON text.\n */\n- (NSString*)stringWithObject:(id)value;\n\n/**\n @brief Return JSON representation for the given object.\n \n Returns an NSData object containing JSON represented as UTF8 text, or nil on error.\n \n @param value any instance that can be represented as JSON text.\n */\n- (NSData*)dataWithObject:(id)value;\n\n/**\n @brief Return JSON representation (or fragment) for the given object.\n \n Returns a string containing JSON representation of the passed in value, or nil on error.\n If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error.\n \n @param value any instance that can be represented as a JSON fragment\n @param error pointer to object to be populated with NSError on failure\n \n */- (NSString*)stringWithObject:(id)value\n                           error:(NSError**)error;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/JSON/SBJsonWriter.m",
    "content": "/*\n Copyright (C) 2009 Stig Brautaset. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n \n * Neither the name of the author nor the names of its contributors may be used\n   to endorse or promote products derived from this software without specific\n   prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\n FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#import \"SBJsonWriter.h\"\n#import \"SBJsonStreamWriter.h\"\n#import \"SBJsonStreamWriterAccumulator.h\"\n\n\n@interface SBJsonWriter ()\n@property (copy) NSString *error;\n@end\n\n@implementation SBJsonWriter\n\n@synthesize sortKeys;\n@synthesize humanReadable;\n\n@synthesize error;\n@synthesize maxDepth;\n\n- (id)init {\n    self = [super init];\n    if (self) {\n        self.maxDepth = 32u;        \n    }\n    return self;\n}\n\n- (void)dealloc {\n    [error release];\n    [super dealloc];\n}\n\n- (NSString*)stringWithObject:(id)value {\n\tNSData *data = [self dataWithObject:value];\n\tif (data)\n\t\treturn [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];\n\treturn nil;\n}\t\n\n- (NSString*)stringWithObject:(id)value error:(NSError**)error_ {\n    NSString *tmp = [self stringWithObject:value];\n    if (tmp)\n        return tmp;\n    \n    if (error_) {\n\t\tNSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:error, NSLocalizedDescriptionKey, nil];\n        *error_ = [NSError errorWithDomain:@\"org.brautaset.SBJsonWriter.ErrorDomain\" code:0 userInfo:ui];\n\t}\n\t\n    return nil;\n}\n\n- (NSData*)dataWithObject:(id)object {\t\n    self.error = nil;\n\n    SBJsonStreamWriterAccumulator *accumulator = [[[SBJsonStreamWriterAccumulator alloc] init] autorelease];\n    \n\tSBJsonStreamWriter *streamWriter = [[[SBJsonStreamWriter alloc] init] autorelease];\n\tstreamWriter.sortKeys = self.sortKeys;\n\tstreamWriter.maxDepth = self.maxDepth;\n\tstreamWriter.humanReadable = self.humanReadable;\n    streamWriter.delegate = accumulator;\n\t\n\tBOOL ok = NO;\n\tif ([object isKindOfClass:[NSDictionary class]])\n\t\tok = [streamWriter writeObject:object];\n\t\n\telse if ([object isKindOfClass:[NSArray class]])\n\t\tok = [streamWriter writeArray:object];\n\t\t\n\telse if ([object respondsToSelector:@selector(proxyForJson)])\n\t\treturn [self dataWithObject:[object proxyForJson]];\n\telse {\n\t\tself.error = @\"Not valid type for JSON\";\n\t\treturn nil;\n\t}\n\t\n\tif (ok)\n\t\treturn accumulator.data;\n\t\n\tself.error = streamWriter.error;\n\treturn nil;\t\n}\n\t\n\t\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/Reachability/Reachability.h",
    "content": "/*\n \n File: Reachability.h\n Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.\n \n Version: 2.0.4ddg\n */\n\n/*\n Significant additions made by Andrew W. Donoho, August 11, 2009.\n This is a derived work of Apple's Reachability v2.0 class.\n \n The below license is the new BSD license with the OSI recommended personalizations.\n <http://www.opensource.org/licenses/bsd-license.php>\n \n Extensions Copyright (C) 2009 Donoho Design Group, LLC. All Rights Reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n * Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n \n * Neither the name of Andrew W. Donoho nor Donoho Design Group, L.L.C.\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY DONOHO DESIGN GROUP, L.L.C. \"AS IS\" AND ANY\n EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR\n CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n \n */\n\n\n/*\n \n Apple's Original License on Reachability v2.0\n \n Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.\n (\"Apple\") in consideration of your agreement to the following terms, and your\n use, installation, modification or redistribution of this Apple software\n constitutes acceptance of these terms.  If you do not agree with these terms,\n please do not use, install, modify or redistribute this Apple software.\n \n In consideration of your agreement to abide by the following terms, and subject\n to these terms, Apple grants you a personal, non-exclusive license, under\n Apple's copyrights in this original Apple software (the \"Apple Software\"), to\n use, reproduce, modify and redistribute the Apple Software, with or without\n modifications, in source and/or binary forms; provided that if you redistribute\n the Apple Software in its entirety and without modifications, you must retain\n this notice and the following text and disclaimers in all such redistributions\n of the Apple Software.\n \n Neither the name, trademarks, service marks or logos of Apple Inc. may be used\n to endorse or promote products derived from the Apple Software without specific\n prior written permission from Apple.  Except as expressly stated in this notice,\n no other rights or licenses, express or implied, are granted by Apple herein,\n including but not limited to any patent rights that may be infringed by your\n derivative works or by other works in which the Apple Software may be\n incorporated.\n \n The Apple Software is provided by Apple on an \"AS IS\" basis.  APPLE MAKES NO\n WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n COMBINATION WITH YOUR PRODUCTS.\n \n IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR\n DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF\n CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF\n APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n \n Copyright (C) 2009 Apple Inc. All Rights Reserved.\n \n */\n\n\n/*\n DDG extensions include:\n Each reachability object now has a copy of the key used to store it in a\n dictionary. This allows each observer to quickly determine if the event is\n important to them.\n \n -currentReachabilityStatus also has a significantly different decision criteria than \n Apple's code.\n \n A multiple convenience test methods have been added.\n */\n\n#import <Foundation/Foundation.h>\n#import <SystemConfiguration/SystemConfiguration.h>\n#import <netinet/in.h>\n\n#define USE_DDG_EXTENSIONS 1 // Use DDG's Extensions to test network criteria.\n// Since NSAssert and NSCAssert are used in this code, \n// I recommend you set NS_BLOCK_ASSERTIONS=1 in the release versions of your projects.\n\nenum {\n\t\n\t// DDG NetworkStatus Constant Names.\n\tkNotReachable = 0, // Apple's code depends upon 'NotReachable' being the same value as 'NO'.\n\tkReachableViaWWAN, // Switched order from Apple's enum. WWAN is active before WiFi.\n\tkReachableViaWiFi\n\t\n};\ntypedef\tuint32_t NetworkStatus;\n\nenum {\n\t\n\t// Apple NetworkStatus Constant Names.\n\tNotReachable     = kNotReachable,\n\tReachableViaWiFi = kReachableViaWiFi,\n\tReachableViaWWAN = kReachableViaWWAN\n\t\n};\n\n\nextern NSString *const kInternetConnection;\nextern NSString *const kLocalWiFiConnection;\nextern NSString *const kReachabilityChangedNotification;\n\n@interface Reachability: NSObject {\n\t\n@private\n\tNSString                *key_;\n\tSCNetworkReachabilityRef reachabilityRef;\n\n}\n\n@property (copy) NSString *key; // Atomic because network operations are asynchronous.\n\n// Designated Initializer.\n- (Reachability *) initWithReachabilityRef: (SCNetworkReachabilityRef) ref;\n\n// Use to check the reachability of a particular host name. \n+ (Reachability *) reachabilityWithHostName: (NSString*) hostName;\n\n// Use to check the reachability of a particular IP address. \n+ (Reachability *) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;\n\n// Use to check whether the default route is available.  \n// Should be used to, at minimum, establish network connectivity.\n+ (Reachability *) reachabilityForInternetConnection;\n\n// Use to check whether a local wifi connection is available.\n+ (Reachability *) reachabilityForLocalWiFi;\n\n//Start listening for reachability notifications on the current run loop.\n- (BOOL) startNotifier;\n- (void)  stopNotifier;\n\n// Comparison routines to enable choosing actions in a notification.\n- (BOOL) isEqual: (Reachability *) r;\n\n// These are the status tests.\n- (NetworkStatus) currentReachabilityStatus;\n\n// The main direct test of reachability.\n- (BOOL) isReachable;\n\n// WWAN may be available, but not active until a connection has been established.\n// WiFi may require a connection for VPN on Demand.\n- (BOOL) isConnectionRequired; // Identical DDG variant.\n- (BOOL)   connectionRequired; // Apple's routine.\n\n// Dynamic, on demand connection?\n- (BOOL) isConnectionOnDemand;\n\n// Is user intervention required?\n- (BOOL) isInterventionRequired;\n\n// Routines for specific connection testing by your app.\n- (BOOL) isReachableViaWWAN;\n- (BOOL) isReachableViaWiFi;\n\n- (SCNetworkReachabilityFlags) reachabilityFlags;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/OtherSources/Reachability/Reachability.m",
    "content": "/*\n \n File: Reachability.m\n Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.\n \n Version: 2.0.4ddg\n */\n\n/*\n Significant additions made by Andrew W. Donoho, August 11, 2009.\n This is a derived work of Apple's Reachability v2.0 class.\n \n The below license is the new BSD license with the OSI recommended personalizations.\n <http://www.opensource.org/licenses/bsd-license.php>\n\n Extensions Copyright (C) 2009 Donoho Design Group, LLC. All Rights Reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n \n * Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n \n * Neither the name of Andrew W. Donoho nor Donoho Design Group, L.L.C.\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n \n THIS SOFTWARE IS PROVIDED BY DONOHO DESIGN GROUP, L.L.C. \"AS IS\" AND ANY\n EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR\n CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n \n */\n\n\n/*\n \n Apple's Original License on Reachability v2.0\n \n Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.\n (\"Apple\") in consideration of your agreement to the following terms, and your\n use, installation, modification or redistribution of this Apple software\n constitutes acceptance of these terms.  If you do not agree with these terms,\n please do not use, install, modify or redistribute this Apple software.\n \n In consideration of your agreement to abide by the following terms, and subject\n to these terms, Apple grants you a personal, non-exclusive license, under\n Apple's copyrights in this original Apple software (the \"Apple Software\"), to\n use, reproduce, modify and redistribute the Apple Software, with or without\n modifications, in source and/or binary forms; provided that if you redistribute\n the Apple Software in its entirety and without modifications, you must retain\n this notice and the following text and disclaimers in all such redistributions\n of the Apple Software.\n\n Neither the name, trademarks, service marks or logos of Apple Inc. may be used\n to endorse or promote products derived from the Apple Software without specific\n prior written permission from Apple.  Except as expressly stated in this notice,\n no other rights or licenses, express or implied, are granted by Apple herein,\n including but not limited to any patent rights that may be infringed by your\n derivative works or by other works in which the Apple Software may be\n incorporated.\n \n The Apple Software is provided by Apple on an \"AS IS\" basis.  APPLE MAKES NO\n WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n COMBINATION WITH YOUR PRODUCTS.\n \n IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR\n DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF\n CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF\n APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n \n Copyright (C) 2009 Apple Inc. All Rights Reserved.\n \n*/\n\n/*\n Each reachability object now has a copy of the key used to store it in a dictionary.\n This allows each observer to quickly determine if the event is important to them.\n*/\n\n#import <sys/socket.h>\n#import <netinet/in.h>\n#import <netinet6/in6.h>\n#import <arpa/inet.h>\n#import <ifaddrs.h>\n#import <netdb.h>\n\n#import <CoreFoundation/CoreFoundation.h>\n\n#import \"Reachability.h\"\n\nNSString *const kInternetConnection  = @\"InternetConnection\";\nNSString *const kLocalWiFiConnection = @\"LocalWiFiConnection\";\nNSString *const kReachabilityChangedNotification = @\"NetworkReachabilityChangedNotification\";\n\n#define CLASS_DEBUG 1 // Turn on logReachabilityFlags. Must also have a project wide defined DEBUG.\n\n#if (defined DEBUG && defined CLASS_DEBUG)\n#define logReachabilityFlags(flags) (logReachabilityFlags_(__PRETTY_FUNCTION__, __LINE__, flags))\n\nstatic NSString *reachabilityFlags_(SCNetworkReachabilityFlags flags) {\n\t\n#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 30000) // Apple advises you to use the magic number instead of a symbol.\n    return [NSString stringWithFormat:@\"Reachability Flags: %c%c %c%c%c%c%c%c%c\",\n\t\t\t(flags & kSCNetworkReachabilityFlagsIsWWAN)               ? 'W' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',\n\t\t\t\n\t\t\t(flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-'];\n#else\n\t// Compile out the v3.0 features for v2.2.1 deployment.\n    return [NSString stringWithFormat:@\"Reachability Flags: %c%c %c%c%c%c%c%c\",\n\t\t\t(flags & kSCNetworkReachabilityFlagsIsWWAN)               ? 'W' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',\n\t\t\t\n\t\t\t(flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',\n\t\t\t// v3 kSCNetworkReachabilityFlagsConnectionOnTraffic == v2 kSCNetworkReachabilityFlagsConnectionAutomatic\n\t\t\t(flags & kSCNetworkReachabilityFlagsConnectionAutomatic)  ? 'C' : '-',\n\t\t\t// (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-', // No v2 equivalent.\n\t\t\t(flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',\n\t\t\t(flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-'];\n#endif\n\t\n} // reachabilityFlags_()\n\nstatic void logReachabilityFlags_(const char *name, int line, SCNetworkReachabilityFlags flags) {\n\t\n    NSLog(@\"%s (%d) \\n\\t%@\", name, line, reachabilityFlags_(flags));\n\t\n} // logReachabilityFlags_()\n\n#define logNetworkStatus(status) (logNetworkStatus_(__PRETTY_FUNCTION__, __LINE__, status))\n\nstatic void logNetworkStatus_(const char *name, int line, NetworkStatus status) {\n\t\n\tNSString *statusString = nil;\n\t\n\tswitch (status) {\n\t\tcase kNotReachable:\n\t\t\tstatusString =  @\"Not Reachable\";\n\t\t\tbreak;\n\t\tcase kReachableViaWWAN:\n\t\t\tstatusString = @\"Reachable via WWAN\";\n\t\t\tbreak;\n\t\tcase kReachableViaWiFi:\n\t\t\tstatusString = @\"Reachable via WiFi\";\n\t\t\tbreak;\n\t}\n\t\n\tNSLog(@\"%s (%d) \\n\\tNetwork Status: %@\", name, line, statusString);\n\t\n} // logNetworkStatus_()\n\n#else\n#define logReachabilityFlags(flags)\n#define logNetworkStatus(status)\n#endif\n\n@interface Reachability (private)\n\n- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags;\n\n@end\n\n@implementation Reachability\n\n@synthesize key = key_;\n\n// Preclude direct access to ivars.\n+ (BOOL) accessInstanceVariablesDirectly {\n\t\n\treturn NO;\n\n} // accessInstanceVariablesDirectly\n\n\n- (void) dealloc {\n\t\n\t[self stopNotifier];\n\tif(reachabilityRef) {\n\t\t\n\t\tCFRelease(reachabilityRef); reachabilityRef = NULL;\n\t\t\n\t}\n\t\n\tself.key = nil;\n\t\n\t[super dealloc];\n\t\n} // dealloc\n\n\n- (Reachability *) initWithReachabilityRef: (SCNetworkReachabilityRef) ref \n{\n    self = [super init];\n\tif (self != nil) \n    {\n\t\treachabilityRef = ref;\n\t}\n\t\n\treturn self;\n\t\n} // initWithReachabilityRef:\n\n\n#if (defined DEBUG && defined CLASS_DEBUG)\n- (NSString *) description {\n\t\n\tNSAssert(reachabilityRef, @\"-description called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags = 0;\n\t\n\tSCNetworkReachabilityGetFlags(reachabilityRef, &flags);\n\t\n\treturn [NSString stringWithFormat: @\"%@\\n\\t%@\", self.key, reachabilityFlags_(flags)];\n\t\n} // description\n#endif\n\n\n#pragma mark -\n#pragma mark Notification Management Methods\n\n\n//Start listening for reachability notifications on the current run loop\nstatic void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {\n\n\t#pragma unused (target, flags)\n\tNSCAssert(info, @\"info was NULL in ReachabilityCallback\");\n\tNSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @\"info was the wrong class in ReachabilityCallback\");\n\t\n\t//We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively\n\t// in case someone uses the Reachablity object in a different thread.\n\tNSAutoreleasePool* pool = [NSAutoreleasePool new];\n\t\n\t// Post a notification to notify the client that the network reachability changed.\n\t[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification \n\t\t\t\t\t\t\t\t\t\t\t\t\t\tobject: (Reachability *) info];\n\t\n\t[pool release];\n\n} // ReachabilityCallback()\n\n\n- (BOOL) startNotifier {\n\t\n\tSCNetworkReachabilityContext\tcontext = {0, self, NULL, NULL, NULL};\n\t\n\tif(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) {\n\t\t\n\t\tif(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {\n\n\t\t\treturn YES;\n\t\t\t\n\t\t}\n\t\t\n\t}\n\t\n\treturn NO;\n\n} // startNotifier\n\n\n- (void) stopNotifier {\n\t\n\tif(reachabilityRef) {\n\t\t\n\t\tSCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);\n\n\t}\n\n} // stopNotifier\n\n\n- (BOOL) isEqual: (Reachability *) r {\n\t\n\treturn [r.key isEqualToString: self.key];\n\t\n} // isEqual:\n\n\n#pragma mark -\n#pragma mark Reachability Allocation Methods\n\n\n+ (Reachability *) reachabilityWithHostName: (NSString *) hostName {\n\t\n\tSCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);\n\t\n\tif (ref) {\n\t\t\n\t\tReachability *r = [[[self alloc] initWithReachabilityRef: ref] autorelease];\n\t\t\n\t\tr.key = hostName;\n\n\t\treturn r;\n\t\t\n\t}\n\t\n\treturn nil;\n\t\n} // reachabilityWithHostName\n\n\n+ (NSString *) makeAddressKey: (in_addr_t) addr {\n\t// addr is assumed to be in network byte order.\n\t\n\tstatic const int       highShift    = 24;\n\tstatic const int       highMidShift = 16;\n\tstatic const int       lowMidShift  =  8;\n\tstatic const in_addr_t mask         = 0x000000ff;\n\t\n\taddr = ntohl(addr);\n\t\n\treturn [NSString stringWithFormat: @\"%d.%d.%d.%d\", \n\t\t\t(addr >> highShift)    & mask, \n\t\t\t(addr >> highMidShift) & mask, \n\t\t\t(addr >> lowMidShift)  & mask, \n\t\t\t addr                  & mask];\n\t\n} // makeAddressKey:\n\n\n+ (Reachability *) reachabilityWithAddress: (const struct sockaddr_in *) hostAddress {\n\t\n\tSCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);\n\n\tif (ref) {\n\t\t\n\t\tReachability *r = [[[self alloc] initWithReachabilityRef: ref] autorelease];\n\t\t\n\t\tr.key = [self makeAddressKey: hostAddress->sin_addr.s_addr];\n\t\t\n\t\treturn r;\n\t\t\n\t}\n\t\n\treturn nil;\n\n} // reachabilityWithAddress\n\n\n+ (Reachability *) reachabilityForInternetConnection {\n\t\n\tstruct sockaddr_in zeroAddress;\n\tbzero(&zeroAddress, sizeof(zeroAddress));\n\tzeroAddress.sin_len = sizeof(zeroAddress);\n\tzeroAddress.sin_family = AF_INET;\n\n\tReachability *r = [self reachabilityWithAddress: &zeroAddress];\n\n\tr.key = kInternetConnection;\n\t\n\treturn r;\n\n} // reachabilityForInternetConnection\n\n\n+ (Reachability *) reachabilityForLocalWiFi {\n\t\n\tstruct sockaddr_in localWifiAddress;\n\tbzero(&localWifiAddress, sizeof(localWifiAddress));\n\tlocalWifiAddress.sin_len = sizeof(localWifiAddress);\n\tlocalWifiAddress.sin_family = AF_INET;\n\t// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0\n\tlocalWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);\n\n\tReachability *r = [self reachabilityWithAddress: &localWifiAddress];\n\n\tr.key = kLocalWiFiConnection;\n\n\treturn r;\n\n} // reachabilityForLocalWiFi\n\n\n#pragma mark -\n#pragma mark Network Flag Handling Methods\n\n\n#if USE_DDG_EXTENSIONS\n//\n// iPhone condition codes as reported by a 3GS running iPhone OS v3.0.\n// Airplane Mode turned on:  Reachability Flag Status: -- -------\n// WWAN Active:              Reachability Flag Status: WR -t-----\n// WWAN Connection required: Reachability Flag Status: WR ct-----\n//         WiFi turned on:   Reachability Flag Status: -R ------- Reachable.\n// Local   WiFi turned on:   Reachability Flag Status: -R xxxxxxd Reachable.\n//         WiFi turned on:   Reachability Flag Status: -R ct----- Connection down. (Non-intuitive, empirically determined answer.)\nconst SCNetworkReachabilityFlags kConnectionDown =  kSCNetworkReachabilityFlagsConnectionRequired | \n\t\t\t\t\t\t\t\t\t\t\t\t    kSCNetworkReachabilityFlagsTransientConnection;\n//         WiFi turned on:   Reachability Flag Status: -R ct-i--- Reachable but it will require user intervention (e.g. enter a WiFi password).\n//         WiFi turned on:   Reachability Flag Status: -R -t----- Reachable via VPN.\n//\n// In the below method, an 'x' in the flag status means I don't care about its value.\n//\n// This method differs from Apple's by testing explicitly for empirically observed values.\n// This gives me more confidence in it's correct behavior. Apple's code covers more cases \n// than mine. My code covers the cases that occur.\n//\n- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags {\n\t\n\tif (flags & kSCNetworkReachabilityFlagsReachable) {\n\t\t\n\t\t// Local WiFi -- Test derived from Apple's code: -localWiFiStatusForFlags:.\n\t\tif (self.key == kLocalWiFiConnection) {\n\n\t\t\t// Reachability Flag Status: xR xxxxxxd Reachable.\n\t\t\treturn (flags & kSCNetworkReachabilityFlagsIsDirect) ? kReachableViaWiFi : kNotReachable;\n\n\t\t}\n\t\t\n\t\t// Observed WWAN Values:\n\t\t// WWAN Active:              Reachability Flag Status: WR -t-----\n\t\t// WWAN Connection required: Reachability Flag Status: WR ct-----\n\t\t//\n\t\t// Test Value: Reachability Flag Status: WR xxxxxxx\n\t\tif (flags & kSCNetworkReachabilityFlagsIsWWAN) { return kReachableViaWWAN; }\n\t\t\n\t\t// Clear moot bits.\n\t\tflags &= ~kSCNetworkReachabilityFlagsReachable;\n\t\tflags &= ~kSCNetworkReachabilityFlagsIsDirect;\n\t\tflags &= ~kSCNetworkReachabilityFlagsIsLocalAddress; // kInternetConnection is local.\n\t\t\n\t\t// Reachability Flag Status: -R ct---xx Connection down.\n\t\tif (flags == kConnectionDown) { return kNotReachable; }\n\t\t\n\t\t// Reachability Flag Status: -R -t---xx Reachable. WiFi + VPN(is up) (Thank you Ling Wang)\n\t\tif (flags & kSCNetworkReachabilityFlagsTransientConnection)  { return kReachableViaWiFi; }\n\t\t\t\n\t\t// Reachability Flag Status: -R -----xx Reachable.\n\t\tif (flags == 0) { return kReachableViaWiFi; }\n\t\t\n\t\t// Apple's code tests for dynamic connection types here. I don't. \n\t\t// If a connection is required, regardless of whether it is on demand or not, it is a WiFi connection.\n\t\t// If you care whether a connection needs to be brought up,   use -isConnectionRequired.\n\t\t// If you care about whether user intervention is necessary,  use -isInterventionRequired.\n\t\t// If you care about dynamically establishing the connection, use -isConnectionIsOnDemand.\n\n\t\t// Reachability Flag Status: -R cxxxxxx Reachable.\n\t\tif (flags & kSCNetworkReachabilityFlagsConnectionRequired) { return kReachableViaWiFi; }\n\t\t\n\t\t// Required by the compiler. Should never get here. Default to not connected.\n#if (defined DEBUG && defined CLASS_DEBUG)\n\t\tNSAssert1(NO, @\"Uncaught reachability test. Flags: %@\", reachabilityFlags_(flags));\n#endif\n\t\treturn kNotReachable;\n\n\t\t}\n\t\n\t// Reachability Flag Status: x- xxxxxxx\n\treturn kNotReachable;\n\t\n} // networkStatusForFlags:\n\n\n- (NetworkStatus) currentReachabilityStatus {\n\t\n\tNSAssert(reachabilityRef, @\"currentReachabilityStatus called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags = 0;\n\tNetworkStatus status = kNotReachable;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n//\t\tlogReachabilityFlags(flags);\n\t\t\n\t\tstatus = [self networkStatusForFlags: flags];\n\t\t\n\t\treturn status;\n\t\t\n\t}\n\t\n\treturn kNotReachable;\n\t\n} // currentReachabilityStatus\n\n\n- (BOOL) isReachable {\n\t\n\tNSAssert(reachabilityRef, @\"isReachable called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags = 0;\n\tNetworkStatus status = kNotReachable;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n//\t\tlogReachabilityFlags(flags);\n\n\t\tstatus = [self networkStatusForFlags: flags];\n\n//\t\tlogNetworkStatus(status);\n\t\t\n\t\treturn (kNotReachable != status);\n\t\t\n\t}\n\t\n\treturn NO;\n\t\n} // isReachable\n\n\n- (BOOL) isConnectionRequired {\n\t\n\tNSAssert(reachabilityRef, @\"isConnectionRequired called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\treturn (flags & kSCNetworkReachabilityFlagsConnectionRequired);\n\n\t}\n\t\n\treturn NO;\n\t\n} // isConnectionRequired\n\n\n- (BOOL) connectionRequired {\n\t\n\treturn [self isConnectionRequired];\n\t\n} // connectionRequired\n#endif\n\n\n#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 30000)\nstatic const SCNetworkReachabilityFlags kOnDemandConnection = kSCNetworkReachabilityFlagsConnectionOnTraffic | \n                                                              kSCNetworkReachabilityFlagsConnectionOnDemand;\n#else\nstatic const SCNetworkReachabilityFlags kOnDemandConnection = kSCNetworkReachabilityFlagsConnectionAutomatic;\n#endif\n\n- (BOOL) isConnectionOnDemand {\n\t\n\tNSAssert(reachabilityRef, @\"isConnectionIsOnDemand called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\treturn ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&\n\t\t\t\t(flags & kOnDemandConnection));\n\t\t\n\t}\n\t\n\treturn NO;\n\t\n} // isConnectionOnDemand\n\n\n- (BOOL) isInterventionRequired {\n\t\n\tNSAssert(reachabilityRef, @\"isInterventionRequired called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\treturn ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&\n\t\t\t\t(flags & kSCNetworkReachabilityFlagsInterventionRequired));\n\t\t\n\t}\n\t\n\treturn NO;\n\t\n} // isInterventionRequired\n\n\n- (BOOL) isReachableViaWWAN {\n\t\n\tNSAssert(reachabilityRef, @\"isReachableViaWWAN called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags = 0;\n\tNetworkStatus status = kNotReachable;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\tstatus = [self networkStatusForFlags: flags];\n\t\t\n\t\treturn  (kReachableViaWWAN == status);\n\t\t\t\n\t}\n\t\n\treturn NO;\n\t\n} // isReachableViaWWAN\n\n\n- (BOOL) isReachableViaWiFi {\n\t\n\tNSAssert(reachabilityRef, @\"isReachableViaWiFi called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags = 0;\n\tNetworkStatus status = kNotReachable;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\tstatus = [self networkStatusForFlags: flags];\n\t\t\n\t\treturn  (kReachableViaWiFi == status);\n\t\t\n\t}\n\t\n\treturn NO;\n\t\n} // isReachableViaWiFi\n\n\n- (SCNetworkReachabilityFlags) reachabilityFlags {\n\t\n\tNSAssert(reachabilityRef, @\"reachabilityFlags called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags = 0;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\treturn flags;\n\t\t\n\t}\n\t\n\treturn 0;\n\t\n} // reachabilityFlags\n\n\n#pragma mark -\n#pragma mark Apple's Network Flag Handling Methods\n\n\n#if !USE_DDG_EXTENSIONS\n/*\n *\n *  Apple's Network Status testing code.\n *  The only changes that have been made are to use the new logReachabilityFlags macro and\n *  test for local WiFi via the key instead of Apple's boolean. Also, Apple's code was for v3.0 only\n *  iPhone OS. v2.2.1 and earlier conditional compiling is turned on. Hence, to mirror Apple's behavior,\n *  set your Base SDK to v3.0 or higher.\n *\n */\n\n- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags\n{\n\tlogReachabilityFlags(flags);\n\t\n\tBOOL retVal = NotReachable;\n\tif((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))\n\t{\n\t\tretVal = ReachableViaWiFi;\t\n\t}\n\treturn retVal;\n}\n\n\n- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags\n{\n\tlogReachabilityFlags(flags);\n\tif (!(flags & kSCNetworkReachabilityFlagsReachable))\n\t{\n\t\t// if target host is not reachable\n\t\treturn NotReachable;\n\t}\n\t\n\tBOOL retVal = NotReachable;\n\t\n\tif (!(flags & kSCNetworkReachabilityFlagsConnectionRequired))\n\t{\n\t\t// if target host is reachable and no connection is required\n\t\t//  then we'll assume (for now) that your on Wi-Fi\n\t\tretVal = ReachableViaWiFi;\n\t}\n\t\n#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 30000) // Apple advises you to use the magic number instead of a symbol.\t\n\tif ((flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ||\n\t\t(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic))\n#else\n\tif (flags & kSCNetworkReachabilityFlagsConnectionAutomatic)\n#endif\n\t\t{\n\t\t\t// ... and the connection is on-demand (or on-traffic) if the\n\t\t\t//     calling application is using the CFSocketStream or higher APIs\n\t\t\t\n\t\t\tif (!(flags & kSCNetworkReachabilityFlagsInterventionRequired))\n\t\t\t{\n\t\t\t\t// ... and no [user] intervention is needed\n\t\t\t\tretVal = ReachableViaWiFi;\n\t\t\t}\n\t\t}\n\t\n\tif (flags & kSCNetworkReachabilityFlagsIsWWAN)\n\t{\n\t\t// ... but WWAN connections are OK if the calling application\n\t\t//     is using the CFNetwork (CFSocketStream?) APIs.\n\t\tretVal = ReachableViaWWAN;\n\t}\n\treturn retVal;\n}\n\n\n- (NetworkStatus) currentReachabilityStatus\n{\n\tNSAssert(reachabilityRef, @\"currentReachabilityStatus called with NULL reachabilityRef\");\n\t\n\tNetworkStatus retVal = NotReachable;\n\tSCNetworkReachabilityFlags flags;\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))\n\t{\n\t\tif(self.key == kLocalWiFiConnection)\n\t\t{\n\t\t\tretVal = [self localWiFiStatusForFlags: flags];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tretVal = [self networkStatusForFlags: flags];\n\t\t}\n\t}\n\treturn retVal;\n}\n\n\n- (BOOL) isReachable {\n\t\n\tNSAssert(reachabilityRef, @\"isReachable called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags = 0;\n\tNetworkStatus status = kNotReachable;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\tif(self.key == kLocalWiFiConnection) {\n\t\t\t\n\t\t\tstatus = [self localWiFiStatusForFlags: flags];\n\t\t\t\n\t\t} else {\n\t\t\t\n\t\t\tstatus = [self networkStatusForFlags: flags];\n\t\t\t\n\t\t}\n\t\t\n\t\treturn (kNotReachable != status);\n\t\t\n\t}\n\t\n\treturn NO;\n\t\n} // isReachable\n\n\n- (BOOL) isConnectionRequired {\n\t\n\treturn [self connectionRequired];\n\t\n} // isConnectionRequired\n\n\n- (BOOL) connectionRequired {\n\t\n\tNSAssert(reachabilityRef, @\"connectionRequired called with NULL reachabilityRef\");\n\t\n\tSCNetworkReachabilityFlags flags;\n\t\n\tif (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {\n\t\t\n\t\tlogReachabilityFlags(flags);\n\t\t\n\t\treturn (flags & kSCNetworkReachabilityFlagsConnectionRequired);\n\t\t\n\t}\n\t\n\treturn NO;\n\t\n} // connectionRequired\n#endif\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/DOUAPIConfig.h",
    "content": "//\n//  DOUAPIConfig.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\nextern NSString * const kHttpsApiBaseUrl;\nextern NSString * const kHttpApiBaseUrl;\n\nextern NSString * const kAuthUrl;\nextern NSString * const kTokenUrl;\n\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/DOUAPIConfig.m",
    "content": "//\n//  DOUAPIConfig.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUAPIConfig.h\"\n\n//\n// Douban parameters:\n//\n//\nNSString * const kHttpsApiBaseUrl = @\"https://api.douban.com\";\nNSString * const kHttpApiBaseUrl = @\"http://api.douban.com\";\n\n//NSString * const kHttpApiBaseUrl = @\"http://loc-zeta.douban.com/service/api\";\n//NSString * const kHttpsApiBaseUrl = @\"https://loc-zeta.douban.com/service/api\";\n\nNSString * const kAuthUrl = @\"https://www.douban.com/service/auth2/auth\";\nNSString * const kTokenUrl = @\"https://www.douban.com/service/auth2/token\";\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/DOUAPIEngine.h",
    "content": "//\n//  DOUAPIEngine.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-2.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUAPIConfig.h\"\n#import \"DOUQuery.h\"\n\n#import \"DoubanDefines.h\"\n#import \"DOUService.h\"\n#import \"DOUOAuthService.h\"\n#import \"DOUOAuth2.h\"\n#import \"DOUOAuthStore.h\"\n#import \"DOUHttpRequest.h\"\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/BaseClasses/GDataEntryBase.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataEntryBase.h\n//\n// This is the base class for all standard GData feed entries.\n//\n\n#import \"GDataDateTime.h\"\n#import \"GDataTextConstruct.h\"\n#import \"GDataEntryContent.h\"\n#import \"GDataPerson.h\"\n#import \"GDataCategory.h\"\n#import \"GDataDeleted.h\"\n#import \"GDataBatchOperation.h\"\n#import \"GDataBatchID.h\"\n#import \"GDataBatchStatus.h\"\n#import \"GDataBatchInterrupted.h\"\n#import \"GDataAtomPubControl.h\"\n#import \"GDataLink.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAENTRYBASE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataCategoryScheme _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#kind\");\n\n\n@interface GDataEntryBase : GDataObject <NSCopying> {\n  // either uploadData_ or uploadFileHandle_ may be set, but not both\n  NSData *uploadData_;\n  NSFileHandle *uploadFileHandle_;\n  NSURL *uploadLocationURL_; // requires uploadFileHandle be set\n  NSString *uploadMIMEType_;\n  NSString *uploadSlug_; // for http slug (filename) header when uploading\n  BOOL shouldUploadDataOnly_;\n}\n\n+ (NSDictionary *)baseGDataNamespaces;\n\n+ (id)entry;\n\n- (id)initWithData:(NSData *)data;\n\n- (id)initWithData:(NSData *)data\n    serviceVersion:(NSString *)serviceVersion\nshouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns;\n\n// basic entry fields\n- (NSString *)identifier;\n- (void)setIdentifier:(NSString *)theIdString;\n\n- (GDataDateTime *)publishedDate;\n- (void)setPublishedDate:(GDataDateTime *)thePublishedDate;\n\n- (GDataDateTime *)updatedDate;\n- (void)setUpdatedDate:(GDataDateTime *)theUpdatedDate;\n\n- (GDataDateTime *)editedDate;\n- (void)setEditedDate:(GDataDateTime *)theEditedDate;\n\n- (NSString *)ETag;\n- (void)setETag:(NSString *)str;\n\n- (NSString *)fieldSelection;\n- (void)setFieldSelection:(NSString *)str;\n\n- (NSString *)kind;\n- (void)setKind:(NSString *)str;\n\n- (NSString *)resourceID;\n- (void)setResourceID:(NSString *)str;\n\n- (GDataTextConstruct *)title;\n- (void)setTitle:(GDataTextConstruct *)theTitle;\n- (void)setTitleWithString:(NSString *)str;\n\n- (GDataTextConstruct *)summary;\n- (void)setSummary:(GDataTextConstruct *)theSummary;\n- (void)setSummaryWithString:(NSString *)str;\n\n- (GDataEntryContent *)content;\n- (void)setContent:(GDataEntryContent *)theContent;\n- (void)setContentWithString:(NSString *)str;\n\n- (GDataTextConstruct *)rightsString;\n- (void)setRightsString:(GDataTextConstruct *)theRightsString;\n- (void)setRightsStringWithString:(NSString *)str;\n\n- (NSArray *)links;\n- (void)setLinks:(NSArray *)links;\n- (void)addLink:(GDataLink *)link;\n\n- (NSArray *)authors;\n- (void)setAuthors:(NSArray *)authors;\n- (void)addAuthor:(GDataPerson *)authorElement;\n\n- (NSArray *)contributors;\n- (void)setContributors:(NSArray *)array;\n- (void)addContributor:(GDataPerson *)obj;\n\n- (NSArray *)categories;\n- (void)setCategories:(NSArray *)categories;\n- (void)addCategory:(GDataCategory *)category;\n- (void)removeCategory:(GDataCategory *)category;\n\n// File upload\n//\n// Either uploadData or uploadFileHandle should be set, but not both\n- (NSData *)uploadData;\n- (void)setUploadData:(NSData *)data;\n\n- (NSFileHandle *)uploadFileHandle;\n- (void)setUploadFileHandle:(NSFileHandle *)fileHandle;\n\n// The location URL is used to restart upload of a file handle\n- (NSURL *)uploadLocationURL;\n- (void)setUploadLocationURL:(NSURL *)url;\n\n- (NSString *)uploadMIMEType;\n- (void)setUploadMIMEType:(NSString *)str;\n\n// support for uploading media data without the XML from the GDataObject\n- (BOOL)shouldUploadDataOnly;\n- (void)setShouldUploadDataOnly:(BOOL)flag;\n\n// http slug (filename) header when uploading\n- (NSString *)uploadSlug;\n- (void)setUploadSlug:(NSString *)str;\n\n// extension for entries which may include deleted elements\n- (BOOL)isDeleted;\n- (void)setIsDeleted:(BOOL)isDeleted;\n\n// extensions for Atom publishing control\n- (GDataAtomPubControl *)atomPubControl;\n- (void)setAtomPubControl:(GDataAtomPubControl *)obj;\n\n// batch support\n+ (NSDictionary *)batchNamespaces;\n\n- (GDataBatchOperation *)batchOperation;\n- (void)setBatchOperation:(GDataBatchOperation *)obj;\n\n// the batch ID is an arbitrary string defined by clients, and present in the\n// batch response feed to let the client match each entry's response to\n// the entry\n- (GDataBatchID *)batchID;\n- (void)setBatchID:(GDataBatchID *)obj;\n- (void)setBatchIDWithString:(NSString *)str;\n\n- (GDataBatchStatus *)batchStatus;\n- (void)setBatchStatus:(GDataBatchStatus *)obj;\n\n- (GDataBatchInterrupted *)batchInterrupted;\n- (void)setBatchInterrupted:(GDataBatchInterrupted *)obj;\n\n// convenience accessors\n\n- (NSArray *)categoriesWithScheme:(NSString *)scheme;\n\n// most entries have a category element with scheme kGDataCategoryScheme\n// that indicates the kind of entry\n- (GDataCategory *)kindCategory;\n\n- (NSArray *)linksWithRelAttributeValue:(NSString *)relValue;\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)relValue;\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel\n                                    type:(NSString *)type;\n\n- (GDataLink *)feedLink;\n- (GDataLink *)editLink;\n- (GDataLink *)editMediaLink;\n- (GDataLink *)alternateLink;\n- (GDataLink *)relatedLink;\n- (GDataLink *)postLink;\n- (GDataLink *)selfLink;\n- (GDataLink *)HTMLLink;\n- (GDataLink *)uploadEditLink;\n\n- (BOOL)canEdit;\n\n///////////////////////////////////////////////////////////////////////////////\n//\n//  Protected methods\n//\n//  All remaining methods are intended for use only by subclasses\n//  of GDataEntryBase.\n//\n\n// subclasses call registerEntryClass to register their standardEntryKind\n+ (void)registerEntryClass;\n\n+ (Class)entryClassForCategoryWithScheme:(NSString *)scheme\n                                    term:(NSString *)term;\n+ (Class)entryClassForKindAttributeValue:(NSString *)kind;\n\n// temporary bridge method\n+ (void)registerEntryClass:(Class)theClass\n     forCategoryWithScheme:(NSString *)scheme\n                      term:(NSString *)term;\n\n\n// subclasses override standardEntryKind to provide the term string for the\n// kind attribute of their kind category element, if any\n+ (NSString *)standardEntryKind;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/BaseClasses/GDataEntryBase.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataEntryBase.m\n//\n\n#define GDATAENTRYBASE_DEFINE_GLOBALS 1\n\n#import \"GDataEntryBase.h\"\n#import \"GDataBaseElements.h\"\n#import \"GTMMIMEDocument.h\"\n\n@implementation GDataEntryBase\n\n+ (NSString *)standardEntryKind {\n\n  // overridden by entry subclasses\n  //\n  // Feeds and entries typically have a \"kind\" atom:category element\n  // indicating their contents; see\n  //    http://code.google.com/apis/gdata/elements.html#Introduction\n  //\n  // Subclasses may override this method with the \"term\" attribute string\n  // for their kind category.  This is used in the plain -init method,\n  // and from +registerEntryClass\n  //\n\n  return nil;\n}\n\n+ (NSString *)standardKindAttributeValue {\n\n  // overridden by entry subclasses\n  //\n  // Feeds and entries in core v2.1 and later have a kind attribute rather than\n  // kind categories\n  //\n  // Subclasses may override this method with the proper kind attribute string\n  // used to identify this class\n  //\n  return nil;\n}\n\n+ (NSDictionary *)baseGDataNamespaces {\n  NSDictionary *namespaces = [NSDictionary dictionaryWithObjectsAndKeys:\n    kGDataNamespaceAtom, @\"\",\n    kGDataNamespaceGData, kGDataNamespaceGDataPrefix,\n    kGDataNamespaceAtomPub, kGDataNamespaceAtomPubPrefix,\n    nil];\n  return namespaces;\n}\n\n+ (id)entry {\n  GDataEntryBase *entry = [self object];\n\n  [entry setNamespaces:[GDataEntryBase baseGDataNamespaces]];\n  return entry;\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  Class entryClass = [self class];\n\n  [self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:\n   // GData extensions\n   [GDataResourceID class],\n\n   // Atom extensions\n   [GDataAtomID class],\n   [GDataAtomPublishedDate class],\n   [GDataAtomUpdatedDate class],\n   [GDataAtomTitle class],\n   [GDataAtomSummary class],\n   [GDataAtomContent class],\n   [GDataAtomRights class],\n   [GDataLink class],\n   [GDataAtomAuthor class],\n   [GDataAtomContributor class],\n   [GDataCategory class],\n\n   // deletion marking support\n   [GDataDeleted class],\n\n   // atom publishing control support\n   [GDataAtomPubControl class],\n   [GDataAtomPubEditedDate class],\n\n   // batch support\n   [GDataBatchOperation class], [GDataBatchID class],\n   [GDataBatchStatus class], [GDataBatchInterrupted class],\n   nil];\n\n  [self addAttributeExtensionDeclarationForParentClass:entryClass\n                                            childClass:[GDataETagAttribute class]];\n  [self addAttributeExtensionDeclarationForParentClass:entryClass\n                                            childClass:[GDataFieldsAttribute class]];\n  [self addAttributeExtensionDeclarationForParentClass:entryClass\n                                            childClass:[GDataKindAttribute class]];\n}\n\n- (id)init {\n  self = [super init];\n  if (self) {\n    // if the subclass declares a kind, then add a category element or\n    // a kind attribute\n    NSString *categoryKind = [[self class] standardEntryKind];\n    if (categoryKind) {\n      GDataCategory *category;\n\n      category = [GDataCategory categoryWithScheme:kGDataCategoryScheme\n                                              term:categoryKind];\n      [self addCategory:category];\n    }\n\n    NSString *attributeKind = [[self class] standardKindAttributeValue];\n    if (attributeKind) {\n      [self setKind:attributeKind];\n    }\n  }\n  return self;\n}\n\n\n- (id)initWithData:(NSData *)data {\n  return [self initWithData:data\n             serviceVersion:nil\n       shouldIgnoreUnknowns:NO];\n}\n\n- (id)initWithData:(NSData *)data\n    serviceVersion:(NSString *)serviceVersion\nshouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns {\n  \n  // entry point for creation of feeds from file or network data\n  NSError *error = nil;\n  NSXMLDocument *xmlDocument = [[[NSXMLDocument alloc] initWithData:data\n                                                            options:0\n                                                              error:&error] autorelease];\n  if (xmlDocument) {\n    \n    NSXMLElement* root = [xmlDocument rootElement];\n    self = [super initWithXMLElement:root\n                              parent:nil\n                      serviceVersion:serviceVersion\n                          surrogates:nil\n                shouldIgnoreUnknowns:NO];\n    if (self) {\n      // we're done parsing; the extension declarations won't be needed again\n      [self clearExtensionDeclarationsCache];\n      \n#if GDATA_USES_LIBXML\n      // retain the document so that pointers to internal nodes remain valid\n      [self setProperty:xmlDocument forKey:kGDataXMLDocumentPropertyKey];\n#endif\n    }\n    return self;\n    \n  } else {\n    // could not parse XML into a document\n    [self release];\n    return nil;\n  }\n}\n\n\n\n- (void)dealloc {\n  [uploadData_ release];\n  [uploadFileHandle_ release];\n  [uploadLocationURL_ release];\n  [uploadMIMEType_ release];\n  [uploadSlug_ release];\n\n  [super dealloc];\n}\n\n- (BOOL)isEqual:(GDataEntryBase *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataEntryBase class]]) return NO;\n\n  return [super isEqual:other]\n    && AreEqualOrBothNil([self uploadData], [other uploadData])\n    && AreEqualOrBothNil([self uploadMIMEType], [other uploadMIMEType])\n    && AreEqualOrBothNil([self uploadSlug], [other uploadSlug])\n    && AreBoolsEqual([self shouldUploadDataOnly], [other shouldUploadDataOnly]);\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataEntryBase* newEntry = [super copyWithZone:zone];\n\n  [newEntry setUploadData:[self uploadData]];\n  [newEntry setUploadFileHandle:[self uploadFileHandle]];\n  [newEntry setUploadLocationURL:[self uploadLocationURL]];\n  [newEntry setUploadMIMEType:[self uploadMIMEType]];\n  [newEntry setUploadSlug:[self uploadSlug]];\n  [newEntry setShouldUploadDataOnly:[self shouldUploadDataOnly]];\n\n  return newEntry;\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n\n- (NSMutableArray *)itemsForDescription {\n\n  // make a list of the interesting parts of links\n  NSArray *linkNames = [GDataLink linkNamesFromLinks:[self links]];\n  NSString *linksStr = [linkNames componentsJoinedByString:@\",\"];\n\n  struct GDataDescriptionRecord descRecs[] = {\n    { @\"v\",                @\"serviceVersion\",           kGDataDescValueLabeled },\n    { @\"title\",            @\"title.stringValue\",        kGDataDescValueLabeled },\n    { @\"summary\",          @\"summary.stringValue\",      kGDataDescValueLabeled },\n    { @\"content\",          @\"content.stringValue\",      kGDataDescValueLabeled },\n    { @\"contentSrc\",       @\"content.sourceURI\",        kGDataDescValueLabeled },\n    { @\"etag\",             @\"ETag\",                     kGDataDescValueLabeled },\n    { @\"kind\",             @\"kind\",                     kGDataDescValueLabeled },\n    { @\"fields\",           @\"fieldSelection\",           kGDataDescValueLabeled },\n    { @\"resourceID\",       @\"resourceID\",               kGDataDescValueLabeled },\n    { @\"authors\",          @\"authors\",                  kGDataDescArrayCount },\n    { @\"contributors\",     @\"contributors\",             kGDataDescArrayCount },\n    { @\"categories\",       @\"categories\",               kGDataDescArrayCount },\n    { @\"links\",            linksStr,                    kGDataDescValueIsKeyPath },\n    { @\"edited\",           @\"editedDate.RFC3339String\", kGDataDescValueLabeled },\n    { @\"id\",               @\"identifier\",               kGDataDescValueLabeled },\n    { @\"app:control\",      @\"atomPubControl\",           kGDataDescValueLabeled },\n    { @\"batchOp\",          @\"batchOperation.type\",      kGDataDescValueLabeled },\n    { @\"batchID\",          @\"batchID.stringValue\",      kGDataDescValueLabeled },\n    { @\"batchStatus\",      @\"batchStatus.code\",         kGDataDescValueLabeled },\n    { @\"batchInterrupted\", @\"batchInterrupted\",         kGDataDescValueLabeled },\n    { @\"MIMEType\",         @\"uploadMIMEType\",           kGDataDescValueLabeled },\n    { @\"slug\",             @\"uploadSlug\",               kGDataDescValueLabeled },\n    { @\"uploadDataOnly\",   @\"shouldUploadDataOnly\",     kGDataDescBooleanPresent },\n    { @\"UploadData\",       @\"uploadData\",               kGDataDescNonZeroLength },\n    { @\"deleted\",          @\"isDeleted\",                kGDataDescBooleanPresent },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n- (NSXMLElement *)XMLElement {\n  NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:@\"entry\"];\n  return element;\n}\n\n#pragma mark -\n\n- (NSDictionary *)contentHeaders {\n  // This is also called from GDataServiceBase so it knows what headers to use\n  // when uploading data chunked but without XML (so the body is empty.)\n  return  [NSDictionary dictionaryWithObjectsAndKeys:\n           [self uploadMIMEType], @\"Content-Type\",\n           @\"1.0\", @\"MIME-Version\",\n           [self uploadSlug], @\"Slug\", // slug may be nil\n           nil];\n}\n\n- (BOOL)generateContentInputStream:(NSInputStream **)outInputStream\n                            length:(unsigned long long *)outLength\n                           headers:(NSDictionary **)outHeaders {\n\n  // check if a subclass is providing data\n  NSData *uploadData = [self uploadData];\n\n  if (uploadData == nil) {\n    // read from the file handle, if one was provided\n    NSFileHandle *fileHandle = [self uploadFileHandle];\n    if (fileHandle) {\n      [fileHandle seekToFileOffset:0];\n      uploadData = [fileHandle readDataToEndOfFile];\n    }\n  }\n\n  NSString *uploadMIMEType = [self uploadMIMEType];\n  NSString *slug = [self uploadSlug];\n\n  BOOL hasUploadData = ([uploadData length] > 0);\n  BOOL hasUploadMIMEType = ([uploadMIMEType length] > 0);\n  GDATA_DEBUG_ASSERT(hasUploadData == hasUploadMIMEType,\n                     @\"upload data must be paired with MIME type\");\n\n  BOOL shouldUploadDataOnly = [self shouldUploadDataOnly];\n  GDATA_DEBUG_ASSERT(!shouldUploadDataOnly\n                     || (hasUploadData && hasUploadMIMEType),\n                     @\"missing data\");\n\n  if (shouldUploadDataOnly && hasUploadData && hasUploadMIMEType) {\n    // we're not uploading the XML, so we don't need a multipart MIME document,\n    // just a stream with the upload data\n    *outInputStream = [NSInputStream inputStreamWithData:uploadData];\n    *outLength = [uploadData length];\n    *outHeaders = [self contentHeaders];\n    return YES;\n  }\n\n  if (!hasUploadData || !hasUploadMIMEType) {\n    // if there's no upload data, just fall back on the superclass since we\n    // don't need a stream\n    return [super generateContentInputStream:outInputStream\n                                      length:outLength\n                                     headers:outHeaders];\n  }\n\n  // make a MIME document with an XML part and a binary part\n  NSDictionary* xmlHeader = [NSDictionary dictionaryWithObjectsAndKeys:\n    @\"application/atom+xml; charset=UTF-8\", @\"Content-Type\", nil];\n\n  NSString *xmlString = [[self XMLElement] XMLString];\n  NSData *xmlBody = [xmlString dataUsingEncoding:NSUTF8StringEncoding];\n\n  NSDictionary *binHeader = [NSDictionary dictionaryWithObjectsAndKeys:\n    uploadMIMEType, @\"Content-Type\",\n    @\"binary\", @\"Content-Transfer-Encoding\", nil];\n\n  GTMMIMEDocument* doc = [GTMMIMEDocument MIMEDocument];\n\n  [doc addPartWithHeaders:xmlHeader body:xmlBody];\n  [doc addPartWithHeaders:binHeader body:uploadData];\n\n  // generate the input stream, and make a header which includes the\n  // boundary used between parts of the mime document\n  NSString *partBoundary = nil; // typically this will be END_OF_PART\n\n  [doc generateInputStream:outInputStream\n                    length:outLength\n                  boundary:&partBoundary];\n\n  NSString *streamTypeTemplate = @\"multipart/related; boundary=\\\"%@\\\"\";\n  NSString *streamType = [NSString stringWithFormat:streamTypeTemplate,\n    partBoundary];\n\n  *outHeaders = [NSDictionary dictionaryWithObjectsAndKeys:\n    streamType, @\"Content-Type\",\n    @\"1.0\", @\"MIME-Version\",\n    slug, @\"Slug\", // slug may be nil\n    nil];\n\n  return YES;\n}\n\n#pragma mark Dynamic object generation - Entry registration\n\n//\n// entry registration & lookup for dynamic object generation\n//\n\nstatic NSMutableDictionary *gEntryClassKindMap = nil;\n\n+ (void)registerEntryClass {\n\n  NSString *categoryKind = [self standardEntryKind];\n  if (categoryKind) {\n    [self registerClass:self\n                  inMap:&gEntryClassKindMap\n  forCategoryWithScheme:kGDataCategoryScheme\n                   term:categoryKind];\n  }\n\n  NSString *attributeKind = [self standardKindAttributeValue];\n  if (attributeKind) {\n    [self registerClass:self\n                  inMap:&gEntryClassKindMap\n  forCategoryWithScheme:nil\n                   term:attributeKind];\n  }\n\n  GDATA_DEBUG_ASSERT(attributeKind != nil || categoryKind != nil,\n                     @\"cannot register entry without a kind\");\n}\n\n+ (void)registerEntryClass:(Class)theClass\n     forCategoryWithScheme:(NSString *)scheme\n                      term:(NSString *)term {\n\n  // temporary bridge method - will be removed when subclasses all call\n  // -registerEntryClass\n  [self registerClass:theClass\n                inMap:&gEntryClassKindMap\nforCategoryWithScheme:scheme\n                 term:term];\n}\n\n+ (Class)entryClassForCategoryWithScheme:(NSString *)scheme\n                                    term:(NSString *)term {\n  return [self classForCategoryWithScheme:scheme\n                                     term:term\n                                  fromMap:gEntryClassKindMap];\n}\n\n+ (Class)entryClassForKindAttributeValue:(NSString *)kind {\n  return [self classForCategoryWithScheme:nil\n                                     term:kind\n                                  fromMap:gEntryClassKindMap];\n}\n\n#pragma mark Getters and Setters\n\n- (NSString *)ETag {\n  NSString *str = [self attributeValueForExtensionClass:[GDataETagAttribute class]];\n  return str;\n}\n\n- (void)setETag:(NSString *)str {\n  [self setAttributeValue:str forExtensionClass:[GDataETagAttribute class]];\n}\n\n- (NSString *)fieldSelection {\n  NSString *str = [self attributeValueForExtensionClass:[GDataFieldsAttribute class]];\n  return str;\n}\n\n- (void)setFieldSelection:(NSString *)str {\n  [self setAttributeValue:str forExtensionClass:[GDataFieldsAttribute class]];\n}\n\n- (NSString *)kind {\n  NSString *str = [self attributeValueForExtensionClass:[GDataKindAttribute class]];\n  return str;\n}\n\n- (void)setKind:(NSString *)str {\n  [self setAttributeValue:str forExtensionClass:[GDataKindAttribute class]];\n}\n\n- (NSString *)resourceID {\n  GDataResourceID *obj = [self objectForExtensionClass:[GDataResourceID class]];\n  return [obj stringValue];\n}\n\n- (void)setResourceID:(NSString *)str {\n  GDataResourceID *obj = [GDataResourceID valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataResourceID class]];\n}\n\n- (NSString *)identifier {\n  GDataAtomID *obj = [self objectForExtensionClass:[GDataAtomID class]];\n  return [obj stringValue];\n}\n\n- (void)setIdentifier:(NSString *)str {\n  GDataAtomID *obj = [GDataAtomID valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomID class]];\n}\n\n- (GDataDateTime *)publishedDate {\n  GDataAtomPublishedDate *obj;\n\n  obj = [self objectForExtensionClass:[GDataAtomPublishedDate class]];\n  return [obj dateTimeValue];\n}\n\n- (void)setPublishedDate:(GDataDateTime *)dateTime {\n  GDataAtomPublishedDate *obj;\n\n  obj = [GDataAtomPublishedDate valueWithDateTime:dateTime];\n  [self setObject:obj forExtensionClass:[GDataAtomPublishedDate class]];\n}\n\n- (GDataDateTime *)updatedDate {\n  GDataAtomUpdatedDate *obj;\n\n  obj = [self objectForExtensionClass:[GDataAtomUpdatedDate class]];\n  return [obj dateTimeValue];\n}\n\n- (void)setUpdatedDate:(GDataDateTime *)dateTime {\n  GDataAtomUpdatedDate *obj;\n\n  obj = [GDataAtomUpdatedDate valueWithDateTime:dateTime];\n  [self setObject:obj forExtensionClass:[GDataAtomUpdatedDate class]];\n}\n\n- (GDataDateTime *)editedDate {\n  GDataValueElementConstruct *obj;\n\n  obj = [self objectForExtensionClass:[GDataAtomPubEditedDate class]];\n  return [obj dateTimeValue];\n}\n\n- (void)setEditedDate:(GDataDateTime *)dateTime {\n  GDataValueElementConstruct *obj;\n\n  obj = [GDataAtomPubEditedDate valueWithDateTime:dateTime];\n  [self setObject:obj forExtensionClass:[GDataAtomPubEditedDate class]];\n}\n\n- (GDataTextConstruct *)title {\n  GDataAtomTitle *obj = [self objectForExtensionClass:[GDataAtomTitle class]];\n  return obj;\n}\n\n- (void)setTitle:(GDataTextConstruct *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomTitle class]];\n}\n\n- (void)setTitleWithString:(NSString *)str {\n  GDataAtomTitle *obj = [GDataAtomTitle textConstructWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomTitle class]];\n}\n\n- (GDataTextConstruct *)summary {\n  GDataAtomSummary *obj = [self objectForExtensionClass:[GDataAtomSummary class]];\n  return obj;\n}\n\n- (void)setSummary:(GDataTextConstruct *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomSummary class]];\n}\n\n- (void)setSummaryWithString:(NSString *)str {\n  GDataAtomSummary *obj = [GDataAtomSummary textConstructWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomSummary class]];\n}\n\n- (GDataEntryContent *)content {\n  GDataAtomContent *obj;\n\n  obj = [self objectForExtensionClass:[GDataAtomContent class]];\n  return obj;\n}\n\n- (void)setContent:(GDataEntryContent *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomContent class]];\n}\n\n- (void)setContentWithString:(NSString *)str {\n  GDataAtomContent *obj = [GDataAtomContent contentWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomContent class]];\n}\n\n- (GDataTextConstruct *)rightsString {\n  GDataTextConstruct *obj;\n\n  obj = [self objectForExtensionClass:[GDataAtomRights class]];\n  return obj;\n}\n\n- (void)setRightsString:(GDataTextConstruct *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomRights class]];\n}\n\n- (void)setRightsStringWithString:(NSString *)str {\n  GDataAtomRights *obj;\n\n  obj = [GDataAtomRights textConstructWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomRights class]];\n}\n\n- (NSArray *)links {\n  NSArray *array = [self objectsForExtensionClass:[GDataLink class]];\n  return array;\n}\n\n- (void)setLinks:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataLink class]];\n}\n\n- (void)addLink:(GDataLink *)obj {\n  [self addObject:obj forExtensionClass:[GDataLink class]];\n}\n\n- (NSArray *)authors {\n  NSArray *array = [self objectsForExtensionClass:[GDataAtomAuthor class]];\n  return array;\n}\n\n- (void)setAuthors:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataAtomAuthor class]];\n}\n\n- (void)addAuthor:(GDataPerson *)obj {\n  [self addObject:obj forExtensionClass:[GDataAtomAuthor class]];\n}\n\n- (NSArray *)contributors {\n  NSArray *array = [self objectsForExtensionClass:[GDataAtomContributor class]];\n  return array;\n}\n\n- (void)setContributors:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataAtomContributor class]];\n}\n\n- (void)addContributor:(GDataPerson *)obj {\n  [self addObject:obj forExtensionClass:[GDataAtomContributor class]];\n}\n\n- (NSArray *)categories {\n  NSArray *array = [self objectsForExtensionClass:[GDataCategory class]];\n  return array;\n}\n\n- (void)setCategories:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataCategory class]];\n}\n\n- (void)addCategory:(GDataCategory *)obj {\n  [self addObject:obj forExtensionClass:[GDataCategory class]];\n}\n\n- (void)removeCategory:(GDataCategory *)obj {\n  [self removeObject:obj forExtensionClass:[GDataCategory class]];\n}\n\n// File uploading\n\n- (NSData *)uploadData {\n  return uploadData_;\n}\n\n- (void)setUploadData:(NSData *)data {\n  [uploadData_ autorelease];\n  uploadData_ = [data retain];\n}\n\n- (NSFileHandle *)uploadFileHandle {\n  return uploadFileHandle_;\n}\n\n- (void)setUploadFileHandle:(NSFileHandle *)data {\n  [uploadFileHandle_ autorelease];\n  uploadFileHandle_ = [data retain];\n}\n\n- (NSURL *)uploadLocationURL {\n  return uploadLocationURL_;\n}\n\n- (void)setUploadLocationURL:(NSURL *)url {\n  [uploadLocationURL_ autorelease];\n  uploadLocationURL_ = [url retain];\n}\n\n- (NSString *)uploadMIMEType {\n  return uploadMIMEType_;\n}\n\n- (void)setUploadMIMEType:(NSString *)str {\n  [uploadMIMEType_ autorelease];\n  uploadMIMEType_ = [str copy];\n}\n\n- (NSString *)uploadSlug {\n  return uploadSlug_;\n}\n\n- (void)setUploadSlug:(NSString *)str {\n  [uploadSlug_ autorelease];\n\n  // encode per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7\n  NSString *encoded = [GDataUtilities stringByPercentEncodingUTF8ForString:str];\n  uploadSlug_ = [encoded copy];\n}\n\n- (BOOL)shouldUploadDataOnly {\n  return shouldUploadDataOnly_;\n}\n\n- (void)setShouldUploadDataOnly:(BOOL)flag {\n  shouldUploadDataOnly_ = flag;\n}\n\n// extension for deletion marking\n- (BOOL)isDeleted {\n  GDataDeleted *deleted = [self objectForExtensionClass:[GDataDeleted class]];\n  return (deleted != nil);\n}\n\n- (void)setIsDeleted:(BOOL)isDeleted {\n  if (isDeleted) {\n    // set the extension\n    [self setObject:[GDataDeleted deleted] forExtensionClass:[GDataDeleted class]];\n  } else {\n    // remove the extension\n    [self setObject:nil forExtensionClass:[GDataDeleted class]];\n  }\n}\n\n// extensions for Atom publishing control\n\n- (GDataAtomPubControl *)atomPubControl {\n  return [self objectForExtensionClass:[GDataAtomPubControl class]];\n}\n\n- (void)setAtomPubControl:(GDataAtomPubControl *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomPubControl class]];\n}\n\n// extensions for batch support\n\n- (GDataBatchOperation *)batchOperation {\n  return (GDataBatchOperation *) [self objectForExtensionClass:[GDataBatchOperation class]];\n}\n\n- (void)setBatchOperation:(GDataBatchOperation *)obj {\n  [self setObject:obj forExtensionClass:[GDataBatchOperation class]];\n}\n\n- (GDataBatchID *)batchID {\n  return (GDataBatchID *) [self objectForExtensionClass:[GDataBatchID class]];\n}\n\n- (void)setBatchID:(GDataBatchID *)obj {\n  [self setObject:obj forExtensionClass:[GDataBatchID class]];\n}\n\n- (void)setBatchIDWithString:(NSString *)str {\n  GDataBatchID *obj = [GDataBatchID batchIDWithString:str];\n  [self setBatchID:obj];\n}\n\n- (GDataBatchStatus *)batchStatus {\n  return (GDataBatchStatus *) [self objectForExtensionClass:[GDataBatchStatus class]];\n}\n\n- (void)setBatchStatus:(GDataBatchStatus *)obj {\n  [self setObject:obj forExtensionClass:[GDataBatchStatus class]];\n}\n\n- (GDataBatchInterrupted *)batchInterrupted {\n  return (GDataBatchInterrupted *) [self objectForExtensionClass:[GDataBatchInterrupted class]];\n}\n\n- (void)setBatchInterrupted:(GDataBatchInterrupted *)obj {\n  [self setObject:obj forExtensionClass:[GDataBatchInterrupted class]];\n}\n\n+ (NSDictionary *)batchNamespaces {\n  NSDictionary *namespaces = [NSDictionary dictionaryWithObjectsAndKeys:\n    kGDataNamespaceBatch, kGDataNamespaceBatchPrefix, nil];\n  return namespaces;\n}\n\n#pragma mark -\n\n- (NSArray *)categoriesWithScheme:(NSString *)scheme {\n  NSArray *array = [GDataCategory categoriesWithScheme:scheme\n                                        fromCategories:[self categories]];\n  return array;\n}\n\n- (GDataCategory *)kindCategory {\n  GDataCategory *cat = [GDataUtilities firstObjectFromArray:[self categories]\n                                                  withValue:kGDataCategoryScheme\n                                                 forKeyPath:@\"scheme\"];\n  return cat;\n}\n\n- (NSArray *)linksWithRelAttributeValue:(NSString *)relValue {\n\n  NSArray *array = [GDataUtilities objectsFromArray:[self links]\n                                          withValue:relValue\n                                         forKeyPath:@\"rel\"];\n  return array;\n}\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel {\n\n  return [GDataLink linkWithRel:rel\n                           type:nil\n                      fromLinks:[self links]];\n}\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel\n                                    type:(NSString *)type {\n  return [GDataLink linkWithRel:rel\n                           type:type\n                      fromLinks:[self links]];\n}\n\n- (GDataLink *)feedLink {\n  return [self linkWithRelAttributeValue:kGDataLinkRelFeed];\n}\n\n- (GDataLink *)editLink {\n  return [self linkWithRelAttributeValue:@\"edit\"];\n}\n\n- (GDataLink *)editMediaLink {\n  return [self linkWithRelAttributeValue:@\"edit-media\"];\n}\n\n- (GDataLink *)alternateLink {\n  return [self linkWithRelAttributeValue:@\"alternate\"];\n}\n\n- (GDataLink *)relatedLink {\n  return [self linkWithRelAttributeValue:@\"related\"];\n}\n\n- (GDataLink *)postLink {\n  return [self linkWithRelAttributeValue:kGDataLinkRelPost];\n}\n\n- (GDataLink *)selfLink {\n  return [self linkWithRelAttributeValue:@\"self\"];\n}\n\n- (GDataLink *)HTMLLink {\n  return [self linkWithRelAttributeValue:@\"alternate\"\n                                    type:kGDataLinkTypeHTML];\n}\n\n- (GDataLink *)uploadEditLink {\n  return [self linkWithRelAttributeValue:kGDataLinkRelResumableEdit];\n}\n\n- (BOOL)canEdit {\n  return ([self editLink] != nil);\n}\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/BaseClasses/GDataFeedBase.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataFeedBase.h\n//\n\n#import \"GDataObject.h\"\n\n#import \"GDataGenerator.h\"\n#import \"GDataTextConstruct.h\"\n#import \"GDataLink.h\"\n#import \"GDataEntryBase.h\"\n#import \"GDataCategory.h\"\n#import \"GDataPerson.h\"\n#import \"GDataBatchOperation.h\"\n#import \"GDataAtomPubControl.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAFEEDBASE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// this constant, returned by a subclass implementation of -classForEntries,\n// specifies that a feed's entry class should be determined by inspecting\n// the XML for a \"kind\" category and looking at the registered entry classes\n// for an appropriate match\n_EXTERN Class const kUseRegisteredEntryClass _INITIALIZE_AS(nil);\n\n@interface GDataFeedBase : GDataObject <NSFastEnumeration> {\n\n  // generator is parsed manually to avoid comparison along with other\n  // extensions\n  GDataGenerator *generator_;\n\n  NSMutableArray *entries_;\n}\n\n+ (id)feedWithXMLData:(NSData *)data;\n- (id)initWithData:(NSData *)data;\n- (id)initWithData:(NSData *)data\n    serviceVersion:(NSString *)serviceVersion\nshouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns;\n\n// subclasses override initFeed to set up their ivars\n- (void)initFeedWithXMLElement:(NSXMLElement *)element;\n\n// subclass may override this to specify an entry class or\n// to return kUseRegisteredEntryClass\n- (Class)classForEntries;\n\n// subclasses may override this to specify a \"generic\" class for\n// the feed's entries, if not GDataEntryBase, mainly for when there\n// is no registered entry class found\n+ (Class)defaultClassForEntries;\n\n- (BOOL)canPost;\n\n// getters and setters\n- (GDataGenerator *)generator;\n- (void)setGenerator:(GDataGenerator *)gen;\n\n- (NSString *)identifier;\n- (void)setIdentifier:(NSString *)theString;\n\n- (GDataTextConstruct *)title;\n- (void)setTitle:(GDataTextConstruct *)theTitle;\n- (void)setTitleWithString:(NSString *)str;\n\n- (GDataTextConstruct *)subtitle;\n- (void)setSubtitle:(GDataTextConstruct *)theSubtitle;\n- (void)setSubtitleWithString:(NSString *)str;\n\n- (GDataTextConstruct *)rights;\n- (void)setRights:(GDataTextConstruct *)theRights;\n- (void)setRightsWithString:(NSString *)str;\n\n- (NSString *)icon;\n- (void)setIcon:(NSString *)theString;\n\n- (NSString *)logo;\n- (void)setLogo:(NSString *)theString;\n\n- (NSArray *)links;\n- (void)setLinks:(NSArray *)links;\n- (void)addLink:(GDataLink *)obj;\n- (void)removeLink:(GDataLink *)obj;\n\n- (NSArray *)authors;\n- (void)setAuthors:(NSArray *)authors;\n- (void)addAuthor:(GDataPerson *)obj;\n\n- (NSArray *)contributors;\n- (void)setContributors:(NSArray *)array;\n- (void)addContributor:(GDataPerson *)obj;\n\n- (NSArray *)categories;\n- (void)setCategories:(NSArray *)categories;\n- (void)addCategory:(GDataCategory *)category;\n- (void)removeCategory:(GDataCategory *)category;\n\n- (GDataDateTime *)updatedDate;\n- (void)setUpdatedDate:(GDataDateTime *)theDate;\n\n- (NSString *)ETag;\n- (void)setETag:(NSString *)str;\n\n- (NSString *)fieldSelection;\n- (void)setFieldSelection:(NSString *)str;\n\n- (NSString *)kind;\n- (void)setKind:(NSString *)str;\n\n- (NSString *)resourceID;\n- (void)setResourceID:(NSString *)str;\n\n- (NSArray *)entries;\n\n// setEntries: and addEntry: assert if the entries have other parents\n// already set; use setEntriesWithEntries: and addEntryWithEntry: to copy\n// entries that have other parents\n- (void)setEntries:(NSArray *)entries;\n- (void)addEntry:(GDataEntryBase *)obj;\n\n- (void)setEntriesWithEntries:(NSArray *)entries;\n- (void)addEntryWithEntry:(GDataEntryBase *)obj;\n\n- (NSNumber *)totalResults;\n- (void)setTotalResults:(NSNumber *)theString;\n\n- (NSNumber *)startIndex;\n- (void)setStartIndex:(NSNumber *)theString;\n\n- (NSNumber *)itemsPerPage;\n- (void)setItemsPerPage:(NSNumber *)theString;\n\n// Atom publishing control\n- (GDataAtomPubControl *)atomPubControl;\n- (void)setAtomPubControl:(GDataAtomPubControl *)obj;\n\n// Batch support\n- (GDataBatchOperation *)batchOperation;\n- (void)setBatchOperation:(GDataBatchOperation *)obj;\n\n// convenience routines\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel;\n\n- (GDataLink *)feedLink;\n- (GDataLink *)alternateLink;\n- (GDataLink *)relatedLink;\n- (GDataLink *)postLink;\n- (GDataLink *)uploadLink; // \"resumable-create\" link\n- (GDataLink *)batchLink;\n- (GDataLink *)selfLink;\n- (GDataLink *)nextLink;\n- (GDataLink *)previousLink;\n\n// return the first entry, or nil if none\n- (id)firstEntry;\n\n// return the specified entry, or nil if index is out of bounds\n// (does not throw an exception if index exceeds the size of the entry array)\n- (id)entryAtIndex:(NSUInteger)index;\n\n// find the entry with the given identifier, or nil if none found\n- (id)entryForIdentifier:(NSString *)str;\n\n// find all entries with a kind category for the specified term\n//\n// this is useful for feeds which contain various kinds of entries with\n// distinct entry kind categories\n- (NSArray *)entriesWithCategoryKind:(NSString *)term;\n\n///////////////////////////////////////////////////////////////////////////////\n//\n//  Protected methods\n//\n//  All remaining methods are intended for use only by subclasses\n//  of GDataFeedBase.\n//\n\n// subclasses call registerEntryClass to register their standardFeedKind\n+ (void)registerFeedClass;\n\n+ (Class)feedClassForCategoryWithScheme:(NSString *)scheme\n                                   term:(NSString *)term;\n+ (Class)feedClassForKindAttributeValue:(NSString *)kind;\n\n// temporary bridge method\n+ (void)registerFeedClass:(Class)theClass\n    forCategoryWithScheme:(NSString *)scheme\n                     term:(NSString *)term;\n\n// subclasses override standardFeedKind to provide the term string for the\n// term attribute of their \"kind\" category element, if any\n+ (NSString *)standardFeedKind;\n\n// subclasses override standardKindAttributeValue to provide the string for the\n// kind attribute identifying their class (for core protocol v2.1 and later)\n+ (NSString *)standardKindAttributeValue;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/BaseClasses/GDataFeedBase.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataFeedBase.m\n//\n\n#define GDATAFEEDBASE_DEFINE_GLOBALS 1\n#import \"GDataFeedBase.h\"\n\n#import \"GDataBaseElements.h\"\n\n\n@interface GDataFeedBase (PrivateMethods)\n- (void)setupFromXMLElement:(NSXMLElement *)root;\n@end\n\n@implementation GDataFeedBase\n\n+ (NSString *)standardFeedKind {\n\n  // overridden by feed subclasses\n  //\n  // Feeds and entries typically have a \"kind\" atom:category element\n  // indicating their contents; see\n  //    http://code.google.com/apis/gdata/elements.html#Introduction\n  //\n  // Subclasses may override this method with the \"term\" attribute string\n  // for their kind category.  This is used in the plain -init method,\n  // and from +registerFeedClass\n  //\n\n  return nil;\n}\n\n+ (NSString *)standardKindAttributeValue {\n\n  // overridden by feed subclasses\n  //\n  // Feeds and entries in core v2.1 and later have a kind attribute rather than\n  // kind categories\n  //\n  // Subclasses may override this method with the proper kind attribute string\n  // used to identify this class\n  //\n  return nil;\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  Class feedClass = [self class];\n\n  [self addExtensionDeclarationForParentClass:feedClass\n                                 childClasses:\n\n   // GData extensions\n   [GDataResourceID class],\n\n   // Atom extensions\n   [GDataAtomID class],\n   [GDataAtomTitle class],\n   [GDataAtomSubtitle class],\n   [GDataAtomRights class],\n   [GDataAtomIcon class],\n   [GDataAtomLogo class],\n   [GDataLink class],\n   [GDataAtomAuthor class],\n   [GDataAtomContributor class],\n   [GDataCategory class],\n   [GDataAtomUpdatedDate class],\n\n   // atom publishing control support\n   [GDataAtomPubControl class],\n\n   // batch support\n   [GDataBatchOperation class],\n   nil];\n\n  [self addExtensionDeclarationForParentClass:feedClass\n                                 childClasses:\n\n   [GDataOpenSearchTotalResults class],\n   [GDataOpenSearchStartIndex class],\n   [GDataOpenSearchItemsPerPage class],\n   nil];\n\n  // Attributes\n  [self addAttributeExtensionDeclarationForParentClass:feedClass\n                                            childClass:[GDataETagAttribute class]];\n  [self addAttributeExtensionDeclarationForParentClass:feedClass\n                                            childClass:[GDataFieldsAttribute class]];\n  [self addAttributeExtensionDeclarationForParentClass:feedClass\n                                            childClass:[GDataKindAttribute class]];\n}\n\n+ (id)feedWithXMLData:(NSData *)data {\n  return [[[self alloc] initWithData:data] autorelease];\n}\n\n- (id)init {\n  self = [super init];\n  if (self) {\n    // if the subclass declares a kind, then add a category element for the\n    // kind\n    NSString *categoryKind = [[self class] standardFeedKind];\n    if (categoryKind) {\n      GDataCategory *category;\n\n      category = [GDataCategory categoryWithScheme:kGDataCategoryScheme\n                                              term:categoryKind];\n      [self addCategory:category];\n    }\n\n    NSString *attributeKind = [[self class] standardKindAttributeValue];\n    if (attributeKind) {\n      [self setKind:attributeKind];\n    }\n  }\n  return self;\n}\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent {\n\n  // entry point for creation of feeds inside elements\n  self = [super initWithXMLElement:element\n                            parent:nil];\n  if (self) {\n    [self setupFromXMLElement:element];\n  }\n  return self;\n}\n\n- (id)initWithData:(NSData *)data {\n  return [self initWithData:data\n             serviceVersion:nil\n       shouldIgnoreUnknowns:NO];\n}\n\n- (id)initWithData:(NSData *)data\n    serviceVersion:(NSString *)serviceVersion\nshouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns {\n\n  // entry point for creation of feeds from file or network data\n  NSError *error = nil;\n  NSXMLDocument *xmlDocument = [[[NSXMLDocument alloc] initWithData:data\n                                                            options:0\n                                                              error:&error] autorelease];\n  if (xmlDocument) {\n\n    NSXMLElement* root = [xmlDocument rootElement];\n    self = [super initWithXMLElement:root\n                              parent:nil\n                      serviceVersion:serviceVersion\n                          surrogates:nil\n                shouldIgnoreUnknowns:NO];\n    if (self) {\n      // we're done parsing; the extension declarations won't be needed again\n      [self clearExtensionDeclarationsCache];\n\n#if GDATA_USES_LIBXML\n      // retain the document so that pointers to internal nodes remain valid\n      [self setProperty:xmlDocument forKey:kGDataXMLDocumentPropertyKey];\n#endif\n    }\n    return self;\n\n  } else {\n    // could not parse XML into a document\n    [self release];\n    return nil;\n  }\n}\n\n- (void)setupFromXMLElement:(NSXMLElement *)root {\n\n  // we'll parse the generator manually rather than declare it to be an\n  // extension so that it won't be compared in isEquals: for the feed\n  [self setGenerator:[self objectForChildOfElement:root\n                                     qualifiedName:@\"generator\"\n                                      namespaceURI:kGDataNamespaceAtom\n                                       objectClass:[GDataGenerator class]]];\n\n  // call subclasses to set up their feed ivars\n  [self initFeedWithXMLElement:root];\n\n  // allocate individual entries\n  Class entryClass = [self classForEntries];\n\n  GDATA_DEBUG_ASSERT([[root localName] isEqual:@\"feed\"],\n            @\"initing a feed from a non-feed element (%@)\", [root name]);\n\n  // create entries of the proper class from each \"entry\" element\n  id entryObj = [self objectOrArrayForChildrenOfElement:root\n                                          qualifiedName:@\"entry\"\n                                           namespaceURI:kGDataNamespaceAtom\n                                            objectClass:entryClass];\n  if ([entryObj isKindOfClass:[NSArray class]]) {\n\n    // save the array\n    [self setEntries:entryObj];\n\n  } else if (entryObj != nil) {\n\n    // save the object into an array\n    [self addEntry:entryObj];\n  }\n}\n\n\n- (void)dealloc {\n  [generator_ release];\n  [entries_ release];\n\n  [super dealloc];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataFeedBase* newFeed = [super copyWithZone:zone];\n\n  [newFeed setGenerator:[self generator]];\n\n  [newFeed setEntriesWithEntries:[self entries]];\n  return newFeed;\n}\n\n\n- (BOOL)isEqual:(GDataFeedBase *)other {\n\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataFeedBase class]]) return NO;\n\n  return [super isEqual:other]\n    && AreEqualOrBothNil([self entries], [other entries]);\n    // excluding generator\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription { // subclasses may implement this\n\n  NSArray *linkNames = [GDataLink linkNamesFromLinks:[self links]];\n  NSString *linksStr = [linkNames componentsJoinedByString:@\",\"];\n\n  struct GDataDescriptionRecord descRecs[] = {\n    { @\"v\",                @\"serviceVersion\",          kGDataDescValueLabeled },\n    { @\"entries\",          @\"entries\",                 kGDataDescArrayCount },\n    { @\"etag\",             @\"ETag\",                    kGDataDescValueLabeled },\n    { @\"kind\",             @\"kind\",                    kGDataDescValueLabeled },\n    { @\"fields\",           @\"fieldSelection\",          kGDataDescValueLabeled },\n    { @\"resourceID\",       @\"resourceID\",              kGDataDescValueLabeled },\n    { @\"title\",            @\"title.stringValue\",       kGDataDescValueLabeled },\n    { @\"subtitle\",         @\"subtitle.stringValue\",    kGDataDescValueLabeled },\n    { @\"rights\",           @\"rights.stringValue\",      kGDataDescValueLabeled },\n    { @\"updated\",          @\"updatedDate.stringValue\", kGDataDescValueLabeled },\n    { @\"authors\",          @\"authors\",                 kGDataDescArrayCount },\n    { @\"contributors\",     @\"contributors\",            kGDataDescArrayCount },\n    { @\"categories\",       @\"categories\",              kGDataDescArrayCount },\n    { @\"links\",            linksStr,                   kGDataDescValueIsKeyPath },\n    { @\"id\",               @\"identifier\",              kGDataDescValueLabeled },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  // these are present but not very useful most of the time...\n  // @\"totalResults\"\n  // @\"startIndex\"\n  // @\"itemsPerPage\"\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n- (NSXMLElement *)XMLElement {\n\n  NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:@\"feed\"];\n\n  if ([self generator]) {\n    [element addChild:[[self generator] XMLElement]];\n  }\n\n  [self addToElement:element XMLElementsForArray:[self entries]];\n\n  return element;\n}\n\n\n#pragma mark -\n\n- (void)initFeedWithXMLElement:(NSXMLElement *)element {\n // subclasses override this to set up their feed ivars from the XML\n}\n\n// subclasses may override this, and may return a specific entry class or\n// kUseRegisteredEntryClass\n- (Class)classForEntries {\n  return kUseRegisteredEntryClass;\n}\n\n// subclasses may override this to specify a \"generic\" class for\n// the feed's entries, if not GDataEntryBase, mainly for when there\n// is no registered entry class found\n+ (Class)defaultClassForEntries {\n  return [GDataEntryBase class];\n}\n\n- (BOOL)canPost {\n  return ([self postLink] != nil);\n}\n\n#pragma mark Dynamic object generation - Entry registration\n\n//\n// feed registration & lookup for dynamic object generation\n//\n\nstatic NSMutableDictionary *gFeedClassKindMap = nil;\n\n+ (void)registerFeedClass {\n\n  NSString *categoryKind = [self standardFeedKind];\n  if (categoryKind) {\n    [self registerClass:self\n                  inMap:&gFeedClassKindMap\n  forCategoryWithScheme:kGDataCategoryScheme\n                   term:categoryKind];\n  }\n\n  NSString *attributeKind = [self standardKindAttributeValue];\n  if (attributeKind) {\n    [self registerClass:self\n                  inMap:&gFeedClassKindMap\n  forCategoryWithScheme:nil\n                   term:attributeKind];\n  }\n\n  GDATA_DEBUG_ASSERT(attributeKind != nil || categoryKind != nil,\n                     @\"cannot register feed without a kind\");\n}\n\n+ (void)registerFeedClass:(Class)theClass\n     forCategoryWithScheme:(NSString *)scheme\n                      term:(NSString *)term {\n\n  // temporary bridge method - will be removed when subclasses all call\n  // -registerFeedClass\n  [self registerClass:theClass\n                inMap:&gFeedClassKindMap\nforCategoryWithScheme:scheme\n                 term:term];\n}\n\n+ (Class)feedClassForCategoryWithScheme:(NSString *)scheme\n                                   term:(NSString *)term {\n  return [self classForCategoryWithScheme:scheme\n                                     term:term\n                                  fromMap:gFeedClassKindMap];\n}\n\n+ (Class)feedClassForKindAttributeValue:(NSString *)kind {\n  return [self classForCategoryWithScheme:nil\n                                     term:kind\n                                  fromMap:gFeedClassKindMap];\n}\n\n#pragma mark Getters and Setters\n\n- (NSString *)identifier {\n  GDataAtomID *obj = [self objectForExtensionClass:[GDataAtomID class]];\n  return [obj stringValue];\n}\n\n- (void)setIdentifier:(NSString *)str {\n  GDataAtomID *obj = [GDataAtomID valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomID class]];\n}\n\n- (GDataGenerator *)generator {\n  return generator_;\n}\n\n- (void)setGenerator:(GDataGenerator *)gen {\n  [generator_ autorelease];\n  generator_ = [gen copy];\n}\n\n- (GDataTextConstruct *)title {\n  GDataAtomTitle *obj = [self objectForExtensionClass:[GDataAtomTitle class]];\n  return obj;\n}\n\n- (void)setTitle:(GDataTextConstruct *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomTitle class]];\n}\n\n- (void)setTitleWithString:(NSString *)str {\n  GDataAtomTitle *obj = [GDataAtomTitle textConstructWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomTitle class]];\n}\n\n- (GDataTextConstruct *)subtitle {\n  GDataAtomSubtitle *obj = [self objectForExtensionClass:[GDataAtomSubtitle class]];\n  return obj;\n}\n\n- (void)setSubtitle:(GDataTextConstruct *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomSubtitle class]];\n}\n\n- (void)setSubtitleWithString:(NSString *)str {\n  GDataAtomSubtitle *obj = [GDataAtomSubtitle textConstructWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomSubtitle class]];\n}\n\n- (GDataTextConstruct *)rights {\n  GDataTextConstruct *obj;\n\n  obj = [self objectForExtensionClass:[GDataAtomRights class]];\n  return obj;\n}\n\n- (void)setRights:(GDataTextConstruct *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomRights class]];\n}\n\n- (void)setRightsWithString:(NSString *)str {\n  GDataAtomRights *obj;\n\n  obj = [GDataAtomRights textConstructWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomRights class]];\n}\n\n- (NSString *)icon {\n  GDataAtomIcon *obj = [self objectForExtensionClass:[GDataAtomIcon class]];\n  return [obj stringValue];\n}\n\n- (void)setIcon:(NSString *)str {\n  GDataAtomIcon *obj = [GDataAtomID valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomIcon class]];\n}\n\n- (NSString *)logo {\n  GDataAtomLogo *obj = [self objectForExtensionClass:[GDataAtomLogo class]];\n  return [obj stringValue];\n}\n\n- (void)setLogo:(NSString *)str {\n  GDataAtomLogo *obj = [GDataAtomLogo valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataAtomLogo class]];\n}\n\n- (NSArray *)links {\n  NSArray *array = [self objectsForExtensionClass:[GDataLink class]];\n  return array;\n}\n\n- (void)setLinks:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataLink class]];\n}\n\n- (void)addLink:(GDataLink *)obj {\n  [self addObject:obj forExtensionClass:[GDataLink class]];\n}\n\n- (void)removeLink:(GDataLink *)obj {\n  [self removeObject:obj forExtensionClass:[GDataLink class]];\n}\n\n- (NSArray *)authors {\n  NSArray *array = [self objectsForExtensionClass:[GDataAtomAuthor class]];\n  return array;\n}\n\n- (void)setAuthors:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataAtomAuthor class]];\n}\n\n- (void)addAuthor:(GDataPerson *)obj {\n  [self addObject:obj forExtensionClass:[GDataAtomAuthor class]];\n}\n\n- (NSArray *)contributors {\n  NSArray *array = [self objectsForExtensionClass:[GDataAtomContributor class]];\n  return array;\n}\n\n- (void)setContributors:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataAtomContributor class]];\n}\n\n- (void)addContributor:(GDataPerson *)obj {\n  [self addObject:obj forExtensionClass:[GDataAtomContributor class]];\n}\n\n- (NSArray *)categories {\n  NSArray *array = [self objectsForExtensionClass:[GDataCategory class]];\n  return array;\n}\n\n- (void)setCategories:(NSArray *)array {\n  [self setObjects:array forExtensionClass:[GDataCategory class]];\n}\n\n- (void)addCategory:(GDataCategory *)obj {\n  [self addObject:obj forExtensionClass:[GDataCategory class]];\n}\n\n- (void)removeCategory:(GDataCategory *)obj {\n  [self removeObject:obj forExtensionClass:[GDataCategory class]];\n}\n\n- (GDataDateTime *)updatedDate {\n  GDataAtomUpdatedDate *obj;\n\n  obj = [self objectForExtensionClass:[GDataAtomUpdatedDate class]];\n  return [obj dateTimeValue];\n}\n\n- (void)setUpdatedDate:(GDataDateTime *)dateTime {\n  GDataAtomUpdatedDate *obj;\n\n  obj = [GDataAtomUpdatedDate valueWithDateTime:dateTime];\n  [self setObject:obj forExtensionClass:[GDataAtomUpdatedDate class]];\n}\n\n- (NSNumber *)totalResults {\n  GDataValueElementConstruct *obj;\n\n  obj = [self objectForExtensionClass:[GDataOpenSearchTotalResults class]];\n  return [obj intNumberValue];\n}\n\n- (void)setTotalResults:(NSNumber *)num {\n  GDataValueElementConstruct *obj;\n\n  obj = [GDataOpenSearchTotalResults valueWithNumber:num];\n  [self setObject:obj forExtensionClass:[GDataOpenSearchTotalResults class]];\n}\n\n- (NSNumber *)startIndex {\n  GDataValueElementConstruct *obj;\n\n  obj = [self objectForExtensionClass:[GDataOpenSearchStartIndex class]];\n  return [obj intNumberValue];\n}\n\n- (void)setStartIndex:(NSNumber *)num {\n  GDataValueElementConstruct *obj;\n\n  obj = [GDataOpenSearchStartIndex valueWithNumber:num];\n  [self setObject:obj forExtensionClass:[GDataOpenSearchStartIndex class]];\n}\n\n- (NSNumber *)itemsPerPage {\n  GDataValueElementConstruct *obj;\n\n  obj = [self objectForExtensionClass:[GDataOpenSearchItemsPerPage class]];\n  return [obj intNumberValue];\n}\n\n- (void)setItemsPerPage:(NSNumber *)num {\n  GDataValueElementConstruct *obj;\n\n  obj = [GDataOpenSearchItemsPerPage valueWithNumber:num];\n  [self setObject:obj forExtensionClass:[GDataOpenSearchItemsPerPage class]];\n}\n\n- (NSString *)ETag {\n  NSString *str = [self attributeValueForExtensionClass:[GDataETagAttribute class]];\n  return str;\n}\n\n- (void)setETag:(NSString *)str {\n  [self setAttributeValue:str forExtensionClass:[GDataETagAttribute class]];\n}\n\n- (NSString *)fieldSelection {\n  NSString *str = [self attributeValueForExtensionClass:[GDataFieldsAttribute class]];\n  return str;\n}\n\n- (void)setFieldSelection:(NSString *)str {\n  [self setAttributeValue:str forExtensionClass:[GDataFieldsAttribute class]];\n}\n\n- (NSString *)kind {\n  NSString *str = [self attributeValueForExtensionClass:[GDataKindAttribute class]];\n  return str;\n}\n\n- (void)setKind:(NSString *)str {\n  [self setAttributeValue:str forExtensionClass:[GDataKindAttribute class]];\n}\n\n- (NSString *)resourceID {\n  GDataResourceID *obj = [self objectForExtensionClass:[GDataResourceID class]];\n  return [obj stringValue];\n}\n\n- (void)setResourceID:(NSString *)str {\n  GDataResourceID *obj = [GDataResourceID valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataResourceID class]];\n}\n\n- (NSArray *)entries {\n  return entries_;\n}\n\n// setEntries: and addEntry: expect the entries to have parents that are\n// nil or this feed instance; setEntriesWithEntries: and addEntryWithEntry:\n// make copies of the supplied entries\n\n- (void)setEntries:(NSArray *)entries {\n\n  [entries_ autorelease];\n  entries_ = [entries mutableCopy];\n\n  // step through the entries, ensure that none have other parents,\n  // make each have this feed as parent\n  for (GDataObject* entry in entries_) {\n#if !NS_BLOCK_ASSERTIONS\n    GDataObject *oldParent = [entry parent];\n    GDATA_ASSERT(oldParent == self || oldParent == nil,\n                 @\"Trying to replace existing feed parent; use setEntriesWithEntries: instead\");\n#endif\n    [entry setParent:self];\n  }\n}\n\n- (void)addEntry:(GDataEntryBase *)obj {\n\n  if (!entries_) {\n    entries_ = [[NSMutableArray alloc] init];\n  }\n\n  // ensure the entry doesn't have another parent\n#if !NS_BLOCK_ASSERTIONS\n  GDataObject *oldParent = [obj parent];\n  GDATA_ASSERT(oldParent == self || oldParent == nil,\n               @\"Trying to replace existing feed parent; use addEntryWithEntry: instead\");\n#endif\n\n  [obj setParent:self];\n  [entries_ addObject:obj];\n}\n\n- (void)setEntriesWithEntries:(NSArray *)entries {\n\n  // make an array containing copies of the entries with this feed\n  // as the parent of each entry copy\n  [entries_ autorelease];\n  entries_ = nil;\n\n  if (entries != nil) {\n    entries_ = [[NSMutableArray alloc] initWithCapacity:[entries count]];\n\n    for (GDataObject *entry in entries) {\n      GDataEntryBase *entryCopy = [[entry copy] autorelease]; // clears parent in copy\n      [entryCopy setParent:self];\n      [entries_ addObject:entryCopy];\n    }\n  }\n}\n\n- (void)addEntryWithEntry:(GDataEntryBase *)obj {\n\n  GDataEntryBase *entryCopy = [[obj copy] autorelease]; // clears parent in copy\n  [self addEntry:entryCopy];\n}\n\n// extensions for Atom publishing control\n\n- (GDataAtomPubControl *)atomPubControl {\n  return [self objectForExtensionClass:[GDataAtomPubControl class]];\n}\n\n- (void)setAtomPubControl:(GDataAtomPubControl *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomPubControl class]];\n}\n\n// extensions for batch support\n\n- (GDataBatchOperation *)batchOperation {\n  return [self objectForExtensionClass:[GDataBatchOperation class]];\n}\n\n- (void)setBatchOperation:(GDataBatchOperation *)obj {\n  [self setObject:obj forExtensionClass:[GDataBatchOperation class]];\n}\n\n// convenience routines\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel {\n\n  return [GDataLink linkWithRel:rel\n                           type:nil\n                      fromLinks:[self links]];\n}\n\n- (GDataLink *)feedLink {\n  return [self linkWithRelAttributeValue:kGDataLinkRelFeed];\n}\n\n- (GDataLink *)alternateLink {\n  return [self linkWithRelAttributeValue:@\"alternate\"];\n}\n\n- (GDataLink *)relatedLink {\n  return [self linkWithRelAttributeValue:@\"related\"];\n}\n\n- (GDataLink *)postLink {\n  return [self linkWithRelAttributeValue:kGDataLinkRelPost];\n}\n\n- (GDataLink *)uploadLink {\n  return [self linkWithRelAttributeValue:kGDataLinkRelResumableCreate];\n}\n\n- (GDataLink *)batchLink {\n  return [self linkWithRelAttributeValue:kGDataLinkRelBatch];\n}\n\n- (GDataLink *)selfLink {\n  return [self linkWithRelAttributeValue:@\"self\"];\n}\n\n- (GDataLink *)nextLink {\n  return [self linkWithRelAttributeValue:@\"next\"];\n}\n\n- (GDataLink *)previousLink {\n  return [self linkWithRelAttributeValue:@\"previous\"];\n}\n\n- (id)entryForIdentifier:(NSString *)str {\n\n  GDataEntryBase *desiredEntry;\n  desiredEntry = [GDataUtilities firstObjectFromArray:[self entries]\n                                            withValue:str\n                                           forKeyPath:@\"identifier\"];\n  return desiredEntry;\n}\n\n- (id)firstEntry {\n  return [self entryAtIndex:0];\n}\n\n- (id)entryAtIndex:(NSUInteger)idx {\n  NSArray *entries = [self entries];\n  if ([entries count] > idx) {\n    return [entries objectAtIndex:idx];\n  }\n  return nil;\n}\n\n- (NSArray *)entriesWithCategoryKind:(NSString *)term {\n\n  NSArray *kindEntries = [GDataUtilities objectsFromArray:[self entries]\n                                                withValue:term\n                                               forKeyPath:@\"kindCategory.term\"];\n  return kindEntries;\n}\n\n// NSFastEnumeration protocol\n- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state\n                                  objects:(id *)stackbuf\n                                    count:(NSUInteger)len {\n  NSUInteger result = [entries_ countByEnumeratingWithState:state\n                                                    objects:stackbuf\n                                                      count:len];\n  return result;\n}\n\n@end\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/BaseClasses/GDataObject.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataObject.h\n//\n\n// This is the base class for most objects in the Objective-C GData implementation.\n// Objects should derive from GDataObject in order to support XML parsing and\n// generation, and to support the extension model.\n\n// Subclasses will typically implement:\n//\n// - (void)addExtensionDeclarations;  -- declaring extensions\n// - (id)initWithXMLElement:(NSXMLElement *)element\n//                   parent:(GDataObject *)parent;  -- parsing\n// - (NSXMLElement *)XMLElement;  -- XML generation\n//\n// Subclasses should implement other typical NSObject methods, too:\n//\n// - (NSString *)description;\n// - (id)copyWithZone:(NSZone *)zone; (be sure to call superclass)\n// - (BOOL)isEqual:(GDataObject *)other; (be sure to call superclass)\n// - (void)dealloc;\n//\n// Subclasses which may be used as extensions should implement the\n// simple GDataExtension protocol.\n//\n\n//\n// Parsing and XML generation\n//\n// Parsing is done in the subclass's -initWithXMLElement:parent: method.\n//\n// For each parsed GData XML element, GDataObject maintains lists of\n// un-parsed attributes and children (unknownChildren_ and unknownAttributes_)\n// as raw NSXMLNodes.  Subclasses MUST use the methods in this class's\n// \"parsing helpers\" (below) to extract properties and elements during parsing;\n// this ensures that the lists of unknown properties and children are\n// accurate.  DO NOT parse using NSXMLElement methods.\n//\n// XML generation is done in the subclass's -XMLElement method.\n// That method will call XMLElementWithExtensionsAndDefaultName to get\n// a \"starter\" NSXMLElement, already decorated with extensions, to which\n// the subclass can add its unique children and attributes, if any.\n//\n//\n//\n// The extension model\n//\n// Extensions enable elements to contain children about which the element\n// may know no details.\n//\n// Typically, entries add extensions to themselves. For example, a Calendar\n// entry declares it may contain a color:\n//\n//  [self addExtensionDeclarationForParentClass:[GDataEntryCalendar class]\n//                                   childClass:[GDataColorProperty class]];\n//\n// This lets the base class handle much of the work of managing the child\n// element.  The Calendar entry can still provide accessor methods to get\n// to the extension by calling into the base class, as in\n//\n//  - (GDataColorProperty *)color {\n//    return (GDataColorProperty *)\n//               [self objectForExtensionClass:[GDataColorProperty class]];\n//  }\n//\n//  - (void)setColor:(GDataColorProperty *)val {\n//    [self setObject:val forExtensionClass:[GDataColorProperty class]];\n//  }\n//\n// The real purpose of extensions is to allow elements to contain children\n// they may not know about.  For example, a CalendarEventEntry declares\n// that GDataLinks contained within the calendar event entry may contain\n// GDataWebContent elements:\n//\n//  [self addExtensionDeclarationForParentClass:[GDataLink class]\n//                                   childClass:[GDataWebContent class]];\n//\n// The CalendarEvent has extended GDataLinks without GDataLinks knowing or\n// caring.  Because GDataLink derives from GDataObject, the GDataLink\n// object will automatically parse and maintain and copy and compare\n// the GDataWebContents contained within.\n//\n\n\n#import <Foundation/Foundation.h>\n\n#import \"GDataDefines.h\"\n#import \"GDataUtilities.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAOBJECT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataNamespaceAtom          _INITIALIZE_AS(@\"http://www.w3.org/2005/Atom\");\n_EXTERN NSString* const kGDataNamespaceAtomPrefix    _INITIALIZE_AS(@\"atom\");\n\n_EXTERN NSString* const kGDataNamespaceAtomPub       _INITIALIZE_AS(@\"http://www.w3.org/2007/app\");\n_EXTERN NSString* const kGDataNamespaceAtomPubPrefix _INITIALIZE_AS(@\"app\");\n\n_EXTERN NSString* const kGDataNamespaceOpenSearch       _INITIALIZE_AS(@\"http://a9.com/-/spec/opensearch/1.1/\");\n_EXTERN NSString* const kGDataNamespaceOpenSearchPrefix _INITIALIZE_AS(@\"openSearch\");\n\n_EXTERN NSString* const kGDataNamespaceXHTML       _INITIALIZE_AS(@\"http://www.w3.org/1999/xhtml\");\n_EXTERN NSString* const kGDataNamespaceXHTMLPrefix _INITIALIZE_AS(@\"xh\");\n\n_EXTERN NSString* const kGDataNamespaceGData       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005\");\n_EXTERN NSString* const kGDataNamespaceGDataPrefix _INITIALIZE_AS(@\"gd\");\n\n_EXTERN NSString* const kGDataNamespaceBatch       _INITIALIZE_AS(@\"http://schemas.google.com/gdata/batch\");\n_EXTERN NSString* const kGDataNamespaceBatchPrefix _INITIALIZE_AS(@\"batch\");\n\n#define GDATA_DEBUG_ASSERT_MIN_SERVICE_VERSION(versionString) \\\n  GDATA_DEBUG_ASSERT([self isServiceVersionAtLeast:versionString], \\\n    @\"%@ requires newer version\", NSStringFromSelector(_cmd))\n\n#define GDATA_DEBUG_ASSERT_MAX_SERVICE_VERSION(versionString) \\\n  GDATA_DEBUG_ASSERT([self isServiceVersionAtMost:versionString], \\\n    @\"%@ deprecated under v%@\", NSStringFromSelector(_cmd), [self serviceVersion])\n\n#define GDATA_DEBUG_ASSERT_MIN_SERVICE_V2() \\\n  GDATA_DEBUG_ASSERT_MIN_SERVICE_VERSION(@\"2.0\")\n\n@class GDataDateTime;\n@class GDataCategory;\n\n@protocol GDataExtension\n+ (NSString *)extensionElementURI;\n+ (NSString *)extensionElementPrefix;\n+ (NSString *)extensionElementLocalName;\n@end\n\n// GDataAttribute is the base class for attribute extensions.\n// It is *not* used for local attributes, which are simply stored in\n// GDataObject' attributes_ dictionary.\n//\n// This returns nil for the attribute's URI and prefix qualifier;\n// subclasses must declare at least a local name.\n//\n// Functionally, this just stores a string value for the attribute.\n\n@interface GDataAttribute : NSObject {\n @private\n    NSString *value_;\n}\n+ (GDataAttribute *)attributeWithValue:(NSString *)str;\n- (id)initWithValue:(NSString *)value;\n\n- (void)setStringValue:(NSString *)str;\n- (NSString *)stringValue;\n@end\n\n// GDataDescriptionRecords are used for describing how the elements\n// and attributes of a GDataObject should be reported when -description\n// is called.\n\ntypedef enum GDataDescRecTypes {\n  kGDataDescValueLabeled = 1,\n  kGDataDescLabelIfNonNil,\n  kGDataDescArrayCount,\n  kGDataDescArrayDescs,\n  kGDataDescBooleanLabeled,\n  kGDataDescBooleanPresent,\n  kGDataDescNonZeroLength,\n  kGDataDescValueIsKeyPath\n} GDataDescRecTypes;\n\ntypedef struct GDataDescriptionRecord {\n  NSString *label;\n  NSString *keyPath;\n  GDataDescRecTypes reportType;\n} GDataDescriptionRecord;\n\n\n@interface GDataObject : NSObject <NSCopying> {\n\n  @private\n\n  // element name from original XML, used for later XML generation\n  NSString *elementName_;\n\n  __weak GDataObject *parent_;  // parent in tree of GData objects\n\n  // GDataObjects keep namespaces as {key:prefix value:URI} dictionary entries\n  NSMutableDictionary *namespaces_;\n\n  // extension declaration cache, retained by the topmost parent\n  //\n  // keys are classes that have declared their extensions\n  //\n  // the values are dictionaries mapping declared parent classes to\n  // GDataExtensionDeclarations objects\n  NSMutableDictionary *extensionDeclarationsCache_;\n\n  // list of attributes to be parsed for each class\n  NSMutableDictionary *attributeDeclarationsCache_;\n\n  // list of attributes to be parsed for this class (points strongly into the\n  // attribute declarations cache)\n  NSMutableArray *attributeDeclarations_;\n\n  // arrays of actual extension elements found for this element, keyed by extension class\n  NSMutableDictionary *extensions_;\n\n  // dictionary of attributes set for this element, keyed by attribute name\n  NSMutableDictionary *attributes_;\n\n  // string for element body, if declared as parseable\n  NSString *contentValue_;\n\n  // XMLElements saved from element body but not parsed, if declared by the subclass\n  NSMutableArray *childXMLElements_;\n\n  // arrays of XMLNodes of attributes and child elements not yet parsed\n  NSMutableArray *unknownChildren_;\n  NSMutableArray *unknownAttributes_;\n  BOOL shouldIgnoreUnknowns_;\n\n  // mapping of standard classes to user's surrogate subclasses, used when\n  // creating objects from XML\n  NSDictionary *surrogates_;\n\n  // service version, set for feeds and entries\n  NSString *serviceVersion_;\n\n  // core protocol version, set from the service version when\n  // -coreProtocolVersion is invoked\n  NSString *coreProtocolVersion_;\n\n  // anything defined by the client; retained but not used internally; not\n  // copied by copyWithZone:\n  id userData_;\n  NSMutableDictionary *userProperties_;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n//\n// Public methods\n//\n// These methods are intended for users of the library\n//\n\n+ (id)object;\n\n- (id)copyWithZone:(NSZone *)zone;\n\n- (id)initWithServiceVersion:(NSString *)serviceVersion;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent; // subclasses must override\n- (NSXMLElement *)XMLElement; // subclasses must override\n\n- (NSXMLDocument *)XMLDocument; // returns this XMLElement wrapped in an NSXMLDocument\n\n// setters/getters\n\n// namespaces here are a dictionary mapping prefix to URI; they are not\n// NSXML namespace objects\n- (void)setNamespaces:(NSDictionary *)namespaces;\n- (void)addNamespaces:(NSDictionary *)namespaces;\n- (NSDictionary *)namespaces;\n\n// return a dictionary containing all namespaces\n// in this object and its parent objects\n- (NSDictionary *)completeNamespaces;\n\n// if a prefix is explicitly defined the same for a parent as it is locally,\n// remove it, since we can rely on the parent's definition\n- (void)pruneInheritedNamespaces;\n\n// name from original XML; this will be used during XML generation\n- (void)setElementName:(NSString *)elementName;\n- (NSString *)elementName;\n\n// parent in object tree (weak reference)\n- (void)setParent:(GDataObject *)obj;\n- (GDataObject *)parent;\n\n// surrogate lists for when alloc'ing classes from XML\n- (void)setSurrogates:(NSDictionary *)surrogates;\n- (NSDictionary *)surrogates;\n\n// service API version\n+ (NSString *)defaultServiceVersion;\n\n// a side-effect of setServiceVersion: is that the coreProtocolVersion is\n// reset\n- (void)setServiceVersion:(NSString *)str;\n- (NSString *)serviceVersion;\n\n- (BOOL)isServiceVersionAtLeast:(NSString *)otherVersion;\n- (BOOL)isServiceVersionAtMost:(NSString *)otherVersion;\n\n// calling -coreProtocolVersion sets the initial core protocol version based\n// on the service version\n- (NSString *)coreProtocolVersion;\n- (void)setCoreProtocolVersion:(NSString *)str;\n- (BOOL)isCoreProtocolVersion1;\n\n// userData is available for client use; retained by GDataObject, but not\n// copied by the copyWithZone\n- (void)setUserData:(id)obj;\n- (id)userData;\n\n// properties are supported for client convenience, but are not copied by\n// copyWithZone.  Properties keys beginning with _ are reserved by the library.\n- (void)setProperties:(NSDictionary *)dict;\n- (NSDictionary *)properties;\n\n- (void)setProperty:(id)obj forKey:(NSString *)key; // pass nil obj to remove property\n- (id)propertyForKey:(NSString *)key;\n\n// XMLNode children not parsed; primarily for internal use by the framework\n- (void)setUnknownChildren:(NSArray *)arr;\n- (NSArray *)unknownChildren;\n\n// XMLNode attributes not parsed; primarily for internal use by the framework\n- (void)setUnknownAttributes:(NSArray *)arr;\n- (NSArray *)unknownAttributes;\n\n// feeds and their elements may exclude tracking of unknown child elements\n// and unknown attributes; see GDataServiceBase for more information\n- (void)setShouldIgnoreUnknowns:(BOOL)flag;\n- (BOOL)shouldIgnoreUnknowns;\n\n///////////////////////////////////////////////////////////////////////////////\n//\n//  Protected methods\n//\n//  All remaining methods are intended for use only by subclasses\n//  of GDataObject.\n//\n\n// this init method should  be used only when creating the base of a tree\n// containing surrogates (the surrogate map is a dictionary of\n// standard GDataObject classes to replacement subclasses); this method\n// calls through to [self initWithXMLElement:parent:]\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent\n          serviceVersion:(NSString *)serviceVersion\n              surrogates:(NSDictionary *)surrogates\n    shouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns;\n\n- (void)addExtensionDeclarations; // subclasses may override this to declare extensions\n\n- (void)addParseDeclarations; // subclasses may override this to declare local attributes and content value\n\n- (void)clearExtensionDeclarationsCache; // used by GDataServiceBase and by subclasses\n\n// content stream and upload data: these always return NO/nil for objects\n// other than entries\n\n- (BOOL)generateContentInputStream:(NSInputStream **)outInputStream\n                            length:(unsigned long long *)outLength\n                           headers:(NSDictionary **)outHeaders;\n\n- (NSString *)uploadMIMEType;\n- (NSData *)uploadData;\n- (NSFileHandle *)uploadFileHandle;\n- (NSURL *)uploadLocationURL;\n- (BOOL)shouldUploadDataOnly;\n\n//\n// Extensions\n//\n\n// declaring a potential extension; applies to this object and its children\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                   childClass:(Class)childClass;\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                 childClasses:(Class)firstChildClass, ...;\n\n- (void)removeExtensionDeclarationForParentClass:(Class)parentClass\n                                      childClass:(Class)childClass;\n\n- (void)addAttributeExtensionDeclarationForParentClass:(Class)parentClass\n                                            childClass:(Class)childClass;\n- (void)removeAttributeExtensionDeclarationForParentClass:(Class)parentClass\n                                               childClass:(Class)childClass;\n\n// accessing actual extensions in this object\n- (NSArray *)objectsForExtensionClass:(Class)theClass;\n- (id)objectForExtensionClass:(Class)theClass;\n\n- (NSString *)attributeValueForExtensionClass:(Class)theClass;\n\n// replacing or adding actual extensions in this object\n- (void)setObjects:(NSArray *)objects forExtensionClass:(Class)theClass;\n- (void)setObject:(id)object forExtensionClass:(Class)theClass; // removes all previous objects for this class\n- (void)addObject:(id)object forExtensionClass:(Class)theClass;\n- (void)removeObject:(id)object forExtensionClass:(Class)theClass;\n\n- (void)setAttributeValue:(NSString *)str forExtensionClass:(Class)theClass;\n\n//\n// Local attributes\n//\n\n// derived classes may override parseAttributesForElement if they need to\n// inspect attributes prior to parsing of element content\n- (void)parseAttributesForElement:(NSXMLElement *)element;\n\n// derived classes should call -addLocalAttributeDeclarations in their\n// -addParseDeclarations method if they want element attributes to\n// automatically be parsed\n- (void)addLocalAttributeDeclarations:(NSArray *)attributeLocalNames;\n\n- (NSString *)stringValueForAttribute:(NSString *)name;\n- (NSNumber *)intNumberForAttribute:(NSString *)name;\n- (NSNumber *)doubleNumberForAttribute:(NSString *)name;\n- (NSNumber *)longLongNumberForAttribute:(NSString *)name;\n- (NSDecimalNumber *)decimalNumberForAttribute:(NSString *)name;\n- (GDataDateTime *)dateTimeForAttribute:(NSString *)name;\n- (BOOL)boolValueForAttribute:(NSString *)name defaultValue:(BOOL)defaultVal;\n\n// setting nil value for attribute removes it\n- (void)setStringValue:(NSString *)str forAttribute:(NSString *)name;\n- (void)setBoolValue:(BOOL)flag defaultValue:(BOOL)defaultVal forAttribute:(NSString *)name;\n- (void)setExplicitBoolValue:(BOOL)flag forAttribute:(NSString *)name;\n- (void)setDecimalNumberValue:(NSDecimalNumber *)num forAttribute:(NSString *)name;\n- (void)setDateTimeValue:(GDataDateTime *)cdate forAttribute:(NSString *)name;\n\n// dictionary of all local attributes actually found in the XML element\n- (void)setAttributes:(NSDictionary *)dict;\n- (NSDictionary *)attributes;\n\n\n//\n// Element Content Value\n//\n\n// derived classes should call -addContentValueDeclaration in their\n// -addParseDeclarations method if they want element content to\n// automatically be parsed as a string\n- (void)addContentValueDeclaration;\n- (BOOL)hasDeclaredContentValue;\n- (void)setContentStringValue:(NSString *)str;\n- (NSString *)contentStringValue;\n\n//\n// Unparsed XML child elements\n//\n\n// derived classes should call -addXMLValuesDeclaration in their\n// -addParseDeclarations method if they want all child elements to\n// be held as an array of NSXMLElements\n- (void)addChildXMLElementsDeclaration;\n- (BOOL)hasDeclaredChildXMLElements;\n- (NSArray *)childXMLElements;\n- (void)setChildXMLElements:(NSArray *)array;\n- (void)addChildXMLElement:(NSXMLNode *)node;\n\n\n//\n// Dynamic GDataObject generation\n//\n// Feeds and entries can register themselves in their + (void)load\n// methods.  When XML is being parsed, if a matching category\n// is found, the proper class is instantiated.\n//\n// The scheme or term in a category may be nil (during\n// registration and lookup) to match any values.\n\n// class registration method\n+ (void)registerClass:(Class)theClass\n                inMap:(NSMutableDictionary **)map\nforCategoryWithScheme:(NSString *)scheme\n                 term:(NSString *)term;\n\n+ (Class)classForCategoryWithScheme:(NSString *)scheme\n                               term:(NSString *)term\n                            fromMap:(NSDictionary *)map;\n\n// objectClassForXMLElement: returns a found registered feed\n// or entry class for the XML according to its contained category\n//\n// If no registered class is found with a matching category,\n// this returns GDataFeedBase for feed elements, GDataEntryBase\n// for entry elements.\n//\n// If the element is not a <feed> or <entry> then nil is returned\n+ (Class)objectClassForXMLElement:(NSXMLElement *)element;\n\n//\n// XML parsing helpers (used in initWithXMLElement:parent:)\n//\n// Use these parsing helpers, since they remove the parsed items from the\n// \"unknown children\" list for this object.\n//\n\n// this creates a single object of the specified class for the first XML child\n// element with the specified name. Returns nil if no child element is present.\n- (id)objectForChildOfElement:(NSXMLElement *)parentElement\n                qualifiedName:(NSString *)qualifiedName\n                 namespaceURI:(NSString *)namespaceURI\n                  objectClass:(Class)objectClass;\n\n// this creates an array of objects of the specified class for each XML child\n// element with the specified name\n- (id)objectOrArrayForChildrenOfElement:(NSXMLElement *)parentElement\n                          qualifiedName:(NSString *)qualifiedName\n                           namespaceURI:(NSString *)namespaceURI\n                            objectClass:(Class)objectClass;\n\n// childOfElement:withName returns the element with the name, or nil of there\n// are not exactly one of the element\n- (NSXMLElement *)childWithQualifiedName:(NSString *)localName\n                            namespaceURI:(NSString *)namespaceURI\n                             fromElement:(NSXMLElement *)parentElement;\n\n// searches up the parent tree to find a surrogate for the standard class;\n// if there is  no surrogate, returns the standard class itself\n- (Class)classOrSurrogateForClass:(Class)standardClass;\n\n// element parsing\n\n+ (NSDictionary *)dictionaryForElementNamespaces:(NSXMLElement *)element;\n\n// this method avoids the \"recursive descent\" behavior of NSXMLElement's\n// stringValue; the element parameter may be nil\n- (NSString *)stringValueFromElement:(NSXMLElement *)element;\n\n- (GDataDateTime *)dateTimeFromElement:(NSXMLElement *)element;\n\n- (NSNumber *)intNumberValueFromElement:(NSXMLElement *)element;\n\n- (NSNumber *)doubleNumberValueFromElement:(NSXMLElement *)element;\n\n// attribute parsing\n- (NSString *)stringForAttributeName:(NSString *)attributeName\n                         fromElement:(NSXMLElement *)element;\n\n- (NSString *)stringForAttributeLocalName:(NSString *)localName\n                                      URI:(NSString *)attributeURI\n                              fromElement:(NSXMLElement *)element;\n\n- (GDataDateTime *)dateTimeForAttributeName:(NSString *)attributeName\n                                fromElement:(NSXMLElement *)element;\n\n- (NSXMLNode *)attributeForName:(NSString *)attributeName\n                    fromElement:(NSXMLElement *)element;\n\n- (BOOL)boolForAttributeName:(NSString *)attributeName\n                 fromElement:(NSXMLElement *)element;\n\n- (NSNumber *)doubleNumberForAttributeName:(NSString *)attributeName\n                               fromElement:(NSXMLElement *)element;\n\n- (NSNumber *)intNumberForAttributeName:(NSString *)attributeName\n                            fromElement:(NSXMLElement *)element;\n\n\n//\n// XML generation helpers\n//\n\n// subclasses start their -XMLElement method by calling this\n- (NSXMLElement *)XMLElementWithExtensionsAndDefaultName:(NSString *)defaultName;\n\n// adding attributes\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n     attributeValueIfNonNil:(NSString *)val\n                   withName:(NSString *)name;\n\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n     attributeValueIfNonNil:(NSString *)val\n          withQualifiedName:(NSString *)qName\n                        URI:(NSString *)attributeURI;\n\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n  attributeValueWithInteger:(NSInteger)val\n                   withName:(NSString *)name;\n\n// adding child elements\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\nchildWithStringValueIfNonEmpty:(NSString *)str\n                   withName:(NSString *)name;\n\n- (void)addToElement:(NSXMLElement *)element\n XMLElementForObject:(id)object;\n\n- (void)addToElement:(NSXMLElement *)element\n XMLElementsForArray:(NSArray *)arrayOfGDataObjects;\n\n//\n// decription method helpers\n//\n\n// the final descRecord in the list should be { nil, nil, 0 }\n- (void)addDescriptionRecords:(GDataDescriptionRecord *)descRecordList\n                      toItems:(NSMutableArray *)items;\n\n- (void)addToArray:(NSMutableArray *)stringItems\nobjectDescriptionIfNonNil:(id)obj\n          withName:(NSString *)name;\n\n- (void)addAttributeDescriptionsToArray:(NSMutableArray *)stringItems;\n\n- (void)addContentDescriptionToArray:(NSMutableArray *)stringItems\n                            withName:(NSString *)name;\n\n// optional methods for overriding\n//\n// subclasses may implement -itemsForDescription and add to or\n// replace the superclass's array of items\n//\n// The base class itemsForDescription provides items for local attributes and\n// content, but not for any element extensions or attribute extensions\n- (NSMutableArray *)itemsForDescription;\n- (NSString *)descriptionWithItems:(NSArray *)items;\n- (NSString *)description;\n\n// coreProtocolVersionForServiceVersion maps the service version to the\n// underlying core protocol version.  The default implementation returns\n// the service version as the core protocol version.\n//\n// Entry and feed subclasses will need to implement this if their service\n// version numbers deviate from the core protocol version numbers.\n+ (NSString *)coreProtocolVersionForServiceVersion:(NSString *)str;\n\n@end\n\n@interface NSXMLElement (GDataObjectExtensions)\n\n// XML generation helpers\n\n// NSXMLNode's setStringValue: wipes out other children, so we'll use this\n// instead\n- (void)addStringValue:(NSString *)str;\n\n// creating objects from child elements\n+ (id)elementWithName:(NSString *)name attributeName:(NSString *)attrName attributeValue:(NSString *)attrValue;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/BaseClasses/GDataObject.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataObject.m\n//\n\n#define GDATAOBJECT_DEFINE_GLOBALS 1\n\n#import \"GDataObject.h\"\n#import \"GDataDateTime.h\"\n\n// for automatic-determination of feed and entry class types\n#import \"GDataFeedBase.h\"\n#import \"GDataEntryBase.h\"\n#import \"GDataCategory.h\"\n\nstatic inline NSMutableDictionary *GDataCreateStaticDictionary(void) {\n  NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];\n#if !GDATA_IPHONE\n  Class cls = NSClassFromString(@\"NSGarbageCollector\");\n  if (cls) {\n    id collector = [cls performSelector:@selector(defaultCollector)];\n    [collector performSelector:@selector(disableCollectorForPointer:)\n                    withObject:dict];\n  }\n#endif\n  return dict;\n}\n\n// in a cache of attribute declarations, this marker indicates that the class\n// also declared that it wants child text parsed as the content value or child\n// xml held as xml element objects\n//\n// these start with a space to avoid colliding with any real attribute name\nstatic NSString* const kContentValueDeclarationMarker = @\" __content\";\nstatic NSString* const kChildXMLDeclarationMarker = @\" __childXML\";\n\n// Elements may call -addExtensionDeclarationForParentClass:childClass: and\n// addAttributeExtensionDeclarationForParentClass: to declare extensions to be\n// parsed; the declaration applies in the element and all children of the element.\n@interface GDataExtensionDeclaration : NSObject {\n  Class parentClass_;\n  Class childClass_;\n  BOOL isAttribute_;\n}\n- (id)initWithParentClass:(Class)parentClass childClass:(Class)childClass isAttribute:(BOOL)attrFlag;\n- (Class)parentClass;\n- (Class)childClass;\n- (BOOL)isAttribute;\n@end\n\n@interface GDataObject (PrivateMethods)\n\n// array of local attribute names to be automatically parsed and\n// generated\n- (void)setAttributeDeclarationsCache:(NSDictionary *)decls;\n- (NSMutableDictionary *)attributeDeclarationsCache;\n\n// array of attribute declarations for the current class, from the cache\n- (void)setAttributeDeclarations:(NSArray *)array;\n- (NSMutableArray *)attributeDeclarations;\n\n- (void)parseAttributesForElement:(NSXMLElement *)element;\n- (void)addAttributesToElement:(NSXMLElement *)element;\n\n// routines for comparing attributes\n- (BOOL)hasAttributesEqualToAttributesOf:(GDataObject *)other;\n- (NSArray *)attributesIgnoredForEquality;\n\n// element string content\n- (void)parseContentValueForElement:(NSXMLElement *)element;\n- (void)addContentValueToElement:(NSXMLElement *)element;\n\n- (BOOL)hasContentValueEqualToContentValueOf:(GDataObject *)other;\n\n// XML values content (kept unparsed)\n- (void)keepChildXMLElementsForElement:(NSXMLElement *)element;\n- (void)addChildXMLElementsToElement:(NSXMLElement *)element;\n\n- (BOOL)hasChildXMLElementsEqualToChildXMLElementsOf:(GDataObject *)other;\n\n// dictionary of all extensions actually found in the XML element\n- (void)setExtensions:(NSDictionary *)extensions;\n- (NSDictionary *)extensions;\n\n// cache of arrays of extensions that may be found in this class and in\n// subclasses of this class.\n- (void)setExtensionDeclarationsCache:(NSDictionary *)decls;\n- (NSMutableDictionary *)extensionDeclarationsCache;\n\n- (NSMutableArray *)extensionDeclarationsForParentClass:(Class)parentClass;\n\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                   childClass:(Class)childClass\n                                  isAttribute:(BOOL)isAttribute;\n\n- (void)addUnknownChildNodesForElement:(NSXMLElement *)element;\n\n- (void)parseExtensionsForElement:(NSXMLElement *)element;\n\n- (void)handleParsedElement:(NSXMLNode *)element;\n- (void)handleParsedElements:(NSArray *)array;\n\n- (NSString *)qualifiedNameForExtensionClass:(Class)theClass;\n\n+ (Class)classForCategoryWithScheme:(NSString *)scheme\n                               term:(NSString *)term\n                            fromMap:(NSDictionary *)map;\n@end\n\n@implementation GDataObject\n\n// The qualified name map avoids the need to regenerate qualified\n// element names (foo:bar) repeatedly\nstatic NSMutableDictionary *gQualifiedNameMap = nil;\n\n+ (void)load {\n  // Initialize gQualifiedNameMap early so we can @synchronize on accesses\n  // to it\n  gQualifiedNameMap = GDataCreateStaticDictionary();\n}\n\n+ (id)object {\n  return [[[self alloc] init] autorelease];\n}\n\n- (id)init {\n  self = [super init];\n  if (self) {\n    // there is no parent\n    extensionDeclarationsCache_ = [[NSMutableDictionary alloc] init];\n\n    attributeDeclarationsCache_ = [[NSMutableDictionary alloc] init];\n\n    [self addParseDeclarations];\n  }\n  return self;\n}\n\n// intended mainly for testing, initWithServiceVersion allows the service\n// version to be set prior to declaring extensions; this is useful\n// for overriding the default service version for the class when\n// manually allocating a copy of the object\n- (id)initWithServiceVersion:(NSString *)serviceVersion {\n  [self setServiceVersion:serviceVersion];\n  return [self init];\n}\n\n// this init routine is only used when passing in a top-level surrogates\n// dictionary\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent\n          serviceVersion:(NSString *)serviceVersion\n              surrogates:(NSDictionary *)surrogates\n    shouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns {\n\n  [self setServiceVersion:serviceVersion];\n\n  [self setSurrogates:surrogates];\n\n  [self setShouldIgnoreUnknowns:shouldIgnoreUnknowns];\n\n  id obj = [self initWithXMLElement:element\n                             parent:parent];\n  return obj;\n}\n\n// subclasses will typically override initWithXMLElement:parent:\n// and do their own parsing after this method returns\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent {\n  self = [super init];\n  if (self) {\n    [self setParent:parent];\n\n    if (parent != nil) {\n      // top-level objects (feeds and entries) have nil parents, and\n      // have their service version set previously in\n      // initWithXMLElement:parent:serviceVersion:surrogates:; child\n      // objects have their service version set here\n      [self setServiceVersion:[parent serviceVersion]];\n\n      // feeds may specify that contained entries and their child elements\n      // should ignore any unparsed XML\n      [self setShouldIgnoreUnknowns:[parent shouldIgnoreUnknowns]];\n\n      // get the parent's declaration caches, and temporarily hang on to them\n      // in our ivar to avoid the need to get them recursively from the topmost\n      // parent\n      //\n      // We'll release these below, so that only the topmost parent retains\n      // them. The topmost parent retains them in case some subclass code still\n      // wants to do parsing after we return.\n      extensionDeclarationsCache_ = [[parent extensionDeclarationsCache] retain];\n      GDATA_DEBUG_ASSERT(extensionDeclarationsCache_ != nil, @\"missing extn decl\");\n\n      attributeDeclarationsCache_ = [[parent attributeDeclarationsCache] retain];\n      GDATA_DEBUG_ASSERT(extensionDeclarationsCache_ != nil, @\"missing attr decl\");\n\n    } else {\n      // parent is nil, so this is the topmost parent\n      extensionDeclarationsCache_ = [[NSMutableDictionary alloc] init];\n\n      attributeDeclarationsCache_ = [[NSMutableDictionary alloc] init];\n    }\n\n    [self setNamespaces:[[self class] dictionaryForElementNamespaces:element]];\n    [self addUnknownChildNodesForElement:element];\n\n    // if we've not previously cached declarations for this class,\n    // add the declarations now\n    Class currClass = [self class];\n    NSDictionary *prevExtnDecls = [extensionDeclarationsCache_ objectForKey:currClass];\n    if (prevExtnDecls == nil) {\n      [self addExtensionDeclarations];\n    }\n\n    NSMutableArray *prevAttrDecls = [attributeDeclarationsCache_ objectForKey:currClass];\n    if (prevAttrDecls == nil) {\n      [self addParseDeclarations];\n      // if any parse declarations are added, attributeDeclarations_ will be set\n      // to the cached copy of this object's attribute decls\n    } else {\n      GDATA_DEBUG_ASSERT(attributeDeclarations_ == nil, @\"attrDecls previously set\");\n      attributeDeclarations_ = [prevAttrDecls retain];\n    }\n\n    [self parseExtensionsForElement:element];\n    [self parseAttributesForElement:element];\n    [self parseContentValueForElement:element];\n    [self keepChildXMLElementsForElement:element];\n    [self setElementName:[element name]];\n\n    if (parent != nil) {\n      // rather than keep a reference to the cache of declarations in the\n      // parent, set our pointer to nil; if a subclass continues to parse, the\n      // getter will obtain them by calling into the parent.  This lets callers\n      // free up the extensionDeclarations_ when parsing is done by just\n      // freeing them in the topmost parent with clearExtensionDeclarationsCache\n      [extensionDeclarationsCache_ release];\n      extensionDeclarationsCache_ = nil;\n\n      [attributeDeclarationsCache_ release];\n      attributeDeclarationsCache_ = nil;\n    }\n\n#if GDATA_USES_LIBXML\n    if (!shouldIgnoreUnknowns_) {\n      // retain the element so that pointers to internal nodes remain valid\n      [self setProperty:element forKey:kGDataXMLElementPropertyKey];\n    }\n#endif\n  }\n  return self;\n}\n\n- (BOOL)isEqual:(GDataObject *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[self class]]) return NO;\n\n  // We used to compare the local names of the objects with\n  // NSXMLNode's localNameForName: on each object's elementName, but that\n  // prevents us from comparing the contents of a manually-constructed object\n  // (which lacks a specific local name) with one found in an actual XML feed.\n\n#if GDATA_USES_LIBXML\n  // libxml adds namespaces when copying elements, so we can't rely\n  // on those when comparing nodes\n  return AreEqualOrBothNil([self extensions], [other extensions])\n    && [self hasAttributesEqualToAttributesOf:other]\n    && [self hasContentValueEqualToContentValueOf:other]\n    && [self hasChildXMLElementsEqualToChildXMLElementsOf:other];\n#else\n  return AreEqualOrBothNil([self extensions], [other extensions])\n    && [self hasAttributesEqualToAttributesOf:other]\n    && [self hasContentValueEqualToContentValueOf:other]\n    && [self hasChildXMLElementsEqualToChildXMLElementsOf:other]\n    && AreEqualOrBothNil([self namespaces], [other namespaces]);\n#endif\n\n  // What we're not comparing here:\n  //   parent object pointers\n  //   extension declarations\n  //   unknown attributes & children\n  //   local element names\n  //   service version\n  //   userData\n}\n\n// By definition, for two objects to potentially be considered equal,\n// they must have the same hash value.  The hash is mostly ignored,\n// but removeObjectsInArray: in Leopard does seem to check the hash,\n// and NSObject's default hash method just returns the instance pointer.\n// We'll define hash here for all of our GDataObjects.\n- (NSUInteger)hash {\n  return (NSUInteger) (void *) [GDataObject class];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataObject* newObject = [[[self class] allocWithZone:zone] init];\n  [newObject setElementName:[self elementName]];\n  [newObject setParent:nil];\n  [newObject setServiceVersion:[self serviceVersion]];\n\n  NSDictionary *namespaces =\n    [GDataUtilities mutableDictionaryWithCopiesOfObjectsInDictionary:[self namespaces]];\n  [newObject setNamespaces:namespaces];\n\n  NSDictionary *extensions =\n    [GDataUtilities mutableDictionaryWithCopiesOfArraysInDictionary:[self extensions]];\n  [newObject setExtensions:extensions];\n\n  NSDictionary *attributes =\n    [GDataUtilities mutableDictionaryWithCopiesOfObjectsInDictionary:[self attributes]];\n  [newObject setAttributes:attributes];\n\n  [newObject setAttributeDeclarations:[self attributeDeclarations]];\n  // we copy the attribute declarations, which are retained by this object,\n  // but we do not copy not the caches of extension or attribute declarations,\n  // as those will be invalid once the top parent is released\n\n  // a marker in the attributes cache indicates the content value and\n  // and child XML declaration settings\n  if ([self hasDeclaredContentValue]) {\n    [newObject setContentStringValue:[self contentStringValue]];\n  }\n\n  if ([self hasDeclaredChildXMLElements]) {\n    NSArray *childElements = [self childXMLElements];\n    NSArray *arr = [GDataUtilities arrayWithCopiesOfObjectsInArray:childElements];\n    [newObject setChildXMLElements:arr];\n  }\n\n  BOOL shouldIgnoreUnknowns = [self shouldIgnoreUnknowns];\n  [newObject setShouldIgnoreUnknowns:shouldIgnoreUnknowns];\n\n  if (!shouldIgnoreUnknowns) {\n    NSArray *unknownChildren =\n      [GDataUtilities mutableArrayWithCopiesOfObjectsInArray:[self unknownChildren]];\n    [newObject setUnknownChildren:unknownChildren];\n\n    NSArray *unknownAttributes =\n      [GDataUtilities mutableArrayWithCopiesOfObjectsInArray:[self unknownAttributes]];\n    [newObject setUnknownAttributes:unknownAttributes];\n  }\n\n  return newObject;\n\n  // What we're not copying:\n  //   parent object pointer\n  //   surrogates\n  //   userData\n  //   userProperties\n}\n\n- (void)dealloc {\n  [elementName_ release];\n  [namespaces_ release];\n  [extensionDeclarationsCache_ release];\n  [attributeDeclarationsCache_ release];\n  [attributeDeclarations_ release];\n  [extensions_ release];\n  [attributes_ release];\n  [contentValue_ release];\n  [childXMLElements_ release];\n  [unknownChildren_ release];\n  [unknownAttributes_ release];\n  [surrogates_ release];\n  [serviceVersion_ release];\n  [coreProtocolVersion_ release];\n  [userData_ release];\n  [userProperties_ release];\n  [super dealloc];\n}\n\n// XMLElement must be implemented by subclasses\n- (NSXMLElement *)XMLElement {\n  // subclass should override if they have custom elements or attributes\n  NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:nil];\n  return element;\n}\n\n- (NSXMLDocument *)XMLDocument {\n  NSXMLElement *element = [self XMLElement];\n  NSXMLDocument *doc = [[[NSXMLDocument alloc] initWithRootElement:(id)element] autorelease];\n  [doc setVersion:@\"1.0\"];\n  [doc setCharacterEncoding:@\"UTF-8\"];\n  return doc;\n}\n\n- (BOOL)generateContentInputStream:(NSInputStream **)outInputStream\n                            length:(unsigned long long *)outLength\n                           headers:(NSDictionary **)outHeaders {\n  // subclasses may return a data stream representing this object\n  // for uploading\n  return NO;\n}\n\n- (NSString *)uploadMIMEType {\n  // subclasses may return the type of data to be uploaded\n  return nil;\n}\n\n- (NSData *)uploadData {\n  // subclasses may return data to be uploaded along with the object\n  return nil;\n}\n\n- (NSFileHandle *)uploadFileHandle {\n  // subclasses may return a file handle to be uploaded along with the object\n  return nil;\n}\n\n- (NSURL *)uploadLocationURL {\n  // subclasses may return a resumable upload location URL for restarting\n  // uploads\n  return nil;\n}\n\n- (BOOL)shouldUploadDataOnly {\n  return NO;\n}\n\n#pragma mark -\n\n- (void)setElementName:(NSString *)name {\n  [elementName_ release];\n  elementName_ = [name copy];\n}\n\n- (NSString *)elementName {\n  return elementName_;\n}\n\n- (void)setNamespaces:(NSDictionary *)dict {\n  [namespaces_ release];\n  namespaces_ = [dict mutableCopy];\n}\n\n- (void)addNamespaces:(NSDictionary *)dict {\n  if (namespaces_ == nil) {\n    namespaces_ = [[NSMutableDictionary alloc] init];\n  }\n  [namespaces_ addEntriesFromDictionary:dict];\n}\n\n- (NSDictionary *)namespaces {\n  return namespaces_;\n}\n\n- (NSDictionary *)completeNamespaces {\n  // return a dictionary containing all namespaces\n  // in this object and its parent objects\n  NSDictionary *parentNamespaces = [parent_ completeNamespaces];\n  NSDictionary *ownNamespaces = namespaces_;\n\n  if (ownNamespaces == nil) return parentNamespaces;\n  if (parentNamespaces == nil) return ownNamespaces;\n\n  // combine them, replacing parent-defined prefixes with own ones\n  NSMutableDictionary *mutableDict;\n\n  mutableDict = [NSMutableDictionary dictionaryWithDictionary:parentNamespaces];\n  [mutableDict addEntriesFromDictionary:ownNamespaces];\n  return mutableDict;\n}\n\n- (void)pruneInheritedNamespaces {\n\n  if (parent_ == nil || [namespaces_ count] == 0) return;\n\n  // if a prefix is explicitly defined the same for the parent as it is locally,\n  // remove it, since we can rely on the parent's definition\n  NSMutableDictionary *prunedNamespaces\n    = [NSMutableDictionary dictionaryWithDictionary:namespaces_];\n\n  NSDictionary *parentNamespaces = [parent_ completeNamespaces];\n\n  for (NSString *prefix in namespaces_) {\n\n    NSString *ownURI = [namespaces_ objectForKey:prefix];\n    NSString *parentURI = [parentNamespaces objectForKey:prefix];\n\n    if (AreEqualOrBothNil(ownURI, parentURI)) {\n      [prunedNamespaces removeObjectForKey:prefix];\n    }\n  }\n\n  [self setNamespaces:prunedNamespaces];\n}\n\n- (void)setParent:(GDataObject *)obj {\n  parent_ = obj; // parent_ is a weak (not retained) reference\n}\n\n- (GDataObject *)parent {\n  return parent_;\n}\n\n- (void)setAttributeDeclarationsCache:(NSDictionary *)cache {\n  [attributeDeclarationsCache_ autorelease];\n  attributeDeclarationsCache_ = [cache mutableCopy];\n}\n\n- (NSMutableDictionary *)attributeDeclarationsCache {\n  // warning: rely on this only during parsing; it will not be safe if the\n  //          top parent is no longer allocated\n  if (attributeDeclarationsCache_) {\n    return attributeDeclarationsCache_;\n  }\n  return [[self parent] attributeDeclarationsCache];\n}\n\n- (void)setAttributeDeclarations:(NSArray *)array {\n  [attributeDeclarations_ autorelease];\n  attributeDeclarations_ = [array mutableCopy];\n}\n\n- (NSMutableArray *)attributeDeclarations {\n  return attributeDeclarations_;\n}\n\n- (void)setAttributes:(NSDictionary *)dict {\n  [attributes_ autorelease];\n  attributes_ = [dict mutableCopy];\n}\n\n- (NSDictionary *)attributes {\n  return attributes_;\n}\n\n- (void)setExtensions:(NSDictionary *)extensions {\n  [extensions_ autorelease];\n  extensions_ = [extensions mutableCopy];\n}\n\n- (NSDictionary *)extensions {\n  return extensions_;\n}\n\n- (void)setExtensionDeclarationsCache:(NSDictionary *)decls {\n  [extensionDeclarationsCache_ autorelease];\n  extensionDeclarationsCache_ = [decls mutableCopy];\n}\n\n- (NSMutableDictionary *)extensionDeclarationsCache {\n  // warning: rely on this only during parsing; it will not be safe if the\n  //          top parent is no longer allocated\n  if (extensionDeclarationsCache_) {\n    return extensionDeclarationsCache_;\n  }\n\n  return [[self parent] extensionDeclarationsCache];\n}\n\n- (void)clearExtensionDeclarationsCache {\n  // allows external classes to free up the declarations\n  [self setExtensionDeclarationsCache:nil];\n}\n\n- (void)setUnknownChildren:(NSArray *)arr {\n  [unknownChildren_ autorelease];\n  unknownChildren_ = [arr mutableCopy];\n}\n\n- (NSArray *)unknownChildren {\n  return unknownChildren_;\n}\n\n- (void)setUnknownAttributes:(NSArray *)arr {\n  [unknownAttributes_ autorelease];\n  unknownAttributes_ = [arr mutableCopy];\n}\n\n- (NSArray *)unknownAttributes {\n  return unknownAttributes_;\n}\n\n- (void)setShouldIgnoreUnknowns:(BOOL)flag {\n  shouldIgnoreUnknowns_ = flag;\n}\n\n- (BOOL)shouldIgnoreUnknowns {\n  return shouldIgnoreUnknowns_;\n}\n\n- (void)setSurrogates:(NSDictionary *)surrogates {\n  [surrogates_ autorelease];\n  surrogates_ = [surrogates retain];\n}\n\n- (NSDictionary *)surrogates {\n  return surrogates_;\n}\n\n+ (NSString *)defaultServiceVersion {\n  return nil;\n}\n\n- (void)setServiceVersion:(NSString *)str {\n  if (!AreEqualOrBothNil(str, serviceVersion_)) {\n    // reset the core protocol version, since it's based on the service version\n    [self setCoreProtocolVersion:nil];\n\n    [serviceVersion_ autorelease];\n    serviceVersion_ = [str copy];\n  }\n}\n\n- (NSString *)serviceVersion {\n  if (serviceVersion_ != nil) {\n    return serviceVersion_;\n  }\n\n  NSString *str = [[self class] defaultServiceVersion];\n  return str;\n}\n\n- (BOOL)isServiceVersionAtLeast:(NSString *)otherVersion {\n  NSString *serviceVersion = [self serviceVersion];\n  NSComparisonResult result = [GDataUtilities compareVersion:serviceVersion\n                                                   toVersion:otherVersion];\n  return (result != NSOrderedAscending);\n}\n\n- (BOOL)isServiceVersionAtMost:(NSString *)otherVersion {\n  NSString *serviceVersion = [self serviceVersion];\n  NSComparisonResult result = [GDataUtilities compareVersion:serviceVersion\n                                                   toVersion:otherVersion];\n  return (result != NSOrderedDescending);\n}\n\n- (void)setCoreProtocolVersion:(NSString *)str {\n  [coreProtocolVersion_ autorelease];\n  coreProtocolVersion_ = [str copy];\n}\n\n- (NSString *)coreProtocolVersion {\n  if (coreProtocolVersion_ != nil) {\n    return coreProtocolVersion_;\n  }\n\n  NSString *serviceVersion = [self serviceVersion];\n  NSString *coreVersion = [[self class] coreProtocolVersionForServiceVersion:serviceVersion];\n\n  [self setCoreProtocolVersion:coreVersion];\n  return coreVersion;\n}\n\n- (BOOL)isCoreProtocolVersion1 {\n  NSString *coreVersion = [self coreProtocolVersion];\n\n  // technically the version number is <integer>.<integer> rather than a float,\n  // but intValue is a simple way to test just the major portion\n  int majorVer = [coreVersion intValue];\n  return (majorVer <= 1);\n}\n\n+ (NSString *)coreProtocolVersionForServiceVersion:(NSString *)str {\n  // subclasses may override this when their service versions\n  // do not match the core protocol version\n  return str;\n}\n\n#pragma mark userData and properties\n\n- (void)setUserData:(id)userData {\n  [userData_ autorelease];\n  userData_ = [userData retain];\n}\n\n- (id)userData {\n  // be sure the returned pointer has the life of the autorelease pool,\n  // in case self is released immediately\n  return [[userData_ retain] autorelease];\n}\n\n- (void)setProperties:(NSDictionary *)dict {\n  [userProperties_ autorelease];\n  userProperties_ = [dict mutableCopy];\n}\n\n- (NSDictionary *)properties {\n  // be sure the returned pointer has the life of the autorelease pool,\n  // in case self is released immediately\n  return [[userProperties_ retain] autorelease];\n}\n\n- (void)setProperty:(id)obj forKey:(NSString *)key {\n\n  if (obj == nil) {\n    // user passed in nil, so delete the property\n    [userProperties_ removeObjectForKey:key];\n  } else {\n    // be sure the property dictionary exists\n    if (userProperties_ == nil) {\n      [self setProperties:[NSDictionary dictionary]];\n    }\n    [userProperties_ setObject:obj forKey:key];\n  }\n}\n\n- (id)propertyForKey:(NSString *)key {\n  id obj = [userProperties_ objectForKey:key];\n\n  // be sure the returned pointer has the life of the autorelease pool,\n  // in case self is released immediately\n  return [[obj retain] autorelease];\n}\n\n#pragma mark XML generation helpers\n\n- (void)addNamespacesToElement:(NSXMLElement *)element {\n\n  // we keep namespaces in a dictionary with prefixes\n  // as keys.  We'll step through our namespaces and convert them\n  // to NSXML-stype namespaces.\n  for (NSString *prefix in namespaces_) {\n\n    NSString *uri = [namespaces_ objectForKey:prefix];\n\n    // no per-version namespace transforms are currently needed\n    // uri = [self updatedVersionedNamespaceURIForPrefix:prefix\n    //                                              URI:uri];\n\n    [element addNamespace:[NSXMLElement namespaceWithName:prefix\n                                              stringValue:uri]];\n  }\n}\n\n- (void)addExtensionsToElement:(NSXMLElement *)element {\n  // extensions are in a dictionary of arrays, keyed by the class\n  // of each kind of element\n\n  // note: this adds actual extensions, not declarations\n  NSDictionary *extensions = [self extensions];\n\n  // step through each extension, by class, and add those\n  // objects to the XML element\n  for (Class oneClass in extensions) {\n\n    id objectOrArray = [extensions_ objectForKey:oneClass];\n\n    if ([objectOrArray isKindOfClass:[NSArray class]]) {\n      [self addToElement:element XMLElementsForArray:objectOrArray];\n    } else {\n      [self addToElement:element XMLElementForObject:objectOrArray];\n    }\n  }\n}\n\n- (void)addUnknownChildNodesToElement:(NSXMLElement *)element {\n\n  // we'll add every element and attribute as \"unknown\", then remove them\n  // from this list as we parse them to create the GData object. Anything\n  // left remaining in this list is considered unknown.\n\n  if (shouldIgnoreUnknowns_) return;\n\n  // we have to copy the children so they don't point at the previous parent\n  // nodes\n  for (NSXMLNode *child in unknownChildren_) {\n    [element addChild:[[child copy] autorelease]];\n  }\n\n  for (NSXMLNode *attr in unknownAttributes_) {\n\n    GDATA_DEBUG_ASSERT([element attributeForName:[attr name]] == nil,\n              @\"adding duplicate of attribute %@ (perhaps an object parsed with\"\n              \"attributeForName: instead of attributeForName:fromElement:)\",\n              attr);\n\n    [element addAttribute:[[attr copy] autorelease]];\n  }\n}\n\n// this method creates a basic XML element from this GData object.\n//\n// this is called by the XMLElement method of subclasses; they will add their\n// own attributes and children to the element returned by this method\n//\n// extensions may pass nil for defaultName to use the name specified in their\n// extensionElementLocalName and extensionElementPrefix\n\n- (NSXMLElement *)XMLElementWithExtensionsAndDefaultName:(NSString *)defaultName {\n\n#if 0\n  // code sometimes useful for finding unparsed xml; this can be turned on\n  // during testing\n  if ([unknownAttributes_ count]) {\n    NSLog(@\"%@ %p: unknown attributes %@\\n%@\\n\", [self class], self, unknownAttributes_, self);\n  }\n  if ([unknownChildren_ count]) {\n    NSLog(@\"%@ %p: unknown children %@\\n%@\\n\", [self class], self, unknownChildren_, self);\n  }\n#endif\n\n  // use the name from the XML\n  NSString *elementName = [self elementName];\n  if (!elementName) {\n\n    // if no name from the XML, use the name our class's XML element\n    // routine supplied as a default\n    if (defaultName) {\n      elementName = defaultName;\n    } else {\n      // if no default name from the class, and this class is an extension,\n      // use the extension's default element name\n      if ([[self class] conformsToProtocol:@protocol(GDataExtension)]) {\n\n        elementName = [self qualifiedNameForExtensionClass:[self class]];\n      } else {\n        // if not an extension, just use the class name\n        elementName = NSStringFromClass([self class]);\n\n        GDATA_DEBUG_LOG(@\"GDataObject generating XML element with unknown name for class %@\",\n              elementName);\n      }\n    }\n  }\n\n  NSXMLElement *element = [NSXMLNode elementWithName:elementName];\n  [self addNamespacesToElement:element];\n  [self addAttributesToElement:element];\n  [self addContentValueToElement:element];\n  [self addChildXMLElementsToElement:element];\n  [self addExtensionsToElement:element];\n  [self addUnknownChildNodesToElement:element];\n  return element;\n}\n\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n     attributeValueIfNonNil:(NSString *)val\n                   withName:(NSString *)name {\n  if (val) {\n    NSString *filtered = [GDataUtilities stringWithControlsFilteredForString:val];\n\n    NSXMLNode* attr = [NSXMLNode attributeWithName:name stringValue:filtered];\n    [element addAttribute:attr];\n    return attr;\n  }\n  return nil;\n}\n\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n     attributeValueIfNonNil:(NSString *)val\n          withQualifiedName:(NSString *)qName\n                        URI:(NSString *)attributeURI {\n\n  if (attributeURI == nil) {\n    return [self addToElement:element\n       attributeValueIfNonNil:val\n                     withName:qName];\n  }\n\n  if (val) {\n    NSString *filtered = [GDataUtilities stringWithControlsFilteredForString:val];\n\n    NSXMLNode *attr = [NSXMLNode attributeWithName:qName\n                                               URI:attributeURI\n                                       stringValue:filtered];\n    if (attr != nil) {\n      [element addAttribute:attr];\n      return attr;\n    }\n  }\n  return nil;\n}\n\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n  attributeValueWithInteger:(NSInteger)val\n                   withName:(NSString *)name {\n  NSString* str = [NSString stringWithFormat:@\"%ld\", (long)val];\n  NSXMLNode* attr = [NSXMLNode attributeWithName:name stringValue:str];\n  [element addAttribute:attr];\n  return attr;\n}\n\n// adding a child to an XML element\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\nchildWithStringValueIfNonEmpty:(NSString *)str\n                   withName:(NSString *)name {\n  if ([str length] > 0) {\n    NSXMLNode *child = [NSXMLElement elementWithName:name stringValue:str];\n    [element addChild:child];\n    return child;\n  }\n  return nil;\n}\n\n// call the object's XMLElement method, and add the result as a new XML child\n// element\n- (void)addToElement:(NSXMLElement *)element\n XMLElementForObject:(id)object {\n\n  if ([object isKindOfClass:[GDataAttribute class]]) {\n\n    // attribute extensions are not GDataObjects and don't implement\n    // XMLElement; we just get the attribute value from them\n    NSString *str = [object stringValue];\n    NSString *qName = [self qualifiedNameForExtensionClass:[object class]];\n    NSString *theURI = [[object class] extensionElementURI];\n\n    [self addToElement:element\nattributeValueIfNonNil:str\n     withQualifiedName:qName\n                   URI:theURI];\n\n  } else {\n    // element extension\n    NSXMLElement *child = [object XMLElement];\n    if (child) {\n      [element addChild:child];\n    }\n  }\n}\n\n// call the XMLElement method for each object in the array\n- (void)addToElement:(NSXMLElement *)element\n XMLElementsForArray:(NSArray *)arrayOfGDataObjects {\n  for(id item in arrayOfGDataObjects) {\n    [self addToElement:element XMLElementForObject:item];\n  }\n}\n\n#pragma mark description method helpers\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n// if the description label begins with version<= or version>= then do a service\n// version check\n//\n// returns the label with any version prefix removed, or returns nil if the\n// description fails the version check and should not be evaluated\n\n- (NSString *)labelAdjustedForVersion:(NSString *)origLabel {\n\n  BOOL checkMinVersion = NO;\n  BOOL checkMaxVersion = NO;\n  NSString *prefix = nil;\n\n  static NSString *const kMinVersionPrefix = @\"version>=\";\n  static NSString *const kMaxVersionPrefix = @\"version<=\";\n\n  if ([origLabel hasPrefix:kMinVersionPrefix]) {\n    checkMinVersion = YES;\n    prefix = kMinVersionPrefix;\n  } else if ([origLabel hasPrefix:kMaxVersionPrefix]) {\n    checkMaxVersion = YES;\n    prefix = kMaxVersionPrefix;\n  }\n\n  if (!checkMaxVersion && !checkMinVersion) return origLabel;\n\n  // there is a version prefix; scan and test the version string,\n  // and if the test succeeds, return the label without the prefix\n  NSString *newLabel = origLabel;\n  NSString *versionStr = nil;\n  NSScanner *scanner = [NSScanner scannerWithString:origLabel];\n\n  if ([scanner scanString:prefix intoString:NULL]\n      && [scanner scanUpToString:@\":\" intoString:&versionStr]\n      && [scanner scanString:@\":\" intoString:NULL]\n      && [scanner scanUpToString:@\"\\n\" intoString:&newLabel]) {\n\n    if ((checkMinVersion && ![self isServiceVersionAtLeast:versionStr])\n        || (checkMaxVersion && ![self isServiceVersionAtMost:versionStr])) {\n      // version test failed\n      return nil;\n    }\n  }\n  return newLabel;\n}\n#endif\n\n- (void)addDescriptionRecords:(GDataDescriptionRecord *)descRecordList\n                      toItems:(NSMutableArray *)items {\n#if !GDATA_SIMPLE_DESCRIPTIONS\n  // the final descRecord in the list should be { nil, nil, 0 }\n\n  for (NSUInteger idx = 0; descRecordList[idx].label != nil; idx++) {\n\n    GDataDescRecTypes reportType = descRecordList[idx].reportType;\n    NSString *label = descRecordList[idx].label;\n    NSString *keyPath = descRecordList[idx].keyPath;\n\n    label = [self labelAdjustedForVersion:label];\n    if (label == nil) continue;\n\n    id value;\n    NSString *str;\n\n    if (reportType == kGDataDescValueIsKeyPath) {\n      value = keyPath;\n    } else {\n      value = [self valueForKeyPath:keyPath];\n    }\n\n    switch (reportType) {\n\n      case kGDataDescValueLabeled:\n      case kGDataDescValueIsKeyPath:\n        [self addToArray:items objectDescriptionIfNonNil:value withName:label];\n        break;\n\n      case kGDataDescLabelIfNonNil:\n        if (value != nil) [items addObject:label];\n        break;\n\n      case kGDataDescArrayCount:\n        if ([(NSArray *)value count] > 0) {\n          str = [NSString stringWithFormat:@\"%lu\", (unsigned long) [(NSArray *)value count]];\n          [self addToArray:items objectDescriptionIfNonNil:str withName:label];\n        }\n        break;\n\n      case kGDataDescArrayDescs:\n        if ([(NSArray *)value count] > 0) {\n          [self addToArray:items objectDescriptionIfNonNil:value withName:label];\n        }\n        break;\n\n      case kGDataDescBooleanLabeled:\n        // display the label with YES or NO\n        str = ([value boolValue] ? @\"YES\" : @\"NO\");\n        [self addToArray:items objectDescriptionIfNonNil:str withName:label];\n        break;\n\n      case kGDataDescBooleanPresent:\n        // display the label:YES only if present\n        if ([value boolValue]) {\n          [self addToArray:items objectDescriptionIfNonNil:@\"YES\" withName:label];\n        }\n        break;\n\n      case kGDataDescNonZeroLength:\n        // display the length if non-zero\n        if ([(NSData *)value length] > 0) {\n          str = [NSString stringWithFormat:@\"#%lu\",\n                 (unsigned long) [(NSData *)value length]];\n          [self addToArray:items objectDescriptionIfNonNil:str withName:label];\n        }\n        break;\n    }\n  }\n#endif\n}\n\n- (void)addToArray:(NSMutableArray *)stringItems\nobjectDescriptionIfNonNil:(id)obj\n          withName:(NSString *)name {\n\n  if (obj) {\n    if (name) {\n      [stringItems addObject:[NSString stringWithFormat:@\"%@:%@\", name, obj]];\n    } else {\n      [stringItems addObject:[obj description]];\n    }\n  }\n}\n\n- (void)addAttributeDescriptionsToArray:(NSMutableArray *)stringItems {\n\n  // add attribute descriptions in the order the attributes were declared\n  NSArray *attributeDeclarations = [self attributeDeclarations];\n  for (NSString *name in attributeDeclarations) {\n\n    NSString *value = [attributes_ valueForKey:name];\n    [self addToArray:stringItems objectDescriptionIfNonNil:value withName:name];\n  }\n}\n\n- (void)addContentDescriptionToArray:(NSMutableArray *)stringItems\n                            withName:(NSString *)name {\n  if ([self hasDeclaredContentValue]) {\n    NSString *value = [self contentStringValue];\n    [self addToArray:stringItems objectDescriptionIfNonNil:value withName:name];\n  }\n}\n\n- (void)addChildXMLElementsDescriptionToArray:(NSMutableArray *)stringItems {\n  if ([self hasDeclaredChildXMLElements]) {\n\n    NSArray *childXMLElements = [self childXMLElements];\n    if ([childXMLElements count] > 0) {\n\n      NSArray *xmlStrings = [childXMLElements valueForKey:@\"XMLString\"];\n      NSString *combinedStr = [xmlStrings componentsJoinedByString:@\"\"];\n\n      [self addToArray:stringItems objectDescriptionIfNonNil:combinedStr withName:@\"XML\"];\n    }\n  }\n}\n\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [NSMutableArray array];\n  [self addAttributeDescriptionsToArray:items];\n  [self addContentDescriptionToArray:items withName:@\"content\"];\n\n#if GDATA_SIMPLE_DESCRIPTIONS\n  // with GDATA_SIMPLE_DESCRIPTIONS set, subclasses aren't adding their\n  // own description items for extensions, so we'll just list the extension\n  // elements that are present, by their qualified xml names\n  //\n  // The description string will look like\n  //   {extensions:(gCal:color,link(3),gd:etag,id,updated)}\n  NSMutableArray *extnsItems = [NSMutableArray array];\n\n  for (Class extClass in extensions_) {\n\n    // add the qualified XML name for each extension, followed by (n) when\n    // there is more than one instance\n    NSString *qname = [self qualifiedNameForExtensionClass:extClass];\n\n    // there's one instance of this extension, unless the value is an array\n    NSUInteger numberOfInstances = 1;\n    id extnObj = [extensions_ objectForKey:extClass];\n    if ([extnObj isKindOfClass:[NSArray class]]) {\n      numberOfInstances = [extnObj count];\n    }\n\n    if (numberOfInstances == 1) {\n      [extnsItems addObject:qname];\n    } else {\n      // append number of occurrences to the xml name\n      NSString *str = [NSString stringWithFormat:@\"%@(%lu)\", qname,\n                       (unsigned long) numberOfInstances];\n      [extnsItems addObject:str];\n    }\n  }\n\n  if ([extnsItems count] > 0) {\n    // sort for predictable ordering in unit tests\n    NSArray *sortedItems = [extnsItems sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];\n    NSString *extnsStr = [NSString stringWithFormat:@\"extensions:(%@)\",\n                          [sortedItems componentsJoinedByString:@\",\"]];\n    [items addObject:extnsStr];\n  }\n#endif\n\n  [self addChildXMLElementsDescriptionToArray:items];\n  return items;\n}\n\n- (NSString *)descriptionWithItems:(NSArray *)items {\n\n  NSString *str;\n\n  if ([items count] > 0) {\n    str = [NSString stringWithFormat:@\"%@ %p: {%@}\",\n      [self class], self, [items componentsJoinedByString:@\" \"]];\n\n  } else {\n    str = [NSString stringWithFormat:@\"%@ %p\", [self class], self];\n  }\n  return str;\n}\n\n- (NSString *)description {\n\n  NSMutableArray *items = [self itemsForDescription];\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n  // add names of unknown children and attributes to the descriptions\n  if ([unknownChildren_ count] > 0) {\n    // remove repeats and put the element names in < > so they are more\n    // readable\n    NSArray *names = [unknownChildren_ valueForKey:@\"name\"];\n    NSSet *namesSet = [NSSet setWithArray:names];\n    NSMutableArray *fmtNames = [NSMutableArray arrayWithCapacity:[namesSet count]];\n\n    for (NSString *name in namesSet) {\n      NSString *fmtName = [NSString stringWithFormat:@\"<%@>\", name];\n      [fmtNames addObject:fmtName];\n    }\n\n    // sort the names so the output is deterministic despite the set/array\n    // conversion\n    NSArray *sortedNames = [fmtNames sortedArrayUsingSelector:@selector(compare:)];\n    NSString *desc = [sortedNames componentsJoinedByString:@\",\"];\n    [self addToArray:items objectDescriptionIfNonNil:desc withName:@\"unparsed\"];\n  }\n\n  if ([unknownAttributes_ count] > 0) {\n    NSArray *names = [unknownAttributes_ valueForKey:@\"name\"];\n    NSString *desc = [names componentsJoinedByString:@\",\"];\n    [self addToArray:items objectDescriptionIfNonNil:desc withName:@\"unparsedAttr\"];\n  }\n#endif\n\n  NSString *str = [self descriptionWithItems:items];\n  return str;\n}\n\n\n#pragma mark XML parsing helpers\n\n+ (NSDictionary *)dictionaryForElementNamespaces:(NSXMLElement *)element {\n\n  NSMutableDictionary *dict = nil;\n\n  // for each namespace node, add a dictionary entry with the namespace\n  // name (prefix) as key and the URI as value\n  //\n  // note: the prefix may be an empty string\n\n  NSArray *namespaceNodes = [element namespaces];\n\n  NSUInteger numberOfNamespaces = [namespaceNodes count];\n\n  if (numberOfNamespaces > 0) {\n\n    dict = [NSMutableDictionary dictionary];\n\n    for (unsigned int idx = 0; idx < numberOfNamespaces; idx++) {\n      NSXMLNode *node = [namespaceNodes objectAtIndex:idx];\n      [dict setObject:[node stringValue]\n               forKey:[node name]];\n    }\n  }\n  return dict;\n}\n\n// classOrSurrogateForClass searches this object instance and all parent\n// instances for a user surrogate for the supplied class, and returns\n// the surrogate, or else the supplied class if no surrogate is found for it\n- (Class)classOrSurrogateForClass:(Class)standardClass {\n\n  for (GDataObject *currentObject = self;\n       currentObject != nil;\n       currentObject = [currentObject parent]) {\n\n    // look for an object with a surrogates dict containing the standardClass\n    NSDictionary *currentSurrogates = [currentObject surrogates];\n\n    Class surrogate = (Class)[currentSurrogates objectForKey:standardClass];\n    if (surrogate) return surrogate;\n  }\n  return standardClass;\n}\n\n// The following routines which parse XML elements remove the parsed elements\n// from the list of unknowns.\n\n// objectForElementWithNameIfAny:objectClass:objectClass: creates\n// a single GDataObject of the specified class for the first XML child element\n// with the specified name. Returns nil if no child element is present\n//\n// If objectClass is nil, the class is looked up from the registrations\n// of entry and feed classes.\n- (id)objectForChildOfElement:(NSXMLElement *)parentElement\n                qualifiedName:(NSString *)qualifiedName\n                 namespaceURI:(NSString *)namespaceURI\n                  objectClass:(Class)objectClass {\n  id object = nil;\n  NSXMLElement *element = [self childWithQualifiedName:qualifiedName\n                                          namespaceURI:namespaceURI\n                                           fromElement:parentElement];\n  if (element) {\n\n    if (objectClass == nil) {\n      // if the object is a feed or an entry, we might be able to determine the\n      // type from the XML\n      objectClass = [[self class] objectClassForXMLElement:element];\n    }\n\n    objectClass = [self classOrSurrogateForClass:objectClass];\n\n    object = [[[objectClass alloc] initWithXMLElement:element\n                                               parent:self] autorelease];\n  }\n  return object;\n}\n\n\n// get child elements from an element matching the given name and namespace\n// (trying the namespace first, falling back on the fully-qualified name)\n- (NSArray *)elementsForName:(NSString *)qualifiedName\n                namespaceURI:(NSString *)namespaceURI\n               parentElement:(NSXMLElement *)parentElement {\n\n  NSArray *objElements = nil;\n\n  if ([namespaceURI length] > 0) {\n\n    NSString *localName = [NSXMLNode localNameForName:qualifiedName];\n\n    objElements = [parentElement elementsForLocalName:localName\n                                                  URI:namespaceURI];\n  }\n\n  // if we couldn't find the elements by name, fall back on the fully-qualified\n  // name\n  if ([objElements count] == 0) {\n\n    objElements = [parentElement elementsForName:qualifiedName];\n  }\n  return objElements;\n\n}\n\n// return all child elements of an element which have the given namespace\n// prefix\n- (NSMutableArray *)childrenOfElement:(NSXMLElement *)parentElement\n                           withPrefix:(NSString *)prefix {\n  NSArray *allChildren = [parentElement children];\n  NSMutableArray *matchingChildren = [NSMutableArray array];\n  for (NSXMLNode *childNode in allChildren) {\n    if ([childNode kind] == NSXMLElementKind\n        && [[childNode prefix] isEqual:prefix]) {\n\n      [matchingChildren addObject:childNode];\n    }\n  }\n\n  return matchingChildren;\n}\n\n// returns a GDataObject or an array of them of the specified class for each XML\n// child element with the specified name\n//\n// If objectClass is nil, the class is looked up from the registrations\n// of entry and feed classes.\n\n- (id)objectOrArrayForChildrenOfElement:(NSXMLElement *)parentElement\n                          qualifiedName:(NSString *)qualifiedName\n                           namespaceURI:(NSString *)namespaceURI\n                            objectClass:(Class)objectClass {\n  id result = nil;\n  BOOL isResultAnArray = NO;\n\n  NSArray *objElements = nil;\n\n  NSString *localName = [NSXMLNode localNameForName:qualifiedName];\n  if (![localName isEqual:@\"*\"]) {\n\n    // searching for an actual element name (not a wildcard)\n    objElements = [self elementsForName:qualifiedName\n                           namespaceURI:namespaceURI\n                          parentElement:parentElement];\n  }\n\n  else {\n    // we weren't given a local name, so get all objects for this namespace\n    // URI's prefix\n    NSString *prefixSought = [NSXMLNode prefixForName:qualifiedName];\n    if ([prefixSought length] == 0) {\n      prefixSought = [parentElement resolvePrefixForNamespaceURI:namespaceURI];\n    }\n\n    if (prefixSought) {\n      objElements = [self childrenOfElement:parentElement\n                                 withPrefix:prefixSought];\n    }\n  }\n\n  // if we're creating entries, we'll use an autorelease pool around each\n  // allocation, just to bound overall pool size.  We'll check the class\n  // of the first created object to determine if we want pools.\n  BOOL hasCheckedObjectClass = NO;\n  BOOL useLocalAutoreleasePool = NO;\n  Class entryBaseClass = [GDataEntryBase class];\n\n  // step through all child elements and create an appropriate GData object\n  for (NSXMLElement *objElement in objElements) {\n\n    Class elementClass = objectClass;\n    if (elementClass == nil) {\n      // if the object is a feed or an entry, we might be able to determine the\n      // type for this element from the XML\n      elementClass = [[self class] objectClassForXMLElement:objElement];\n\n      // if a base feed class doesn't specify entry class, and the entry object\n      // class can't be determined by examining its XML, fall back on\n      // instantiating the base entry class\n      if (elementClass == nil\n        && [qualifiedName isEqual:@\"entry\"]\n        && [namespaceURI isEqual:kGDataNamespaceAtom]) {\n\n        elementClass = entryBaseClass;\n      }\n    }\n\n    elementClass = [self classOrSurrogateForClass:elementClass];\n\n    NSAutoreleasePool *pool = nil;\n\n    if (!hasCheckedObjectClass) {\n      useLocalAutoreleasePool = [elementClass isSubclassOfClass:entryBaseClass];\n      hasCheckedObjectClass = YES;\n    }\n\n    if (useLocalAutoreleasePool) {\n      pool = [[NSAutoreleasePool alloc] init];\n    }\n\n    id obj = [[elementClass alloc] initWithXMLElement:objElement\n                                               parent:self];\n\n    // We drain here to keep the clang static analyzer quiet.\n    [pool drain];\n\n    [obj autorelease];\n\n    if (obj) {\n      if (result == nil) {\n        // first result\n        result = obj;\n      } else if (!isResultAnArray) {\n        // second result; create an array with the previous and the new result\n        result = [NSMutableArray arrayWithObjects:result, obj, nil];\n        isResultAnArray = YES;\n      } else {\n        // third or later result\n        [result addObject:obj];\n      }\n    }\n  }\n\n  // remove these elements from the unknown list\n  [self handleParsedElements:objElements];\n\n  return result;\n}\n\n// childOfElement:withName returns the element with the name, or nil if there\n// are not exactly one of the element.  Pass \"*\" wildcards for name and URI\n// to retrieve the child element if there is exactly one.\n- (NSXMLElement *)childWithQualifiedName:(NSString *)qualifiedName\n                            namespaceURI:(NSString *)namespaceURI\n                             fromElement:(NSXMLElement *)parentElement {\n\n  NSArray *elementArray;\n\n  if ([qualifiedName isEqual:@\"*\"] && [namespaceURI isEqual:@\"*\"]) {\n    // wilcards\n    elementArray = [parentElement children];\n  } else {\n    // find the element by name and namespace URI\n    elementArray = [self elementsForName:qualifiedName\n                            namespaceURI:namespaceURI\n                           parentElement:parentElement];\n  }\n\n  NSUInteger numberOfElements = [elementArray count];\n\n  if (numberOfElements == 1) {\n    NSXMLElement *element = [elementArray objectAtIndex:0];\n\n    // remove this element from the unknown list\n    [self handleParsedElement:element];\n\n    return element;\n  }\n\n  // We might want to get rid of this assert if there turns out to be\n  // legitimate reasons to call this where there are >1 elements available\n  GDATA_ASSERT(numberOfElements == 0, @\"childWithQualifiedName: could not handle \"\n               \"multiple '%@' elements in list, use elementsForName:\\n\"\n               \"Found elements: %@\\nURI: %@\", qualifiedName, elementArray,\n               namespaceURI);\n  return nil;\n}\n\n#pragma mark element parsing\n\n- (void)handleParsedElement:(NSXMLNode *)element {\n  if (unknownChildren_ != nil && element != nil) {\n    [unknownChildren_ removeObjectIdenticalTo:element];\n\n    if ([unknownChildren_ count] == 0) {\n      [unknownChildren_ release];\n      unknownChildren_ = nil;\n    }\n  }\n}\n\n- (void)handleParsedElements:(NSArray *)array {\n  if (unknownChildren_ != nil) {\n    // rather than use NSMutableArray's removeObjects:, it's faster to iterate and\n    // and use removeObjectIdenticalTo: since it avoids comparing the underlying\n    // XML for equality\n    for (NSXMLNode* element in array) {\n      [unknownChildren_ removeObjectIdenticalTo:element];\n    }\n\n    if ([unknownChildren_ count] == 0) {\n      [unknownChildren_ release];\n      unknownChildren_ = nil;\n    }\n  }\n}\n\n- (NSString *)stringValueFromElement:(NSXMLElement *)element {\n  // Originally, this was\n  //    NSString *result = [element stringValue];\n  // but that recursively descends children to build the string\n  // so we'll just walk the remaining nodes and build the string ourselves\n\n  if (element == nil) {\n    return nil;\n  }\n\n  NSString *result = nil;\n\n  // consider all text child nodes used to make this string value to now be\n  // known\n  //\n  // in most cases, there is only one text node, so we'll optimize for that\n  NSArray *children = [element children];\n\n  for (NSXMLNode *childNode in children) {\n    if ([childNode kind] == NSXMLTextKind) {\n\n      NSString *newNodeString = [childNode stringValue];\n\n      if (result == nil) {\n        result = newNodeString;\n      } else {\n        result = [result stringByAppendingString:newNodeString];\n      }\n      [self handleParsedElement:childNode];\n    }\n  }\n\n  return (result != nil ? result : @\"\");\n}\n\n- (GDataDateTime *)dateTimeFromElement:(NSXMLElement *)element {\n  NSString *str = [self stringValueFromElement:element];\n  if ([str length] > 0) {\n    return [GDataDateTime dateTimeWithRFC3339String:str];\n  }\n  return nil;\n}\n\n\n- (NSNumber *)intNumberValueFromElement:(NSXMLElement *)element {\n  NSString *str = [self stringValueFromElement:element];\n  if ([str length] > 0) {\n    NSNumber *number = [NSNumber numberWithInt:[str intValue]];\n    return number;\n  }\n  return nil;\n}\n\n- (NSNumber *)doubleNumberValueFromElement:(NSXMLElement *)element {\n  NSString *str = [self stringValueFromElement:element];\n  return [GDataUtilities doubleNumberOrInfForString:str];\n}\n\n#pragma mark attribute parsing\n\n- (void)handleParsedAttribute:(NSXMLNode *)attribute {\n\n  if (unknownAttributes_ != nil && attribute != nil) {\n    [unknownAttributes_ removeObjectIdenticalTo:attribute];\n\n    if ([unknownAttributes_ count] == 0) {\n      [unknownAttributes_ release];\n      unknownAttributes_ = nil;\n    }\n  }\n}\n\n- (NSXMLNode *)attributeForName:(NSString *)attributeName\n                    fromElement:(NSXMLElement *)element {\n\n  NSXMLNode* attribute = [element attributeForName:attributeName];\n\n  [self handleParsedAttribute:attribute];\n\n  return attribute;\n}\n\n- (NSXMLNode *)attributeForLocalName:(NSString *)localName\n                                 URI:(NSString *)attributeURI\n                         fromElement:(NSXMLElement *)element {\n\n  NSXMLNode* attribute = [element attributeForLocalName:localName\n                                                    URI:attributeURI];\n  [self handleParsedAttribute:attribute];\n\n  return attribute;\n}\n\n- (NSString *)stringForAttributeLocalName:(NSString *)localName\n                                      URI:(NSString *)attributeURI\n                              fromElement:(NSXMLElement *)element {\n\n  NSXMLNode* attribute = [self attributeForLocalName:localName\n                                                 URI:attributeURI\n                                         fromElement:element];\n  return [attribute stringValue];\n}\n\n\n- (NSString *)stringForAttributeName:(NSString *)attributeName\n                         fromElement:(NSXMLElement *)element {\n  NSXMLNode* attribute = [self attributeForName:attributeName\n                                    fromElement:element];\n  return [attribute stringValue];\n}\n\n- (GDataDateTime *)dateTimeForAttributeName:(NSString *)attributeName\n                                fromElement:(NSXMLElement *)element {\n\n  NSXMLNode* attribute = [self attributeForName:attributeName\n                                    fromElement:element];\n\n  NSString* str = [attribute stringValue];\n  if ([str length] > 0) {\n    return [GDataDateTime dateTimeWithRFC3339String:str];\n  }\n  return nil;\n}\n\n- (BOOL)boolForAttributeName:(NSString *)attributeName\n                 fromElement:(NSXMLElement *)element {\n  NSXMLNode* attribute = [self attributeForName:attributeName\n                                    fromElement:element];\n  NSString* str = [attribute stringValue];\n  BOOL isTrue = (str && [str caseInsensitiveCompare:@\"true\"] == NSOrderedSame);\n  return isTrue;\n}\n\n- (NSNumber *)doubleNumberForAttributeName:(NSString *)attributeName\n                               fromElement:(NSXMLElement *)element {\n  NSXMLNode* attribute = [self attributeForName:attributeName\n                                    fromElement:element];\n  NSString* str = [attribute stringValue];\n  return [GDataUtilities doubleNumberOrInfForString:str];\n}\n\n- (NSNumber *)intNumberForAttributeName:(NSString *)attributeName\n                            fromElement:(NSXMLElement *)element {\n  NSXMLNode* attribute = [self attributeForName:attributeName\n                                    fromElement:element];\n  NSString* str = [attribute stringValue];\n  if (str) {\n    NSNumber *number = [NSNumber numberWithInt:[str intValue]];\n    return number;\n  }\n  return nil;\n}\n\n\n#pragma mark Extensions\n\n- (void)addExtensionDeclarations {\n  // overridden by subclasses which have extensions to add, like:\n  //\n  //  [self addExtensionDeclarationForParentClass:[GDataLink class]\n  //                                   childClass:[GDataWebContent class]];\n  // and\n  //\n  //  [self addAttributeExtensionDeclarationForParentClass:[GDataExtendedProperty class]\n  //                                            childClass:[GDataExtPropValueAttribute class]];\n\n}\n\n- (void)addParseDeclarations {\n\n  // overridden by subclasses which have local attributes, like:\n  //\n  //  [self addLocalAttributeDeclarations:[NSArray arrayWithObject:@\"size\"]];\n  //\n  //  Subclasses should add the attributes in the order they most usefully will\n  //  appear in the object's -description output (or alternatively they may\n  //  override -description).\n  //\n  // Note: this is only for namespace-less attributes or attributes with the\n  // fixed xml: namespace, not for attributes that are qualified with variable\n  // prefixes.  Those attributes should be parsed explicitly in\n  // initWithXMLElement: methods, and generated by XMLElement: methods.\n}\n\n// subclasses call these to declare possible extensions for themselves and their\n// children.\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                   childClass:(Class)childClass {\n  // add an element extension\n  [self addExtensionDeclarationForParentClass:parentClass\n                                   childClass:childClass\n                                  isAttribute:NO];\n}\n\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                 childClasses:(Class)firstChildClass, ... {\n\n  // like the method above, but for a list of child classes\n  Class nextClass;\n  va_list argumentList;\n\n  if (firstChildClass != nil) {\n    [self addExtensionDeclarationForParentClass:parentClass\n                                     childClass:firstChildClass\n                                    isAttribute:NO];\n\n    va_start(argumentList, firstChildClass);\n    while ((nextClass = (Class)va_arg(argumentList, Class)) != nil) {\n\n      [self addExtensionDeclarationForParentClass:parentClass\n                                       childClass:nextClass\n                                      isAttribute:NO];\n    }\n    va_end(argumentList);\n  }\n}\n\n- (void)addAttributeExtensionDeclarationForParentClass:(Class)parentClass\n                                   childClass:(Class)childClass {\n  // add an attribute extension\n  [self addExtensionDeclarationForParentClass:parentClass\n                                   childClass:childClass\n                                  isAttribute:YES];\n}\n\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                   childClass:(Class)childClass\n                                  isAttribute:(BOOL)isAttribute {\n\n  // get or make the dictionary which caches the extension declarations for\n  // this class\n  Class currClass = [self class];\n  NSMutableDictionary *extensionDeclarationsCache = [self extensionDeclarationsCache];\n  GDATA_DEBUG_ASSERT(extensionDeclarationsCache != nil, @\"missing extnDecls\");\n\n  NSMutableDictionary *extensionDecls = [extensionDeclarationsCache objectForKey:currClass];\n\n  if (extensionDecls == nil) {\n    extensionDecls = [NSMutableDictionary dictionary];\n    [extensionDeclarationsCache setObject:extensionDecls forKey:currClass];\n  }\n\n  // get this class's extensions for the specified parent class\n  NSMutableArray *array = [extensionDecls objectForKey:parentClass];\n  if (array == nil) {\n    array = [NSMutableArray array];\n    [extensionDecls setObject:array forKey:parentClass];\n  }\n\n  GDATA_DEBUG_ASSERT([childClass conformsToProtocol:@protocol(GDataExtension)],\n                @\"%@ does not conform to GDataExtension protocol\", childClass);\n\n  GDataExtensionDeclaration *decl =\n    [[[GDataExtensionDeclaration alloc] initWithParentClass:parentClass\n                                                 childClass:childClass\n                                                isAttribute:isAttribute] autorelease];\n  [array addObject:decl];\n}\n\n- (void)removeExtensionDeclarationForParentClass:(Class)parentClass\n                                      childClass:(Class)childClass {\n  GDataExtensionDeclaration *decl =\n    [[[GDataExtensionDeclaration alloc] initWithParentClass:parentClass\n                                                 childClass:childClass\n                                                isAttribute:NO] autorelease];\n\n  NSMutableArray *array = [self extensionDeclarationsForParentClass:parentClass];\n  [array removeObject:decl];\n}\n\n- (void)removeAttributeExtensionDeclarationForParentClass:(Class)parentClass\n                                               childClass:(Class)childClass {\n  GDataExtensionDeclaration *decl =\n    [[[GDataExtensionDeclaration alloc] initWithParentClass:parentClass\n                                                 childClass:childClass\n                                                isAttribute:YES] autorelease];\n\n  NSMutableArray *array = [self extensionDeclarationsForParentClass:parentClass];\n  [array removeObject:decl];\n}\n\n// utility routine for getting declared extensions to the specified class\n- (NSMutableArray *)extensionDeclarationsForParentClass:(Class)parentClass {\n\n  // get the declarations for this class\n  Class currClass = [self class];\n  NSMutableDictionary *cache = [self extensionDeclarationsCache];\n  NSMutableDictionary *classMap = [cache objectForKey:currClass];\n\n  // get the extensions for the specified parent class\n  NSMutableArray *array = [classMap objectForKey:parentClass];\n  return array;\n}\n\n// objectsForExtensionClass: returns the array of all\n// extension objects of the specified class, or nil\n//\n// this is typically called by the getter methods of subclasses\n\n- (NSArray *)objectsForExtensionClass:(Class)theClass {\n  id obj = [extensions_ objectForKey:theClass];\n  if (obj == nil) return nil;\n\n  if ([obj isKindOfClass:[NSArray class]]) {\n    return obj;\n  }\n\n  return [NSArray arrayWithObject:obj];\n}\n\n// objectForExtensionClass: returns the first element of\n// any extension objects of the specified class, or nil\n//\n// this is typically called by the getter methods of subclasses\n\n- (id)objectForExtensionClass:(Class)theClass {\n  id obj = [extensions_ objectForKey:theClass];\n\n  if ([obj isKindOfClass:[NSArray class]]) {\n    if ([(NSArray *)obj count] > 0) {\n      return [obj objectAtIndex:0];\n    }\n    // an empty array\n    return nil;\n  }\n\n  return obj;\n}\n\n// attributeValueForExtensionClass: returns the value of the first object of\n// the array of attribute extension objects of the specified class, or nil\n- (NSString *)attributeValueForExtensionClass:(Class)theClass {\n  GDataAttribute *attr = [self objectForExtensionClass:theClass];\n  NSString *str = [attr stringValue];\n  return str;\n}\n\n- (void)setAttributeValue:(NSString *)str forExtensionClass:(Class)theClass {\n  GDataAttribute *obj = [theClass attributeWithValue:str];\n  [self setObject:obj forExtensionClass:theClass];\n}\n\n// generate the qualified name for this extension's element\n- (NSString *)qualifiedNameForExtensionClass:(Class)theClass {\n\n  NSString *name;\n\n  @synchronized(gQualifiedNameMap) {\n\n    name = [gQualifiedNameMap objectForKey:theClass];\n    if (name == nil) {\n\n      NSString *extensionURI = [theClass extensionElementURI];\n\n      if (extensionURI == nil || [extensionURI isEqual:kGDataNamespaceAtom]) {\n        name = [theClass extensionElementLocalName];\n      } else {\n        name = [NSString stringWithFormat:@\"%@:%@\",\n                [theClass extensionElementPrefix],\n                [theClass extensionElementLocalName]];\n      }\n\n      [gQualifiedNameMap setObject:name forKey:theClass];\n    }\n  }\n  return name;\n}\n\n- (void)ensureObject:(GDataObject *)obj hasXMLNameForExtensionClass:(Class)theClass {\n  // utility routine for setObjects:forExtensionClass:\n  if ([obj isKindOfClass:[GDataObject class]]\n      && [[obj elementName] length] == 0) {\n\n    NSString *name = [self qualifiedNameForExtensionClass:theClass];\n    [obj setElementName:name];\n  }\n}\n\n// replace all actual extensions of the specified class with an array\n//\n// this is typically called by the setter methods of subclasses\n\n- (void)setObjects:(NSArray *)objects forExtensionClass:(Class)theClass {\n\n  GDATA_DEBUG_ASSERT(objects == nil || [objects isKindOfClass:[NSArray class]],\n                     @\"array expected\");\n\n  if (extensions_ == nil && objects != nil) {\n    extensions_ = [[NSMutableDictionary alloc] init];\n  }\n\n  if (objects) {\n    // be sure each object has an element name so we can generate XML for it\n    for (GDataObject *obj in objects) {\n      [self ensureObject:obj hasXMLNameForExtensionClass:theClass];\n    }\n    [extensions_ setObject:objects forKey:theClass];\n  } else {\n    [extensions_ removeObjectForKey:theClass];\n  }\n}\n\n// replace all actual extensions of the specified class with a single object\n//\n// this is typically called by the setter methods of subclasses\n\n- (void)setObject:(id)object forExtensionClass:(Class)theClass {\n\n  GDATA_DEBUG_ASSERT(![object isKindOfClass:[NSArray class]], @\"array unexpected\");\n\n  if (extensions_ == nil && object != nil) {\n    extensions_ = [[NSMutableDictionary alloc] init];\n  }\n\n  if (object) {\n    [self ensureObject:object hasXMLNameForExtensionClass:theClass];\n    [extensions_ setObject:object forKey:theClass];\n  } else {\n    [extensions_ removeObjectForKey:theClass];\n  }\n}\n\n// add an extension of the specified class\n//\n// this is typically called by addObject methods of subclasses\n\n- (void)addObject:(id)newObj forExtensionClass:(Class)theClass {\n\n  if (newObj == nil) return;\n\n  id previousObjOrArray = [extensions_ objectForKey:theClass];\n  if (previousObjOrArray) {\n\n    if ([previousObjOrArray isKindOfClass:[NSArray class]]) {\n\n      // add to the existing array\n      [self ensureObject:newObj hasXMLNameForExtensionClass:theClass];\n      [previousObjOrArray addObject:newObj];\n\n    } else {\n\n      // create an array with the previous object and the new object\n      NSMutableArray *array = [NSMutableArray arrayWithObjects:\n                               previousObjOrArray, newObj, nil];\n      [extensions_ setObject:array forKey:theClass];\n    }\n  } else {\n\n    // no previous object\n    [self setObject:newObj forExtensionClass:theClass];\n  }\n}\n\n// remove a known extension of the specified class\n//\n// this is typically called by removeObject methods of subclasses\n\n- (void)removeObject:(id)object forExtensionClass:(Class)theClass {\n  id previousObjOrArray = [extensions_ objectForKey:theClass];\n  if ([previousObjOrArray isKindOfClass:[NSArray class]]) {\n\n    // remove from the array\n    [(NSMutableArray *)previousObjOrArray removeObject:object];\n\n  } else if ([(GDataObject *)object isEqual:previousObjOrArray]) {\n\n    // no array, so remove if it matches the sole object\n    [extensions_ removeObjectForKey:theClass];\n  }\n}\n\n// addUnknownChildNodesForElement: is called by initWithXMLElement.  It builds\n// the initial list of unknown child elements; this list is whittled down by\n// parseExtensionsForElement and objectForChildOfElement.\n- (void)addUnknownChildNodesForElement:(NSXMLElement *)element {\n\n  GDATA_DEBUG_ASSERT(unknownChildren_ == nil, @\"unknChildren added twice\");\n  GDATA_DEBUG_ASSERT(unknownAttributes_ == nil, @\"unknAttr added twice\");\n\n  if (!shouldIgnoreUnknowns_) {\n\n    NSArray *children = [element children];\n    if ([children count] > 0) {\n      unknownChildren_ = [[NSMutableArray alloc] initWithArray:children];\n    }\n\n    NSArray *attributes = [element attributes];\n    if ([attributes count] > 0) {\n      unknownAttributes_ = [[NSMutableArray alloc] initWithArray:attributes];\n    }\n  }\n}\n\n// parseExtensionsForElement: is called by initWithXMLElement. It starts\n// from the current object and works up the chain of parents, grabbing\n// the declared extensions by each GDataObject in the ancestry and looking\n// at the current element to see if any of the declared extensions are present.\n\n- (void)parseExtensionsForElement:(NSXMLElement *)element {\n  Class classBeingParsed = [self class];\n\n  // For performance, we'll avoid looking up extension elements whose\n  // local names aren't present in the element.  We don't bother doing\n  // this for attribute extensions since those are so rare (most attributes\n  // are parsed just by local declaration in parseAttributesForElement:.)\n\n  NSArray *childLocalNames = [element valueForKeyPath:@\"children.localName\"];\n\n  // allow wildcard lookups\n  childLocalNames = [childLocalNames arrayByAddingObject:@\"*\"];\n\n  Class arrayClass = [NSArray class];\n\n  for (GDataObject * currentExtensionSupplier = self;\n       currentExtensionSupplier != nil;\n       currentExtensionSupplier = [currentExtensionSupplier parent]) {\n\n    // find all extensions in this supplier with the current class as the parent\n    NSArray *extnDecls = [currentExtensionSupplier extensionDeclarationsForParentClass:classBeingParsed];\n\n    if (extnDecls) {\n      for (GDataExtensionDeclaration *decl in extnDecls) {\n        // if we've not already found this class when parsing at an earlier supplier\n        Class extensionClass = [decl childClass];\n        if ([extensions_ objectForKey:extensionClass] == nil) {\n\n          // if this extension's local name really matches some child's local\n          // name (or this is an attribute extension)\n\n          NSString *declLocalName = [extensionClass extensionElementLocalName];\n          if ([childLocalNames containsObject:declLocalName]\n              || [decl isAttribute]) {\n\n            GDATA_DEBUG_ASSERT([extensionClass conformsToProtocol:@protocol(GDataExtension)],\n                      @\"%@ does not conform to GDataExtension protocol\",\n                      extensionClass);\n\n            NSString *namespaceURI = [extensionClass extensionElementURI];\n            NSString *qualifiedName = [self qualifiedNameForExtensionClass:extensionClass];\n\n            id objectOrArray = nil;\n\n            if ([decl isAttribute]) {\n              // parse for an attribute extension\n              NSString *str = [self stringForAttributeName:qualifiedName\n                                               fromElement:element];\n              if (str) {\n                id attr = [[[extensionClass alloc] init] autorelease];\n                [attr setStringValue:str];\n                objectOrArray = attr;\n              }\n\n            } else {\n              // parse for an element extension\n              objectOrArray = [self objectOrArrayForChildrenOfElement:element\n                                                        qualifiedName:qualifiedName\n                                                         namespaceURI:namespaceURI\n                                                          objectClass:extensionClass];\n            }\n\n            if ([objectOrArray isKindOfClass:arrayClass]) {\n              if ([(NSArray *)objectOrArray count] > 0) {\n\n                // save the non-empty array of extensions\n                [self setObjects:objectOrArray forExtensionClass:extensionClass];\n              }\n            } else if (objectOrArray != nil) {\n\n              // save the single extension\n              [self setObject:objectOrArray forExtensionClass:extensionClass];\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\n#pragma mark Local Attributes\n\n- (void)addLocalAttributeDeclarations:(NSArray *)attributeLocalNames {\n\n  // get or make the array which caches the attribute declarations for\n  // this class\n  if (attributeDeclarations_ == nil) {\n\n    Class currClass = [self class];\n    NSMutableDictionary *cache = [self attributeDeclarationsCache];\n    GDATA_DEBUG_ASSERT(cache != nil, @\"missing attrDeclsCache\");\n\n    // we keep a strong pointer to the array in the cache since the cache\n    // belongs to the feed or the topmost parent, and that may go away\n    attributeDeclarations_ = [[cache objectForKey:currClass] retain];\n    if (attributeDeclarations_ == nil) {\n      attributeDeclarations_ = [[NSMutableArray alloc] init];\n      [cache setObject:attributeDeclarations_ forKey:currClass];\n    }\n  }\n\n#if DEBUG\n  // check that no local attributes being declared have a prefix, except for\n  // the hardcoded xml: prefix. Namespaced attributes must be parsed and\n  // emitted manually, or be declared as GDataAttribute extensions;\n  // they cannot be handled as local attributes, since this class makes no\n  // attempt to keep track of namespace URIs for local attributes\n  for (NSString *attr in attributeLocalNames) {\n    GDATA_ASSERT([attr rangeOfString:@\":\"].location == NSNotFound\n                 || [attr hasPrefix:@\"xml:\"],\n                 @\"invalid namespaced local attribute: %@\", attr);\n  }\n#endif\n\n  [attributeDeclarations_ addObjectsFromArray:attributeLocalNames];\n}\n\n- (void)addAttributeDeclarationMarker:(NSString *)marker {\n\n  if (![attributeDeclarations_ containsObject:marker]) {\n\n    // add the marker\n    if (attributeDeclarations_ != nil) {\n\n      // no need to create the cache\n      [attributeDeclarations_ addObject:marker];\n    } else {\n\n      // create the cache by calling addLocalAttributeDeclarations:\n      NSArray *array = [NSArray arrayWithObject:marker];\n      [self addLocalAttributeDeclarations:array];\n    }\n  }\n}\n\n// attribute value getters\n- (NSString *)stringValueForAttribute:(NSString *)name {\n\n  GDATA_DEBUG_ASSERT([[self attributeDeclarations] containsObject:name],\n            @\"%@ getting undeclared attribute: %@\", [self class], name);\n\n  return [attributes_ valueForKey:name];\n}\n\n- (NSNumber *)intNumberForAttribute:(NSString *)name {\n\n  NSString *str = [self stringValueForAttribute:name];\n  if ([str length] > 0) {\n    NSNumber *number = [NSNumber numberWithInt:[str intValue]];\n    return number;\n  }\n  return nil;\n}\n\n- (NSNumber *)doubleNumberForAttribute:(NSString *)name {\n\n  NSString *str = [self stringValueForAttribute:name];\n  return [GDataUtilities doubleNumberOrInfForString:str];\n}\n\n- (NSNumber *)longLongNumberForAttribute:(NSString *)name {\n\n  NSString *str = [self stringValueForAttribute:name];\n  if (str) {\n    long long val = [str longLongValue];\n    NSNumber *number = [NSNumber numberWithLongLong:val];\n    return number;\n  }\n  return nil;\n}\n\n- (NSDecimalNumber *)decimalNumberForAttribute:(NSString *)name {\n\n  NSString *str = [self stringValueForAttribute:name];\n  if ([str length] > 0) {\n\n    // require periods as the separator\n    NSLocale *usLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@\"en_US\"] autorelease];\n    NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:str\n                                    locale:usLocale];\n    return number;\n  }\n  return nil;\n}\n\n- (GDataDateTime *)dateTimeForAttribute:(NSString *)name  {\n\n  NSString *str = [self stringValueForAttribute:name];\n  if ([str length] > 0) {\n    GDataDateTime *dateTime = [GDataDateTime dateTimeWithRFC3339String:str];\n    return dateTime;\n  }\n  return nil;\n}\n\n- (BOOL)boolValueForAttribute:(NSString *)name defaultValue:(BOOL)defaultVal {\n  NSString *str = [self stringValueForAttribute:name];\n  BOOL isTrue;\n\n  if (defaultVal) {\n    // default to true, so true if attribute is missing or is not \"false\"\n    isTrue = (str == nil\n              || [str caseInsensitiveCompare:@\"false\"] != NSOrderedSame);\n  } else {\n    // default to false, so true only if attribute is present and \"true\"\n    isTrue = (str != nil\n              && [str caseInsensitiveCompare:@\"true\"] == NSOrderedSame);\n  }\n  return isTrue;\n}\n\n// attribute value setters\n- (void)setStringValue:(NSString *)str forAttribute:(NSString *)name {\n\n  GDATA_DEBUG_ASSERT([[self attributeDeclarations] containsObject:name],\n            @\"%@ setting undeclared attribute: %@\", [self class], name);\n\n  if (attributes_ == nil) {\n    attributes_ = [[NSMutableDictionary alloc] init];\n  }\n\n  [attributes_ setValue:str forKey:name];\n}\n\n- (void)setBoolValue:(BOOL)flag defaultValue:(BOOL)defaultVal forAttribute:(NSString *)name {\n  NSString *str;\n  if (defaultVal) {\n    // default to true, so include attribute only if false\n    str = (flag ? nil : @\"false\");\n  } else {\n    // default to false, so include attribute only if true\n    str = (flag ? @\"true\" : nil);\n  }\n  [self setStringValue:str forAttribute:name];\n}\n\n- (void)setExplicitBoolValue:(BOOL)flag forAttribute:(NSString *)name {\n  NSString *value = (flag ? @\"true\" : @\"false\");\n  [self setStringValue:value forAttribute:name];\n}\n\n- (void)setDecimalNumberValue:(NSDecimalNumber *)num forAttribute:(NSString *)name {\n\n  // for most NSNumbers, just calling -stringValue is fine, but for decimal\n  // numbers we want to specify that a period be the separator\n  NSLocale *usLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@\"en_US\"] autorelease];\n\n  NSString *str = [num descriptionWithLocale:usLocale];\n  [self setStringValue:str forAttribute:name];\n}\n\n- (void)setDateTimeValue:(GDataDateTime *)cdate forAttribute:(NSString *)name {\n  NSString *str = [cdate RFC3339String];\n  [self setStringValue:str forAttribute:name];\n}\n\n\n// parseAttributesForElement: is called by initWithXMLElement.\n// It stores the value of all declared & present attributes in the dictionary\n- (void)parseAttributesForElement:(NSXMLElement *)element {\n\n  // for better performance, look up the values for declared attributes only\n  // if they are really present in the node\n  NSArray *attributes = [element attributes];\n  NSArray *attributeDeclarations = [self attributeDeclarations];\n\n  for (NSXMLNode *attribute in attributes) {\n\n    NSString *attrName = [attribute name];\n    if ([attributeDeclarations containsObject:attrName]) {\n\n      NSString *str = [attribute stringValue];\n      if (str != nil) {\n        [self setStringValue:str forAttribute:attrName];\n      }\n\n      [self handleParsedAttribute:attribute];\n    }\n  }\n}\n\n// XML generator for local attributes\n- (void)addAttributesToElement:(NSXMLElement *)element {\n\n  for (NSString *name in attributes_) {\n\n    NSString *value = [attributes_ valueForKey:name];\n    if (value != nil) {\n      [self addToElement:element attributeValueIfNonNil:value withName:name];\n    }\n  }\n}\n\n// attribute comparison: subclasses may implement attributesIgnoredForEquality:\n// to specify attributes not to be considered for equality comparison\n\n- (BOOL)hasAttributesEqualToAttributesOf:(GDataObject *)other {\n\n  NSArray *attributesToIgnore = [self attributesIgnoredForEquality];\n\n  NSDictionary *selfAttrs = [self attributes];\n  NSDictionary *otherAttrs = [other attributes];\n\n  if ([attributesToIgnore count] == 0) {\n    // none to ignore; just compare attribute dictionaries\n    return AreEqualOrBothNil(selfAttrs, otherAttrs);\n  }\n\n  // step through attributes, comparing each non-ignored attribute\n  // to look for a mismatch\n  NSArray *attributeDeclarations = [self attributeDeclarations];\n  for (NSString *attrKey in attributeDeclarations) {\n\n    if (![attributesToIgnore containsObject:attrKey]) {\n\n      NSString *val1 = [selfAttrs objectForKey:attrKey];\n      NSString *val2 = [otherAttrs objectForKey:attrKey];\n\n      if (!AreEqualOrBothNil(val1, val2)) {\n        return NO;\n      }\n    }\n  }\n  return YES;\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n  // subclasses may override this to specify attributes that should\n  // not be considered when comparing objects for equality\n  return nil;\n}\n\n#pragma mark Content Value\n\n- (void)addContentValueDeclaration {\n  // derived classes should call this if they want the element's content\n  // to be automatically parsed as a string\n  [self addAttributeDeclarationMarker:kContentValueDeclarationMarker];\n}\n\n- (BOOL)hasDeclaredContentValue {\n  NSMutableArray *attrDecls = [self attributeDeclarations];\n  BOOL flag = [attrDecls containsObject:kContentValueDeclarationMarker];\n  return flag;\n}\n\n- (void)setContentStringValue:(NSString *)str {\n\n  GDATA_ASSERT([self hasDeclaredContentValue], @\"%@ setting undeclared content value\",\n               [self class]);\n\n  [contentValue_ autorelease];\n  contentValue_ = [str copy];\n}\n\n- (NSString *)contentStringValue {\n\n  GDATA_ASSERT([self hasDeclaredContentValue], @\"%@ getting undeclared content value\",\n               [self class]);\n\n  return contentValue_;\n\n}\n\n// parseContentForElement: is called by initWithXMLElement.\n// This stores the content value parsed from the element.\n- (void)parseContentValueForElement:(NSXMLElement *)element {\n\n  if ([self hasDeclaredContentValue]) {\n    [self setContentStringValue:[self stringValueFromElement:element]];\n  }\n}\n\n// XML generator for content\n- (void)addContentValueToElement:(NSXMLElement *)element {\n\n  if ([self hasDeclaredContentValue]) {\n    NSString *str = [self contentStringValue];\n    if ([str length] > 0) {\n      [element addStringValue:str];\n    }\n  }\n}\n\n- (BOOL)hasContentValueEqualToContentValueOf:(GDataObject *)other {\n\n  if (![self hasDeclaredContentValue]) {\n    // no content being stored\n    return YES;\n  }\n\n  return AreEqualOrBothNil([self contentStringValue], [other contentStringValue]);\n}\n\n#pragma mark Child XML Elements\n\n- (void)addChildXMLElementsDeclaration {\n  // derived classes should call this if they want the element's unparsed\n  // XML children to be accessible later\n  [self addAttributeDeclarationMarker:kChildXMLDeclarationMarker];\n}\n\n- (BOOL)hasDeclaredChildXMLElements {\n  NSMutableArray *attrDecls = [self attributeDeclarations];\n  BOOL flag = [attrDecls containsObject:kChildXMLDeclarationMarker];\n  return flag;\n}\n\n- (NSArray *)childXMLElements {\n  if ([childXMLElements_ count] == 0) {\n    return nil;\n  }\n  return childXMLElements_;\n}\n\n- (void)setChildXMLElements:(NSArray *)array {\n  GDATA_DEBUG_ASSERT([self hasDeclaredChildXMLElements],\n                     @\"%@ setting undeclared XML values\", [self class]);\n\n  [childXMLElements_ release];\n  childXMLElements_ = [array mutableCopy];\n}\n\n- (void)addChildXMLElement:(NSXMLNode *)node {\n  GDATA_DEBUG_ASSERT([self hasDeclaredChildXMLElements],\n                     @\"%@ adding undeclared XML values\", [self class]);\n\n  if (childXMLElements_ == nil) {\n    childXMLElements_ = [[NSMutableArray alloc] init];\n  }\n  [childXMLElements_ addObject:node];\n}\n\n// keepChildXMLElementsForElement: is called by initWithXMLElement.\n// This stores a copy of the element's child XMLElements.\n- (void)keepChildXMLElementsForElement:(NSXMLElement *)element {\n\n  if ([self hasDeclaredChildXMLElements]) {\n\n    NSArray *children = [element children];\n    if (children != nil) {\n\n      // save only top-level nodes that are elements\n      for (NSXMLNode *childNode in children) {\n        if ([childNode kind] == NSXMLElementKind) {\n          if (childXMLElements_ == nil) {\n            childXMLElements_ = [[NSMutableArray alloc] init];\n          }\n          NSXMLNode *childCopy = [[childNode copy] autorelease];\n          [childXMLElements_ addObject:childCopy];\n\n          [self handleParsedElement:childNode];\n        }\n      }\n    }\n  }\n}\n\n// XML generator for kept child XML elements\n- (void)addChildXMLElementsToElement:(NSXMLElement *)element {\n\n  if ([self hasDeclaredChildXMLElements]) {\n\n    NSArray *childXMLElements = [self childXMLElements];\n    if (childXMLElements != nil) {\n\n      for (NSXMLNode *child in childXMLElements) {\n        [element addChild:child];\n      }\n    }\n  }\n}\n\n- (BOOL)hasChildXMLElementsEqualToChildXMLElementsOf:(GDataObject *)other {\n\n  if (![self hasDeclaredChildXMLElements]) {\n    // no values being stored\n    return YES;\n  }\n  return AreEqualOrBothNil([self childXMLElements], [other childXMLElements]);\n}\n\n#pragma mark Dynamic GDataObject\n\n// Dynamic object generation is used when the class being created is nil.\n//\n// These maps are populated by +load routines in feeds and entries.\n// They specify category elements which identify the class of feed or entry\n// to be created for a blob of XML.\n\nstatic NSString *const kCategoryTemplate = @\"{\\\"%@\\\":\\\"%@\\\"}\";\n\n\n// registerClass:inMap:forCategoryWithScheme:term: does the work for\n// registerFeedClass: and registerEntryClass:\n//\n// This adds the class to the {\"scheme\":\"term\"} map, ensuring\n// that it won't conflict with a previous class or category\n// entry\n\n+ (void)registerClass:(Class)theClass\n                inMap:(NSMutableDictionary **)map\nforCategoryWithScheme:(NSString *)scheme\n                 term:(NSString *)term {\n\n  // there's no autorelease pool in place at +load time, so we'll create our own\n  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\n\n  if (*map == nil) {\n    *map = GDataCreateStaticDictionary();\n  }\n\n  // ensure this is a unique registration\n  GDATA_DEBUG_ASSERT(nil == [*map objectForKey:theClass],\n               @\"%@ already registered\", theClass);\n\n#if !NS_BLOCK_ASSERTIONS\n  Class prevClass = [self classForCategoryWithScheme:scheme\n                                                term:term\n                                             fromMap:*map];\n  GDATA_ASSERT(prevClass == nil, @\"%@ registration conflicts with %@\",\n               theClass, prevClass);\n#endif\n\n  // we have a map from the key \"scheme:term\" to the class\n  //\n  // generally, scheme will be nil or kGDataCategoryScheme, so we'll\n  // use just the term as the key for those categories, avoiding\n  // the need to format a string when looking up\n\n  NSString *key;\n  if (scheme == nil || [scheme isEqual:kGDataCategoryScheme]) {\n    key = term;\n  } else {\n    key = [NSString stringWithFormat:kCategoryTemplate,\n           scheme, term ? term : @\"\"];\n  }\n\n  [*map setValue:theClass forKey:key];\n\n  // We drain here to keep the clang static analyzer quiet.\n  [pool drain];\n}\n\n\n// classForCategoryWithScheme does the work for feedClassForCategory\n// and entryClassForCategory.  This method searches the entry\n// or feed map for a class with a matching category.\n//\n// If the registration of the class specified a value, then the corresponding\n// parameter values |scheme| or |term| must match and not be nil.\n+ (Class)classForCategoryWithScheme:(NSString *)scheme\n                               term:(NSString *)term\n                            fromMap:(NSDictionary *)map {\n\n  // |scheme| and |term| are from the XML that we're using to look up\n  // a registered class.  The |term| value should be non-nil,\n  // though the values stored in the map may have nil scheme or term.\n  //\n  // if the registered scheme was nil or kGDataCategoryScheme then the key\n  // is just the term value.\n\n  NSString *key = term;\n  Class result = (Class)[map objectForKey:key];\n  if (result) return result;\n\n  if (scheme) {\n    key = [NSString stringWithFormat:kCategoryTemplate, scheme, term];\n    result = (Class)[map objectForKey:key];\n    if (result) return result;\n\n    key = [NSString stringWithFormat:kCategoryTemplate, scheme, @\"\"];\n    result = (Class)[map objectForKey:key];\n    if (result) return result;\n  }\n\n  return nil;\n}\n\n// objectClassForXMLElement: returns a found registered feed\n// or entry class for the XML according to its contained category,\n// or an Atom service document class\n//\n// If no registered class is found with a matching category,\n// this returns GDataFeedBase for feed elements, GDataEntryBase\n// for entry elements.\n+ (Class)objectClassForXMLElement:(NSXMLElement *)element {\n\n  Class result = nil;\n  NSString *elementName = [element localName];\n  BOOL isFeed = [elementName isEqual:@\"feed\"];\n  BOOL isEntry = [elementName isEqual:@\"entry\"];\n\n  if (isFeed || isEntry) {\n    // get the kind attribute, and see if it matches a registered feed or entry\n    // class\n    NSXMLNode *kindAttr = [element attributeForLocalName:@\"kind\"\n                                                     URI:kGDataNamespaceGData];\n    NSString *kind = [kindAttr stringValue];\n\n    if (kind) {\n      if (isFeed) {\n        result = [GDataFeedBase feedClassForKindAttributeValue:kind];\n      } else {\n        result = [GDataEntryBase entryClassForKindAttributeValue:kind];\n      }\n    }\n\n    if (result == nil) {\n      // step through the feed or entry's category elements, looking for one\n      // that matches a registered feed or entry class\n      //\n      // category elements look like <category scheme=\"blah\" term=\"blahblah\"/>\n      // and there may be more than one\n\n      NSArray *categories = [element elementsForLocalName:@\"category\"\n                                                      URI:kGDataNamespaceAtom];\n      if ([categories count] == 0) {\n        NSString *atomPrefix = [element resolvePrefixForNamespaceURI:kGDataNamespaceAtom];\n        if ([atomPrefix length] == 0) {\n          categories = [element elementsForName:@\"category\"];\n        }\n      }\n\n      for (NSXMLElement *categoryNode in categories) {\n\n        NSString *scheme = [[categoryNode attributeForName:@\"scheme\"] stringValue];\n        NSString *term = [[categoryNode attributeForName:@\"term\"] stringValue];\n\n        if (scheme || term) {\n          // we have a scheme or a term, so look for a registered class\n          if (isFeed) {\n            result = [GDataFeedBase feedClassForCategoryWithScheme:scheme\n                                                              term:term];\n          } else {\n            result = [GDataEntryBase entryClassForCategoryWithScheme:scheme\n                                                                    term:term];\n          }\n          if (result) {\n            break;\n          }\n        }\n      }\n    }\n  }\n\n  if (result == nil) {\n    if (isFeed) {\n      // default to returning a feed base class\n      result = [GDataFeedBase class];\n    } else if (isEntry) {\n      // default to returning this feed's entry base class\n      if ([self isSubclassOfClass:[GDataFeedBase class]]) {\n        result = (Class)[self performSelector:@selector(defaultClassForEntries)];\n      } else {\n        result = [GDataEntryBase class];\n      }\n    } else if ([elementName isEqual:@\"service\"]) {\n      // introspection - return service document, if the class is available\n      NSString *serviceDocClassName = @\"GDataAtomServiceDocument\";\n\n  #ifdef GDATA_TARGET_NAMESPACE\n      // prepend the class name prefix\n      serviceDocClassName = [NSString stringWithFormat:@\"%s_%@\",\n                            GDATA_TARGET_NAMESPACE_STRING, serviceDocClassName];\n  #endif\n\n      result = NSClassFromString(serviceDocClassName);\n\n      GDATA_DEBUG_ASSERT(result != nil, @\"service class %@ unavailable\",\n                         serviceDocClassName);\n    } else {\n      // this element is not a feed, entry, or service class; give up\n    }\n  }\n\n  return result;\n}\n\n@end\n\n@implementation NSXMLElement (GDataObjectExtensions)\n\n- (void)addStringValue:(NSString *)str {\n  // NSXMLNode's setStringValue: wipes out other children, so we'll use this\n  // instead\n\n  // filter out non-whitespace control characters\n  NSString *filtered = [GDataUtilities stringWithControlsFilteredForString:str];\n\n  NSXMLNode *strNode = [NSXMLNode textWithStringValue:filtered];\n  [self addChild:strNode];\n}\n\n+ (id)elementWithName:(NSString *)name attributeName:(NSString *)attrName attributeValue:(NSString *)attrValue {\n\n  NSString *filtered = [GDataUtilities stringWithControlsFilteredForString:attrValue];\n\n  NSXMLNode *attr = [NSXMLNode attributeWithName:attrName stringValue:filtered];\n  NSXMLElement *element = [NSXMLNode elementWithName:name];\n  [element addAttribute:attr];\n  return element;\n}\n\n@end\n\n@implementation GDataExtensionDeclaration\n\n- (id)initWithParentClass:(Class)parentClass\n               childClass:(Class)childClass\n              isAttribute:(BOOL)isAttribute {\n  self = [super init];\n  if (self) {\n    parentClass_ = parentClass;\n    childClass_ = childClass;\n    isAttribute_ = isAttribute;\n  }\n  return self;\n}\n\n- (NSString *)description {\n  return [NSString stringWithFormat:@\"%@: {%@ can contain %@}%@\",\n    [self class], parentClass_, childClass_,\n          isAttribute_ ? @\" (attribute)\" : @\"\"];\n}\n\n- (Class)parentClass {\n  return parentClass_;\n}\n\n- (Class)childClass {\n  return childClass_;\n}\n\n- (BOOL)isAttribute {\n  return isAttribute_;\n}\n\n- (BOOL)isEqual:(GDataExtensionDeclaration *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataExtensionDeclaration class]]) return NO;\n\n  return AreEqualOrBothNil((id)[self parentClass], (id)[other parentClass])\n    && AreEqualOrBothNil((id)[self childClass], (id)[other childClass])\n    && [self isAttribute] == [other isAttribute];\n}\n\n- (NSUInteger)hash {\n  return (NSUInteger) (void *) [GDataExtensionDeclaration class];\n}\n\n@end\n\n@implementation GDataAttribute\n\n// This is the base class for attribute extensions.\n//\n// Functionally, this just stores a string value for the attribute.\n\n+ (GDataAttribute *)attributeWithValue:(NSString *)str {\n  return [[[self alloc] initWithValue:str] autorelease];\n}\n\n- (id)initWithValue:(NSString *)value {\n  self = [super init];\n  if (self) {\n    [self setStringValue:value];\n  }\n  return self;\n}\n\n- (void)dealloc {\n  [value_ release];\n  [super dealloc];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataAttribute* newObj = [[[self class] allocWithZone:zone] init];\n  [newObj setStringValue:[self stringValue]];\n  return newObj;\n}\n\n- (NSString *)description {\n\n  NSString *name;\n\n  NSString *localName = [[self class] extensionElementLocalName];\n  NSString *prefix = [[self class] extensionElementPrefix];\n  if (prefix) {\n    name = [NSString stringWithFormat:@\"%@:%@\", prefix, localName];\n  } else {\n    name = localName;\n  }\n\n  return [NSString stringWithFormat:@\"%@ %p: {%@=%@}\",\n          [self class], self, name, [self stringValue]];\n}\n\n- (BOOL)isEqual:(GDataAttribute *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataAttribute class]]) return NO;\n\n  return AreEqualOrBothNil([self stringValue], [other stringValue]);\n}\n\n- (NSUInteger)hash {\n  return (NSUInteger) (void *) [GDataAttribute class];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [value_ autorelease];\n  value_ = [str copy];\n}\n\n- (NSString *)stringValue {\n  return value_;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataAtomPubControl.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataAtomPubControl.h\n//\n\n#import \"GDataObject.h\"\n\n// For app:control, like:\n//   <app:control><app:draft>yes</app:draft></app:control>\n\n@interface GDataAtomPubControl : GDataObject <GDataExtension>\n+ (GDataAtomPubControl *)atomPubControl;\n+ (GDataAtomPubControl *)atomPubControlWithIsDraft:(BOOL)isDraft;\n\n- (BOOL)isDraft;\n- (void)setIsDraft:(BOOL)flag;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataAtomPubControl.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataAtomPubControl.m\n//\n\n#import \"GDataAtomPubControl.h\"\n#import \"GDataValueConstruct.h\"\n\n// app:draft, like\n//   <app:draft>yes<app:draft>\n\n@interface GDataAtomPubDraft : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataAtomPubDraft\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtomPub; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPubPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"draft\"; }\n@end\n\n@implementation GDataAtomPubControl\n\n// For app:control, like:\n//   <app:control><app:draft>yes</app:draft></app:control>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtomPub; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPubPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"control\"; }\n\n+ (GDataAtomPubControl *)atomPubControl {\n  GDataAtomPubControl *obj = [self object];\n\n  // add the \"app\" namespace\n  NSString *nsURI = [[self class] extensionElementURI];\n  NSDictionary *namespaceDict = [NSDictionary dictionaryWithObject:nsURI\n                                                            forKey:kGDataNamespaceAtomPubPrefix];\n  [obj setNamespaces:namespaceDict];\n\n  return obj;\n}\n\n+ (GDataAtomPubControl *)atomPubControlWithIsDraft:(BOOL)isDraft {\n  GDataAtomPubControl *obj = [self atomPubControl];\n  [obj setIsDraft:isDraft];\n  return obj;\n}\n\n+ (NSString *)defaultServiceVersion {\n  return @\"2.0\";\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  [self addExtensionDeclarationForParentClass:[self class]\n                                   childClass:[GDataAtomPubDraft class]];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [NSMutableArray array];\n\n  NSString *str = ([self isDraft] ? @\"yes\" : @\"no\");\n  [self addToArray:items objectDescriptionIfNonNil:str\n          withName:@\"isDraft\"];\n\n  return items;\n}\n#endif\n\n- (BOOL)isDraft {\n  GDataValueElementConstruct *obj;\n  obj = [self objectForExtensionClass:[GDataAtomPubDraft class]];\n\n  NSString *str = [obj stringValue];\n  BOOL isDraft = (str != nil\n                  && [str caseInsensitiveCompare:@\"yes\"] == NSOrderedSame);\n  return isDraft;\n}\n\n- (void)setIsDraft:(BOOL)isDraft {\n\n  id obj = nil;\n  if (isDraft) {\n    obj = [GDataAtomPubDraft valueWithString:@\"yes\"];\n  }\n\n  [self setObject:obj forExtensionClass:[GDataAtomPubDraft class]];\n}\n\n@end\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBaseElements.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataBaseElements.h\n//\n// Elements used by the GDataEntryBase and GDataFeedBase classes\n//\n\n#import \"GDataCategory.h\"\n#import \"GDataPerson.h\"\n#import \"GDataTextConstruct.h\"\n#import \"GDataValueConstruct.h\"\n#import \"GDataEntryContent.h\"\n\n// GData\n\n@interface GDataResourceID : GDataValueElementConstruct <GDataExtension>\n@end\n\n// Atom\n\n@interface GDataAtomID : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomPublishedDate : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomUpdatedDate : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomTitle : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomSubtitle : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomSummary : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomContent : GDataEntryContent <GDataExtension>\n@end\n\n@interface GDataAtomRights : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomAuthor : GDataPerson <GDataExtension>\n@end\n\n@interface GDataAtomContributor : GDataPerson <GDataExtension>\n@end\n\n@interface GDataAtomIcon : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomLogo : GDataValueElementConstruct <GDataExtension>\n@end\n\n// AtomPub\n\n@interface GDataAtomPubEditedDate : GDataValueElementConstruct <GDataExtension>\n@end\n\n// OpenSearch 1.1, adopted for GData version 2\n\n@interface GDataOpenSearchTotalResults : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataOpenSearchStartIndex : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataOpenSearchItemsPerPage : GDataValueElementConstruct <GDataExtension>\n@end\n\n// Attributes\n@interface GDataETagAttribute : GDataAttribute <GDataExtension>\n@end\n\n@interface GDataFieldsAttribute : GDataAttribute <GDataExtension>\n@end\n\n@interface GDataKindAttribute : GDataAttribute <GDataExtension>\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBaseElements.m",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataBaseElements.m\n//\n// Elements used by the GDataEntryBase and GDataFeedBase classes\n//\n\n#import \"GDataBaseElements.h\"\n#import \"GDataLink.h\"\n\n#pragma mark gd\n\n@implementation GDataResourceID\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"resourceId\"; }\n@end\n\n#pragma mark Atom\n\n@implementation GDataAtomID\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"id\"; }\n@end\n\n@implementation GDataAtomPublishedDate\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"published\"; }\n@end\n\n@implementation GDataAtomUpdatedDate\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"updated\"; }\n@end\n\n@implementation GDataAtomTitle\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"title\"; }\n@end\n\n@implementation GDataAtomSubtitle\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"subtitle\"; }\n@end\n\n@implementation GDataAtomSummary\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"summary\"; }\n@end\n\n@implementation GDataAtomContent\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"content\"; }\n@end\n\n@implementation GDataAtomRights\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"rights\"; }\n@end\n\n@implementation GDataAtomAuthor\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"author\"; }\n\n\n- (void)addExtensionDeclarations {\n  \n  [super addExtensionDeclarations];\n  \n  [self addExtensionDeclarationForParentClass:[self class]\n                                 childClasses:[GDataLink class],\n   nil];\n}\n\n@end\n\n@implementation GDataAtomContributor\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"contributor\"; }\n@end\n\n@implementation GDataAtomIcon\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"icon\"; }\n@end\n\n@implementation GDataAtomLogo\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"logo\"; }\n@end\n\n#pragma mark AtomPub\n\n// standard AtomPub namespace\n@implementation GDataAtomPubEditedDate\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtomPub; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPubPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"edited\"; }\n@end\n\n#pragma mark OpenSearch\n\n// OpenSearch 1.1, adopted for GData version 2\n@implementation GDataOpenSearchTotalResults\n+ (NSString *)extensionElementURI       { return kGDataNamespaceOpenSearch; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceOpenSearchPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"totalResults\"; }\n@end\n\n@implementation GDataOpenSearchStartIndex\n+ (NSString *)extensionElementURI       { return kGDataNamespaceOpenSearch; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceOpenSearchPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"startIndex\"; }\n@end\n\n@implementation GDataOpenSearchItemsPerPage\n+ (NSString *)extensionElementURI       { return kGDataNamespaceOpenSearch; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceOpenSearchPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"itemsPerPage\"; }\n@end\n\n// Attributes\n\n@implementation GDataETagAttribute\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"etag\"; }\n@end\n\n@implementation GDataFieldsAttribute\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"fields\"; }\n@end\n\n@implementation GDataKindAttribute\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"kind\"; }\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchID.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchID.h\n//\n\n#import \"GDataObject.h\"\n\n// For batchID, like:\n//   <batch:id>item2</batch:id>\n\n@interface GDataBatchID : GDataObject <GDataExtension> {\n}\n\n+ (GDataBatchID *)batchIDWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchID.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchID.m\n//\n\n#import \"GDataBatchID.h\"\n\n@implementation GDataBatchID\n\n// For batchID, like:\n//   <batch:id>item2</batch:id>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceBatch; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceBatchPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"id\"; }\n\n\n+ (GDataBatchID *)batchIDWithString:(NSString *)str {\n  GDataBatchID *obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  [self addContentValueDeclaration];\n}\n\n- (NSString *)stringValue {\n  return [self contentStringValue];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchInterrupted.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchInterrupted.h\n//\n\n#import \"GDataObject.h\"\n\n\n// for batch Interrupteds, like\n//  <batch:interrupted reason=\"reason\" success=\"N\" failures=\"N\" parsed=\"N\" />\n\n@interface GDataBatchInterrupted : GDataObject <GDataExtension> {\n}\n\n+ (GDataBatchInterrupted *)batchInterrupted;\n\n- (NSString *)reason;\n- (void)setReason:(NSString *)str;\n\n- (NSNumber *)successCount;\n- (void)setSuccessCount:(NSNumber *)val;\n\n- (NSNumber *)errorCount;\n- (void)setErrorCount:(NSNumber *)val;\n\n- (NSNumber *)totalCount;\n- (void)setTotalCount:(NSNumber *)val;\n\n- (NSString *)contentType;\n- (void)setContentType:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchInterrupted.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchInterrupted.m\n//\n\n#import \"GDataBatchInterrupted.h\"\n\nstatic NSString* const kReasonAttr = @\"reason\";\nstatic NSString* const kSuccessAttr = @\"success\";\nstatic NSString* const kFailuresAttr = @\"failures\";\nstatic NSString* const kParsedAttr = @\"parsed\";\nstatic NSString* const kContentTypeAttr = @\"content-type\";\n\n@implementation GDataBatchInterrupted\n\n// for batch Interrupteds, like\n//  <batch:interrupted reason=\"reason\" success=\"N\" failures=\"N\" parsed=\"N\" />\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceBatch; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceBatchPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"interrupted\"; }\n\n+ (GDataBatchInterrupted *)batchInterrupted {\n  GDataBatchInterrupted* obj = [self object];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kReasonAttr, kSuccessAttr, kFailuresAttr, kParsedAttr,\n                    kContentTypeAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [NSMutableArray array];\n\n  [self addAttributeDescriptionsToArray:items];\n  [self addContentDescriptionToArray:items withName:@\"content\"];\n\n  return items;\n}\n#endif\n\n- (NSString *)reason {\n  return [self stringValueForAttribute:kReasonAttr];\n}\n\n- (void)setReason:(NSString *)str {\n  [self setStringValue:str forAttribute:kReasonAttr];\n}\n\n- (NSNumber *)successCount {\n  return [self intNumberForAttribute:kSuccessAttr];\n}\n\n- (void)setSuccessCount:(NSNumber *)val {\n  [self setStringValue:[val stringValue] forAttribute:kSuccessAttr];\n}\n\n- (NSNumber *)errorCount {\n  return [self intNumberForAttribute:kFailuresAttr];\n}\n\n- (void)setErrorCount:(NSNumber *)val {\n  [self setStringValue:[val stringValue] forAttribute:kFailuresAttr];\n}\n\n- (NSNumber *)totalCount {\n  return [self intNumberForAttribute:kParsedAttr];\n}\n\n- (void)setTotalCount:(NSNumber *)val {\n  [self setStringValue:[val stringValue] forAttribute:kParsedAttr];\n}\n\n- (NSString *)contentType {\n  return [self stringValueForAttribute:kContentTypeAttr];\n}\n\n- (void)setContentType:(NSString *)str {\n  [self setStringValue:str forAttribute:kContentTypeAttr];\n}\n\n- (NSString *)stringValue {\n  return [self contentStringValue];;\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchOperation.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchOperation.h\n//\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATABATCH_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataBatchOperationInsert _INITIALIZE_AS(@\"insert\");\n_EXTERN NSString* const kGDataBatchOperationUpdate _INITIALIZE_AS(@\"update\");\n_EXTERN NSString* const kGDataBatchOperationDelete _INITIALIZE_AS(@\"delete\");\n_EXTERN NSString* const kGDataBatchOperationQuery  _INITIALIZE_AS(@\"query\");\n\n\n// for batch operations, like\n//  <batch:operation type=\"insert\"/>\n@interface GDataBatchOperation : GDataObject <GDataExtension>\n\n+ (GDataBatchOperation *)batchOperationWithType:(NSString *)type;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchOperation.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchOperation.m\n//\n\n#define GDATABATCH_DEFINE_GLOBALS 1\n#import \"GDataBatchOperation.h\"\n\nstatic NSString* const kTypeAttr = @\"type\";\n\n@implementation GDataBatchOperation\n// for batch operations, like\n//  <batch:operation type=\"insert\"/>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceBatch; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceBatchPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"operation\"; }\n\n+ (GDataBatchOperation *)batchOperationWithType:(NSString *)type {\n  GDataBatchOperation* obj = [self object];\n  [obj setType:type];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObject:kTypeAttr];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n- (NSString *)type {\n  return [self stringValueForAttribute:kTypeAttr];\n}\n\n- (void)setType:(NSString *)str {\n  [self setStringValue:str forAttribute:kTypeAttr];\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchStatus.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchStatus.h\n//\n\n#import \"GDataObject.h\"\n\n@class GDataFeedBase;\n\n// a batch response status\n//  <batch:status  code=\"404\"\n//    reason=\"Bad request\"\n//    content-type=\"application/xml\">\n//    <errors>\n//      <error type=\"request\" reason=\"Cannot find item\"/>\n//    </errors>\n//  </batch:status>\n\n@interface GDataBatchStatus : GDataObject <GDataExtension> {\n}\n\n+ (GDataBatchStatus *)batchStatusWithCode:(NSInteger)code\n                                   reason:(NSString *)reason;\n\n- (NSString *)reason;\n- (void)setReason:(NSString *)str;\n\n- (NSNumber *)code;\n- (void)setCode:(NSNumber *)val;\n\n- (NSString *)contentType;\n- (void)setContentType:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataBatchStatus.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchStatus.m\n//\n\n\n#import \"GDataBatchStatus.h\"\n\nstatic NSString *const kCodeAttr = @\"code\";\nstatic NSString *const kReasonAttr = @\"reason\";\nstatic NSString *const kContentTypeAttr = @\"content-type\";\n\n\n@implementation GDataBatchStatus\n// a batch response status\n//  <batch:status  code=\"404\"\n//    reason=\"Bad request\"\n//    content-type=\"application/xml\">\n//    <errors>\n//      <error type=\"request\" reason=\"Cannot find item\"/>\n//    </errors>\n//  </batch:status>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceBatch; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceBatchPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"status\"; }\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kCodeAttr, kReasonAttr, kContentTypeAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n+ (GDataBatchStatus *)batchStatusWithCode:(NSInteger)code\n                                   reason:(NSString *)reason {\n  GDataBatchStatus* obj = [self object];\n  [obj setReason:reason];\n  [obj setCode:[NSNumber numberWithInt:(int)code]];\n  return obj;\n}\n\n- (NSString *)reason {\n  return [self stringValueForAttribute:kReasonAttr];\n}\n\n- (void)setReason:(NSString *)str {\n  [self setStringValue:str forAttribute:kReasonAttr];\n}\n\n- (NSNumber *)code {\n  return [self intNumberForAttribute:kCodeAttr];\n}\n\n- (void)setCode:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kCodeAttr];\n}\n\n- (NSString *)contentType {\n  return [self stringValueForAttribute:kContentTypeAttr];\n}\n\n- (void)setContentType:(NSString *)str {\n  [self setStringValue:str forAttribute:kContentTypeAttr];\n}\n\n- (NSString *)stringValue {\n  return [self contentStringValue];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n@end\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataCategory.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataCategory.h\n//\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATACATEGORY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataCategoryLabelScheme _INITIALIZE_AS(@\"http://schemas.google.com/g/2005/labels\");\n\n_EXTERN NSString* const kGDataCategoryLabelStarred          _INITIALIZE_AS(@\"starred\");\n_EXTERN NSString* const kGDataCategoryLabelTrashed          _INITIALIZE_AS(@\"trashed\");\n_EXTERN NSString* const kGDataCategoryLabelPublished        _INITIALIZE_AS(@\"published\");\n_EXTERN NSString* const kGDataCategoryLabelPrivate          _INITIALIZE_AS(@\"private\");\n_EXTERN NSString* const kGDataCategoryLabelMine             _INITIALIZE_AS(@\"mine\");\n_EXTERN NSString* const kGDataCategoryLabelSharedWithDomain _INITIALIZE_AS(@\"shared-with-domain\");\n_EXTERN NSString* const kGDataCategoryLabelHidden           _INITIALIZE_AS(@\"hidden\");\n_EXTERN NSString* const kGDataCategoryLabelViewed           _INITIALIZE_AS(@\"viewed\");\n\n// for categories, like\n//  <category scheme=\"http://schemas.google.com/g/2005#kind\"\n//        term=\"http://schemas.google.com/g/2005#event\"/>\n@interface GDataCategory : GDataObject <GDataExtension>\n\n+ (GDataCategory *)categoryWithScheme:(NSString *)scheme\n                                 term:(NSString *)term;\n\n+ (GDataCategory *)categoryWithLabel:(NSString *)label;\n\n- (NSString *)scheme;\n- (void)setScheme:(NSString *)str;\n- (NSString *)term;\n- (void)setTerm:(NSString *)str;\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n- (NSString *)labelLang;\n- (void)setLabelLang:(NSString *)str;\n\n#pragma mark -\n\n// utilities for extracting a subset of categories\n+ (NSArray *)categoriesWithScheme:(NSString *)scheme fromCategories:(NSArray *)array;\n+ (NSArray *)categoriesWithSchemePrefix:(NSString *)prefix fromCategories:(NSArray *)array;\n\n+ (NSArray *)categoryLabelsFromCategories:(NSArray *)array;\n+ (BOOL)categories:(NSArray *)array containsCategoryWithLabel:(NSString *)label;\n\n// this general search routine allows nil as \"don't care\" for scheme, term,\n// and label\n+ (BOOL)categories:(NSArray *)array\ncontainsCategoryWithScheme:(NSString *)scheme\n              term:(NSString *)term\n             label:(NSString *)label;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataCategory.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataCategory.m\n//\n\n#define GDATACATEGORY_DEFINE_GLOBALS 1\n#import \"GDataCategory.h\"\n\nstatic NSString* const kSchemeAttr = @\"scheme\";\nstatic NSString* const kTermAttr = @\"term\";\nstatic NSString* const kLabelAttr = @\"label\";\nstatic NSString* const kLangAttr = @\"xml:lang\";\n\n@implementation GDataCategory\n// for categories, like\n//  <category scheme=\"http://schemas.google.com/g/2005#kind\"\n//        term=\"http://schemas.google.com/g/2005#event\"/>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"category\"; }\n\n+ (GDataCategory *)categoryWithScheme:(NSString *)scheme\n                                 term:(NSString *)term {\n  GDataCategory* obj = [self object];\n  [obj setScheme:scheme];\n  [obj setTerm:term];\n  return obj;\n}\n\n+ (GDataCategory *)categoryWithLabel:(NSString *)label {\n\n  NSString *term = [NSString stringWithFormat:@\"%@#%@\",\n    kGDataCategoryLabelScheme, label];\n\n  GDataCategory *obj = [self categoryWithScheme:kGDataCategoryLabelScheme\n                                           term:term];\n  [obj setLabel:label];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kSchemeAttr, kTermAttr, kLabelAttr, kLangAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n\n  // per Category.java: this should exclude label and labelLang,\n  // but the GMail provider is generating categories which\n  // have identical terms but unique labels, so we need to compare\n  // label values as well, though not xml:lang\n\n  return [NSArray arrayWithObject:kLangAttr];\n}\n\n// should we override hash function like Java does?\n\n- (NSString *)scheme {\n  return [self stringValueForAttribute:kSchemeAttr];\n}\n\n- (void)setScheme:(NSString *)str {\n  [self setStringValue:str forAttribute:kSchemeAttr];\n}\n\n- (NSString *)term {\n  return [self stringValueForAttribute:kTermAttr];\n}\n\n- (void)setTerm:(NSString *)str {\n  [self setStringValue:str forAttribute:kTermAttr];\n}\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (NSString *)labelLang {\n  return [self stringValueForAttribute:kLangAttr];\n}\n\n- (void)setLabelLang:(NSString *)str {\n  [self setStringValue:str forAttribute:kLangAttr];\n}\n\n#pragma mark Utilities\n\n// return all categories with the specified scheme\n+ (NSArray *)categoriesWithScheme:(NSString *)scheme\n                   fromCategories:(NSArray *)array {\n\n  NSArray *cats = [GDataUtilities objectsFromArray:array\n                                         withValue:scheme\n                                        forKeyPath:@\"scheme\"];\n  return cats;\n}\n\n// return all categories whose schemes have the specified prefix\n+ (NSArray *)categoriesWithSchemePrefix:(NSString *)prefix\n                         fromCategories:(NSArray *)array {\n  NSMutableArray *matches = [NSMutableArray array];\n\n  for (GDataCategory *category in array) {\n    NSString *scheme = [category scheme];\n    if (scheme != nil && [scheme hasPrefix:prefix]) {\n      [matches addObject:category];\n    }\n  }\n  return matches;\n}\n\n+ (NSArray *)categoryLabelsFromCategories:(NSArray *)array {\n\n  NSMutableArray *labels = [NSMutableArray array];\n\n  for (GDataCategory *category in array) {\n    NSString *label = [category label];\n    if (label != nil && ![labels containsObject:label]) {\n      [labels addObject:label];\n    }\n  }\n  return labels;\n}\n\n+ (BOOL)categories:(NSArray *)array\ncontainsCategoryWithScheme:(NSString *)scheme\n              term:(NSString *)term\n             label:(NSString *)label {\n  // nil argument means \"don't care\"\n  for (GDataCategory *category in array) {\n    if ((scheme == nil || AreEqualOrBothNil([category scheme], scheme))\n        && (term == nil || AreEqualOrBothNil([category term], term))\n        && (label == nil || AreEqualOrBothNil([category label], label))) {\n      return YES;\n    }\n  }\n  return NO;\n}\n\n+ (BOOL)categories:(NSArray *)array containsCategoryWithLabel:(NSString *)label {\n  // to be rigorous, we'd construct a term string for comparison as done\n  // above in +categoryWithLabel: but that would make this a much more\n  // expensive routine to call\n  BOOL flag = [self categories:array\n    containsCategoryWithScheme:kGDataCategoryLabelScheme\n                          term:nil\n                         label:label];\n  return flag;\n}\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataComment.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataComment.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_BOOKS_SERVICE \\\n  || GDATA_INCLUDE_CALENDAR_SERVICE || GDATA_INCLUDE_YOUTUBE_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataFeedLink.h\"\n\n// a commments entry, as in\n// <gd:comments>\n//    <gd:feedLink href=\"http://www.google.com/calendar/feeds/t...\"/>\n// </gd:comments>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdComments\n\n@interface GDataComment : GDataObject <GDataExtension> {\n}\n\n+ (GDataComment *)commentWithFeedLink:(GDataFeedLink *)feedLink;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (GDataFeedLink *)feedLink;\n- (void)setFeedLink:(GDataFeedLink *)feedLink;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataComment.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataComment.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_BOOKS_SERVICE \\\n  || GDATA_INCLUDE_CALENDAR_SERVICE || GDATA_INCLUDE_YOUTUBE_SERVICE\n\n#import \"GDataComment.h\"\n\nstatic NSString* const kRelAttr = @\"rel\";\n\n@implementation GDataComment\n// a commments entry, as in\n// <gd:comments>\n//    <gd:feedLink href=\"http://www.google.com/calendar/feeds/t...\"/>\n// </gd:comments>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdComments\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"comments\"; }\n\n+ (GDataComment *)commentWithFeedLink:(GDataFeedLink *)feedLink {\n  GDataComment *obj = [self object];\n  [obj setFeedLink:feedLink];\n  return obj;\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  [self addExtensionDeclarationForParentClass:[self class]\n                                   childClass:[GDataFeedLink class]];\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObject:kRelAttr];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [super itemsForDescription];\n\n  [self addToArray:items objectDescriptionIfNonNil:[self feedLink] withName:@\"feedLink\"];\n\n  return items;\n}\n#endif\n\n#pragma mark -\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (GDataFeedLink *)feedLink {\n  return [self objectForExtensionClass:[GDataFeedLink class]];\n}\n\n- (void)setFeedLink:(GDataFeedLink *)feedLink {\n  [self setObject:feedLink forExtensionClass:[GDataFeedLink class]];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataCustomProperty.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataCustomProperty.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE\n\n#import \"GDataObject.h\"\n\n// custom property element, like\n//\n//   <gd:customProperty name=\"milk\" type=\"integer\" unit=\"gallons\">\n//     5\n//   </gd:customProperty>\n\n@interface GDataCustomProperty : GDataObject <GDataExtension>\n\n+ (GDataCustomProperty *)customPropertyWithName:(NSString *)name\n                                           type:(NSString *)type\n                                          value:(NSString *)value\n                                           unit:(NSString *)unit;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n- (NSString *)unit;\n- (void)setUnit:(NSString *)str;\n\n- (NSString *)value;\n- (void)setValue:(NSString *)str;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataCustomProperty.m",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataCustomProperty.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE\n\n#import \"GDataCustomProperty.h\"\n\nstatic NSString* const kNameAttr = @\"name\";\nstatic NSString* const kTypeAttr = @\"type\";\nstatic NSString* const kUnitAttr = @\"unit\";\n\n@implementation GDataCustomProperty\n\n// custom property element, like\n//\n//   <gd:customProperty name=\"milk\" type=\"integer\" unit=\"gallons\">\n//     5\n//   </gd:customProperty>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"customProperty\"; }\n\n+ (GDataCustomProperty *)customPropertyWithName:(NSString *)name\n                                           type:(NSString *)type\n                                          value:(NSString *)value\n                                           unit:(NSString *)unit {\n\n  GDataCustomProperty *obj = [self object];\n  [obj setName:name];\n  [obj setType:type];\n  [obj setUnit:unit];\n  [obj setValue:value];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kNameAttr, kTypeAttr, kUnitAttr, nil];\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n#pragma mark -\n\n- (NSString *)name {\n  return [self stringValueForAttribute:kNameAttr];\n}\n\n- (void)setName:(NSString *)str {\n  [self setStringValue:str forAttribute:kNameAttr];\n}\n\n- (NSString *)type {\n  return [self stringValueForAttribute:kTypeAttr];\n}\n\n- (void)setType:(NSString *)str {\n  [self setStringValue:str forAttribute:kTypeAttr];\n}\n\n- (NSString *)unit {\n  return [self stringValueForAttribute:kUnitAttr];\n}\n\n- (void)setUnit:(NSString *)str {\n  [self setStringValue:str forAttribute:kUnitAttr];\n}\n\n- (NSString *)value {\n  return [self contentStringValue];\n}\n\n- (void)setValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataDateTime.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataDateTime.h\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataDefines.h\"\n\n@interface GDataDateTime : NSObject <NSCopying> {\n  NSDateComponents *dateComponents_;\n  NSInteger offsetSeconds_; // may be NSUndefinedDateComponent\n  BOOL isUniversalTime_; // preserves \"Z\"\n  NSTimeZone *timeZone_; // specific time zone by name, if known\n}\n\n// Note: Nil can be passed for time zone arguments when the time zone is not\n//       known.\n\n+ (GDataDateTime *)dateTimeWithRFC3339String:(NSString *)str;\n+ (GDataDateTime *)dateTimeWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz;\n\n- (id)initWithRFC3339String:(NSString *)str;\n- (id)initWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz;\n\n- (void)setFromDate:(NSDate *)date timeZone:(NSTimeZone *)tz;\n- (void)setFromRFC3339String:(NSString *)str;\n\n- (NSDate *)date;\n- (NSCalendar *)calendar;\n\n- (NSTimeZone *)timeZone;\n- (void)setTimeZone:(NSTimeZone *)timeZone;\n- (void)setTimeZone:(NSTimeZone *)timeZone withOffsetSeconds:(NSInteger)val;\n\n- (NSString *)RFC3339String;\n- (NSString *)stringValue; // same as RFC3339String\n\n- (BOOL)hasTime;\n- (void)setHasTime:(BOOL)shouldHaveTime;\n\n- (NSInteger)offsetSeconds;\n- (void)setOffsetSeconds:(NSInteger)val;\n\n- (BOOL)isUniversalTime;\n- (void)setIsUniversalTime:(BOOL)flag;\n\n- (NSDateComponents *)dateComponents;\n- (void)setDateComponents:(NSDateComponents *)dateComponents;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataDateTime.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataDateTime.m\n//\n\n#import \"GDataDateTime.h\"\n\n\n@implementation GDataDateTime\n\n+ (GDataDateTime *)dateTimeWithRFC3339String:(NSString *)str {\n  return [[[GDataDateTime alloc] initWithRFC3339String:str] autorelease];\n}\n\n+ (GDataDateTime *)dateTimeWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz {\n return [[[GDataDateTime alloc] initWithDate:date\n                                    timeZone:tz] autorelease];\n}\n\n- (id)initWithRFC3339String:(NSString *)str {\n\n  self = [super init];\n  if (self) {\n    [self setFromRFC3339String:str];\n  }\n  return self;\n}\n\n- (id)initWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz {\n\n  self = [super init];\n  if (self) {\n    [self setFromDate:date timeZone:tz];\n  }\n  return self;\n}\n\n- (void)dealloc {\n  [dateComponents_ release];\n  [timeZone_ release];\n  [super dealloc];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n\n  GDataDateTime *newObj = [[GDataDateTime alloc] init];\n\n  [newObj setIsUniversalTime:[self isUniversalTime]];\n  [newObj setTimeZone:[self timeZone] withOffsetSeconds:[self offsetSeconds]];\n\n  NSDateComponents *newDateComponents;\n  NSDateComponents *oldDateComponents = [self dateComponents];\n\n// TODO: Experiments show it lies in 10.4.8 commented out for now.\n  if (NO && [NSDateComponents conformsToProtocol:@protocol(NSCopying)]) {\n\n    newDateComponents = [[oldDateComponents copyWithZone:zone] autorelease];\n\n  } else {\n    // NSDateComponents doesn't implement NSCopying in 10.4. We'll just retain\n    // it, which is fine since we never set individual components\n    // except after allocating a new NSDateCompoents instance.\n    newDateComponents = oldDateComponents;\n  }\n  [newObj setDateComponents:newDateComponents];\n\n  return newObj;\n}\n\n// until NSDateComponent implements isEqual, we'll use this\n- (BOOL)doesDateComponents:(NSDateComponents *)dc1\n       equalDateComponents:(NSDateComponents *)dc2 {\n\n  return [dc1 era] == [dc2 era]\n          && [dc1 year] == [dc2 year]\n          && [dc1 month] == [dc2 month]\n          && [dc1 day] == [dc2 day]\n          && [dc1 hour] == [dc2 hour]\n          && [dc1 minute] == [dc2 minute]\n          && [dc1 second] == [dc2 second]\n          && [dc1 week] == [dc2 week]\n          && [dc1 weekday] == [dc2 weekday]\n          && [dc1 weekdayOrdinal] == [dc2 weekdayOrdinal];\n}\n\n- (BOOL)isEqual:(GDataDateTime *)other {\n\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataDateTime class]]) return NO;\n\n  return [self offsetSeconds] == [other offsetSeconds]\n    && [self isUniversalTime] == [other isUniversalTime]\n    && [self timeZone] == [other timeZone]\n    && [self doesDateComponents:[self dateComponents]\n            equalDateComponents:[other dateComponents]];\n}\n\n- (NSString *)description {\n  return [NSString stringWithFormat:@\"%@ %p: {%@}\",\n    [self class], self, [self RFC3339String]];\n}\n\n- (NSTimeZone *)timeZone {\n  if (timeZone_) {\n    return timeZone_;\n  }\n\n  if ([self isUniversalTime]) {\n    NSTimeZone *ztz = [NSTimeZone timeZoneWithName:@\"Universal\"];\n    return ztz;\n  }\n\n  NSInteger offsetSeconds = [self offsetSeconds];\n\n  if (offsetSeconds != NSUndefinedDateComponent) {\n    NSTimeZone *tz = [NSTimeZone timeZoneForSecondsFromGMT:offsetSeconds];\n    return tz;\n  }\n  return nil;\n}\n\n- (void)setTimeZone:(NSTimeZone *)timeZone {\n  [timeZone_ release];\n  timeZone_ = [timeZone retain];\n\n  if (timeZone) {\n    NSInteger offsetSeconds = [timeZone secondsFromGMTForDate:[self date]];\n    [self setOffsetSeconds:offsetSeconds];\n  } else {\n    [self setOffsetSeconds:NSUndefinedDateComponent];\n  }\n}\n\n- (void)setTimeZone:(NSTimeZone *)timeZone withOffsetSeconds:(NSInteger)val {\n  [timeZone_ release];\n  timeZone_ = [timeZone retain];\n\n  offsetSeconds_ = val;\n}\n\n- (NSCalendar *)calendar {\n  NSCalendar *cal = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];\n  NSTimeZone *tz = [self timeZone];\n  if (tz) {\n    [cal setTimeZone:tz];\n  }\n  return cal;\n}\n\n- (NSDate *)date {\n  NSCalendar *cal = [self calendar];\n  NSDateComponents *dateComponents = [self dateComponents];\n\n  if (![self hasTime]) {\n    // we're not keeping track of a time, but NSDate always is based on\n    // an absolute time. We want to avoid returning an NSDate where the\n    // calendar date appears different from what was used to create our\n    // date-time object.\n    //\n    // We'll make a copy of the date components, setting the time on our\n    // copy to noon GMT, since that ensures the date renders correctly for\n    // any time zone\n    //\n    // Note that on 10.4 NSDateComponents does not implement NSCopying, so we'll\n    // assemble an NSDateComponents manually here\n    NSDateComponents *noonDateComponents = [[[NSDateComponents alloc] init] autorelease];\n    [noonDateComponents setYear:[dateComponents year]];\n    [noonDateComponents setMonth:[dateComponents month]];\n    [noonDateComponents setDay:[dateComponents day]];\n    [noonDateComponents setHour:12];\n    [noonDateComponents setMinute:0];\n    [noonDateComponents setSecond:0];\n    dateComponents = noonDateComponents;\n\n    NSTimeZone *gmt = [NSTimeZone timeZoneWithName:@\"Universal\"];\n    [cal setTimeZone:gmt];\n  }\n\n  NSDate *date = [cal dateFromComponents:dateComponents];\n  return date;\n}\n\n- (NSString *)stringValue {\n  return [self RFC3339String];\n}\n\n- (NSString *)RFC3339String {\n  NSDateComponents *dateComponents = [self dateComponents];\n  NSInteger offset = [self offsetSeconds];\n\n  NSString *timeString = @\"\"; // timeString like \"T15:10:46-08:00\"\n\n  if ([self hasTime]) {\n\n    NSString *timeOffsetString; // timeOffsetString like \"-08:00\"\n\n    if ([self isUniversalTime]) {\n     timeOffsetString = @\"Z\";\n    } else if (offset == NSUndefinedDateComponent) {\n      // unknown offset is rendered as -00:00 per\n      // http://www.ietf.org/rfc/rfc3339.txt section 4.3\n      timeOffsetString = @\"-00:00\";\n    } else {\n      NSString *sign = @\"+\";\n      if (offset < 0) {\n        sign = @\"-\";\n        offset = -offset;\n      }\n      timeOffsetString = [NSString stringWithFormat:@\"%@%02ld:%02ld\",\n        sign, (long)(offset/(60*60)) % 24, (long)(offset / 60) % 60];\n    }\n    timeString = [NSString stringWithFormat:@\"T%02ld:%02ld:%02ld%@\",\n      (long)[dateComponents hour], (long)[dateComponents minute],\n      (long)[dateComponents second], timeOffsetString];\n  }\n\n  // full dateString like \"2006-11-17T15:10:46-08:00\"\n  NSString *dateString = [NSString stringWithFormat:@\"%04ld-%02ld-%02ld%@\",\n    (long)[dateComponents year], (long)[dateComponents month],\n    (long)[dateComponents day], timeString];\n\n  return dateString;\n}\n\n- (void)setFromDate:(NSDate *)date timeZone:(NSTimeZone *)tz {\n  NSCalendar *cal = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];\n  if (tz) {\n    [cal setTimeZone:tz];\n  }\n\n  NSUInteger const kComponentBits = (NSYearCalendarUnit | NSMonthCalendarUnit\n    | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit\n    | NSSecondCalendarUnit);\n\n  NSDateComponents *components = [cal components:kComponentBits fromDate:date];\n  [self setDateComponents:components];\n\n  [self setIsUniversalTime:NO];\n\n  NSInteger offset = NSUndefinedDateComponent;\n\n  if (tz) {\n    offset = [tz secondsFromGMTForDate:date];\n\n    if (offset == 0 && [tz isEqualToTimeZone:[NSTimeZone timeZoneWithName:@\"Universal\"]]) {\n      [self setIsUniversalTime:YES];\n    }\n  }\n  [self setOffsetSeconds:offset];\n\n  // though offset seconds are authoritative, we'll retain the time zone\n  // since we can't regenerate it reliably from just the offset\n  timeZone_ = [tz retain];\n}\n\nstatic inline BOOL ScanInteger(NSScanner *scanner, NSInteger *targetInteger) {\n  return [scanner scanInteger:targetInteger];\n}\n\n- (void)setFromRFC3339String:(NSString *)str {\n\n  NSInteger year = NSUndefinedDateComponent;\n  NSInteger month = NSUndefinedDateComponent;\n  NSInteger day = NSUndefinedDateComponent;\n  NSInteger hour = NSUndefinedDateComponent;\n  NSInteger minute = NSUndefinedDateComponent;\n  NSInteger sec = NSUndefinedDateComponent;\n  float secFloat = -1.0f;\n  NSString* sign = nil;\n  NSInteger offsetHour = 0;\n  NSInteger offsetMinute = 0;\n\n  NSScanner* scanner = [NSScanner scannerWithString:str];\n\n  NSCharacterSet* dashSet = [NSCharacterSet characterSetWithCharactersInString:@\"-\"];\n  NSCharacterSet* tSet = [NSCharacterSet characterSetWithCharactersInString:@\"Tt \"];\n  NSCharacterSet* colonSet = [NSCharacterSet characterSetWithCharactersInString:@\":\"];\n  NSCharacterSet* plusMinusZSet = [NSCharacterSet characterSetWithCharactersInString:@\"+-zZ\"];\n\n  // for example, scan 2006-11-17T15:10:46-08:00\n  //                or 2006-11-17T15:10:46Z\n  if (// yyyy-mm-dd\n      ScanInteger(scanner, &year) &&\n      [scanner scanCharactersFromSet:dashSet intoString:NULL] &&\n      ScanInteger(scanner, &month) &&\n      [scanner scanCharactersFromSet:dashSet intoString:NULL] &&\n      ScanInteger(scanner, &day) &&\n      // Thh:mm:ss\n      [scanner scanCharactersFromSet:tSet intoString:NULL] &&\n      ScanInteger(scanner, &hour) &&\n      [scanner scanCharactersFromSet:colonSet intoString:NULL] &&\n      ScanInteger(scanner, &minute) &&\n      [scanner scanCharactersFromSet:colonSet intoString:NULL] &&\n      [scanner scanFloat:&secFloat] &&\n      // Z or +hh:mm\n      [scanner scanCharactersFromSet:plusMinusZSet intoString:&sign] &&\n      ScanInteger(scanner, &offsetHour) &&\n      [scanner scanCharactersFromSet:colonSet intoString:NULL] &&\n      ScanInteger(scanner, &offsetMinute)) {\n  }\n\n  NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease];\n  [dateComponents setYear:year];\n  [dateComponents setMonth:month];\n  [dateComponents setDay:day];\n  [dateComponents setHour:hour];\n  [dateComponents setMinute:minute];\n\n  if (secFloat < -1.0f || secFloat > -1.0f) sec = (NSInteger)secFloat;\n  [dateComponents setSecond:sec];\n\n  [self setDateComponents:dateComponents];\n\n  // determine the offset, like from Z, or -08:00:00.0\n\n  [self setTimeZone:nil];\n\n  NSInteger totalOffset = NSUndefinedDateComponent;\n  [self setIsUniversalTime:NO];\n\n  if ([sign caseInsensitiveCompare:@\"Z\"] == NSOrderedSame) {\n\n    [self setIsUniversalTime:YES];\n    totalOffset = 0;\n\n  } else if (sign != nil) {\n\n    totalOffset = (60 * offsetMinute) + (60 * 60 * offsetHour);\n\n    if ([sign isEqual:@\"-\"]) {\n\n      if (totalOffset == 0) {\n        // special case: offset of -0.00 means undefined offset\n        totalOffset = NSUndefinedDateComponent;\n      } else {\n        totalOffset *= -1;\n      }\n    }\n  }\n\n  [self setOffsetSeconds:totalOffset];\n}\n\n- (BOOL)hasTime {\n  NSDateComponents *dateComponents = [self dateComponents];\n\n  BOOL hasTime = ([dateComponents hour] != NSUndefinedDateComponent\n                  && [dateComponents minute] != NSUndefinedDateComponent);\n\n  return hasTime;\n}\n\n- (void)setHasTime:(BOOL)shouldHaveTime {\n\n  // we'll set time values to zero or NSUndefinedDateComponent as appropriate\n  BOOL hadTime = [self hasTime];\n\n  if (shouldHaveTime && !hadTime) {\n    [dateComponents_ setHour:0];\n    [dateComponents_ setMinute:0];\n    [dateComponents_ setSecond:0];\n    offsetSeconds_ = NSUndefinedDateComponent;\n    isUniversalTime_ = NO;\n\n  } else if (hadTime && !shouldHaveTime) {\n    [dateComponents_ setHour:NSUndefinedDateComponent];\n    [dateComponents_ setMinute:NSUndefinedDateComponent];\n    [dateComponents_ setSecond:NSUndefinedDateComponent];\n    offsetSeconds_ = NSUndefinedDateComponent;\n    isUniversalTime_ = NO;\n    [self setTimeZone:nil];\n  }\n}\n\n- (NSInteger)offsetSeconds {\n  return offsetSeconds_;\n}\n\n- (void)setOffsetSeconds:(NSInteger)val {\n  offsetSeconds_ = val;\n}\n\n- (BOOL)isUniversalTime {\n  return isUniversalTime_;\n}\n\n- (void)setIsUniversalTime:(BOOL)flag {\n  isUniversalTime_ = flag;\n}\n\n- (NSDateComponents *)dateComponents {\n  return dateComponents_;\n}\n\n- (void)setDateComponents:(NSDateComponents *)dateComponents {\n  [dateComponents_ autorelease];\n  dateComponents_ = [dateComponents retain]; // NSDateComponents doesn't implement NSCopying in 10.4\n}\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataDeleted.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataDeleted.h\n//\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n// marker for a deleted entry, as in\n// <gd:deleted/>\n\n@interface GDataDeleted : GDataImplicitValueConstruct <GDataExtension>\n\n+ (GDataDeleted *)deleted;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataDeleted.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataDeleted.m\n//\n\n#import \"GDataDeleted.h\"\n\n@implementation GDataDeleted\n// marker for a deleted entry, as in\n// <gd:deleted/>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"deleted\"; }\n\n+ (GDataDeleted *)deleted {\n  return [self implicitValue];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataElements.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n// GDataElements.h\n//\n// Common classes needed for any service\n//\n\n#import \"GDataFramework.h\"\n\n// utility classes\n#import \"GTMHTTPFetcher.h\"\n#import \"GTMHTTPFetcherLogging.h\"\n#import \"GTMHTTPUploadFetcher.h\"\n#import \"GTMGatherInputStream.h\"\n#import \"GTMMIMEDocument.h\"\n\n#import \"GDataDateTime.h\"\n#import \"GDataServerError.h\"\n\n// base classes\n#import \"GDataObject.h\"\n#import \"GDataEntryBase.h\"\n#import \"GDataFeedBase.h\"\n#import \"GDataServiceBase.h\"\n#import \"GDataServiceGoogle.h\"\n#import \"GDataQuery.h\"\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataEmail.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataEmail.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n\n// email element\n// <gd:email label=\"Personal\" address=\"fubar@gmail.com\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdEmail\n\n@interface GDataEmail : GDataObject <GDataExtension>\n\n+ (GDataEmail *)emailWithLabel:(NSString *)label\n                       address:(NSString *)address;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)address;\n- (void)setAddress:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataEmail.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataEmail.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataEmail.h\"\n\nstatic NSString* const kLabelAttr = @\"label\";\nstatic NSString* const kAddressAttr = @\"address\";\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kPrimaryAttr = @\"primary\";\n\n@implementation GDataEmail\n// email element\n// <gd:email label=\"Personal\" address=\"fubar@gmail.com\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdEmail\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"email\"; }\n\n+ (GDataEmail *)emailWithLabel:(NSString *)label\n                       address:(NSString *)address {\n  GDataEmail *obj = [self object];\n  [obj setLabel:label];\n  [obj setAddress:address];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kLabelAttr, kAddressAttr, kRelAttr, kPrimaryAttr, nil];\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n\n  return [NSArray arrayWithObject:kPrimaryAttr];\n}\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (NSString *)address {\n  return [self stringValueForAttribute:kAddressAttr];\n}\n\n- (void)setAddress:(NSString *)str {\n  [self setStringValue:str forAttribute:kAddressAttr];\n}\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (BOOL)isPrimary {\n  return [self boolValueForAttribute:kPrimaryAttr defaultValue:NO];\n}\n\n- (void)setIsPrimary:(BOOL)flag {\n  [self setBoolValue:flag defaultValue:NO forAttribute:kPrimaryAttr];\n}\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataEntryContent.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataEntryContent.h\n//\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAENTRYCONTENT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataContentTypeKML _INITIALIZE_AS(@\"application/vnd.google-earth.kml+xml\");\n\n\n// per http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.content\n//\n// For typed content, like <content type=\"text\">Here go the ferrets</content>\n//\n// or media content with a source URI specified,\n//  <content src=\"http://lh.google.com/image/Car.jpg\" type=\"image/jpeg\"/>\n//\n// or a child feed or entry, like\n//  <content type=\"application/atom+xml;feed\"> <feed>...</feed> </content>\n//\n// Text type can be text, text/plain, html, text/html, xhtml, text/xhtml\n\n@interface GDataEntryContent : GDataObject {\n  GDataObject *childObject_;\n}\n\n+ (id)contentWithString:(NSString *)str;\n\n+ (id)contentWithSourceURI:(NSString *)str type:(NSString *)type;\n\n+ (id)contentWithXMLValue:(NSXMLNode *)node type:(NSString *)type;\n\n+ (id)textConstructWithString:(NSString *)str; // deprecated\n\n- (NSString *)lang;\n- (void)setLang:(NSString *)str;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n- (NSString *)sourceURI;\n- (void)setSourceURI:(NSString *)str;\n- (NSURL *)sourceURL;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (GDataObject *)childObject;\n- (void)setChildObject:(GDataObject *)obj;\n\n- (NSArray *)XMLValues;\n- (void)setXMLValues:(NSArray *)arr;\n- (void)addXMLValue:(NSXMLNode *)node;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataEntryContent.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataEntryContent.m\n//\n\n#define GDATAENTRYCONTENT_DEFINE_GLOBALS 1\n#import \"GDataEntryContent.h\"\n\nstatic NSString* const kLangAttr = @\"xml:lang\";\nstatic NSString* const kTypeAttr = @\"type\";\nstatic NSString* const kSourceAttr = @\"src\";\n\nstatic BOOL IsTypeEqualToText(NSString *str) {\n  // internal utility routine\n  return (str == nil)\n  || [str isEqual:@\"text\"]\n  || [str hasPrefix:@\"text/\"]\n  || [str isEqual:@\"html\"]\n  || [str isEqual:@\"xhtml\"];\n}\n\n\n@implementation GDataEntryContent\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"content\"; }\n\n+ (id)contentWithString:(NSString *)str {\n\n  // RFC4287 Sec 4.1.3.1. says that omitted type attributes are assumed to be\n  // \"text\", so we don't need to explicitly set it to text\n\n  GDataEntryContent *obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n+ (id)contentWithSourceURI:(NSString *)str type:(NSString *)type {\n\n  GDataEntryContent *obj = [self object];\n  [obj setSourceURI:str];\n  [obj setType:type];\n  return obj;\n}\n\n+ (id)contentWithXMLValue:(NSXMLNode *)node type:(NSString *)type {\n\n  GDataEntryContent *obj = [self object];\n\n  // declare that we'll be using child elements as XML values\n  [obj addChildXMLElementsDeclaration];\n\n  [obj setType:type];\n\n  if (node != nil) {\n    [obj addXMLValue:node];\n  }\n  return obj;\n}\n\n+ (id)textConstructWithString:(NSString *)str {\n\n  // deprecated; kept for compatibility with the previous\n  // implementation of GDataEntryContent\n  GDATA_DEBUG_LOG(@\"GDataEntryContent: +textConstructWithString deprecated, use +contentWithString\");\n\n  return [self contentWithString:str];\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kTypeAttr, kLangAttr, kSourceAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  // we're not calling -addContentValueDeclaration since the content may not\n  // be plain text but rather XML for an entry or feed that we will parse\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n\n  // ignore the \"type\" attribute since we test for it uniquely below\n  return [NSArray arrayWithObject:kTypeAttr];\n}\n\n- (void)parseAttributesForElement:(NSXMLElement *)element {\n\n  // override the attribute parsing method\n  //\n  // once we have parsed the attributes, we can decide\n  // how to parse the contents or children\n  [super parseAttributesForElement:element];\n\n  NSString *type = [self type];\n  if (IsTypeEqualToText(type)) {\n\n    // content is plain text\n    [self addContentValueDeclaration];\n\n  } else if ([type hasPrefix:@\"application/atom+xml;\"]) {\n\n    // content is a feed or entry stored in unknownChildren\n    GDataObject *obj = [self objectForChildOfElement:element\n                                       qualifiedName:@\"*\"\n                                        namespaceURI:@\"*\"\n                                         objectClass:nil];\n    [self setChildObject:obj];\n\n  } else if ([type hasPrefix:kGDataContentTypeKML]) {\n\n    // content is KML\n    [self addChildXMLElementsDeclaration];\n  }\n}\n\n- (void)dealloc {\n  [childObject_ release];\n  [super dealloc];\n}\n\n- (NSXMLElement *)XMLElement {\n\n  NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:nil];\n\n  GDataObject *obj = [self childObject];\n  if (obj) {\n    NSXMLElement *elem = [obj XMLElement];\n    [element addChild:elem];\n  }\n\n  return element;\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataEntryContent* newObj = [super copyWithZone:zone];\n\n  [newObj setChildObject:[[[self childObject] copy] autorelease]];\n\n  return newObj;\n}\n\n- (BOOL)isEqual:(GDataEntryContent *)other {\n\n  // override isEqual: to allow nil types to be considered equal to \"text\"\n  return [super isEqual:other]\n\n    // a missing type attribute is equal to \"text\" per RFC 4287 3.1.1\n    //\n    // consider them equal if both are some flavor of \"text\"\n    && (AreEqualOrBothNil([self type], [other type])\n        || (IsTypeEqualToText([self type]) && IsTypeEqualToText([other type])))\n    && AreEqualOrBothNil([self childObject], [other childObject]);\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n\n  NSMutableArray *items = [super itemsForDescription];\n\n  // if the base class is not storing the content value, we must provide the\n  // description item here\n  if (![self hasDeclaredContentValue]) {\n    [self addToArray:items objectDescriptionIfNonNil:[self stringValue] withName:@\"content\"];\n  }\n\n  [self addToArray:items objectDescriptionIfNonNil:[self XMLValues] withName:@\"xml\"];\n\n  GDataObject *obj = [self childObject];\n  if (obj != nil) {\n    NSString *className = NSStringFromClass([obj class]);\n    [self addToArray:items objectDescriptionIfNonNil:className withName:@\"childObject\"];\n  }\n  return items;\n}\n#endif\n\n#pragma mark -\n\n- (NSString *)lang {\n  return [self stringValueForAttribute:kLangAttr];\n}\n\n- (void)setLang:(NSString *)str {\n  [self setStringValue:str forAttribute:kLangAttr];\n}\n\n- (NSString *)type {\n  return [self stringValueForAttribute:kTypeAttr];\n}\n\n- (NSString *)sourceURI {\n  return [self stringValueForAttribute:kSourceAttr];\n}\n\n- (void)setSourceURI:(NSString *)str {\n  [self setStringValue:str forAttribute:kSourceAttr];\n}\n\n- (NSURL *)sourceURL {\n  NSString *sourceURI = [self sourceURI];\n  if ([sourceURI length] > 0) {\n\n    NSURL *url = [NSURL URLWithString:sourceURI];\n    return url;\n  }\n  return nil;\n}\n\n- (void)setType:(NSString *)str {\n  [self setStringValue:str forAttribute:kTypeAttr];\n}\n\n- (NSString *)stringValue {\n  if ([self hasDeclaredContentValue]) {\n    return [self contentStringValue];\n  }\n  return nil;\n}\n\n- (void)setStringValue:(NSString *)str {\n  if (![self hasDeclaredContentValue]) {\n    // if we emit XML later on, we'll want to emit this string\n    [self addContentValueDeclaration];\n  }\n\n  [self setContentStringValue:str];\n}\n\n- (GDataObject *)childObject {\n  return childObject_;\n}\n\n- (void)setChildObject:(GDataObject *)obj {\n  [childObject_ autorelease];\n  childObject_ = [obj retain];\n}\n\n- (NSArray *)XMLValues {\n  return [super childXMLElements];\n}\n\n- (void)setXMLValues:(NSArray *)arr {\n  [self setChildXMLElements:arr];\n}\n\n- (void)addXMLValue:(NSXMLNode *)node {\n  [self addChildXMLElement:node];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataEntryLink.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataEntryLink.h\n//\n\n#import \"GDataObject.h\"\n\n@class GDataEntryBase;\n\n// used inside GDataWhere, a link to an entry, like\n// <gd:entryLink href=\"http://gmail.com/jo/contacts/Jo\">\n@interface GDataEntryLink : GDataObject <GDataExtension> {\n  GDataEntryBase *entry_;\n}\n\n+ (GDataEntryLink *)entryLinkWithHref:(NSString *)href\n                           isReadOnly:(BOOL)isReadOnly;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent;\n\n- (NSXMLElement *)XMLElement;\n\n- (NSString *)href;\n- (void)setHref:(NSString *)str;\n\n- (BOOL)isReadOnly;\n- (void)setIsReadOnly:(BOOL)isReadOnly;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (GDataEntryBase *)entry;\n- (void)setEntry:(GDataEntryBase *)entry;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataEntryLink.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataEntryLink.m\n//\n\n#import \"GDataEntryLink.h\"\n\n#import \"GDataEntryBase.h\"\n\nstatic NSString* const kHrefAttr = @\"href\";\nstatic NSString* const kReadOnlyAttr = @\"readOnly\";\nstatic NSString* const kRelAttr = @\"rel\";\n\n@implementation GDataEntryLink\n// used instead GDataWhere, a link to an entry, like\n// <gd:entryLink href=\"http://gmail.com/jo/contacts/Jo\">\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"entryLink\"; }\n\n+ (GDataEntryLink *)entryLinkWithHref:(NSString *)href\n                           isReadOnly:(BOOL)isReadOnly {\n  GDataEntryLink* entryLink = [self object];\n  [entryLink setHref:href];\n  [entryLink setIsReadOnly:isReadOnly];\n  return entryLink;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kHrefAttr, kReadOnlyAttr, kRelAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent {\n  self = [super initWithXMLElement:element\n                            parent:parent];\n  if (self) {\n    // GDataEntryBase, the base class for entries, is not an extension,\n    // so we parse it manually\n    [self setEntry:[self objectForChildOfElement:element\n                                   qualifiedName:@\"entry\"\n                                    namespaceURI:kGDataNamespaceAtom\n                                     objectClass:nil]];\n  }\n  return self;\n}\n\n- (void)dealloc {\n  [entry_ release];\n  [super dealloc];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataEntryLink* newLink = [super copyWithZone:zone];\n  [newLink setEntry:[[[self entry] copyWithZone:zone] autorelease]];\n  return newLink;\n}\n\n- (BOOL)isEqual:(GDataEntryLink *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataEntryLink class]]) return NO;\n\n  return [super isEqual:other]\n    && (AreEqualOrBothNil([self entry], [other entry]));\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [super itemsForDescription];\n\n  [self addToArray:items objectDescriptionIfNonNil:entry_ withName:@\"entry\"];\n\n  return items;\n}\n#endif\n\n- (NSXMLElement *)XMLElement {\n\n  NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:nil];\n\n  if ([self entry]) {\n    [element addChild:[entry_ XMLElement]];\n  }\n  return element;\n}\n\n#pragma mark -\n\n- (NSString *)href {\n  return [self stringValueForAttribute:kHrefAttr];\n}\n\n- (void)setHref:(NSString *)str {\n  [self setStringValue:str forAttribute:kHrefAttr];\n}\n\n- (BOOL)isReadOnly {\n  return [self boolValueForAttribute:kReadOnlyAttr defaultValue:NO];\n}\n\n- (void)setIsReadOnly:(BOOL)isReadOnly {\n  [self setBoolValue:isReadOnly defaultValue:NO forAttribute:kReadOnlyAttr];\n}\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (GDataEntryBase *)entry {\n  return entry_;\n}\n\n- (void)setEntry:(GDataEntryBase *)entry {\n  [entry_ autorelease];\n  entry_ = [entry retain];\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataExtendedProperty.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataExtendedProperty.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n   || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAEXTENDEDPROPERTY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataExtendedPropertyRealmShared _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#shared\");\n\n\n// an element with a name=\"\" and a value=\"\" attribute, as in\n//  <gd:extendedProperty name='X-MOZ-ALARM-LAST-ACK' value='2006-10-03T19:01:14Z'/>\n//\n// or an arbitrary XML blob, as in\n//  <gd:extendedProperty name='com.myCompany.myProperties'> <myXMLBlob /> </gd:extendedProperty>\n//\n// Servers may impose additional restrictions on names or on the size\n// or composition of the values.\n\n@interface GDataExtendedProperty : GDataObject <GDataExtension>\n\n+ (id)propertyWithName:(NSString *)name\n                 value:(NSString *)value;\n\n- (NSString *)value;\n- (void)setValue:(NSString *)str;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)realm;\n- (void)setRealm:(NSString *)str;\n\n- (NSArray *)XMLValues;\n- (void)setXMLValues:(NSArray *)arr;\n- (void)addXMLValue:(NSXMLNode *)node;\n\n// Obj-C style interface to XML values storage\n//\n// keys are XMLValue node names, values are XMLValue node string values,\n// as in\n//   <key1>value1</key1>\n//   <key2>value2</key2>\n//\n// Behavior is undefined if child nodes are in some other format.\n\n- (void)setXMLValue:(NSString *)value forKey:(NSString *)key;\n- (NSString *)XMLValueForKey:(NSString *)key;\n\n- (NSDictionary *)XMLValuesDictionary;\n- (void)setXMLValuesDictionary:(NSDictionary *)dict;\n\n@end\n\n#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataExtendedProperty.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataExtendedProperty.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n  || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#define GDATAEXTENDEDPROPERTY_DEFINE_GLOBALS 1\n\n#import \"GDataExtendedProperty.h\"\n\nstatic NSString* const kNameAttr = @\"name\";\nstatic NSString* const kValueAttr = @\"value\";\nstatic NSString* const kRealmAttr = @\"realm\";\n\n@implementation GDataExtendedProperty\n// an element with a name=\"\" and a value=\"\" attribute, as in\n//  <gd:extendedProperty name='X-MOZ-ALARM-LAST-ACK' value='2006-10-03T19:01:14Z'/>\n//\n// or an arbitrary XML blob, as in\n//  <gd:extendedProperty name='com.myCompany.myProperties'> <myXMLBlob /> </gd:extendedProperty>\n//\n// Servers may impose additional restrictions on names or on the size\n// or composition of the values.\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"extendedProperty\"; }\n\n- (void)addEmptyDefaultNamespace {\n\n  // We don't want child XML lacking a prefix to be intepreted as being in the\n  // atom namespace, so we'll specify that no default namespace applies.\n  // This will add the attribute xmlns=\"\" to the extendedProperty element.\n\n  NSDictionary *defaultNS = [NSDictionary dictionaryWithObject:@\"\"\n                                                        forKey:@\"\"];\n  [self addNamespaces:defaultNS];\n}\n\n+ (id)propertyWithName:(NSString *)name\n                 value:(NSString *)value {\n\n  GDataExtendedProperty* obj = [self object];\n  [obj setName:name];\n  [obj setValue:value];\n  [obj addEmptyDefaultNamespace];\n  return obj;\n}\n\n- (id)init {\n  self = [super init];\n  if (self) {\n    if ([[self namespaces] objectForKey:@\"\"] == nil) {\n      [self addEmptyDefaultNamespace];\n    }\n  }\n  return self;\n}\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent {\n  self = [super initWithXMLElement:element\n                            parent:parent];\n  if (self) {\n    if ([[self namespaces] objectForKey:@\"\"] == nil) {\n      [self addEmptyDefaultNamespace];\n    }\n  }\n  return self;\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kNameAttr, kValueAttr, kRealmAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addChildXMLElementsDeclaration];\n}\n\n- (NSString *)value {\n  return [self stringValueForAttribute:kValueAttr];\n}\n\n- (void)setValue:(NSString *)str {\n  [self setStringValue:str forAttribute:kValueAttr];\n}\n\n- (NSString *)name {\n  return [self stringValueForAttribute:kNameAttr];\n}\n\n- (void)setName:(NSString *)str {\n  [self setStringValue:str forAttribute:kNameAttr];\n}\n\n- (NSString *)realm {\n  return [self stringValueForAttribute:kRealmAttr];\n}\n\n- (void)setRealm:(NSString *)str {\n  [self setStringValue:str forAttribute:kRealmAttr];\n}\n\n- (NSArray *)XMLValues {\n  return [super childXMLElements];\n}\n\n- (void)setXMLValues:(NSArray *)arr {\n  [self setChildXMLElements:arr];\n}\n\n- (void)addXMLValue:(NSXMLNode *)node {\n  [self addChildXMLElement:node];\n}\n\n#pragma mark -\n\n- (void)setXMLValue:(NSString *)value forKey:(NSString *)key {\n\n  // change or remove an entry in the values dictionary\n  //\n  // dict may be nil\n  NSMutableDictionary *dict = [[[self XMLValuesDictionary] mutableCopy] autorelease];\n\n  if (dict == nil && value != nil) {\n    dict = [NSMutableDictionary dictionary];\n  }\n  [dict setValue:value forKey:key];\n\n  [self setXMLValuesDictionary:dict];\n}\n\n- (NSString *)XMLValueForKey:(NSString *)key {\n\n  NSDictionary *dict = [self XMLValuesDictionary];\n  NSString *value = [dict valueForKey:key];\n  return value;\n}\n\n- (NSDictionary *)XMLValuesDictionary {\n\n  NSArray *xmlNodes = [self XMLValues];\n  if (xmlNodes == nil) return nil;\n\n  // step through all elements in the XML children and make a dictionary\n  // entry for each\n  NSMutableDictionary *dict = [NSMutableDictionary dictionary];\n  for (id xmlNode in xmlNodes) {\n\n    NSString *qualifiedName = [xmlNode name];\n    NSString *value = [xmlNode stringValue];\n\n    [dict setValue:value forKey:qualifiedName];\n  }\n  return dict;\n}\n\n- (void)setXMLValuesDictionary:(NSDictionary *)dict {\n\n  NSMutableArray *nodes = [NSMutableArray array];\n\n  // replace the XML child elements with elements from the dictionary\n  for (NSString *key in dict) {\n    NSString *value = [dict objectForKey:key];\n    NSXMLNode *node = [NSXMLNode elementWithName:key\n                                     stringValue:value];\n    [nodes addObject:node];\n  }\n\n  if ([nodes count] > 0) {\n    [self setXMLValues:nodes];\n  } else {\n    [self setXMLValues:nil];\n  }\n}\n\n@end\n\n#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataFeedLink.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataFeedLink.h\n//\n\n#import \"GDataObject.h\"\n\n@class GDataFeedBase;\n\n// a link to a feed, like\n// <gd:feedLink href=\"http://example.com/Jo/posts/MyFirstPost/comments\" countHint=\"10\">\n\n@interface GDataFeedLink : GDataObject <NSCopying, GDataExtension> {\n  GDataFeedBase *feed_;\n}\n\n+ (id)feedLinkWithHref:(NSString *)href\n            isReadOnly:(BOOL)isReadOnly;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent;\n\n- (NSXMLElement *)XMLElement;\n\n- (NSString *)href;\n- (void)setHref:(NSString *)str;\n\n- (BOOL)isReadOnly;\n- (void)setIsReadOnly:(BOOL)isReadOnly;\n\n- (NSNumber *)countHint;\n- (void)setCountHint:(NSNumber *)val;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (GDataFeedBase *)feed;\n- (void)setFeed:(GDataFeedBase *)feed;\n\n// convert the href string into an URL\n- (NSURL *)URL;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataFeedLink.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataFeedLink.m\n//\n\n\n#import \"GDataFeedLink.h\"\n#import \"GDataFeedBase.h\"\n\nstatic NSString *const kHrefAttr = @\"href\";\nstatic NSString *const kRelAttr = @\"rel\";\nstatic NSString *const KReadOnlyAttr = @\"readOnly\";\nstatic NSString *const kCountHintAttr = @\"countHint\";\n\n@implementation GDataFeedLink\n// a link to a feed, like\n// <gd:feedLink href=\"http://example.com/Jo/posts/MyFirstPost/comments\" countHint=\"10\">\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdFeedLink\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"feedLink\"; }\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kHrefAttr, kRelAttr, KReadOnlyAttr, kCountHintAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n+ (id)feedLinkWithHref:(NSString *)href\n            isReadOnly:(BOOL)isReadOnly {\n  GDataFeedLink* feedLink = [self object];\n  [feedLink setHref:href];\n  [feedLink setIsReadOnly:isReadOnly];\n  return feedLink;\n}\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent {\n  self = [super initWithXMLElement:element\n                            parent:parent];\n  if (self) {\n\n    [self setFeed:[self objectForChildOfElement:element\n                                  qualifiedName:@\"feed\"\n                                   namespaceURI:kGDataNamespaceAtom\n                                    objectClass:nil]];\n  }\n  return self;\n}\n\n- (void)dealloc {\n  [feed_ release];\n  [super dealloc];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataFeedLink* newLink = [super copyWithZone:zone];\n  [newLink setFeed:[[[self feed] copyWithZone:zone] autorelease]];\n  return newLink;\n}\n\n- (BOOL)isEqual:(GDataFeedLink *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataFeedLink class]]) return NO;\n\n  return [super isEqual:other]\n    && AreEqualOrBothNil([self feed], [other feed]);\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n\n  static struct GDataDescriptionRecord descRecs[] = {\n    { @\"href\",      @\"href\",                  kGDataDescValueLabeled   },\n    { @\"readOnly\",  @\"isReadOnly\",            kGDataDescBooleanPresent },\n    { @\"countHint\", @\"countHint.stringValue\", kGDataDescValueLabeled   },\n    { @\"feed\",      @\"feed\",                  kGDataDescValueLabeled   },\n    { @\"rel\",       @\"rel\",                   kGDataDescValueLabeled   },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n- (NSXMLElement *)XMLElement {\n\n  NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:nil];\n\n  if ([self feed]) {\n    [element addChild:[[self feed] XMLElement]];\n  }\n  return element;\n}\n\n- (NSString *)href {\n  return [self stringValueForAttribute:kHrefAttr];\n}\n\n- (void)setHref:(NSString *)str {\n  [self setStringValue:str forAttribute:kHrefAttr];\n}\n\n- (BOOL)isReadOnly {\n  return [self boolValueForAttribute:KReadOnlyAttr defaultValue:NO];\n}\n\n- (void)setIsReadOnly:(BOOL)isReadOnly {\n  [self setBoolValue:isReadOnly defaultValue:NO forAttribute:KReadOnlyAttr];\n}\n\n- (NSNumber *)countHint {\n  return [self intNumberForAttribute:kCountHintAttr];\n}\n\n-(void)setCountHint:(NSNumber *)val {\n  [self setStringValue:[val stringValue] forAttribute:kCountHintAttr];\n}\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (GDataFeedBase *)feed {\n  return feed_;\n}\n\n- (void)setFeed:(GDataFeedBase *)feed {\n  [feed_ autorelease];\n  feed_ = [feed retain];\n}\n\n// convenience method\n\n- (NSURL *)URL {\n  NSString *href = [self href];\n  if ([href length] > 0) {\n    return [NSURL URLWithString:href];\n  }\n  return nil;\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataGenerator.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataGenerator.h\n//\n\n#import \"GDataObject.h\"\n\n// Feed generator element, as in\n//   <generator version='1.0' uri='http://www.google.com/calendar/'>CL2</generator>\n@interface GDataGenerator : GDataObject <GDataExtension> {\n}\n+ (GDataGenerator *)generatorWithName:(NSString *)name\n                              version:(NSString *)version\n                                  URI:(NSString *)uri;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)version;\n- (void)setVersion:(NSString *)str;\n\n- (NSString *)URI;\n- (void)setURI:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataGenerator.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataGenerator.m\n//\n\n#import \"GDataGenerator.h\"\n\nstatic NSString* const kVersionAttr = @\"version\";\nstatic NSString* const kURIAttr = @\"uri\";\n\n@implementation GDataGenerator\n// Feed generator element, as in\n//   <generator version='1.0' uri='http://www.google.com/calendar/'>CL2</generator>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"generator\"; }\n\n+ (GDataGenerator *)generatorWithName:(NSString *)name\n                              version:(NSString *)version\n                                  URI:(NSString *)uri {\n  GDataGenerator *obj = [self object];\n  [obj setName:name];\n  [obj setVersion:version];\n  [obj setURI:uri];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kVersionAttr, kURIAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n- (NSString *)name {\n  return [self contentStringValue];\n}\n\n- (void)setName:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n- (NSString *)version {\n  return [self stringValueForAttribute:kVersionAttr];\n}\n\n- (void)setVersion:(NSString *)str {\n  [self setStringValue:str forAttribute:kVersionAttr];\n}\n\n- (NSString *)URI {\n  return [self stringValueForAttribute:kURIAttr];\n}\n\n- (void)setURI:(NSString *)str {\n  [self setStringValue:str forAttribute:kURIAttr];\n}\n\n@end\n\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataGeoPt.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataGeoPt.h\n//\n//  NOTE: As of July 2007, GDataGeoPt is deprecated.  Use GDataGeo instead.\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n\n#import \"GDataObject.h\"\n\n@class GDataDateTime;\n\n// geoPt element, as in\n//   <gd:geoPt lat=\"27.98778\" lon=\"86.94444\" elev=\"8850.0\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdGeoPt\n\n\n@interface GDataGeoPt : GDataObject <NSCopying, GDataExtension> {\n  NSString *label_;\n  NSNumber *lat_;\n  NSNumber *lon_;\n  NSNumber *elev_;\n  GDataDateTime* time_;\n}\n+ (GDataGeoPt *)geoPtWithLabel:(NSString *)label\n                           lat:(NSNumber *)lat\n                           lon:(NSNumber *)lon\n                          elev:(NSNumber *)elev\n                          time:(GDataDateTime *)aTime;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent;\n- (NSXMLElement *)XMLElement;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n- (NSNumber *)lat;\n- (void)setLat:(NSNumber *)val;\n- (NSNumber *)lon;\n- (void)setLon:(NSNumber *)val;\n- (NSNumber *)elev;\n- (void)setElev:(NSNumber *)val;\n- (GDataDateTime *)time;\n- (void)setTime:(GDataDateTime *)cdate;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataGeoPt.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataGeoPt.m\n//\n//  NOTE: As of July 2007, GDataGeoPt is deprecated.  Use GDataGeo instead.\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n\n#import \"GDataGeoPt.h\"\n#import \"GDataDateTime.h\"\n\n@implementation GDataGeoPt\n// geoPt element, as in\n//   <gd:geoPt lat=\"27.98778\" lon=\"86.94444\" elev=\"8850.0\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdGeoPt\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"geoPt\"; }\n\n+ (GDataGeoPt *)geoPtWithLabel:(NSString *)label\n                           lat:(NSNumber *)lat\n                           lon:(NSNumber *)lon\n                          elev:(NSNumber *)elev\n                          time:(GDataDateTime *)aTime {\n  GDataGeoPt *obj = [self object];\n  [obj setLabel:label];\n  [obj setLat:lat];\n  [obj setLon:lon];\n  [obj setElev:elev];\n  [obj setTime:aTime];\n  return obj;\n}\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent {\n  self = [super initWithXMLElement:element\n                            parent:parent];\n  if (self) {\n    [self setLabel:[self stringForAttributeName:@\"label\"\n                                    fromElement:element]];\n    [self setLat:[self doubleNumberForAttributeName:@\"lat\"\n                                        fromElement:element]];\n    [self setLon:[self doubleNumberForAttributeName:@\"lon\"\n                                        fromElement:element]];\n    [self setElev:[self doubleNumberForAttributeName:@\"elev\"\n                                         fromElement:element]];\n    [self setTime:[self dateTimeForAttributeName:@\"time\"\n                                     fromElement:element]];\n  }\n  return self;\n}\n\n- (void)dealloc {\n  [label_ release];\n  [lat_ release];\n  [lon_ release];\n  [elev_ release];\n  [time_ release];\n  [super dealloc];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  GDataGeoPt* newObj = [super copyWithZone:zone];\n  [newObj setLabel:[self label]];\n  [newObj setLat:[self lat]];\n  [newObj setLon:[self lon]];\n  [newObj setElev:[self elev]];\n  [newObj setTime:[[[self time] copyWithZone:zone] autorelease]];\n  return newObj;\n}\n\n- (BOOL)isEqual:(GDataGeoPt *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataGeoPt class]]) return NO;\n\n  // the stringValue of an NSNumber is a rounded version; compare those\n  // rather than non-rounded versions\n  return [super isEqual:other]\n    && AreEqualOrBothNil([self label], [other label])\n    && AreEqualOrBothNil([[self lat] stringValue], [[other lat] stringValue])\n    && AreEqualOrBothNil([[self lon] stringValue], [[other lon] stringValue])\n    && AreEqualOrBothNil([[self elev] stringValue], [[other elev] stringValue])\n    && AreEqualOrBothNil([self time], [other time]);\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  static struct GDataDescriptionRecord descRecs[] = {\n    { @\"label\", @\"label\",            kGDataDescValueLabeled },\n    { @\"lat\",   @\"lat\",              kGDataDescValueLabeled },\n    { @\"lon\",   @\"lon\",              kGDataDescValueLabeled },\n    { @\"elev\",  @\"elev\",             kGDataDescValueLabeled },\n    { @\"time\",  @\"time.stringValue\", kGDataDescValueLabeled },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n- (NSXMLElement *)XMLElement {\n\n  NSXMLElement *element = [self XMLElementWithExtensionsAndDefaultName:@\"gd:geoPt\"];\n\n  [self addToElement:element attributeValueIfNonNil:[self label] withName:@\"label\"];\n  [self addToElement:element attributeValueIfNonNil:[[self lat] stringValue] withName:@\"lat\"];\n  [self addToElement:element attributeValueIfNonNil:[[self lon] stringValue] withName:@\"lon\"];\n  [self addToElement:element attributeValueIfNonNil:[[self elev] stringValue] withName:@\"elev\"];\n  [self addToElement:element attributeValueIfNonNil:[[self time] RFC3339String] withName:@\"time\"];\n\n  return element;\n}\n\n- (NSString *)label {\n  return label_;\n}\n\n- (void)setLabel:(NSString *)str {\n  [label_ autorelease];\n  label_ = [str copy];\n}\n\n- (NSNumber *)lat {\n  return lat_;\n}\n\n- (void)setLat:(NSNumber *)num {\n  [lat_ autorelease];\n  lat_ = [num copy];\n}\n\n- (NSNumber *)lon {\n  return lon_;\n}\n\n- (void)setLon:(NSNumber *)num {\n  [lon_ autorelease];\n  lon_ = [num copy];\n}\n\n- (NSNumber *)elev {\n  return elev_;\n}\n\n- (void)setElev:(NSNumber *)num {\n  [elev_ autorelease];\n  elev_ = [num copy];\n}\n\n- (GDataDateTime *)time {\n  return time_;\n}\n\n- (void)setTime:(GDataDateTime *)cdate {\n  [time_ autorelease];\n  time_ = [cdate retain];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataIM.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataIM.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAIM_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataIMProtocolAIM        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#AIM\");\n_EXTERN NSString* const kGDataIMProtocolGoogleTalk _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#GOOGLE_TALK\");\n_EXTERN NSString* const kGDataIMProtocolICQ        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#ICQ\");\n_EXTERN NSString* const kGDataIMProtocolJabber     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#JABBER\");\n_EXTERN NSString* const kGDataIMProtocolMSN        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#MSN\");\n_EXTERN NSString* const kGDataIMProtocolNetMeeting _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#NETMEETING\");\n_EXTERN NSString* const kGDataIMProtocolQQ         _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#QQ\");\n_EXTERN NSString* const kGDataIMProtocolSkype      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#SKYPE\");\n_EXTERN NSString* const kGDataIMProtocolYahoo      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#YAHOO\");\n\n// IM element, as in\n//   <gd:im protocol=\"http://schemas.google.com/g/2005#MSN\"\n//      address=\"foo@bar.example.com\" label=\"Alternate\"\n//      rel=\"http://schemas.google.com/g/2005#other\" >\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdIm\n\n@interface GDataIM : GDataObject <GDataExtension> {\n}\n\n+ (GDataIM *)IMWithProtocol:(NSString *)protocol\n                        rel:(NSString *)rel\n                      label:(NSString *)label\n                    address:(NSString *)address;\n\n- (NSString *)address;\n- (void)setAddress:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)protocol;\n- (void)setProtocol:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataIM.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataIM.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#define GDATAIM_DEFINE_GLOBALS 1\n#import \"GDataIM.h\"\n\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kLabelAttr = @\"label\";\nstatic NSString* const kAddressAttr = @\"address\";\nstatic NSString* const kProtocolAttr = @\"protocol\";\nstatic NSString* const kPrimaryAttr = @\"primary\";\n\n@implementation GDataIM\n// IM element, as in\n//   <gd:im protocol=\"http://schemas.google.com/g/2005#MSN\"\n//      address=\"foo@bar.example.com\" label=\"Alternate\"\n//      rel=\"http://schemas.google.com/g/2005#other\" >\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdIm\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"im\"; }\n\n+ (GDataIM *)IMWithProtocol:(NSString *)protocol\n                        rel:(NSString *)rel\n                      label:(NSString *)label\n                    address:(NSString *)address {\n\n  GDataIM *obj = [self object];\n  [obj setProtocol:protocol];\n  [obj setRel:rel];\n  [obj setLabel:label];\n  [obj setAddress:address];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kAddressAttr, kProtocolAttr, kLabelAttr, kRelAttr,\n                    kPrimaryAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n\n  return [NSArray arrayWithObject:kPrimaryAttr];\n}\n\n#pragma mark -\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSString *)address {\n  return [self stringValueForAttribute:kAddressAttr];\n}\n\n- (void)setAddress:(NSString *)str {\n  [self setStringValue:str forAttribute:kAddressAttr];\n}\n\n- (NSString *)protocol {\n  return [self stringValueForAttribute:kProtocolAttr];\n}\n\n- (void)setProtocol:(NSString *)str {\n  [self setStringValue:str forAttribute:kProtocolAttr];\n}\n\n- (BOOL)isPrimary {\n  return [self boolValueForAttribute:kPrimaryAttr defaultValue:NO];\n}\n\n- (void)setIsPrimary:(BOOL)flag {\n  [self setBoolValue:flag defaultValue:NO forAttribute:kPrimaryAttr];\n}\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataLink.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataLink.h\n//\n\n#import \"GDataObject.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATALINK_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataLinkRelFeed            _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#feed\");\n_EXTERN NSString* const kGDataLinkRelPost            _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#post\");\n_EXTERN NSString* const kGDataLinkRelBatch           _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#batch\");\n_EXTERN NSString* const kGDataLinkRelResumableCreate _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#resumable-create-media\");\n_EXTERN NSString* const kGDataLinkRelResumableEdit   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#resumable-edit-media\");\n\n_EXTERN NSString* const kGDataLinkTypeAtom _INITIALIZE_AS(@\"application/atom+xml\");\n_EXTERN NSString* const kGDataLinkTypeHTML _INITIALIZE_AS(@\"text/html\");\n\n// for links, like\n//\n//  <link rel=\"alternate\" type=\"text/html\"\n//        href=\"http://www.google.com/calendar/event?eid=b...\" title=\"alternate\">\n//     <content type=\"application/atom+xml;feed\"> <feed>...</feed> </content>\n//  </link>\n//\n\n@class GDataAtomContent;\n\n@interface GDataLink : GDataObject <GDataExtension>\n\n+ (GDataLink *)linkWithRel:(NSString *)rel\n                      type:(NSString *)type\n                      href:(NSString *)href;  // parameters may be nil\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n- (NSString *)href;\n- (void)setHref:(NSString *)str;\n\n- (NSString *)hrefLang;\n- (void)setHrefLang:(NSString *)str;\n\n- (NSString *)title;\n- (void)setTitle:(NSString *)str;\n\n- (NSString *)titleLang;\n- (void)setTitleLang:(NSString *)str;\n\n- (NSNumber *)resourceLength;\n- (void)setResourceLength:(NSNumber *)length;\n\n- (NSString *)ETag;\n- (void)setETag:(NSString *)str;\n\n- (GDataAtomContent *)content;\n- (void)setContent:(GDataAtomContent *)obj;\n\n// convenience method\n\n// convert the href string into an URL\n- (NSURL *)URL;\n\n// utility methods\n\n// get a list of short names for links in the array\n+ (NSArray *)linkNamesFromLinks:(NSArray *)links;\n\n// utilities for extracting a GDataLink from an array of links\n\n// to search by rel only, use nil type to match any type\n+ (GDataLink *)linkWithRel:(NSString *)relValue type:(NSString *)typeValue fromLinks:(NSArray *)array;\n\n+ (GDataLink *)linkWithRelAttributeSuffix:(NSString *)relSuffix fromLinks:(NSArray *)array;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataLink.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataLink.m\n//\n\n#define GDATALINK_DEFINE_GLOBALS 1\n\n#import \"GDataLink.h\"\n#import \"GDataBaseElements.h\"\n\nstatic NSString *const kRelAttr = @\"rel\";\nstatic NSString *const kTypeAttr = @\"type\";\nstatic NSString *const kHrefAttr = @\"href\";\nstatic NSString *const kHrefLangAttr = @\"hrefLang\";\nstatic NSString *const kTitleAttr = @\"title\";\nstatic NSString *const kLangAttr = @\"xml:lang\";\nstatic NSString *const kLengthAttr = @\"length\";\n\n@implementation GDataLink\n// for links, like <link rel=\"alternate\" type=\"text/html\"\n//     href=\"http://www.google.com/calendar/event?eid=b...\" title=\"alternate\"/>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"link\"; }\n\n+ (GDataLink *)linkWithRel:(NSString *)rel\n                      type:(NSString *)type\n                      href:(NSString *)href {\n  GDataLink *dataLink = [self object];\n  [dataLink setRel:rel];\n  [dataLink setType:type];\n  [dataLink setHref:href];\n  return dataLink;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kRelAttr, kTypeAttr, kHrefAttr, kHrefLangAttr,\n                    kTitleAttr, kLangAttr, kLengthAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  Class elementClass = [self class];\n\n  [self addExtensionDeclarationForParentClass:elementClass\n                                   childClass:[GDataAtomContent class]];\n\n  [self addAttributeExtensionDeclarationForParentClass:elementClass\n                                            childClass:[GDataETagAttribute class]];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n\n  NSMutableArray *items = [super itemsForDescription];\n\n  [self addToArray:items objectDescriptionIfNonNil:[self content] withName:@\"content\"];\n  [self addToArray:items objectDescriptionIfNonNil:[self ETag] withName:@\"etag\"];\n\n  return items;\n}\n#endif\n\n#pragma mark -\n\n- (NSString *)rel {\n  NSString *str = [self stringValueForAttribute:kRelAttr];\n  return [str length] > 0 ? str : @\"alternate\"; // per Link.java\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSString *)type {\n  return [self stringValueForAttribute:kTypeAttr];\n}\n\n- (void)setType:(NSString *)str {\n  [self setStringValue:str forAttribute:kTypeAttr];\n}\n\n- (NSString *)href {\n  return [self stringValueForAttribute:kHrefAttr];\n}\n\n- (void)setHref:(NSString *)str {\n  [self setStringValue:str forAttribute:kHrefAttr];\n}\n\n- (NSString *)hrefLang {\n  return [self stringValueForAttribute:kHrefLangAttr];\n}\n\n- (void)setHrefLang:(NSString *)str {\n  [self setStringValue:str forAttribute:kHrefLangAttr];\n}\n\n- (NSString *)title {\n  return [self stringValueForAttribute:kTitleAttr];\n}\n\n- (void)setTitle:(NSString *)str {\n  [self setStringValue:str forAttribute:kTitleAttr];\n}\n\n- (NSString *)titleLang {\n  return [self stringValueForAttribute:kLangAttr];\n}\n\n- (void)setTitleLang:(NSString *)str {\n  [self setStringValue:str forAttribute:kLangAttr];\n}\n\n- (NSNumber *)resourceLength {\n  return [self intNumberForAttribute:kLengthAttr];\n}\n\n- (void)setResourceLength:(NSNumber *)length {\n  [self setStringValue:[length stringValue] forAttribute:kLengthAttr];\n}\n\n- (NSString *)ETag {\n  NSString *str = [self attributeValueForExtensionClass:[GDataETagAttribute class]];\n  return str;\n}\n\n- (void)setETag:(NSString *)str {\n  [self setAttributeValue:str forExtensionClass:[GDataETagAttribute class]];\n}\n\n- (GDataAtomContent *)content {\n  return [self objectForExtensionClass:[GDataAtomContent class]];\n}\n\n- (void)setContent:(GDataAtomContent *)obj {\n  [self setObject:obj forExtensionClass:[GDataAtomContent class]];\n}\n\n// convenience method\n\n- (NSURL *)URL {\n  NSString *href = [self href];\n  if ([href length] > 0) {\n    return [NSURL URLWithString:href];\n  }\n  return nil;\n}\n\n// utility method\n\n+ (NSArray *)linkNamesFromLinks:(NSArray *)links {\n  // we'll make a list of short, readable link names\n  // by grabbing the rel values, and removing anything before\n  // the last pound sign if there is one\n\n  NSMutableArray *names = nil;\n\n  for (GDataLink *dataLink in links) {\n\n    NSString *rel = [dataLink rel];\n    NSString *displayName;\n\n    NSRange range = [rel rangeOfString:@\"#\" options:NSBackwardsSearch];\n    if (range.location != NSNotFound) {\n      // the display name is the suffix of the link's rel string\n      displayName = [rel substringFromIndex:(1 + range.location)];\n    } else {\n      displayName = rel;\n    }\n\n    if (names == nil) {\n      names = [NSMutableArray array];\n    }\n    [names addObject:displayName];\n  }\n  return names;\n}\n\n#pragma mark Utilities\n\n// Find the first link with the given rel and type values. Either argument\n// may be nil, which means \"match any value\".\n+ (GDataLink *)linkWithRel:(NSString *)relValue\n                      type:(NSString *)typeValue\n                 fromLinks:(NSArray *)array {\n\n  for (GDataLink *dataLink in array) {\n\n    NSString *foundRelValue = [dataLink rel];\n    NSString *foundTypeValue = [dataLink type];\n\n    if ((relValue == nil || AreEqualOrBothNil(relValue, foundRelValue))\n        && (typeValue == nil || AreEqualOrBothNil(typeValue, foundTypeValue))) {\n      return dataLink;\n    }\n  }\n  return nil;\n}\n\n+ (GDataLink *)linkWithRelAttributeSuffix:(NSString *)relSuffix\n                                fromLinks:(NSArray *)array {\n\n  for (GDataLink *dataLink in array) {\n\n    NSString *attrValue = [dataLink rel];\n    if (attrValue && [attrValue hasSuffix:relSuffix]) {\n      return dataLink;\n    }\n  }\n  return nil;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataMoney.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataMoney.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_FINANCE_SERVICE || GDATA_INCLUDE_BOOKS_SERVICE\n\n#import \"GDataObject.h\"\n\n// money element, as in\n//  <gd:money amount=\"10\" currencycode=\"USD\"/>\n\n@interface GDataMoney : GDataObject <GDataExtension>\n\n+ (GDataMoney *)moneyWithAmount:(NSNumber *)amount\n                   currencyCode:(NSString *)currencyCode;\n\n- (NSDecimalNumber *)amount;\n- (void)setAmount:(NSNumber *)num;\n\n- (NSString *)currencyCode;\n- (void)setCurrencyCode:(NSString *)str;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_FINANCE_SERVICE || GDATA_INCLUDE_BOOKS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataMoney.m",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataMoney.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_FINANCE_SERVICE || GDATA_INCLUDE_BOOKS_SERVICE\n\n#import \"GDataMoney.h\"\n\nstatic NSString* const kAmountAttr = @\"amount\";\nstatic NSString* const kCurrencyCodeAttr = @\"currencyCode\";\n\n@implementation GDataMoney\n// money element, as in\n//  <gd:money amount=\"10\" currencyCode=\"USD\"/>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"money\"; }\n\n+ (GDataMoney *)moneyWithAmount:(NSNumber *)amount\n                   currencyCode:(NSString *)currencyCode {\n  GDataMoney *obj = [self object];\n  [obj setAmount:amount];\n  [obj setCurrencyCode:currencyCode];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects: \n                    kAmountAttr, kCurrencyCodeAttr, nil];\n  \n  [self addLocalAttributeDeclarations:attrs];\n}\n\n#pragma mark -\n\n- (NSDecimalNumber *)amount {\n  return [self decimalNumberForAttribute:kAmountAttr];\n}\n\n- (void)setAmount:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kAmountAttr];\n}\n\n- (NSString *)currencyCode {\n  return [self stringValueForAttribute:kCurrencyCodeAttr]; \n}\n\n- (void)setCurrencyCode:(NSString *)str {\n  [self setStringValue:str forAttribute:kCurrencyCodeAttr];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_FINANCE_SERVICE || GDATA_INCLUDE_BOOKS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataName.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataName.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n@interface GDataNameElement : GDataObject\n\n+ (id)nameElementWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n// an optional yomi attribute for pronunciation\n- (void)setYomi:(NSString *)str;\n- (NSString *)yomi;\n@end\n\n@interface GDataName : GDataObject <GDataExtension>\n\n+ (GDataName *)name;\n+ (GDataName *)nameWithFullNameString:(NSString *)str;\n+ (GDataName *)nameWithPrefix:(NSString *)prefix\n                  givenString:(NSString *)first\n             additionalString:(NSString *)middle\n                 familyString:(NSString *)last\n                       suffix:(NSString *)suffix;\n\n- (GDataNameElement *)additionalName;\n- (void)setAdditionalName:(GDataNameElement *)obj;\n- (void)setAdditionalNameWithString:(NSString *)str;\n\n- (GDataNameElement *)familyName;\n- (void)setFamilyName:(GDataNameElement *)obj;\n- (void)setFamilyNameWithString:(NSString *)str;\n\n- (GDataNameElement *)fullName;\n- (void)setFullName:(GDataNameElement *)obj;\n- (void)setFullNameWithString:(NSString *)str;\n\n- (GDataNameElement *)givenName;\n- (void)setGivenName:(GDataNameElement *)obj;\n- (void)setGivenNameWithString:(NSString *)str;\n\n- (NSString *)namePrefix;\n- (void)setNamePrefix:(NSString *)str;\n\n- (NSString *)nameSuffix;\n- (void)setNameSuffix:(NSString *)str;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataName.m",
    "content": "/* Copyright (c) 2009 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataName.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataName.h\"\n#import \"GDataValueConstruct.h\"\n\n//\n// private internal classes used as extensions by GDataName\n//\n\n@interface GDataNameAdditional : GDataNameElement <GDataExtension>\n@end\n\n@implementation GDataNameAdditional;\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"additionalName\"; }\n@end\n\n@interface GDataNameFamily : GDataNameElement <GDataExtension>\n@end\n\n@implementation GDataNameFamily;\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"familyName\"; }\n@end\n\n@interface GDataNameFull : GDataNameElement <GDataExtension>\n@end\n\n@implementation GDataNameFull;\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"fullName\"; }\n@end\n\n@interface GDataNameGiven : GDataNameElement <GDataExtension>\n@end\n\n@implementation GDataNameGiven;\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"givenName\"; }\n@end\n\n@interface GDataNamePrefix : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataNamePrefix;\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"namePrefix\"; }\n@end\n\n@interface GDataNameSuffix : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataNameSuffix;\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"nameSuffix\"; }\n@end\n\n//\n// GDataNameElement is the base class for the full, given, family, and\n// additional name elements.  Each name element has a string value and\n// an optional yomi attribute for pronunciation.\n//\n\n@implementation GDataNameElement\n\nstatic NSString* const kYomiAttr = @\"yomi\";\n\n+ (id)nameElementWithString:(NSString *)str {\n  // the contacts API does not want empty name elements\n  if ([str length] == 0) return nil;\n  \n  GDataNameElement *obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n// internal method for converting name element types, since the setters below\n// take a generic GDataNameElement argument, but those don't have the extension\n// methods specifying localName, etc\n\n+ (id)nameElementWithNameElement:(GDataNameElement *)source {\n  GDataNameElement *obj = [self object];\n  [obj setStringValue:[source stringValue]];\n  [obj setYomi:[source yomi]];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n\n  [self addLocalAttributeDeclarations:[NSArray arrayWithObject:kYomiAttr]];\n\n  [self addContentValueDeclaration];\n}\n\n- (NSString *)stringValue {\n  return [self contentStringValue];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n- (NSString *)yomi {\n  return [self stringValueForAttribute:kYomiAttr];\n}\n\n- (void)setYomi:(NSString *)str {\n  // the contacts API does not want empty name elements\n  if ([str length] == 0) str = nil;\n\n  [self setStringValue:str forAttribute:kYomiAttr];\n}\n\n@end\n\n\n//\n// GDataName class\n//\n\n@implementation GDataName\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"name\"; }\n\n+ (GDataName *)name {\n  GDataName* obj = [self object];\n  return obj;\n}\n\n+ (GDataName *)nameWithFullNameString:(NSString *)str {\n  GDataName* obj = [self object];\n  [obj setFullNameWithString:str];\n  return obj;\n}\n\n+ (GDataName *)nameWithPrefix:(NSString *)prefix\n                  givenString:(NSString *)first\n             additionalString:(NSString *)middle\n                 familyString:(NSString *)last\n                       suffix:(NSString *)suffix {\n  GDataName* obj = [self object];\n\n  [obj setNamePrefix:prefix];\n  [obj setGivenNameWithString:first];\n  [obj setAdditionalNameWithString:middle];\n  [obj setFamilyNameWithString:last];\n  [obj setNameSuffix:suffix];\n  return obj;\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  [self addExtensionDeclarationForParentClass:[self class]\n                                 childClasses:\n   [GDataNameAdditional class],\n   [GDataNameFamily class],\n   [GDataNameFull class],\n   [GDataNameGiven class],\n   [GDataNamePrefix class],\n   [GDataNameSuffix class],\n   nil];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n\n  static struct GDataDescriptionRecord descRecs[] = {\n    { @\"prefix\",     @\"namePrefix\",                 kGDataDescValueLabeled },\n    { @\"given\",      @\"givenName.stringValue\",      kGDataDescValueLabeled },\n    { @\"additional\", @\"additionalName.stringValue\", kGDataDescValueLabeled },\n    { @\"family\",     @\"familyName.stringValue\",     kGDataDescValueLabeled },\n    { @\"suffix\",     @\"nameSuffix\",                 kGDataDescValueLabeled },\n    { @\"full\",       @\"fullName.stringValue\",       kGDataDescValueLabeled },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n#pragma mark -\n\n- (GDataNameElement *)additionalName {\n  GDataNameAdditional *obj;\n\n  obj = [self objectForExtensionClass:[GDataNameAdditional class]];\n  return obj;\n}\n\n- (void)setAdditionalName:(GDataNameElement *)obj {\n  GDataNameAdditional *typedObj = [GDataNameAdditional nameElementWithNameElement:obj];\n  [self setObject:typedObj forExtensionClass:[GDataNameAdditional class]];\n}\n\n- (void)setAdditionalNameWithString:(NSString *)str {\n  GDataNameAdditional *obj = [GDataNameAdditional nameElementWithString:str];\n  [self setObject:obj forExtensionClass:[GDataNameAdditional class]];\n}\n\n\n- (GDataNameElement *)familyName {\n  GDataNameFamily *obj;\n\n  obj = [self objectForExtensionClass:[GDataNameFamily class]];\n  return obj;\n}\n\n- (void)setFamilyName:(GDataNameElement *)obj {\n  GDataNameFamily *typedObj = [GDataNameFamily nameElementWithNameElement:obj];\n  [self setObject:typedObj forExtensionClass:[GDataNameFamily class]];\n}\n\n- (void)setFamilyNameWithString:(NSString *)str {\n  GDataNameFamily *obj = [GDataNameFamily nameElementWithString:str];\n  [self setObject:obj forExtensionClass:[GDataNameFamily class]];\n}\n\n\n- (GDataNameElement *)fullName {\n  GDataNameFull *obj;\n\n  obj = [self objectForExtensionClass:[GDataNameFull class]];\n  return obj;\n}\n\n- (void)setFullName:(GDataNameElement *)obj {\n  GDataNameFull *typedObj = [GDataNameFull nameElementWithNameElement:obj];\n  [self setObject:typedObj forExtensionClass:[GDataNameFull class]];\n}\n\n- (void)setFullNameWithString:(NSString *)str {\n  GDataNameFull *obj = [GDataNameFull nameElementWithString:str];\n  [self setObject:obj forExtensionClass:[GDataNameFull class]];\n}\n\n\n- (GDataNameElement *)givenName {\n  GDataNameGiven *obj;\n\n  obj = [self objectForExtensionClass:[GDataNameGiven class]];\n  return obj;\n}\n\n- (void)setGivenName:(GDataNameElement *)obj {\n  GDataNameGiven *typedObj = [GDataNameGiven nameElementWithNameElement:obj];\n  [self setObject:typedObj forExtensionClass:[GDataNameGiven class]];\n}\n\n- (void)setGivenNameWithString:(NSString *)str {\n  GDataNameGiven *obj = [GDataNameGiven nameElementWithString:str];\n  [self setObject:obj forExtensionClass:[GDataNameGiven class]];\n}\n\n\n- (NSString *)namePrefix {\n  GDataNamePrefix *obj;\n\n  obj = [self objectForExtensionClass:[GDataNamePrefix class]];\n  return [obj stringValue];\n}\n\n- (void)setNamePrefix:(NSString *)str {\n  // the contacts API does not want empty name elements\n  if ([str length] == 0) str = nil;\n\n  GDataNamePrefix *obj = [GDataNamePrefix valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataNamePrefix class]];\n}\n\n\n- (NSString *)nameSuffix {\n  GDataNameSuffix *obj;\n\n  obj = [self objectForExtensionClass:[GDataNameSuffix class]];\n  return [obj stringValue];\n}\n\n- (void)setNameSuffix:(NSString *)str {\n  // the contacts API does not want empty name elements\n  if ([str length] == 0) str = nil;\n\n  GDataNameSuffix *obj = [GDataNameSuffix valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataNameSuffix class]];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataOrganization.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataOrganization.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n@class GDataWhere;\n\n// organization, as in\n//\n// <gd:organization rel=\"http://schemas.google.com/g/2005#work\" label=\"Work\" primary=\"true\"/>\n//   <gd:orgName>Google</gd:orgName>\n//   <gd:orgTitle>Tech Writer</gd:orgTitle>\n//   <gd:orgJobDescription>Writes documentation</gd:orgJobDescription>\n//   <gd:orgDepartment>Software Development</gd:orgDepartment>\n//   <gd:orgSymbol>GOOG</gd:orgSymbol>\n// </gd:organization>\n\n@interface GDataOrganization : GDataObject <GDataExtension>\n\n+ (GDataOrganization *)organizationWithName:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n\n- (NSString *)orgName;\n- (void)setOrgName:(NSString *)str;\n\n- (NSString *)orgNameYomi;\n- (void)setOrgNameYomi:(NSString *)str;\n\n- (NSString *)orgTitle;\n- (void)setOrgTitle:(NSString *)str;\n\n- (NSString *)orgDepartment;\n- (void)setOrgDepartment:(NSString *)str;\n\n- (NSString *)orgJobDescription;\n- (void)setOrgJobDescription:(NSString *)str;\n\n- (NSString *)orgSymbol;\n- (void)setOrgSymbol:(NSString *)str;\n\n- (GDataWhere *)where;\n- (void)setWhere:(GDataWhere *)obj;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataOrganization.m",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataOrganization.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataOrganization.h\"\n#import \"GDataOrganizationName.h\"\n#import \"GDataWhere.h\"\n\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kLabelAttr = @\"label\";\nstatic NSString* const kPrimaryAttr = @\"primary\";\n\nstatic NSString* StringOrNilIfBlank(NSString *str) {\n  // return nil if the string only has whitespace\n  NSCharacterSet *wsSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];\n  NSString *trimmed = [str stringByTrimmingCharactersInSet:wsSet];\n  if ([trimmed length] == 0) return nil;\n\n  return str;\n}\n\n\n@interface GDataOrgDepartment : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataOrgDepartment\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData;       }\n+ (NSString *)extensionElementLocalName { return @\"orgDepartment\";           }\n@end\n\n@interface GDataOrgJobDescription : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataOrgJobDescription\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData;       }\n+ (NSString *)extensionElementLocalName { return @\"orgJobDescription\";       }\n@end\n\n@interface GDataOrgSymbol : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataOrgSymbol\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData;       }\n+ (NSString *)extensionElementLocalName { return @\"orgSymbol\";               }\n@end\n\n@interface GDataOrgTitle : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataOrgTitle\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData;       }\n+ (NSString *)extensionElementLocalName { return @\"orgTitle\";                }\n@end\n\n\n@implementation GDataOrganization\n// organization, as in\n//  <gd:organization primary=\"true\" rel=\"http://schemas.google.com/g/2005#work\">\n//    <gd:orgName yomi=\"Ak Me\">Acme Corp</gd:orgName>\n//    <gd:orgTitle>Prezident</gd:orgTitle>\n//  </gd:organization>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"organization\"; }\n\n+ (GDataOrganization *)organizationWithName:(NSString *)str {\n  GDataOrganization *obj = [self object];\n  [obj setOrgName:str];\n  return obj;\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  Class elementClass = [self class];\n\n  [self addExtensionDeclarationForParentClass:elementClass\n                                 childClasses:\n   [GDataOrgDepartment class],\n   [GDataOrgJobDescription class],\n   [GDataOrgSymbol class],\n   [GDataOrgTitle class],\n   [GDataOrganizationName class],\n   [GDataWhere class],\n   nil];\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kLabelAttr, kRelAttr, kPrimaryAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  static struct GDataDescriptionRecord descRecs[] = {\n    { @\"name\",        @\"orgName\",           kGDataDescValueLabeled   },\n    { @\"orgNameYomi\", @\"orgNameYomi\",       kGDataDescValueLabeled   },\n    { @\"title\",       @\"orgTitle\",          kGDataDescValueLabeled   },\n    { @\"dept\",        @\"orgDepartment\",     kGDataDescValueLabeled   },\n    { @\"jobDesc\",     @\"orgJobDescription\", kGDataDescValueLabeled   },\n    { @\"symbol\",      @\"orgSymbol\",         kGDataDescValueLabeled   },\n    { @\"where\",       @\"where\",             kGDataDescValueLabeled   },\n    { @\"rel\",         @\"rel\",               kGDataDescValueLabeled   },\n    { @\"label\",       @\"label\",             kGDataDescValueLabeled   },\n    { @\"primary\",     @\"isPrimary\",         kGDataDescBooleanPresent },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n#pragma mark -\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (BOOL)isPrimary {\n  return [self boolValueForAttribute:kPrimaryAttr defaultValue:NO];\n}\n\n- (void)setIsPrimary:(BOOL)flag {\n  [self setBoolValue:flag defaultValue:NO forAttribute:kPrimaryAttr];\n}\n\n// orgName and orgNameYomi are both inside the GDataOrganizationName extension\n// element\n- (NSString *)orgName {\n  GDataOrganizationName *obj;\n\n  obj = [self objectForExtensionClass:[GDataOrganizationName class]];\n  return [obj stringValue];\n}\n\n- (void)setOrgName:(NSString *)str {\n  GDataOrganizationName *obj;\n\n  obj = [self objectForExtensionClass:[GDataOrganizationName class]];\n  if (obj == nil && str != nil) {\n    // lacked the element; create one only if we're really setting a value\n    obj = [GDataOrganizationName organizationNameWithString:nil];\n    [self setObject:obj forExtensionClass:[GDataOrganizationName class]];\n  }\n  [obj setStringValue:StringOrNilIfBlank(str)];\n}\n\n- (NSString *)orgNameYomi {\n  GDataOrganizationName *obj;\n\n  obj = [self objectForExtensionClass:[GDataOrganizationName class]];\n  return [obj yomi];\n}\n\n- (void)setOrgNameYomi:(NSString *)str {\n  GDataOrganizationName *obj;\n\n  obj = [self objectForExtensionClass:[GDataOrganizationName class]];\n  if (obj == nil && str != nil) {\n    // lacked the element; create one only if we're really setting a value\n    obj = [GDataOrganizationName organizationNameWithString:nil];\n    [self setObject:obj forExtensionClass:[GDataOrganizationName class]];\n  }\n  [obj setYomi:str];\n}\n\n- (NSString *)orgDepartment {\n  GDataOrgDepartment *obj;\n\n  obj = [self objectForExtensionClass:[GDataOrgDepartment class]];\n  return [obj stringValue];\n}\n\n- (void)setOrgDepartment:(NSString *)str {\n  GDataOrgDepartment *obj;\n\n  obj = [GDataOrgDepartment valueWithString:StringOrNilIfBlank(str)];\n  [self setObject:obj forExtensionClass:[GDataOrgDepartment class]];\n}\n\n- (NSString *)orgJobDescription {\n  GDataOrgJobDescription *obj;\n\n  obj = [self objectForExtensionClass:[GDataOrgJobDescription class]];\n  return [obj stringValue];\n}\n\n- (void)setOrgJobDescription:(NSString *)str {\n  GDataOrgJobDescription *obj;\n\n  obj = [GDataOrgJobDescription valueWithString:StringOrNilIfBlank(str)];\n  [self setObject:obj forExtensionClass:[GDataOrgJobDescription class]];\n}\n\n- (NSString *)orgSymbol {\n  GDataOrgSymbol *obj;\n\n  obj = [self objectForExtensionClass:[GDataOrgSymbol class]];\n  return [obj stringValue];\n}\n\n- (void)setOrgSymbol:(NSString *)str {\n  GDataOrgSymbol *obj;\n\n  obj = [GDataOrgSymbol valueWithString:StringOrNilIfBlank(str)];\n  [self setObject:obj forExtensionClass:[GDataOrgSymbol class]];\n}\n\n- (NSString *)orgTitle {\n  GDataOrgTitle *obj = [self objectForExtensionClass:[GDataOrgTitle class]];\n  return [obj stringValue];\n}\n\n- (void)setOrgTitle:(NSString *)str {\n  GDataOrgTitle *obj = [GDataOrgTitle valueWithString:StringOrNilIfBlank(str)];\n  [self setObject:obj forExtensionClass:[GDataOrgTitle class]];\n}\n\n- (GDataWhere *)where {\n  return [self objectForExtensionClass:[GDataWhere class]];\n}\n\n- (void)setWhere:(GDataWhere *)obj {\n  [self setObject:obj forExtensionClass:[GDataWhere class]];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataOrganizationName.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataOrganizationName.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n// organization name\n//    <gd:orgName yomi=\"Ak Me\">Acme Corp</gd:orgName>\n\n@interface GDataOrganizationName : GDataObject <GDataExtension>\n\n+ (id)organizationNameWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSString *)yomi;\n- (void)setYomi:(NSString *)str;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataOrganizationName.m",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataOrganizationName.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataOrganizationName.h\"\n\nstatic NSString* const kYomiAttr = @\"yomi\";\n\n@implementation GDataOrganizationName\n// organization name\n//    <gd:orgName yomi=\"Ak Me\">Acme Corp</gd:orgName>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"orgName\"; }\n\n+ (id)organizationNameWithString:(NSString *)str {\n  GDataOrganizationName *obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObject:kYomiAttr];\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  static struct GDataDescriptionRecord descRecs[] = {\n    { @\"value\", @\"stringValue\", kGDataDescValueLabeled },\n    { @\"yomi\",  @\"yomi\",        kGDataDescValueLabeled },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n#pragma mark -\n\n- (NSString *)stringValue {\n  return [self contentStringValue];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n- (NSString *)yomi {\n  return [self stringValueForAttribute:kYomiAttr];\n}\n\n- (void)setYomi:(NSString *)str {\n  [self setStringValue:str forAttribute:kYomiAttr];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataPerson.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataPerson.h\n//\n\n#import \"GDataObject.h\"\n// a person, as in\n// <author>\n//   <name>Fred Flintstone</name>\n//   <email>test@domain.net</email>\n// </author>\n@interface GDataPerson : GDataObject <GDataExtension>\n\n+ (GDataPerson *)personWithName:(NSString *)name email:(NSString *)email;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)nameLang;\n- (void)setNameLang:(NSString *)str;\n\n- (NSString *)URI;\n- (void)setURI:(NSString *)str;\n\n- (NSString *)email;\n- (void)setEmail:(NSString *)str;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataPerson.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataPerson.m\n//\n\n#import \"GDataPerson.h\"\n#import \"GDataValueConstruct.h\"\n\nstatic NSString *const kLangAttr = @\"xml:lang\";\n\n// name, like <atom:name>Fred Flintstone<atom:name>\n@interface GDataPersonName : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPersonName\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"name\"; }\n@end\n\n// email, like <atom:email>fred@flintstone.com<atom:email>\n@interface GDataPersonEmail : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPersonEmail\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"email\"; }\n@end\n\n// URI, like <atom:uri>http://flintstone.com/resource<atom:uri>\n@interface GDataPersonURI : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPersonURI\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"uri\"; }\n@end\n\n@implementation GDataPerson\n// a person, as in\n// <author>\n//   <name>Fred Flintstone</name>\n//   <email>fred@flintstone.com</email>\n// </author>\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceAtom; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceAtomPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"author\"; }\n\n+ (GDataPerson *)personWithName:(NSString *)name email:(NSString *)email {\n  GDataPerson* obj = [self object];\n  [obj setName:name];\n  [obj setEmail:email];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  [self addLocalAttributeDeclarations:[NSArray arrayWithObject:kLangAttr]];\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  [self addExtensionDeclarationForParentClass:[self class]\n                                 childClasses:\n   [GDataPersonName class],\n   [GDataPersonEmail class],\n   [GDataPersonURI class],\n   nil];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [super itemsForDescription];\n\n  [self addToArray:items objectDescriptionIfNonNil:[self name] withName:@\"name\"];\n  [self addToArray:items objectDescriptionIfNonNil:[self URI] withName:@\"URI\"];\n  [self addToArray:items objectDescriptionIfNonNil:[self email] withName:@\"email\"];\n\n  return items;\n}\n#endif\n\n- (NSString *)name {\n  GDataPersonName *obj = [self objectForExtensionClass:[GDataPersonName class]];\n  return [obj stringValue];\n}\n\n- (void)setName:(NSString *)str {\n  GDataPersonName *obj = [GDataPersonName valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPersonName class]];\n}\n\n- (NSString *)nameLang {\n  return [self stringValueForAttribute:kLangAttr];\n}\n\n- (void)setNameLang:(NSString *)str {\n  [self setStringValue:str forAttribute:kLangAttr];\n}\n\n- (NSString *)URI {\n  GDataPersonURI *obj = [self objectForExtensionClass:[GDataPersonURI class]];\n  return [obj stringValue];\n}\n\n- (void)setURI:(NSString *)str {\n  GDataPersonURI *obj = [GDataPersonURI valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPersonURI class]];\n}\n\n- (NSString *)email {\n  GDataPersonEmail *obj = [self objectForExtensionClass:[GDataPersonEmail class]];\n  return [obj stringValue];\n}\n\n- (void)setEmail:(NSString *)str {\n  GDataPersonEmail *obj = [GDataPersonEmail valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPersonEmail class]];\n}\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataPhoneNumber.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataPhoneNumber.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAPHONENUMBER_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// Note: kGDataContactMobile, kGDataContactHome, and kGDataContactWork are\n// equivalent to kGDataPhoneNumberMobile, kGDataPhoneNumberHome, kGDataPhoneNumberWork\n\n_EXTERN NSString* const kGDataPhoneNumberAssistant   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#assistant\");\n_EXTERN NSString* const kGDataPhoneNumberCallback    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#callback\");\n_EXTERN NSString* const kGDataPhoneNumberCar         _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#car\");\n_EXTERN NSString* const kGDataPhoneNumberCompanyMain _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#company_main\");\n_EXTERN NSString* const kGDataPhoneNumberFax         _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#fax\");\n_EXTERN NSString* const kGDataPhoneNumberHome        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#home\");\n_EXTERN NSString* const kGDataPhoneNumberHomeFax     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#home_fax\");\n_EXTERN NSString* const kGDataPhoneNumberISDN        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#isdn\");\n_EXTERN NSString* const kGDataPhoneNumberMobile      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#mobile\");\n_EXTERN NSString* const kGDataPhoneNumberOther       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#other\");\n_EXTERN NSString* const kGDataPhoneNumberOtherFax    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#other_fax\");\n_EXTERN NSString* const kGDataPhoneNumberPager       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#pager\");\n_EXTERN NSString* const kGDataPhoneNumberRadio       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#radio\");\n_EXTERN NSString* const kGDataPhoneNumberTelex       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#telex\");\n_EXTERN NSString* const kGDataPhoneNumberTTYTDD      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#tty_tdd\");\n_EXTERN NSString* const kGDataPhoneNumberWork        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work\");\n_EXTERN NSString* const kGDataPhoneNumberWorkFax     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work_fax\");\n_EXTERN NSString* const kGDataPhoneNumberWorkMobile  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work_mobile\");\n_EXTERN NSString* const kGDataPhoneNumberWorkPager   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work_pager\");\n\n// phone number, as in\n//  <gd:phoneNumber rel=\"http://schemas.google.com/g/2005#work\" >\n//    (425) 555-8080 ext. 52585\n//  </gd:phoneNumber>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdPhoneNumber\n\n@interface GDataPhoneNumber : GDataObject <GDataExtension> {\n}\n\n+ (GDataPhoneNumber *)phoneNumberWithString:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)URI;\n- (void)setURI:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataPhoneNumber.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataPhoneNumber.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#define GDATAPHONENUMBER_DEFINE_GLOBALS 1\n#import \"GDataPhoneNumber.h\"\n\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kLabelAttr = @\"label\";\nstatic NSString* const kURIAttr = @\"uri\";\nstatic NSString* const kPrimaryAttr = @\"primary\";\n\n@implementation GDataPhoneNumber\n// phone number, as in\n//  <gd:phoneNumber rel=\"http://schemas.google.com/g/2005#work\" uri=\"tel:+1-425-555-8080;ext=52585\">\n//    (425) 555-8080 ext. 52585\n//  </gd:phoneNumber>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdPhoneNumber\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"phoneNumber\"; }\n\n+ (GDataPhoneNumber *)phoneNumberWithString:(NSString *)str {\n  GDataPhoneNumber *obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kLabelAttr, kRelAttr, kURIAttr, kPrimaryAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n\n  return [NSArray arrayWithObject:kPrimaryAttr];\n}\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (NSString *)URI {\n  return [self stringValueForAttribute:kURIAttr];\n}\n\n- (void)setURI:(NSString *)str {\n  [self setStringValue:str forAttribute:kURIAttr];\n}\n\n- (NSString *)stringValue {\n  return [self contentStringValue];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n- (BOOL)isPrimary {\n  return [self boolValueForAttribute:kPrimaryAttr defaultValue:NO];\n}\n\n- (void)setIsPrimary:(BOOL)flag {\n  [self setBoolValue:flag defaultValue:NO forAttribute:kPrimaryAttr];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataPostalAddress.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataPostalAddress.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n// postal address, as in\n//  <gd:postalAddress>\n//    500 West 45th Street\n//    New York, NY 10036\n//  </gd:postalAddress>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdPostalAddress\n\n@interface GDataPostalAddress : GDataObject <GDataExtension> {\n}\n\n+ (GDataPostalAddress *)postalAddressWithString:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataPostalAddress.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataPostalAddress.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataPostalAddress.h\"\n\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kLabelAttr = @\"label\";\nstatic NSString* const kPrimaryAttr = @\"primary\";\n\n@implementation GDataPostalAddress\n// postal address, as in\n//  <gd:postalAddress>\n//    500 West 45th Street\n//    New York, NY 10036\n//  </gd:postalAddress>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdPostalAddress\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"postalAddress\"; }\n\n+ (GDataPostalAddress *)postalAddressWithString:(NSString *)str {\n  GDataPostalAddress* obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kLabelAttr, kRelAttr, kPrimaryAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n\n  return [NSArray arrayWithObject:kPrimaryAttr];\n}\n\n#pragma mark -\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (NSString *)stringValue {\n  return [self contentStringValue];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (BOOL)isPrimary {\n  return [self boolValueForAttribute:kPrimaryAttr defaultValue:NO];\n}\n\n- (void)setIsPrimary:(BOOL)flag {\n  [self setBoolValue:flag defaultValue:NO forAttribute:kPrimaryAttr];\n}\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataRating.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataRating.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_BOOKS_SERVICE \\\n  || GDATA_INCLUDE_CALENDAR_SERVICE || GDATA_INCLUDE_YOUTUBE_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATARATING_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataRatingPrice   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#price\");\n_EXTERN NSString* const kGDataRatingQuality _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#quality\");\n\n// rating, as in\n//  <gd:rating rel=\"http://schemas.google.com/g/2005#price\" value=\"5\" min=\"1\" max=\"5\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdRating\n\n@interface GDataRating : GDataObject <GDataExtension>\n\n+ (GDataRating *)ratingWithValue:(NSInteger)value\n                             max:(NSInteger)max\n                             min:(NSInteger)min;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSNumber *)value; // int\n- (void)setValue:(NSNumber *)num;\n\n- (NSNumber *)max; // int\n- (void)setMax:(NSNumber *)num;\n\n- (NSNumber *)min; // int\n- (void)setMin:(NSNumber *)num;\n\n- (NSNumber *)average; // double\n- (void)setAverage:(NSNumber *)num;\n\n- (NSNumber *)numberOfRaters; // int\n- (void)setNumberOfRaters:(NSNumber *)num;\n@end\n\n#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataRating.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataRating.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_BOOKS_SERVICE \\\n  || GDATA_INCLUDE_CALENDAR_SERVICE || GDATA_INCLUDE_YOUTUBE_SERVICE\n\n#define GDATARATING_DEFINE_GLOBALS 1\n#import \"GDataRating.h\"\n\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kValueAttr = @\"value\";\nstatic NSString* const kMaxAttr = @\"max\";\nstatic NSString* const kMinAttr = @\"min\";\nstatic NSString* const kAverageAttr = @\"average\";\nstatic NSString* const kNumRatersAttr = @\"numRaters\";\n\n@implementation GDataRating\n// rating, as in\n//  <gd:rating rel=\"http://schemas.google.com/g/2005#price\" value=\"5\" min=\"1\" max=\"5\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdRating\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"rating\"; }\n\n+ (GDataRating *)ratingWithValue:(NSInteger)value\n                             max:(NSInteger)max\n                             min:(NSInteger)min {\n  GDataRating *obj = [self object];\n  [obj setValue:[NSNumber numberWithInt:(int)value]];\n  [obj setMax:[NSNumber numberWithInt:(int)max]];\n  [obj setMin:[NSNumber numberWithInt:(int)min]];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kRelAttr, kValueAttr, kMaxAttr, kMinAttr,\n                    kAverageAttr, kNumRatersAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n#pragma mark -\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSNumber *)value {\n  return [self intNumberForAttribute:kValueAttr];\n}\n\n- (void)setValue:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kValueAttr];\n}\n\n- (NSNumber *)max {\n  return [self intNumberForAttribute:kMaxAttr];\n}\n\n- (void)setMax:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kMaxAttr];\n}\n\n- (NSNumber *)min {\n  return [self intNumberForAttribute:kMinAttr];\n}\n\n- (void)setMin:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kMinAttr];\n}\n\n- (NSNumber *)average {\n  return [self doubleNumberForAttribute:kAverageAttr];\n}\n\n- (void)setAverage:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kAverageAttr];\n}\n\n- (NSNumber *)numberOfRaters {\n  return [self intNumberForAttribute:kNumRatersAttr];\n}\n\n- (void)setNumberOfRaters:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kNumRatersAttr];\n}\n\n@end\n\n#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataStructuredPostalAddress.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataStructuredPostalAddress.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE \\\n  || GDATA_INCLUDE_MAPS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATASTRUCTUREDPOSTALADDRESS_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// rel values\n_EXTERN NSString* kGDataPostalAddressHome  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#home\");\n_EXTERN NSString* kGDataPostalAddressWork  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work\");\n_EXTERN NSString* kGDataPostalAddressOther _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#other\");\n\n// mail class values\n_EXTERN NSString* kGDataPostalAddressLetters _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#letters\");\n_EXTERN NSString* kGDataPostalAddressParcels _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#parcels\");\n_EXTERN NSString* kGDataPostalAddressNeither _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#neither\");\n_EXTERN NSString* kGDataPostalAddressBoth    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#both\");\n\n// usage values\n_EXTERN NSString* kGDataPostalAddressGeneral  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#general\");\n_EXTERN NSString* kGDataPostalAddressLocal    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#local\");\n\n@interface GDataStructuredPostalAddress : GDataObject <GDataExtension>\n\n+ (id)structuredPostalAddress;\n\n// receiver of mail, or in care of (\"c/o\")\n- (NSString *)agent;\n- (void)setAgent:(NSString *)str;\n\n- (NSString *)city;\n- (void)setCity:(NSString *)str;\n\n// country name and code are in the same element, but we'll expose them\n// here as if they're independent to keep the interface simpler & KVC-compliant\n- (NSString *)countryName;\n- (void)setCountryName:(NSString *)str;\n\n// 3166-1 alpha-2 country codes\n// http://www.iso.org/iso/english_country_names_and_code_elements\n- (NSString *)countryCode;\n- (void)setCountryCode:(NSString *)str;\n\n// building name\n- (NSString *)houseName;\n- (void)setHouseName:(NSString *)str;\n\n- (NSString *)neighborhood;\n- (void)setNeighborhood:(NSString *)str;\n\n- (NSString *)POBox;\n- (void)setPOBox:(NSString *)str;\n\n- (NSString *)postCode;\n- (void)setPostCode:(NSString *)str;\n\n// region is a state, province, county (in Ireland), Land (in Germany),\n// departement (in France), or similar\n- (NSString *)region;\n- (void)setRegion:(NSString *)str;\n\n- (NSString *)street;\n- (void)setStreet:(NSString *)str;\n\n// subregion is not intended for delivery addresses\n- (NSString *)subregion;\n- (void)setSubregion:(NSString *)str;\n\n\n- (NSString *)formattedAddress;\n- (void)setFormattedAddress:(NSString *)str;\n\n// attributes\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)mailClass;\n- (void)setMailClass:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)usage;\n- (void)setUsage:(NSString *)str;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataStructuredPostalAddress.m",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataStructuredPostalAddress.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE \\\n  || GDATA_INCLUDE_MAPS_SERVICE\n\n#define GDATASTRUCTUREDPOSTALADDRESS_DEFINE_GLOBALS 1\n#import \"GDataStructuredPostalAddress.h\"\n\n#import \"GDataValueConstruct.h\"\n\n//\n// GDataStructuredPostalAddress private classes\n//\n\n@interface GDataPostalAddressAgent : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressAgent\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"agent\"; }\n@end\n\n@interface GDataPostalAddressCity : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressCity\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"city\"; }\n@end\n\n@interface GDataPostalAddressCountry : GDataValueElementConstruct <GDataExtension>\n- (NSString *)code;\n- (void)setCode:(NSString *)str;\n@end\n\n@implementation GDataPostalAddressCountry\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"country\"; }\n\nstatic NSString* const kCodeAttr = @\"code\";\n\n- (void)addParseDeclarations {\n\n  // this is a subclass of GDataValueElementConstruct, which has its own parse\n  // declarations\n  [super addParseDeclarations];\n\n  NSArray *attrs = [NSArray arrayWithObject:kCodeAttr];\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n- (NSString *)code {\n  return [self stringValueForAttribute:kCodeAttr];\n}\n\n- (void)setCode:(NSString *)str {\n  [self setStringValue:str forAttribute:kCodeAttr];\n}\n@end\n\n@interface GDataPostalAddressFormattedAddress : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressFormattedAddress\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"formattedAddress\"; }\n@end\n\n@interface GDataPostalAddressHouseName : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressHouseName\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"housename\"; }\n@end\n\n@interface GDataPostalAddressNeighborhood : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressNeighborhood\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"neighborhood\"; }\n@end\n\n@interface GDataPostalAddressPOBox : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressPOBox\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"pobox\"; }\n@end\n\n@interface GDataPostalAddressPostCode : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressPostCode\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"postcode\"; }\n@end\n\n@interface GDataPostalAddressRegion : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressRegion\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"region\"; }\n@end\n\n@interface GDataPostalAddressStreet : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressStreet\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"street\"; }\n@end\n\n@interface GDataPostalAddressSubregion : GDataValueElementConstruct <GDataExtension>\n@end\n\n@implementation GDataPostalAddressSubregion\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"subregion\"; }\n@end\n\n\n//\n// GDataStructuredPostalAddress\n//\n\n// attributes\nstatic NSString* const kLabelAttr = @\"label\";\nstatic NSString* const kMailClassAttr = @\"mailClass\";\nstatic NSString* const kPrimaryAttr = @\"primary\";\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kUsageAttr = @\"usage\";\n\n@implementation GDataStructuredPostalAddress\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"structuredPostalAddress\"; }\n\n+ (id)structuredPostalAddress {\n  GDataStructuredPostalAddress *obj = [self object];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kLabelAttr, kMailClassAttr, kPrimaryAttr, kRelAttr,\n                    kUsageAttr, nil];\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  [self addExtensionDeclarationForParentClass:[self class]\n                                   childClasses:\n   [GDataPostalAddressAgent class],\n   [GDataPostalAddressCity class],\n   [GDataPostalAddressCountry class],\n   [GDataPostalAddressFormattedAddress class],\n   [GDataPostalAddressHouseName class],\n   [GDataPostalAddressNeighborhood class],\n   [GDataPostalAddressPOBox class],\n   [GDataPostalAddressPostCode class],\n   [GDataPostalAddressRegion class],\n   [GDataPostalAddressStreet class],\n   [GDataPostalAddressSubregion class],\n   nil];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n\n  static struct GDataDescriptionRecord descRecs[] = {\n    { @\"agent\",        @\"agent\",            kGDataDescValueLabeled },\n    { @\"city\",         @\"city\",             kGDataDescValueLabeled },\n    { @\"country\",      @\"countryName\",      kGDataDescValueLabeled },\n    { @\"countryCode\",  @\"countryCode\",      kGDataDescValueLabeled },\n    { @\"fmtAddr\",      @\"formattedAddress\", kGDataDescValueLabeled },\n    { @\"house\",        @\"houseName\",        kGDataDescValueLabeled },\n    { @\"neighborhood\", @\"neighborhood\",     kGDataDescValueLabeled },\n    { @\"pobox\",        @\"POBox\",            kGDataDescValueLabeled },\n    { @\"postCode\",     @\"postCode\",         kGDataDescValueLabeled },\n    { @\"region\",       @\"region\",           kGDataDescValueLabeled },\n    { @\"street\",       @\"street\",           kGDataDescValueLabeled },\n    { @\"subregion\",    @\"subregion\",        kGDataDescValueLabeled },\n    { nil, nil, (GDataDescRecTypes)0 }\n  };\n\n  NSMutableArray *items = [super itemsForDescription];\n  [self addDescriptionRecords:descRecs toItems:items];\n  return items;\n}\n#endif\n\n#pragma mark -\n\n// extensions\n\n- (NSString *)agent {\n  GDataPostalAddressAgent *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressAgent class]];\n  return [obj stringValue];\n}\n\n- (void)setAgent:(NSString *)str {\n  GDataPostalAddressAgent *obj;\n\n  obj = [GDataPostalAddressAgent valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressAgent class]];\n}\n\n- (NSString *)city {\n  GDataPostalAddressCity *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressCity class]];\n  return [obj stringValue];\n}\n\n- (void)setCity:(NSString *)str {\n  GDataPostalAddressCity *obj;\n\n  obj = [GDataPostalAddressCity valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressCity class]];\n}\n\n// country name and code are in the same element, but we'll expose them\n// as if they're independent to keep the interface simpler & KVC-compliant\n- (NSString *)countryName {\n  GDataPostalAddressCountry *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressCountry class]];\n  return [obj stringValue];\n}\n\n- (void)setCountryName:(NSString *)str {\n\n  GDataPostalAddressCountry *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressCountry class]];\n\n  if (obj == nil && str != nil) {\n    // lacked the element; create one only if we're really setting a value\n    obj = [GDataPostalAddressCountry valueWithString:str];\n    [self setObject:obj forExtensionClass:[GDataPostalAddressCountry class]];\n  }\n  [obj setStringValue:str];\n}\n\n- (NSString *)countryCode {\n  GDataPostalAddressCountry *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressCountry class]];\n  return [obj code];\n}\n\n- (void)setCountryCode:(NSString *)str {\n  GDataPostalAddressCountry *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressCountry class]];\n\n  if (obj == nil && str != nil) {\n    // lacked the element; create one only if we're really setting a value\n    obj = [GDataPostalAddressCountry valueWithString:nil];\n    [self setObject:obj forExtensionClass:[GDataPostalAddressCountry class]];\n  }\n  [obj setCode:str];\n}\n\n- (NSString *)formattedAddress {\n  GDataPostalAddressFormattedAddress *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressFormattedAddress class]];\n  return [obj stringValue];\n}\n\n- (void)setFormattedAddress:(NSString *)str {\n  GDataPostalAddressFormattedAddress *obj;\n\n  obj = [GDataPostalAddressFormattedAddress valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressFormattedAddress class]];\n}\n\n- (NSString *)houseName {\n  GDataPostalAddressHouseName *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressHouseName class]];\n  return [obj stringValue];\n}\n\n- (void)setHouseName:(NSString *)str {\n  GDataPostalAddressHouseName *obj;\n\n  obj = [GDataPostalAddressHouseName valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressHouseName class]];\n}\n\n- (NSString *)neighborhood {\n  GDataPostalAddressNeighborhood *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressNeighborhood class]];\n  return [obj stringValue];\n}\n\n- (void)setNeighborhood:(NSString *)str {\n  GDataPostalAddressNeighborhood *obj;\n\n  obj = [GDataPostalAddressNeighborhood valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressNeighborhood class]];\n}\n\n- (NSString *)POBox {\n  GDataPostalAddressPOBox *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressPOBox class]];\n  return [obj stringValue];\n}\n\n- (void)setPOBox:(NSString *)str {\n  GDataPostalAddressPOBox *obj;\n\n  obj = [GDataPostalAddressPOBox valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressPOBox class]];\n}\n\n- (NSString *)postCode {\n  GDataPostalAddressPostCode *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressPostCode class]];\n  return [obj stringValue];\n}\n\n- (void)setPostCode:(NSString *)str {\n  GDataPostalAddressPostCode *obj;\n\n  obj = [GDataPostalAddressPostCode valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressPostCode class]];\n}\n\n- (NSString *)region {\n  GDataPostalAddressRegion *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressRegion class]];\n  return [obj stringValue];\n}\n\n- (void)setRegion:(NSString *)str {\n  GDataPostalAddressRegion *obj;\n\n  obj = [GDataPostalAddressRegion valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressRegion class]];\n}\n\n- (NSString *)street {\n  GDataPostalAddressStreet *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressStreet class]];\n  return [obj stringValue];\n}\n\n- (void)setStreet:(NSString *)str {\n  GDataPostalAddressStreet *obj;\n\n  obj = [GDataPostalAddressStreet valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressStreet class]];\n}\n\n- (NSString *)subregion {\n  GDataPostalAddressSubregion *obj;\n\n  obj = [self objectForExtensionClass:[GDataPostalAddressSubregion class]];\n  return [obj stringValue];\n}\n\n- (void)setSubregion:(NSString *)str {\n  GDataPostalAddressSubregion *obj;\n\n  obj = [GDataPostalAddressSubregion valueWithString:str];\n  [self setObject:obj forExtensionClass:[GDataPostalAddressSubregion class]];\n}\n\n// attributes\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (NSString *)mailClass {\n  return [self stringValueForAttribute:kMailClassAttr];\n}\n\n- (void)setMailClass:(NSString *)str {\n  [self setStringValue:str forAttribute:kMailClassAttr];\n}\n\n- (BOOL)isPrimary {\n  return [self boolValueForAttribute:kPrimaryAttr defaultValue:NO];\n}\n\n- (void)setIsPrimary:(BOOL)flag {\n  [self setBoolValue:flag defaultValue:NO forAttribute:kPrimaryAttr];\n}\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSString *)usage {\n  return [self stringValueForAttribute:kUsageAttr];\n}\n\n- (void)setUsage:(NSString *)str {\n  [self setStringValue:str forAttribute:kUsageAttr];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataTextConstruct.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataTextConstruct.h\n//\n\n#import \"GDataObject.h\"\n\n// For typed text, like: <title type=\"text\">Event title</title>\n//\n// type can be text, text/plain, html, text/html, xhtml, or other things\n@interface GDataTextConstruct : GDataObject {\n}\n\n+ (id)textConstructWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n- (NSString *)lang;\n- (void)setLang:(NSString *)str;\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataTextConstruct.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataTextConstruct.m\n//\n\n#import \"GDataTextConstruct.h\"\n\nstatic NSString* const kLangAttr = @\"xml:lang\";\nstatic NSString* const kTypeAttr = @\"type\";\n\n@implementation GDataTextConstruct\n// For typed text, like: <title type=\"text\">Event title</title>\n\n+ (id)textConstructWithString:(NSString *)str {\n  GDataTextConstruct *obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n// RFC4287 Sec 3.1 says that omitted type attributes are assumed to be\n// \"text\", so we don't need to explicitly set it\n// [self setType:@\"text\"];\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kTypeAttr, kLangAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n\n  [self addContentValueDeclaration];\n}\n\n- (NSArray *)attributesIgnoredForEquality {\n\n  // ignore the \"type\" attribute since we test for it uniquely below\n  return [NSArray arrayWithObject:kTypeAttr];\n}\n\n\n- (BOOL)isTypeEqualToText:(NSString *)str {\n  // internal utility routine\n  return (str == nil)\n    || [str isEqual:@\"text\"]\n    || [str isEqual:@\"text/plain\"];\n}\n\n- (BOOL)isEqual:(GDataTextConstruct *)other {\n\n  // override isEqual: to allow nil types to be considered equal to \"text\"\n  return [super isEqual:other]\n\n    // a missing type attribute is equal to \"text\" per RFC 4287 3.1.1\n    //\n    // consider them equal if both are some flavor of \"text\"\n\n    && (AreEqualOrBothNil([self type], [other type])\n        || ([self isTypeEqualToText:[self type]]\n            && [self isTypeEqualToText:[other type]]));\n}\n\n\n- (NSString *)stringValue {\n  return [self contentStringValue];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setContentStringValue:str];\n}\n\n- (NSString *)lang {\n  return [self stringValueForAttribute:kLangAttr];\n}\n\n- (void)setLang:(NSString *)str {\n  [self setStringValue:str forAttribute:kLangAttr];\n}\n\n- (NSString *)type {\n  return [self stringValueForAttribute:kTypeAttr];\n}\n\n- (void)setType:(NSString *)str {\n  [self setStringValue:str forAttribute:kTypeAttr];\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataValueConstruct.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataValueConstruct.h\n//\n\n// GDataValueConstruct is meant to be subclassed for elements that\n// store just a single string either as an attribute or as the\n// element child text.\n//\n// See the examples with each subclass below.\n\n#import \"GDataObject.h\"\n#import \"GDataDateTime.h\"\n\n// an element with a value=\"\" attribute, as in\n// <gCal:timezone value=\"America/Los_Angeles\"/>\n// (subclasses may override the attribute name)\n@interface GDataValueConstruct : GDataObject\n\n// convenience functions: subclasses may call into these and\n// return the result, cast to the appropriate type\n//\n// if nil is passed in for pointer type args for these, nil is returned\n+ (id)valueWithString:(NSString *)str;\n+ (id)valueWithNumber:(NSNumber *)num;\n+ (id)valueWithInt:(int)val;\n+ (id)valueWithLongLong:(long long)val;\n+ (id)valueWithDouble:(double)val;\n+ (id)valueWithBool:(BOOL)flag;\n+ (id)valueWithDateTime:(GDataDateTime *)dateTime;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSString *)attributeName; // defaults to \"value\", subclasses can override\n\n// subclass value utilities\n- (NSNumber *)intNumberValue;\n- (int)intValue;\n- (void)setIntValue:(int)val;\n\n- (NSNumber *)longLongNumberValue;\n- (long long)longLongValue;\n- (void)setLongLongValue:(long long)val;\n\n- (NSNumber *)doubleNumberValue;\n- (double)doubleValue;\n- (void)setDoubleValue:(double)value;\n\n- (NSNumber *)boolNumberValue;\n- (BOOL)boolValue;\n- (void)setBoolValue:(BOOL)flag;\n\n- (GDataDateTime *)dateTimeValue;\n- (void)setDateTimeValue:(GDataDateTime *)dateTime;\n\n@end\n\n// GDataValueElementConstruct is for subclasses that keep the value\n// in the child text nodes, like <yt:books>Pride and Prejudice</yt:books>\n@interface GDataValueElementConstruct : GDataValueConstruct\n- (NSString *)attributeName; // returns nil\n@end\n\n// GDataImplicitValueConstruct is for subclasses that want a fixed value\n// because the element is merely present or absent, like <gd:deleted/>\n@interface GDataImplicitValueConstruct : GDataValueElementConstruct\n+ (id)implicitValue;\n- (NSString *)stringValue; // returns nil\n@end\n\n// an element with a value=true or false attribute, as in\n//   <gCal:sendEventNotifications value=\"true\"/>\n@interface GDataBoolValueConstruct : GDataValueConstruct\n+ (id)boolValueWithBool:(BOOL)flag;\n@end\n\n// GDataNameValueConstruct is for subclasses that have \"name\" and \"value\"\n// attributes\n@interface GDataNameValueConstruct : GDataValueConstruct\n+ (id)valueWithName:(NSString *)name stringValue:(NSString *)value;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)nameAttributeName; // the default implementation returns @\"name\"\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataValueConstruct.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataValueConstruct.m\n//\n\n#import \"GDataValueConstruct.h\"\n\n@implementation GDataValueConstruct\n// an element with a value=\"\" attribute, as in\n// <gCal:timezone value=\"America/Los_Angeles\"/>\n// (subclasses may override the attribute name,\n// or return nil for it to indicate the value is\n// in the child node text)\n\n\n// convenience functions\n//\n// subclasses may re-use call into these convenience functions\n// and coerce the return type appropriately\n\n+ (id)valueWithString:(NSString *)str {\n  if (str == nil) return nil;\n\n  GDataValueConstruct* obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n+ (id)valueWithNumber:(NSNumber *)num {\n  if (num == nil) return nil;\n\n  GDataValueConstruct* obj = [self object];\n  [obj setStringValue:[num stringValue]];\n  return obj;\n}\n\n+ (id)valueWithInt:(int)val {\n  GDataValueConstruct* obj = [self object];\n  [obj setIntValue:val];\n  return obj;\n}\n\n+ (id)valueWithLongLong:(long long)val {\n  GDataValueConstruct* obj = [self object];\n  [obj setLongLongValue:val];\n  return obj;\n}\n\n+ (id)valueWithDouble:(double)val {\n  GDataValueConstruct* obj = [self object];\n  [obj setDoubleValue:val];\n  return obj;\n}\n\n+ (id)valueWithBool:(BOOL)flag {\n  GDataValueConstruct* obj = [self object];\n  [obj setBoolValue:flag];\n  return obj;\n}\n\n+ (id)valueWithDateTime:(GDataDateTime *)dateTime {\n  if (dateTime == nil) return nil;\n\n  GDataValueConstruct* obj = [self object];\n  [obj setDateTimeValue:dateTime];\n  return obj;\n}\n\n\n#pragma mark -\n\n- (void)addParseDeclarations {\n\n  NSString *attrName = [self attributeName];\n  if (attrName) {\n    // there's a value attribute\n    NSArray *attr = [NSArray arrayWithObject:attrName];\n    [self addLocalAttributeDeclarations:attr];\n\n  } else {\n    // no named attribute; use the element's child text as the value\n    [self addContentValueDeclaration];\n  }\n}\n\n- (NSString *)stringValue {\n  NSString *attrName = [self attributeName];\n  if (attrName != nil) {\n    return [self stringValueForAttribute:attrName];\n  } else {\n    return [self contentStringValue];\n  }\n}\n\n- (void)setStringValue:(NSString *)str {\n  NSString *attrName = [self attributeName];\n  if (attrName != nil) {\n    [self setStringValue:str forAttribute:attrName];\n  } else {\n    [self setContentStringValue:str];\n  }\n}\n\n- (NSString *)attributeName {\n  // subclasses can override if they store their value under a different\n  // attribute name, or can return nil to indicate the value is in the child\n  // node text (or just use GDataValueElementConstruct which returns nil\n  // for this method)\n  return @\"value\";\n}\n\n// subclass value utilities\n\n- (int)intValue {\n  NSString *str = [self stringValue];\n  if (str) {\n    int result;\n    NSScanner *scanner = [NSScanner scannerWithString:str];\n    if ([scanner scanInt:&result]) {\n      return result;\n    }\n  }\n  return 0;\n}\n\n- (NSNumber *)intNumberValue {\n  return [NSNumber numberWithInt:[self intValue]];\n}\n\n- (void)setIntValue:(int)val {\n  NSString *str = [[NSNumber numberWithInt:val] stringValue];\n  [self setStringValue:str];\n}\n\n- (long long)longLongValue {\n  NSString *str = [self stringValue];\n  if (str) {\n    long long result;\n    NSScanner *scanner = [NSScanner scannerWithString:str];\n    if ([scanner scanLongLong:&result]) {\n      return result;\n    }\n  }\n  return 0;\n}\n\n- (NSNumber *)longLongNumberValue {\n  return [NSNumber numberWithLongLong:[self longLongValue]];\n}\n\n- (void)setLongLongValue:(long long)val {\n  NSString *str = [[NSNumber numberWithLongLong:val] stringValue];\n  [self setStringValue:str];\n}\n\n- (double)doubleValue {\n  NSNumber *num = [self doubleNumberValue];\n  double val = [num doubleValue];\n  return val;\n}\n\n- (NSNumber *)doubleNumberValue {\n  NSString *str = [self stringValue];\n  NSNumber *num = [GDataUtilities doubleNumberOrInfForString:str];\n  if (num != nil) return num;\n\n  return [NSNumber numberWithDouble:0];\n}\n\n- (void)setDoubleValue:(double)val {\n  NSString *str = [[NSNumber numberWithDouble:val] stringValue];\n  [self setStringValue:str];\n}\n\n- (BOOL)boolValue {\n  NSString *value = [self stringValue];\n  if (value) {\n    return ([value caseInsensitiveCompare:@\"true\"] == NSOrderedSame);\n  }\n  return NO;\n}\n\n- (NSNumber *)boolNumberValue {\n  return [NSNumber numberWithBool:[self boolValue]];\n}\n\n- (void)setBoolValue:(BOOL)flag {\n  [self setStringValue:(flag ? @\"true\" : @\"false\")];\n}\n\n- (GDataDateTime *)dateTimeValue {\n  NSString *str = [self stringValue];\n  if ([str length] > 0) {\n    GDataDateTime *dateTime = [GDataDateTime dateTimeWithRFC3339String:str];\n    return dateTime;\n  }\n  return nil;\n}\n\n- (void)setDateTimeValue:(GDataDateTime *)dateTime {\n  NSString *str = [dateTime RFC3339String];\n  [self setStringValue:str];\n}\n\n@end\n\n@implementation GDataNameValueConstruct // derives from GDataValueConstruct\n+ (id)valueWithName:(NSString *)name stringValue:(NSString *)value {\n  if (name == nil && value == nil) return nil;\n\n  GDataNameValueConstruct* obj = [self object];\n  [obj setStringValue:value];\n  [obj setName:name];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  [super addParseDeclarations];\n\n  // add the name attribute\n  NSString *nameAttrName = [self nameAttributeName];\n  if (nameAttrName) {\n    NSArray *attr = [NSArray arrayWithObject:nameAttrName];\n    [self addLocalAttributeDeclarations:attr];\n  }\n}\n\n- (NSString *)name {\n  NSString *nameAttrName = [self nameAttributeName];\n  if (nameAttrName) {\n    return [self stringValueForAttribute:nameAttrName];\n  }\n  return nil;\n}\n\n- (void)setName:(NSString *)str {\n  NSString *nameAttrName = [self nameAttributeName];\n  if (nameAttrName) {\n    [self setStringValue:str forAttribute:nameAttrName];\n  }\n}\n\n- (NSString *)nameAttributeName {\n  return @\"name\";\n}\n@end\n\n@implementation GDataValueElementConstruct // derives from GDataValueConstruct\n- (NSString *)attributeName {\n  // return nil to indicate the value is contained in the child text nodes\n  return nil;\n}\n@end\n\n// GDataImplicitValueConstruct is for subclasses that want a fixed value\n// because the element is merely present or absent, like <foo:bar/>\n//\n// This derives from GDataValueElementConstruct\n@implementation GDataImplicitValueConstruct\n+ (id)implicitValue {\n  GDataImplicitValueConstruct* obj = [self object];\n  return obj;\n}\n\n- (NSString *)stringValue {\n  return nil;  // no body\n}\n\n@end\n\n@implementation GDataBoolValueConstruct // derives from GDataValueConstruct\n\n+ (id)boolValueWithBool:(BOOL)flag {\n  return [super valueWithBool:flag];\n}\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataWhen.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWhen.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n   || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#import \"GDataDateTime.h\"\n\n// when element, as in\n// <gd:when startTime=\"2005-06-06\" endTime=\"2005-06-07\" valueString=\"This weekend\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWhen\n\n@interface GDataWhen : GDataObject <GDataExtension> {\n}\n\n+ (GDataWhen *)whenWithStartTime:(GDataDateTime *)startTime\n                         endTime:(GDataDateTime *)endTime;\n\n- (GDataDateTime *)startTime;\n- (void)setStartTime:(GDataDateTime *)cdate;\n\n- (GDataDateTime *)endTime;\n- (void)setEndTime:(GDataDateTime *)cdate;\n\n- (NSString *)value;\n- (void)setValue:(NSString *)str;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataWhen.m",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWhen.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n  || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataWhen.h\"\n\nstatic NSString* const kValueAttr = @\"valueString\";\nstatic NSString* const kStartTimeAttr = @\"startTime\";\nstatic NSString* const kEndTimeAttr = @\"endTime\";\n\n@implementation GDataWhen\n// when element, as in\n// <gd:when startTime=\"2005-06-06\" endTime=\"2005-06-07\" valueString=\"This weekend\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWhen\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"when\"; }\n\n+ (GDataWhen *)whenWithStartTime:(GDataDateTime *)startTime\n                         endTime:(GDataDateTime *)endTime {\n  GDataWhen *obj = [self object];\n  [obj setStartTime:startTime];\n  [obj setEndTime:endTime];\n  return obj;\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kValueAttr, kStartTimeAttr, kEndTimeAttr, nil];\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n#pragma mark -\n\n- (GDataDateTime *)startTime {\n  return [self dateTimeForAttribute:kStartTimeAttr];\n}\n\n- (void)setStartTime:(GDataDateTime *)cdate {\n  [self setDateTimeValue:cdate forAttribute:kStartTimeAttr];\n}\n\n- (GDataDateTime *)endTime {\n  return [self dateTimeForAttribute:kEndTimeAttr];\n}\n\n- (void)setEndTime:(GDataDateTime *)cdate {\n  [self setDateTimeValue:cdate forAttribute:kEndTimeAttr];\n}\n\n- (NSString *)value {\n  return [self stringValueForAttribute:kValueAttr];\n}\n\n- (void)setValue:(NSString *)str {\n  [self setStringValue:str forAttribute:kValueAttr];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataWhere.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWhere.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n  || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAWHERE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// rel values\n_EXTERN NSString* const kGDataEventWhereEventLocation _INITIALIZE_AS(nil); // use the enclosing event's location\n_EXTERN NSString* const kGDataEventWhereAlternate _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.alternate\");\n_EXTERN NSString* const kGDataEventWhereParking _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.parking\");\n\n@class GDataEntryLink;\n\n// where element, as in\n// <gd:where rel=\"http://schemas.google.com/g/2005#event\" valueString=\"Joe's Pub\">\n//    <gd:entryLink href=\"http://local.example.com/10018/JoesPub\">\n// </gd:where>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWhere\n\n@interface GDataWhere : GDataObject <GDataExtension>\n\n+ (GDataWhere *)whereWithString:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)stringValue; // gets the \"valueString\" XML attribute\n- (void)setStringValue:(NSString *)str; // sets the \"valueString\" XML attribute\n\n- (GDataEntryLink *)entryLink;\n- (void)setEntryLink:(GDataEntryLink *)entryLink;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataWhere.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWhere.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n    || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#define GDATAWHERE_DEFINE_GLOBALS 1\n#import \"GDataWhere.h\"\n\n#import \"GDataEntryLink.h\"\n\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kValueStringAttr = @\"valueString\";\nstatic NSString* const kLabelAttr = @\"label\";\n\n@implementation GDataWhere\n// where element, as in\n// <gd:where rel=\"http://schemas.google.com/g/2005#event\" valueString=\"Joe's Pub\">\n//    <gd:entryLink href=\"http://local.example.com/10018/JoesPub\">\n// </gd:where>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWhere\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"where\"; }\n\n+ (GDataWhere *)whereWithString:(NSString *)str {\n  GDataWhere* obj = [self object];\n  [obj setStringValue:str];\n  return obj;\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  [self addExtensionDeclarationForParentClass:[self class]\n                                   childClass:[GDataEntryLink class]];\n}\n\n- (void)addParseDeclarations {\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kRelAttr, kValueStringAttr, kLabelAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [super itemsForDescription];\n\n  // add the entryLink extension to the description\n  [self addToArray:items objectDescriptionIfNonNil:[self entryLink] withName:@\"entryLink\"];\n\n  return items;\n}\n#endif\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSString *)label {\n  return [self stringValueForAttribute:kLabelAttr];\n}\n\n- (void)setLabel:(NSString *)str {\n  [self setStringValue:str forAttribute:kLabelAttr];\n}\n\n- (NSString *)stringValue {\n  return [self stringValueForAttribute:kValueStringAttr];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setStringValue:str forAttribute:kValueStringAttr];\n}\n\n- (GDataEntryLink *)entryLink {\n  return [self objectForExtensionClass:[GDataEntryLink class]];\n}\n\n- (void)setEntryLink:(GDataEntryLink *)entryLink {\n  [self setObject:entryLink forExtensionClass:[GDataEntryLink class]];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataWho.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWho.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAWHO_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataWhoEventAttendee  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.attendee\");\n_EXTERN NSString* const kGDataWhoEventOrganizer _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.organizer\");\n_EXTERN NSString* const kGDataWhoEventSpeaker   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.speaker\");\n_EXTERN NSString* const kGDataWhoEventPerformer _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.performer\");\n\n_EXTERN NSString* const kGDataWhoAttendeeTypeRequired     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.required\");\n_EXTERN NSString* const kGDataWhoAttendeeTypeOptional     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.optional\");\n\n_EXTERN NSString* const kGDataWhoAttendeeStatusInvited    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.invited\");\n_EXTERN NSString* const kGDataWhoAttendeeStatusAccepted   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.accepted\");\n_EXTERN NSString* const kGDataWhoAttendeeStatusTentative  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.tentative\");\n_EXTERN NSString* const kGDataWhoAttendeeStatusDeclined   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.declined\");\n\n_EXTERN NSString* const kGDataWhoTaskAssignedTo _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#task.assigned-to\");\n\n_EXTERN NSString* const kGDataWhoMessageFrom    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.from\");\n_EXTERN NSString* const kGDataWhoMessageTo      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.to\");\n_EXTERN NSString* const kGDataWhoMessageCC      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.cc\");\n_EXTERN NSString* const kGDataWhoMessageBCC     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.bcc\");\n\n@class GDataEntryLink;\n\n@interface GDataAttendeeStatus : GDataValueConstruct <GDataExtension>\n+ (NSString *)extensionElementURI;\n+ (NSString *)extensionElementPrefix;\n+ (NSString *)extensionElementLocalName;\n@end\n\n@interface GDataAttendeeType : GDataValueConstruct <GDataExtension>\n+ (NSString *)extensionElementURI;\n+ (NSString *)extensionElementPrefix;\n+ (NSString *)extensionElementLocalName;\n@end\n\n\n// a who entry, as in\n// <gd:who rel=\"http://schemas.google.com/g/2005#event.organizer\" valueString=\"Fred Flintstone\" email=\"fred@domain.com\">\n//   <gd:attendeeStatus value=\"http://schemas.google.com/g/2005#event.accepted\"/>\n// </gd:who>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWho\n@interface GDataWho : GDataObject <GDataExtension> {\n}\n\n+ (GDataWho *)whoWithRel:(NSString *)rel\n                    name:(NSString *)valueString\n                   email:(NSString *)email; // name and email may be nil\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)email;\n- (void)setEmail:(NSString *)str;\n\n- (NSString *)stringValue; // gets the \"valueString\" XML attribute\n- (void)setStringValue:(NSString *)str; // sets the \"valueString\" XML attribute\n\n- (GDataAttendeeType *)attendeeType;\n- (void)setAttendeeType:(GDataAttendeeType *)val;\n\n- (GDataAttendeeStatus *)attendeeStatus;\n- (void)setAttendeeStatus:(GDataAttendeeStatus *)val;\n\n- (GDataEntryLink *)entryLink;\n- (void)setEntryLink:(GDataEntryLink *)entryLink;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/Elements/GDataWho.m",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWho.m\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n\n#define GDATAWHO_DEFINE_GLOBALS 1\n#import \"GDataWho.h\"\n\n#import \"GDataEntryLink.h\"\n\n@implementation GDataAttendeeStatus\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"attendeeStatus\"; }\n@end\n\n@implementation GDataAttendeeType\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"attendeeType\"; }\n@end\n\nstatic NSString* const kRelAttr = @\"rel\";\nstatic NSString* const kValueStringAttr = @\"valueString\";\nstatic NSString* const kEmailAttr = @\"email\";\n\n@implementation GDataWho\n// a who entry, as in\n// <gd:who rel=\"http://schemas.google.com/g/2005#event.organizer\" valueString=\"Fred Flintstone\" email=\"fred@domain.com\">\n//   <gd:attendeeStatus value=\"http://schemas.google.com/g/2005#event.accepted\"/>\n// </gd:who>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWho\n\n+ (NSString *)extensionElementURI       { return kGDataNamespaceGData; }\n+ (NSString *)extensionElementPrefix    { return kGDataNamespaceGDataPrefix; }\n+ (NSString *)extensionElementLocalName { return @\"who\"; }\n\n+ (GDataWho *)whoWithRel:(NSString *)rel\n                    name:(NSString *)valueString\n                   email:(NSString *)email {\n  GDataWho *obj = [self object];\n  [obj setRel:rel];\n  [obj setStringValue:valueString];\n  [obj setEmail:email];\n  return obj;\n}\n\n- (void)addExtensionDeclarations {\n\n  [super addExtensionDeclarations];\n\n  Class elementClass = [self class];\n\n  [self addExtensionDeclarationForParentClass:elementClass\n                                   childClass:[GDataAttendeeType class]];\n  [self addExtensionDeclarationForParentClass:elementClass\n                                   childClass:[GDataAttendeeStatus class]];\n  [self addExtensionDeclarationForParentClass:elementClass\n                                   childClass:[GDataEntryLink class]];\n}\n\n- (void)addParseDeclarations {\n\n  NSArray *attrs = [NSArray arrayWithObjects:\n                    kRelAttr, kValueStringAttr, kEmailAttr, nil];\n\n  [self addLocalAttributeDeclarations:attrs];\n}\n\n#if !GDATA_SIMPLE_DESCRIPTIONS\n- (NSMutableArray *)itemsForDescription {\n  NSMutableArray *items = [super itemsForDescription];\n\n  // add extensions to the description\n  [self addToArray:items objectDescriptionIfNonNil:[self attendeeType] withName:@\"attendeeType\"];\n  [self addToArray:items objectDescriptionIfNonNil:[self attendeeStatus] withName:@\"attendeeStatus\"];\n  [self addToArray:items objectDescriptionIfNonNil:[self entryLink] withName:@\"entryLink\"];\n\n  return items;\n}\n#endif\n\n#pragma mark -\n\n- (NSString *)rel {\n  return [self stringValueForAttribute:kRelAttr];\n}\n\n- (void)setRel:(NSString *)str {\n  [self setStringValue:str forAttribute:kRelAttr];\n}\n\n- (NSString *)email {\n  return [self stringValueForAttribute:kEmailAttr];\n}\n\n- (void)setEmail:(NSString *)str {\n  [self setStringValue:str forAttribute:kEmailAttr];\n}\n\n- (NSString *)stringValue {\n  return [self stringValueForAttribute:kValueStringAttr];\n}\n\n- (void)setStringValue:(NSString *)str {\n  [self setStringValue:str forAttribute:kValueStringAttr];\n}\n\n- (GDataAttendeeType *)attendeeType {\n  return [self objectForExtensionClass:[GDataAttendeeType class]];\n}\n\n- (void)setAttendeeType:(GDataAttendeeType *)val {\n  [self setObject:val forExtensionClass:[GDataAttendeeType class]];\n}\n\n- (GDataAttendeeStatus *)attendeeStatus {\n  return [self objectForExtensionClass:[GDataAttendeeStatus class]];\n}\n\n- (void)setAttendeeStatus:(GDataAttendeeStatus *)val {\n  [self setObject:val forExtensionClass:[GDataAttendeeStatus class]];\n}\n\n- (GDataEntryLink *)entryLink {\n  return [self objectForExtensionClass:[GDataEntryLink class]];\n}\n\n- (void)setEntryLink:(GDataEntryLink *)entryLink {\n  [self setObject:entryLink forExtensionClass:[GDataEntryLink class]];\n}\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/GDataDefines.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataDefines.h\n//\n\n// Ensure Apple's conditionals we depend on are defined.\n#import <TargetConditionals.h>\n#import <AvailabilityMacros.h>\n\n//\n// The developer may choose to define these in the project:\n//\n//   #define GDATA_TARGET_NAMESPACE Xxx  // preface all GData class names with Xxx (recommended for building plug-ins)\n//   #define GDATA_FOUNDATION_ONLY 1     // builds without AppKit or Carbon (default for iPhone builds)\n//   #define GDATA_SIMPLE_DESCRIPTIONS 1 // remove elaborate -description methods, reducing code size (default for iPhone release builds)\n//   #define STRIP_GDATA_FETCH_LOGGING 1 // omit http logging code (default for iPhone release builds)\n//\n// Mac developers may find GDATA_SIMPLE_DESCRIPTIONS and STRIP_GDATA_FETCH_LOGGING useful for\n// reducing code size.\n//\n\n// Define later OS versions when building on earlier versions\n#ifdef MAC_OS_X_VERSION_10_0\n  #ifndef MAC_OS_X_VERSION_10_6\n    #define MAC_OS_X_VERSION_10_6 1060\n  #endif\n#endif\n\n\n#ifdef GDATA_TARGET_NAMESPACE\n// prefix all GData class names with GDATA_TARGET_NAMESPACE for this target\n  #import \"GDataTargetNamespace.h\"\n#endif\n\n// Provide a common definition for externing constants/functions\n#if defined(__cplusplus)\n#define GDATA_EXTERN extern \"C\"\n#else\n#define GDATA_EXTERN extern\n#endif\n\n#if TARGET_OS_IPHONE // iPhone SDK\n\n  #define GDATA_IPHONE 1\n\n#endif\n\n#if GDATA_IPHONE\n\n  #define GDATA_FOUNDATION_ONLY 1\n\n  #define GDATA_USES_LIBXML 1\n\n  #import \"GDataXMLNode.h\"\n\n  #define NSXMLDocument                  GDataXMLDocument\n  #define NSXMLElement                   GDataXMLElement\n  #define NSXMLNode                      GDataXMLNode\n  #define NSXMLNodeKind                  GDataXMLNodeKind\n  #define NSXMLInvalidKind               GDataXMLInvalidKind\n  #define NSXMLDocumentKind              GDataXMLDocumentKind\n  #define NSXMLElementKind               GDataXMLElementKind\n  #define NSXMLAttributeKind             GDataXMLAttributeKind\n  #define NSXMLNamespaceKind             GDataXMLNamespaceKind\n  #define NSXMLProcessingInstructionKind GDataXMLDocumentKind\n  #define NSXMLCommentKind               GDataXMLCommentKind\n  #define NSXMLTextKind                  GDataXMLTextKind\n  #define NSXMLDTDKind                   GDataXMLDTDKind\n  #define NSXMLEntityDeclarationKind     GDataXMLEntityDeclarationKind\n  #define NSXMLAttributeDeclarationKind  GDataXMLAttributeDeclarationKind\n  #define NSXMLElementDeclarationKind    GDataXMLElementDeclarationKind\n  #define NSXMLNotationDeclarationKind   GDataXMLNotationDeclarationKind\n\n  // properties used for retaining the XML tree in the classes that use them\n  #define kGDataXMLDocumentPropertyKey @\"_XMLDocument\"\n  #define kGDataXMLElementPropertyKey  @\"_XMLElement\"\n#endif\n\n//\n// GDATA_ASSERT is like NSAssert, but takes a variable number of arguments:\n//\n//     GDATA_ASSERT(condition, @\"Problem in argument %@\", argStr);\n//\n// GDATA_DEBUG_ASSERT is similar, but compiles in only for debug builds\n//\n\n#ifndef GDATA_ASSERT\n  // we directly invoke the NSAssert handler so we can pass on the varargs\n  #if !defined(NS_BLOCK_ASSERTIONS)\n    #define GDATA_ASSERT(condition, ...)                                       \\\n      do {                                                                     \\\n        if (!(condition)) {                                                    \\\n          [[NSAssertionHandler currentHandler]                                 \\\n              handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \\\n                                 file:[NSString stringWithUTF8String:__FILE__] \\\n                           lineNumber:__LINE__                                 \\\n                          description:__VA_ARGS__];                            \\\n        }                                                                      \\\n      } while(0)\n  #else\n    #define GDATA_ASSERT(condition, ...) do { } while (0)\n  #endif // !defined(NS_BLOCK_ASSERTIONS)\n#endif // GDATA_ASSERT\n\n#ifndef GDATA_DEBUG_ASSERT\n  #if DEBUG\n    #define GDATA_DEBUG_ASSERT(condition, ...) GDATA_ASSERT(condition, __VA_ARGS__)\n  #else\n    #define GDATA_DEBUG_ASSERT(condition, ...) do { } while (0)\n  #endif\n#endif\n\n#ifndef GDATA_DEBUG_LOG\n  #if DEBUG\n    #define GDATA_DEBUG_LOG(...) NSLog(__VA_ARGS__)\n  #else\n    #define GDATA_DEBUG_LOG(...) do { } while (0)\n  #endif\n#endif\n\n\n//\n// To reduce code size on iPhone release builds, we compile out the helpful\n// description methods for GData objects\n//\n#ifndef GDATA_SIMPLE_DESCRIPTIONS\n  #if GDATA_IPHONE && !DEBUG\n    #define GDATA_SIMPLE_DESCRIPTIONS 1\n  #else\n    #define GDATA_SIMPLE_DESCRIPTIONS 0\n  #endif\n#endif\n\n#ifndef STRIP_GDATA_FETCH_LOGGING\n  #if GDATA_IPHONE && !DEBUG\n    #define STRIP_GDATA_FETCH_LOGGING 1\n  #else\n    #define STRIP_GDATA_FETCH_LOGGING 0\n  #endif\n#endif\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/GDataUtilities.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#import <Foundation/Foundation.h>\n\n#ifndef SKIP_GDATA_DEFINES\n  #import \"GDataDefines.h\"\n#endif\n\n// helper functions for implementing isEqual:\nBOOL AreEqualOrBothNil(id obj1, id obj2);\nBOOL AreBoolsEqual(BOOL b1, BOOL b2);\n\n@interface GDataUtilities : NSObject\n\n// utility for removing non-whitespace control characters\n+ (NSString *)stringWithControlsFilteredForString:(NSString *)str;\n\n// utility for replacing whitespace and removing unsafe symbols for a\n// user-agent string\n+ (NSString *)userAgentStringForString:(NSString *)str;\n\n// utility for converting NSNumber to/from string, including inf/-inf\n//\n// an empty string returns a nil NSNumber\n+ (NSNumber *)doubleNumberOrInfForString:(NSString *)str;\n\n//\n// copy method helpers\n//\n\n// array with copies of the objects in the source array (1-deep)\n+ (NSArray *)arrayWithCopiesOfObjectsInArray:(NSArray *)source;\n+ (NSMutableArray *)mutableArrayWithCopiesOfObjectsInArray:(NSArray *)source;\n\n// dicionary with copies of the objects in the source dictionary (1-deep)\n+ (NSDictionary *)dictionaryWithCopiesOfObjectsInDictionary:(NSDictionary *)source;\n+ (NSMutableDictionary *)mutableDictionaryWithCopiesOfObjectsInDictionary:(NSDictionary *)source;\n\n// dictionary with 1-deep copies of the arrays which are the source dictionary's\n// values (2-deep)\n+ (NSDictionary *)dictionaryWithCopiesOfArraysInDictionary:(NSDictionary *)source;\n+ (NSMutableDictionary *)mutableDictionaryWithCopiesOfArraysInDictionary:(NSDictionary *)source;\n\n//\n// string encoding\n//\n\n// URL encoding, different for parts of URLs and parts of URL parameters\n//\n// +stringByURLEncodingString just makes a string legal for a URL\n//\n// +stringByURLEncodingForURI also encodes some characters that are legal in\n// URLs but should not be used in URIs,\n// per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7\n//\n// +stringByURLEncodingStringParameter is like +stringByURLEncodingForURI but\n// replaces space characters with + characters rather than percent-escaping them\n//\n+ (NSString *)stringByURLEncodingString:(NSString *)str;\n+ (NSString *)stringByURLEncodingForURI:(NSString *)str;\n+ (NSString *)stringByURLEncodingStringParameter:(NSString *)str;\n\n// percent-encoded UTF-8\n+ (NSString *)stringByPercentEncodingUTF8ForString:(NSString *)str;\n\n//\n// key-value coding searches in an array\n//\n// utilities to get from an array objects having a known value (or nil)\n// at a keyPath\n\n+ (NSArray *)objectsFromArray:(NSArray *)sourceArray\n                    withValue:(id)desiredValue\n                   forKeyPath:(NSString *)keyPath;\n\n+ (id)firstObjectFromArray:(NSArray *)sourceArray\n                 withValue:(id)desiredValue\n                forKeyPath:(NSString *)keyPath;\n\n//\n// version helpers\n//\n\n+ (NSComparisonResult)compareVersion:(NSString *)ver1 toVersion:(NSString *)ver2;\n\n//\n// response string helpers\n//\n\n// convert responses of the form \"a=foo \\n b=bar\"   to a dictionary\n+ (NSDictionary *)dictionaryWithResponseString:(NSString *)str;\n+ (NSDictionary *)dictionaryWithResponseData:(NSData *)data;\n\n//\n// file type helpers\n//\n\n// utility routine to convert a file path to the file's MIME type using\n// Mac OS X's UTI database\n+ (NSString *)MIMETypeForFileAtPath:(NSString *)path\n                    defaultMIMEType:(NSString *)defaultType;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/GDataUtilities.m",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#import \"GDataUtilities.h\"\n#include <math.h>\n\n@implementation GDataUtilities\n\n+ (NSString *)stringWithControlsFilteredForString:(NSString *)str {\n  // Ensure that control characters are not present in the string, since they\n  // would lead to XML that likely will make servers unhappy.  (Are control\n  // characters ever legal in XML?)\n  //\n  // Why not assert on debug builds for the caller when the string has a control\n  // character?  The characters may never be present in the data until the\n  // program is deployed to users.  This filtering will make it less likely\n  // that bad XML might be generated for users and sent to servers.\n  //\n  // Since we generate our XML directly from the elements with\n  // XMLData, we won't later have a good chance to look for and clean out\n  // the control characters.\n\n  if (str == nil) return nil;\n\n  static NSCharacterSet *filterChars = nil;\n\n  @synchronized([GDataUtilities class]) {\n\n    if (filterChars == nil) {\n      // make a character set of control characters (but not whitespace/newline\n      // characters), and keep a static immutable copy to use for filtering\n      // strings\n      NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];\n      NSCharacterSet *newlineWsChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];\n      NSCharacterSet *nonNewlineWsChars = [newlineWsChars invertedSet];\n\n      NSMutableCharacterSet *mutableChars = [[ctrlChars mutableCopy] autorelease];\n      [mutableChars formIntersectionWithCharacterSet:nonNewlineWsChars];\n\n      [mutableChars addCharactersInRange:NSMakeRange(0x0B, 2)]; // filter vt, ff\n\n      filterChars = [mutableChars copy];\n    }\n  }\n\n  // look for any invalid characters\n  NSRange range = [str rangeOfCharacterFromSet:filterChars];\n  if (range.location != NSNotFound) {\n\n    // copy the string to a mutable, and remove null and non-whitespace\n    // control characters\n    NSMutableString *mutableStr = [NSMutableString stringWithString:str];\n    while (range.location != NSNotFound) {\n\n#if DEBUG\n      NSLog(@\"GDataObject: Removing char 0x%lx from XML element string \\\"%@\\\"\",\n            (unsigned long) [mutableStr characterAtIndex:range.location], str);\n#endif\n\n      [mutableStr deleteCharactersInRange:range];\n\n      range = [mutableStr rangeOfCharacterFromSet:filterChars];\n    }\n\n    return mutableStr;\n  }\n\n  return str;\n}\n\n+ (NSString *)userAgentStringForString:(NSString *)str {\n\n  // make a proper token without whitespace from the given string\n  //\n  // per http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html\n  // and http://www.mozilla.org/build/user-agent-strings.html\n\n  if (str == nil) return nil;\n\n  NSMutableString *result = [NSMutableString stringWithString:str];\n\n  // replace spaces with underscores\n  [result replaceOccurrencesOfString:@\" \"\n                          withString:@\"_\"\n                             options:0\n                               range:NSMakeRange(0, [result length])];\n\n  // delete http token separators and remaining whitespace\n  static NSCharacterSet *charsToDelete = nil;\n\n  @synchronized([GDataUtilities class]) {\n\n    if (charsToDelete == nil) {\n\n      // make a set of unwanted characters\n      NSString *const kSeparators = @\"()<>@,;:\\\\\\\"/[]?={}\";\n\n      NSMutableCharacterSet *mutableChars\n        = [[[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy] autorelease];\n\n      [mutableChars addCharactersInString:kSeparators];\n\n      charsToDelete = [mutableChars copy]; // hang on to an immutable copy\n    }\n  }\n\n  while (1) {\n    NSRange separatorRange = [result rangeOfCharacterFromSet:charsToDelete];\n    if (separatorRange.location == NSNotFound) break;\n\n    [result deleteCharactersInRange:separatorRange];\n  };\n\n  return result;\n}\n\n+ (NSNumber *)doubleNumberOrInfForString:(NSString *)str {\n  if ([str length] == 0) return nil;\n\n  double val = [str doubleValue];\n  NSNumber *number = [NSNumber numberWithDouble:val];\n\n  // Incase fpclassify doesn't exist, default to always checking for INF.\n  BOOL checkForINF = YES;\n#if defined(fpclassify)\n  checkForINF = (fpclassify(val) == FP_ZERO);\n#endif\n\n  if (checkForINF) {\n    if ([str caseInsensitiveCompare:@\"INF\"] == NSOrderedSame) {\n      number = [NSNumber numberWithDouble:HUGE_VAL];\n    } else if ([str caseInsensitiveCompare:@\"-INF\"] == NSOrderedSame) {\n      number = [NSNumber numberWithDouble:-HUGE_VAL];\n    }\n  }\n  return number;\n}\n\n#pragma mark Copy method helpers\n\n+ (NSArray *)arrayWithCopiesOfObjectsInArray:(NSArray *)source {\n  if (source == nil) return nil;\n\n  NSArray *result = [[[NSArray alloc] initWithArray:source\n                                          copyItems:YES] autorelease];\n  return result;\n}\n\n+ (NSMutableArray *)mutableArrayWithCopiesOfObjectsInArray:(NSArray *)source {\n\n  if (source == nil) return nil;\n\n  NSMutableArray *result;\n\n  result = [[[NSMutableArray alloc] initWithArray:source\n                                        copyItems:YES] autorelease];\n  return result;\n}\n\n+ (NSDictionary *)dictionaryWithCopiesOfObjectsInDictionary:(NSDictionary *)source {\n  if (source == nil) return nil;\n\n  NSDictionary *result = [[[NSDictionary alloc] initWithDictionary:source\n                                                         copyItems:YES] autorelease];\n  return result;\n}\n\n+ (NSMutableDictionary *)mutableDictionaryWithCopiesOfObjectsInDictionary:(NSDictionary *)source {\n\n  if (source == nil) return nil;\n\n  NSMutableDictionary *result;\n\n  result = [[[NSMutableDictionary alloc] initWithDictionary:source\n                                                  copyItems:YES] autorelease];\n  return result;\n}\n\n+ (NSDictionary *)dictionaryWithCopiesOfArraysInDictionary:(NSDictionary *)source {\n  // we don't enforce return of an immutable for this\n  return [self mutableDictionaryWithCopiesOfArraysInDictionary:source];\n}\n\n+ (NSMutableDictionary *)mutableDictionaryWithCopiesOfArraysInDictionary:(NSDictionary *)source {\n\n  // Copy a dictionary that has arrays as its values\n  //\n  // We want to copy each object in each array.\n\n  if (source == nil) return nil;\n\n  Class arrayClass = [NSArray class];\n\n  // Using CFPropertyListCreateDeepCopy would be nice, but it fails on non-plist\n  // classes of objects\n\n  NSMutableDictionary *dict = [NSMutableDictionary dictionary];\n  for (id key in source) {\n\n    id origObj = [source objectForKey:key];\n    id copyObj;\n\n    if ([origObj isKindOfClass:arrayClass]) {\n\n      copyObj = [self mutableArrayWithCopiesOfObjectsInArray:origObj];\n    } else {\n      copyObj = [[origObj copy] autorelease];\n    }\n    [dict setObject:copyObj forKey:key];\n  }\n\n  return dict;\n}\n\n#pragma mark String encoding\n\n// URL Encoding\n\n+ (NSString *)stringByURLEncodingString:(NSString *)str {\n  NSString *result = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];\n  return result;\n}\n\n// NSURL's stringByAddingPercentEscapesUsingEncoding: does not escape\n// some characters that should be escaped in URL parameters, like / and ?;\n// we'll use CFURL to force the encoding of those\n//\n// Reference: http://www.ietf.org/rfc/rfc3986.txt\n\nstatic const CFStringRef kCharsToForceEscape = CFSTR(\"!*'();:@&=+$,/?%#[]\");\n\n+ (NSString *)stringByURLEncodingForURI:(NSString *)str {\n\n  NSString *resultStr = str;\n\n  CFStringRef originalString = (CFStringRef) str;\n  CFStringRef leaveUnescaped = NULL;\n\n  CFStringRef escapedStr;\n  escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,\n                                                       originalString,\n                                                       leaveUnescaped,\n                                                       kCharsToForceEscape,\n                                                       kCFStringEncodingUTF8);\n  if (escapedStr) {\n    resultStr = [(id)CFMakeCollectable(escapedStr) autorelease];\n  }\n  return resultStr;\n}\n\n+ (NSString *)stringByURLEncodingStringParameter:(NSString *)str {\n\n  // For parameters, we'll explicitly leave spaces unescaped now, and replace\n  // them with +'s\n\n  NSString *resultStr = str;\n\n  CFStringRef originalString = (CFStringRef) str;\n  CFStringRef leaveUnescaped = CFSTR(\" \");\n\n  CFStringRef escapedStr;\n  escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,\n                                                       originalString,\n                                                       leaveUnescaped,\n                                                       kCharsToForceEscape,\n                                                       kCFStringEncodingUTF8);\n\n  if (escapedStr) {\n    NSMutableString *mutableStr = [NSMutableString stringWithString:(NSString *)escapedStr];\n    CFRelease(escapedStr);\n\n    // replace spaces with plusses\n    [mutableStr replaceOccurrencesOfString:@\" \"\n                                withString:@\"+\"\n                                   options:0\n                                     range:NSMakeRange(0, [mutableStr length])];\n    resultStr = mutableStr;\n  }\n  return resultStr;\n}\n\n// percent-encoding UTF-8\n\n+ (NSString *)stringByPercentEncodingUTF8ForString:(NSString *)inputStr {\n\n  // encode per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7\n  //\n  // step through the string as UTF-8, and replace characters outside 20..7E\n  // (and the percent symbol itself, 25) with percent-encodings\n  //\n  // we avoid creating an encoding string unless we encounter some characters\n  // that require it\n\n  const char* utf8 = [inputStr UTF8String];\n  if (utf8 == NULL) {\n    return nil;\n  }\n\n  NSMutableString *encoded = nil;\n\n  for (unsigned int idx = 0; utf8[idx] != '\\0'; idx++) {\n\n    unsigned char currChar = utf8[idx];\n    if (currChar < 0x20 || currChar == 0x25 || currChar > 0x7E) {\n\n      if (encoded == nil) {\n        // start encoding and catch up on the character skipped so far\n        encoded = [[[NSMutableString alloc] initWithBytes:utf8\n                                                   length:idx\n                                                 encoding:NSUTF8StringEncoding] autorelease];\n      }\n\n      // append this byte as a % and then uppercase hex\n      [encoded appendFormat:@\"%%%02X\", currChar];\n\n    } else {\n      // this character does not need encoding\n      //\n      // encoded is nil here unless we've encountered a previous character\n      // that needed encoding\n      [encoded appendFormat:@\"%c\", currChar];\n    }\n  }\n\n  if (encoded) {\n    return encoded;\n  }\n\n  return inputStr;\n}\n\n#pragma mark Key-Value Coding Searches in an Array\n\n+ (NSArray *)objectsFromArray:(NSArray *)sourceArray\n                    withValue:(id)desiredValue\n                   forKeyPath:(NSString *)keyPath {\n  // step through all entries, get the value from\n  // the key path, and see if it's equal to the\n  // desired value\n  NSMutableArray *results = [NSMutableArray array];\n\n  for (id obj in sourceArray) {\n    id val = [obj valueForKeyPath:keyPath];\n    if (AreEqualOrBothNil(val, desiredValue)) {\n\n      // found a match; add it to the results array\n      [results addObject:obj];\n    }\n  }\n  return results;\n}\n\n+ (id)firstObjectFromArray:(NSArray *)sourceArray\n                 withValue:(id)desiredValue\n                forKeyPath:(NSString *)keyPath {\n\n  for (id obj in sourceArray) {\n    id val = [obj valueForKeyPath:keyPath];\n    if (AreEqualOrBothNil(val, desiredValue)) {\n\n      // found a match; return it\n      return obj;\n    }\n  }\n  return nil;\n}\n\n#pragma mark Response-string helpers\n\n// convert responses of the form \"a=foo \\n b=bar\" to a dictionary\n+ (NSDictionary *)dictionaryWithResponseString:(NSString *)str {\n\n  if (str == nil) return nil;\n\n  NSArray *allLines = [str componentsSeparatedByString:@\"\\n\"];\n  NSMutableDictionary *responseDict;\n\n  responseDict = [NSMutableDictionary dictionaryWithCapacity:[allLines count]];\n\n  for (NSString *line in allLines) {\n    NSScanner *scanner = [NSScanner scannerWithString:line];\n    NSString *key;\n    NSString *value;\n\n    if ([scanner scanUpToString:@\"=\" intoString:&key]\n        && [scanner scanString:@\"=\" intoString:NULL]\n        && [scanner scanUpToString:@\"\\n\" intoString:&value]) {\n\n      [responseDict setObject:value forKey:key];\n    }\n  }\n  return responseDict;\n}\n\n+ (NSDictionary *)dictionaryWithResponseData:(NSData *)data {\n  NSString *str = [[[NSString alloc] initWithData:data\n                                         encoding:NSUTF8StringEncoding] autorelease];\n  return [self dictionaryWithResponseString:str];\n}\n\n#pragma mark Version helpers\n\n// compareVersion compares two strings in 1.2.3.4 format\n// missing fields are interpreted as zeros, so 1.2 = 1.2.0.0\n+ (NSComparisonResult)compareVersion:(NSString *)ver1 toVersion:(NSString *)ver2 {\n\n  static NSCharacterSet* dotSet = nil;\n  if (dotSet == nil) {\n    dotSet = [[NSCharacterSet characterSetWithCharactersInString:@\".\"] retain];\n  }\n\n  if (ver1 == nil) ver1 = @\"\";\n  if (ver2 == nil) ver2 = @\"\";\n\n  NSScanner* scanner1 = [NSScanner scannerWithString:ver1];\n  NSScanner* scanner2 = [NSScanner scannerWithString:ver2];\n\n  [scanner1 setCharactersToBeSkipped:dotSet];\n  [scanner2 setCharactersToBeSkipped:dotSet];\n\n  int partA1 = 0, partA2 = 0, partB1 = 0, partB2 = 0;\n  int partC1 = 0, partC2 = 0, partD1 = 0, partD2 = 0;\n\n  if ([scanner1 scanInt:&partA1] && [scanner1 scanInt:&partB1]\n      && [scanner1 scanInt:&partC1] && [scanner1 scanInt:&partD1]) {\n  }\n  if ([scanner2 scanInt:&partA2] && [scanner2 scanInt:&partB2]\n      && [scanner2 scanInt:&partC2] && [scanner2 scanInt:&partD2]) {\n  }\n\n  if (partA1 != partA2) return ((partA1 < partA2) ? NSOrderedAscending : NSOrderedDescending);\n  if (partB1 != partB2) return ((partB1 < partB2) ? NSOrderedAscending : NSOrderedDescending);\n  if (partC1 != partC2) return ((partC1 < partC2) ? NSOrderedAscending : NSOrderedDescending);\n  if (partD1 != partD2) return ((partD1 < partD2) ? NSOrderedAscending : NSOrderedDescending);\n  return NSOrderedSame;\n}\n\n#pragma mark File type helpers\n\n// utility routine to convert a file path to the file's MIME type using\n// Mac OS X's UTI database\n+ (NSString *)MIMETypeForFileAtPath:(NSString *)path\n                    defaultMIMEType:(NSString *)defaultType {\n#ifndef GDATA_FOUNDATION_ONLY\n\n  NSString *result = defaultType;\n\n  // convert the path to an FSRef\n  FSRef fileFSRef;\n  Boolean isDirectory;\n  OSStatus err = FSPathMakeRef((UInt8 *) [path fileSystemRepresentation],\n                               &fileFSRef, &isDirectory);\n  if (err == noErr) {\n\n    // get the UTI (content type) for the FSRef\n    CFStringRef fileUTI;\n    err = LSCopyItemAttribute(&fileFSRef, kLSRolesAll, kLSItemContentType,\n                              (CFTypeRef *)&fileUTI);\n    if (err == noErr) {\n\n      // get the MIME type for the UTI\n      CFStringRef mimeTypeTag;\n      mimeTypeTag = UTTypeCopyPreferredTagWithClass(fileUTI,\n                                                    kUTTagClassMIMEType);\n      if (mimeTypeTag) {\n\n        // convert the CFStringRef to an autoreleased NSString (ObjC 2.0-safe)\n        result = [(id)CFMakeCollectable(mimeTypeTag) autorelease];\n      }\n      CFRelease(fileUTI);\n    }\n  }\n  return result;\n\n#else // !GDATA_FOUNDATION_ONLY\n\n  return defaultType;\n\n#endif\n}\n\n@end\n\n// isEqual: has the fatal flaw that it doesn't deal well with the receiver\n// being nil. We'll use this utility instead.\nBOOL AreEqualOrBothNil(id obj1, id obj2) {\n  if (obj1 == obj2) {\n    return YES;\n  }\n  if (obj1 && obj2) {\n    BOOL areEqual = [obj1 isEqual:obj2];\n\n    // the following commented-out lines are useful for finding out what\n    // comparisons are failing when XML regeneration fails in unit tests\n\n    //if (!areEqual) NSLog(@\">>>\\n%@\\n  !=\\n%@\", obj1, obj2);\n\n    return areEqual;\n  } else {\n    //NSLog(@\">>>\\n%@\\n  !=\\n%@\", obj1, obj2);\n  }\n  return NO;\n}\n\nBOOL AreBoolsEqual(BOOL b1, BOOL b2) {\n  // avoid comparison problems with boolean types by negating\n  // both booleans\n  return (!b1 == !b2);\n}\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/HTTPFetcher/GTMGatherInputStream.h",
    "content": "/* Copyright (c) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n// The GTMGatherInput stream is an input stream implementation that is to be\n// instantiated with an NSArray of NSData objects.  It works in the traditional\n// scatter/gather vector I/O model.  Rather than allocating a big NSData object\n// to hold all of the data and performing a copy into that object, the\n// GTMGatherInputStream will maintain a reference to the NSArray and read from\n// each NSData in turn as the read method is called.  You should not alter the\n// underlying set of NSData objects until all read operations on this input\n// stream have completed.\n\n#import <Foundation/Foundation.h>\n\n#if defined(GTL_TARGET_NAMESPACE)\n  // we need NSInteger for the 10.4 SDK, or we're using target namespace macros\n  #import \"GTLDefines.h\"\n#elif defined(GDATA_TARGET_NAMESPACE)\n  #import \"GDataDefines.h\"\n#endif\n\n// Define <NSStreamDelegate> only for Mac OS X 10.6+ or iPhone OS 4.0+.\n#undef GTM_NSSTREAM_DELEGATE\n#if (TARGET_OS_MAC && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \\\n    (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000))\n #define GTM_NSSTREAM_DELEGATE <NSStreamDelegate>\n#else\n #define GTM_NSSTREAM_DELEGATE\n#endif\n\n@interface GTMGatherInputStream : NSInputStream GTM_NSSTREAM_DELEGATE {\n\n  NSArray* dataArray_;   // NSDatas that should be \"gathered\" and streamed.\n  NSUInteger arrayIndex_;       // Index in the array of the current NSData.\n  long long dataOffset_; // Offset in the current NSData we are processing.\n\n  __weak id delegate_;          // stream delegate, defaults to self\n\n  // Since various undocumented methods get called on a stream, we'll\n  // use a 1-byte dummy stream object to handle all unexpected messages.\n  // Actual reads from the stream we will perform using the data array, not\n  // from the dummy stream.\n  NSInputStream* dummyStream_;\n  NSData* dummyData_;\n}\n\n+ (NSInputStream *)streamWithArray:(NSArray *)dataArray;\n\n- (id)initWithArray:(NSArray *)dataArray;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/HTTPFetcher/GTMGatherInputStream.m",
    "content": "/* Copyright (c) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#import \"GTMGatherInputStream.h\"\n\n@implementation GTMGatherInputStream\n\n+ (NSInputStream *)streamWithArray:(NSArray *)dataArray {\n  return [[[self alloc] initWithArray:dataArray] autorelease];\n}\n\n- (id)initWithArray:(NSArray *)dataArray {\n  self = [super init];\n  if (self) {\n    dataArray_ = [dataArray retain];\n    arrayIndex_ = 0;\n    dataOffset_ = 0;\n\n    [self setDelegate:self];  // An NSStream's default delegate should be self.\n\n    // We use a dummy input stream to handle all the various undocumented\n    // messages the system sends to an input stream.\n    //\n    // Contrary to documentation, inputStreamWithData neither copies nor\n    // retains the data in Mac OS X 10.4, so we must retain it.\n    // (Radar 5167591)\n\n    dummyData_ = [[NSData alloc] initWithBytes:\"x\" length:1];\n    dummyStream_ = [[NSInputStream alloc] initWithData:dummyData_];\n  }\n  return self;\n}\n\n- (void)dealloc {\n  [dataArray_ release];\n  [dummyStream_ release];\n  [dummyData_ release];\n\n  [super dealloc];\n}\n\n- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len {\n\n  NSUInteger bytesRead = 0;\n  NSUInteger bytesRemaining = len;\n\n  // read bytes from the currently-indexed array\n  while ((bytesRemaining > 0) && (arrayIndex_ < [dataArray_ count])) {\n\n    NSData* data = [dataArray_ objectAtIndex:arrayIndex_];\n\n    NSUInteger dataLen = [data length];\n    NSUInteger dataBytesLeft = dataLen - (NSUInteger)dataOffset_;\n\n    NSUInteger bytesToCopy = MIN(bytesRemaining, dataBytesLeft);\n    NSRange range = NSMakeRange((NSUInteger) dataOffset_, bytesToCopy);\n\n    [data getBytes:(buffer + bytesRead) range:range];\n\n    bytesRead += bytesToCopy;\n    dataOffset_ += bytesToCopy;\n    bytesRemaining -= bytesToCopy;\n\n    if (dataOffset_ == dataLen) {\n      dataOffset_ = 0;\n      arrayIndex_++;\n    }\n  }\n\n  if (bytesRead == 0) {\n    // We are at the end our our stream, so we read all of the data on our\n    // dummy input stream to make sure it is in the \"fully read\" state.\n    uint8_t leftOverBytes[2];\n    (void) [dummyStream_ read:leftOverBytes maxLength:sizeof(leftOverBytes)];\n  }\n\n  return bytesRead;\n}\n\n- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {\n  return NO;  // We don't support this style of reading.\n}\n\n- (BOOL)hasBytesAvailable {\n  // if we return no, the read never finishes, even if we've already\n  // delivered all the bytes\n  return YES;\n}\n\n#pragma mark -\n\n// Pass other expected messages on to the dummy input stream\n\n- (void)open {\n  [dummyStream_ open];\n}\n\n- (void)close {\n  [dummyStream_ close];\n\n  // 10.4's NSURLConnection tends to retain streams needlessly,\n  // so we'll free up the data array right away\n  [dataArray_ release];\n  dataArray_ = nil;\n}\n\n- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {\n  if (delegate_ != self) {\n    [delegate_ stream:self handleEvent:streamEvent];\n  }\n}\n\n- (id)delegate {\n  return delegate_;\n}\n\n- (void)setDelegate:(id)delegate {\n  if (delegate == nil) {\n    delegate_ = self;\n    [dummyStream_ setDelegate:nil];\n  } else {\n    delegate_ = delegate;\n    [dummyStream_ setDelegate:self];\n  }\n}\n\n- (id)propertyForKey:(NSString *)key {\n  return [dummyStream_ propertyForKey:key];\n}\n\n- (BOOL)setProperty:(id)property forKey:(NSString *)key {\n  return [dummyStream_ setProperty:property forKey:key];\n}\n\n- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {\n  [dummyStream_ scheduleInRunLoop:aRunLoop forMode:mode];\n}\n\n- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {\n  [dummyStream_ removeFromRunLoop:aRunLoop forMode:mode];\n}\n\n- (NSStreamStatus)streamStatus {\n  return [dummyStream_ streamStatus];\n}\n- (NSError *)streamError {\n  return [dummyStream_ streamError];\n}\n\n#pragma mark -\n\n// We'll forward all unexpected messages to our dummy stream\n\n+ (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {\n  return [NSInputStream methodSignatureForSelector:selector];\n}\n\n+ (void)forwardInvocation:(NSInvocation*)invocation {\n  [invocation invokeWithTarget:[NSInputStream class]];\n}\n\n- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {\n  return [dummyStream_ methodSignatureForSelector:(SEL)selector];\n}\n\n- (void)forwardInvocation:(NSInvocation*)invocation {\n\n#if 0\n  // uncomment this section to see the messages the NSInputStream receives\n  SEL selector;\n  NSString *selName;\n\n  selector=[invocation selector];\n  selName=NSStringFromSelector(selector);\n  NSLog(@\"-forwardInvocation: %@\",selName);\n#endif\n\n  [invocation invokeWithTarget:dummyStream_];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/HTTPFetcher/GTMMIMEDocument.h",
    "content": "/* Copyright (c) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n// This is a simple class to create a MIME document.  To use, allocate\n// a new GTMMIMEDocument and start adding parts as necessary.  When you are\n// done adding parts, call generateInputStream to get an NSInputStream\n// containing the contents of your MIME document.\n//\n// A good reference for MIME is http://en.wikipedia.org/wiki/MIME\n\n#import <Foundation/Foundation.h>\n\n#if defined(GTL_TARGET_NAMESPACE)\n  // we're using target namespace macros\n  #import \"GTLDefines.h\"\n#elif defined(GDATA_TARGET_NAMESPACE)\n  #import \"GDataDefines.h\"\n#endif\n\n@interface GTMMIMEDocument : NSObject {\n  NSMutableArray* parts_;         // Contains an ordered set of MimeParts\n  unsigned long long length_;     // Length in bytes of the document.\n  u_int32_t randomSeed_;          // for testing\n}\n\n+ (GTMMIMEDocument *)MIMEDocument;\n\n// Adds a new part to this mime document with the given headers and body.  The\n// headers keys and values should be NSStrings\n- (void)addPartWithHeaders:(NSDictionary *)headers\n                      body:(NSData *)body;\n\n// An inputstream that can be used to efficiently read the contents of the\n// mime document.\n- (void)generateInputStream:(NSInputStream **)outStream\n                     length:(unsigned long long*)outLength\n                   boundary:(NSString **)outBoundary;\n\n// ------ UNIT TESTING ONLY BELOW ------\n\n// For unittesting only, seeds the random number generator\n- (void)seedRandomWith:(u_int32_t)seed;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/HTTPFetcher/GTMMIMEDocument.m",
    "content": "/* Copyright (c) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n#import \"GTMMIMEDocument.h\"\n#import \"GTMGatherInputStream.h\"\n\n// memsrch\n//\n// Helper routine to search for the existence of a set of bytes (needle) within\n// a presumed larger set of bytes (haystack).\n//\nstatic BOOL memsrch(const unsigned char* needle, NSUInteger needle_len,\n                    const unsigned char* haystack, NSUInteger haystack_len);\n\n@interface GTMMIMEPart : NSObject {\n  NSData* headerData_;  // Header content including the ending \"\\r\\n\".\n  NSData* bodyData_;    // The body data.\n}\n\n+ (GTMMIMEPart *)partWithHeaders:(NSDictionary *)headers body:(NSData *)body;\n- (id)initWithHeaders:(NSDictionary *)headers body:(NSData *)body;\n- (BOOL)containsBytes:(const unsigned char *)bytes length:(NSUInteger)length;\n- (NSData *)header;\n- (NSData *)body;\n- (NSUInteger)length;\n@end\n\n@implementation GTMMIMEPart\n\n+ (GTMMIMEPart *)partWithHeaders:(NSDictionary *)headers body:(NSData *)body {\n\n  return [[[self alloc] initWithHeaders:headers\n                                   body:body] autorelease];\n}\n\n- (id)initWithHeaders:(NSDictionary *)headers\n                 body:(NSData *)body {\n\n  if ((self = [super init]) != nil) {\n\n    bodyData_ = [body retain];\n\n    // generate the header data by coalescing the dictionary as\n    // lines of \"key: value\\r\\m\"\n    NSMutableString* headerString = [NSMutableString string];\n\n    // sort the header keys so we have a deterministic order for\n    // unit testing\n    SEL sortSel = @selector(caseInsensitiveCompare:);\n    NSArray *sortedKeys = [[headers allKeys] sortedArrayUsingSelector:sortSel];\n\n    for (NSString *key in sortedKeys) {\n      NSString* value = [headers objectForKey:key];\n\n#if DEBUG\n      // look for troublesome characters in the header keys & values\n      static NSCharacterSet *badChars = nil;\n      if (!badChars) {\n        badChars = [[NSCharacterSet characterSetWithCharactersInString:@\":\\r\\n\"] retain];\n      }\n\n      NSRange badRange = [key rangeOfCharacterFromSet:badChars];\n      NSAssert1(badRange.location == NSNotFound, @\"invalid key: %@\", key);\n\n      badRange = [value rangeOfCharacterFromSet:badChars];\n      NSAssert1(badRange.location == NSNotFound, @\"invalid value: %@\", value);\n#endif\n\n      [headerString appendFormat:@\"%@: %@\\r\\n\", key, value];\n    }\n\n    // headers end with an extra blank line\n    [headerString appendString:@\"\\r\\n\"];\n\n    headerData_ = [[headerString dataUsingEncoding:NSUTF8StringEncoding] retain];\n  }\n  return self;\n}\n\n- (void) dealloc {\n  [headerData_ release];\n  [bodyData_ release];\n  [super dealloc];\n}\n\n// Returns true if the parts contents contain the given set of bytes.\n//\n// NOTE: We assume that the 'bytes' we are checking for do not contain \"\\r\\n\",\n// so we don't need to check the concatenation of the header and body bytes.\n- (BOOL)containsBytes:(const unsigned char*)bytes length:(NSUInteger)length {\n\n  // This uses custom memsrch() rather than strcpy because the encoded data may\n  // contain null values.\n  return memsrch(bytes, length, [headerData_ bytes], [headerData_ length]) ||\n         memsrch(bytes, length, [bodyData_ bytes],   [bodyData_ length]);\n}\n\n- (NSData *)header {\n  return headerData_;\n}\n\n- (NSData *)body {\n  return bodyData_;\n}\n\n- (NSUInteger)length {\n  return [headerData_ length] + [bodyData_ length];\n}\n@end\n\n@implementation GTMMIMEDocument\n\n+ (GTMMIMEDocument *)MIMEDocument {\n  return [[[self alloc] init] autorelease];\n}\n\n- (id)init {\n  if ((self = [super init]) != nil) {\n\n    parts_ = [[NSMutableArray alloc] init];\n\n    // Seed the random number generator used to generate mime boundaries\n    srandomdev();\n  }\n  return self;\n}\n\n- (void)dealloc {\n  [parts_ release];\n  [super dealloc];\n}\n\n// Adds a new part to this mime document with the given headers and body.\n- (void)addPartWithHeaders:(NSDictionary *)headers\n                      body:(NSData *)body {\n\n  GTMMIMEPart* part = [GTMMIMEPart partWithHeaders:headers body:body];\n  [parts_ addObject:part];\n}\n\n// For unit testing only, seeds the random number generator so that we will\n// have reproducible boundary strings.\n- (void)seedRandomWith:(u_int32_t)seed {\n  randomSeed_ = seed;\n}\n\n- (u_int32_t)random {\n  if (randomSeed_) {\n    // for testing only\n    return randomSeed_++;\n  } else {\n    return arc4random();\n  }\n}\n\n// Computes the mime boundary to use.  This should only be called\n// after all the desired document parts have been added since it must compute\n// a boundary that does not exist in the document data.\n- (NSString *)uniqueBoundary {\n\n  // use an easily-readable boundary string\n  NSString *const kBaseBoundary = @\"END_OF_PART\";\n\n  NSMutableString *boundary = [NSMutableString stringWithString:kBaseBoundary];\n\n  // if the boundary isn't unique, append random numbers, up to 10 attempts;\n  // if that's still not unique, use a random number sequence instead,\n  // and call it good\n  BOOL didCollide = NO;\n\n  const int maxTries = 10;  // Arbitrarily chosen maximum attempts.\n  for (int tries = 0; tries < maxTries; ++tries) {\n\n    NSData *data = [boundary dataUsingEncoding:NSUTF8StringEncoding];\n    const void *dataBytes = [data bytes];\n    NSUInteger dataLen = [data length];\n\n    for (GTMMIMEPart *part in parts_) {\n      didCollide = [part containsBytes:dataBytes length:dataLen];\n      if (didCollide) break;\n    }\n\n    if (!didCollide) break; // we're fine, no more attempts needed\n\n    // try again with a random number appended\n    boundary = [NSString stringWithFormat:@\"%@_%08lx\", kBaseBoundary,\n                [self random]];\n  }\n\n  if (didCollide) {\n    // fallback... two random numbers\n    boundary = [NSString stringWithFormat:@\"%08lx_tedborg_%08lx\",\n                                          [self random], [self random]];\n  }\n\n  return boundary;\n}\n\n- (void)generateInputStream:(NSInputStream **)outStream\n                     length:(unsigned long long*)outLength\n                   boundary:(NSString **)outBoundary {\n\n  // The input stream is of the form:\n  //   --boundary\n  //    [part_1_headers]\n  //    [part_1_data]\n  //   --boundary\n  //    [part_2_headers]\n  //    [part_2_data]\n  //   --boundary--\n\n  // First we set up our boundary NSData objects.\n  NSString *boundary = [self uniqueBoundary];\n\n  NSString *mainBoundary = [NSString stringWithFormat:@\"\\r\\n--%@\\r\\n\", boundary];\n  NSString *endBoundary = [NSString stringWithFormat:@\"\\r\\n--%@--\\r\\n\", boundary];\n\n  NSData *mainBoundaryData = [mainBoundary dataUsingEncoding:NSUTF8StringEncoding];\n  NSData *endBoundaryData = [endBoundary dataUsingEncoding:NSUTF8StringEncoding];\n\n  // Now we add them all in proper order to our dataArray.\n  NSMutableArray* dataArray = [NSMutableArray array];\n  unsigned long long length = 0;\n\n  for (GTMMIMEPart* part in parts_) {\n    [dataArray addObject:mainBoundaryData];\n    [dataArray addObject:[part header]];\n    [dataArray addObject:[part body]];\n\n    length += [part length] + [mainBoundaryData length];\n  }\n\n  [dataArray addObject:endBoundaryData];\n  length += [endBoundaryData length];\n\n  if (outLength)   *outLength = length;\n  if (outStream)   *outStream = [GTMGatherInputStream streamWithArray:dataArray];\n  if (outBoundary) *outBoundary = boundary;\n}\n\n@end\n\n\n// memsrch - Return YES if needle is found in haystack, else NO.\nstatic BOOL memsrch(const unsigned char* needle, NSUInteger needleLen,\n                    const unsigned char* haystack, NSUInteger haystackLen) {\n\n  // This is a simple approach.  We start off by assuming that both memchr() and\n  // memcmp are implemented efficiently on the given platform.  We search for an\n  // instance of the first char of our needle in the haystack.  If the remaining\n  // size could fit our needle, then we memcmp to see if it occurs at this point\n  // in the haystack.  If not, we move on to search for the first char again,\n  // starting from the next character in the haystack.\n  const unsigned char* ptr = haystack;\n  NSUInteger remain = haystackLen;\n  while ((ptr = memchr(ptr, needle[0], remain)) != 0) {\n    remain = haystackLen - (ptr - haystack);\n    if (remain < needleLen) {\n      return NO;\n    }\n    if (memcmp(ptr, needle, needleLen) == 0) {\n      return YES;\n    }\n    ptr++;\n    remain--;\n  }\n  return NO;\n}\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/XMLSupport/GDataXMLNode.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// These node, element, and document classes implement a subset of the methods\n// provided by NSXML.  While NSXML behavior is mimicked as much as possible,\n// there are important differences.\n//\n// The biggest difference is that, since this is based on libxml2, there\n// is no retain model for the underlying node data.  Rather than copy every\n// node obtained from a parse tree (which would have a substantial memory\n// impact), we rely on weak references, and it is up to the code that\n// created a document to retain it for as long as any\n// references rely on nodes inside that document tree.\n\n\n#import <Foundation/Foundation.h>\n\n// libxml includes require that the target Header Search Paths contain\n//\n//   /usr/include/libxml2\n//\n// and Other Linker Flags contain\n//\n//   -lxml2\n\n#import <libxml/tree.h>\n#import <libxml/parser.h>\n#import <libxml/xmlstring.h>\n#import <libxml/xpath.h>\n#import <libxml/xpathInternals.h>\n\n\n#ifdef GDATA_TARGET_NAMESPACE\n  // we're using target namespace macros\n  #import \"GDataDefines.h\"\n#endif\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAXMLNODE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#if defined(__cplusplus)\n#define _EXTERN extern \"C\"\n#else\n#define _EXTERN extern\n#endif\n#define _INITIALIZE_AS(x)\n#endif\n\n// when no namespace dictionary is supplied for XPath, the default namespace\n// for the evaluated tree is registered with the prefix _def_ns\n_EXTERN const char* kGDataXMLXPathDefaultNamespacePrefix _INITIALIZE_AS(\"_def_ns\");\n\n// Nomenclature for method names:\n//\n// Node = GData node\n// XMLNode = xmlNodePtr\n//\n// So, for example:\n//  + (id)nodeConsumingXMLNode:(xmlNodePtr)theXMLNode;\n\n@class NSArray, NSDictionary, NSError, NSString, NSURL;\n@class GDataXMLElement, GDataXMLDocument;\n\nenum {\n  GDataXMLInvalidKind = 0,\n  GDataXMLDocumentKind,\n  GDataXMLElementKind,\n  GDataXMLAttributeKind,\n  GDataXMLNamespaceKind,\n  GDataXMLProcessingInstructionKind,\n  GDataXMLCommentKind,\n  GDataXMLTextKind,\n  GDataXMLDTDKind,\n  GDataXMLEntityDeclarationKind,\n  GDataXMLAttributeDeclarationKind,\n  GDataXMLElementDeclarationKind,\n  GDataXMLNotationDeclarationKind\n};\n\ntypedef NSUInteger GDataXMLNodeKind;\n\n@interface GDataXMLNode : NSObject <NSCopying> {\n@protected\n  // NSXMLNodes can have a namespace URI or prefix even if not part\n  // of a tree; xmlNodes cannot.  When we create nodes apart from\n  // a tree, we'll store the dangling prefix or URI in the xmlNode's name,\n  // like\n  //   \"prefix:name\"\n  // or\n  //   \"{http://uri}:name\"\n  //\n  // We will fix up the node's namespace and name (and those of any children)\n  // later when adding the node to a tree with addChild: or addAttribute:.\n  // See fixUpNamespacesForNode:.\n\n  xmlNodePtr xmlNode_; // may also be an xmlAttrPtr or xmlNsPtr\n  BOOL shouldFreeXMLNode_; // if yes, xmlNode_ will be free'd in dealloc\n\n  // cached values\n  NSString *cachedName_;\n  NSArray *cachedChildren_;\n  NSArray *cachedAttributes_;\n}\n\n+ (GDataXMLElement *)elementWithName:(NSString *)name;\n+ (GDataXMLElement *)elementWithName:(NSString *)name stringValue:(NSString *)value;\n+ (GDataXMLElement *)elementWithName:(NSString *)name URI:(NSString *)value;\n\n+ (id)attributeWithName:(NSString *)name stringValue:(NSString *)value;\n+ (id)attributeWithName:(NSString *)name URI:(NSString *)attributeURI stringValue:(NSString *)value;\n\n+ (id)namespaceWithName:(NSString *)name stringValue:(NSString *)value;\n\n+ (id)textWithStringValue:(NSString *)value;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSUInteger)childCount;\n- (NSArray *)children;\n- (GDataXMLNode *)childAtIndex:(unsigned)index;\n\n- (NSString *)localName;\n- (NSString *)name;\n- (NSString *)prefix;\n- (NSString *)URI;\n\n- (GDataXMLNodeKind)kind;\n\n- (NSString *)XMLString;\n\n+ (NSString *)localNameForName:(NSString *)name;\n+ (NSString *)prefixForName:(NSString *)name;\n\n// This is the preferred entry point for nodesForXPath.  This takes an explicit\n// namespace dictionary (keys are prefixes, values are URIs).\n- (NSArray *)nodesForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;\n\n// This implementation of nodesForXPath registers namespaces only from the\n// document's root node.  _def_ns may be used as a prefix for the default\n// namespace, though there's no guarantee that the default namespace will\n// be consistenly the same namespace in server responses.\n- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;\n\n// access to the underlying libxml node; be sure to release the cached values\n// if you change the underlying tree at all\n- (xmlNodePtr)XMLNode;\n- (void)releaseCachedValues;\n\n@end\n\n\n@interface GDataXMLElement : GDataXMLNode\n\n- (id)initWithXMLString:(NSString *)str error:(NSError **)error;\n\n- (NSArray *)namespaces;\n- (void)setNamespaces:(NSArray *)namespaces;\n- (void)addNamespace:(GDataXMLNode *)aNamespace;\n\n// addChild adds a copy of the child node to the element\n- (void)addChild:(GDataXMLNode *)child;\n- (void)removeChild:(GDataXMLNode *)child;\n\n- (NSArray *)elementsForName:(NSString *)name;\n- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI;\n\n- (NSArray *)attributes;\n- (GDataXMLNode *)attributeForName:(NSString *)name;\n- (GDataXMLNode *)attributeForLocalName:(NSString *)name URI:(NSString *)attributeURI;\n- (void)addAttribute:(GDataXMLNode *)attribute;\n\n- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI;\n\n@end\n\n@interface GDataXMLDocument : NSObject {\n@protected\n  xmlDoc* xmlDoc_; // strong; always free'd in dealloc\n}\n\n- (id)initWithXMLString:(NSString *)str options:(unsigned int)mask error:(NSError **)error;\n- (id)initWithData:(NSData *)data options:(unsigned int)mask error:(NSError **)error;\n\n// initWithRootElement uses a copy of the argument as the new document's root\n- (id)initWithRootElement:(GDataXMLElement *)element;\n\n- (GDataXMLElement *)rootElement;\n\n- (NSData *)XMLData;\n\n- (void)setVersion:(NSString *)version;\n- (void)setCharacterEncoding:(NSString *)encoding;\n\n// This is the preferred entry point for nodesForXPath.  This takes an explicit\n// namespace dictionary (keys are prefixes, values are URIs).\n- (NSArray *)nodesForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;\n\n// This implementation of nodesForXPath registers namespaces only from the\n// document's root node.  _def_ns may be used as a prefix for the default\n// namespace, though there's no guarantee that the default namespace will\n// be consistenly the same namespace in server responses.\n- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;\n\n- (NSString *)description;\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GData/XMLSupport/GDataXMLNode.m",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#define GDATAXMLNODE_DEFINE_GLOBALS 1\n#import \"GDataXMLNode.h\"\n\n@class NSArray, NSDictionary, NSError, NSString, NSURL;\n@class GDataXMLElement, GDataXMLDocument;\n\n\nstatic const int kGDataXMLParseOptions = (XML_PARSE_NOCDATA | XML_PARSE_NOBLANKS);\n\n// dictionary key callbacks for string cache\nstatic const void *StringCacheKeyRetainCallBack(CFAllocatorRef allocator, const void *str);\nstatic void StringCacheKeyReleaseCallBack(CFAllocatorRef allocator, const void *str);\nstatic CFStringRef StringCacheKeyCopyDescriptionCallBack(const void *str);\nstatic Boolean StringCacheKeyEqualCallBack(const void *str1, const void *str2);\nstatic CFHashCode StringCacheKeyHashCallBack(const void *str);\n\n// isEqual: has the fatal flaw that it doesn't deal well with the received\n// being nil. We'll use this utility instead.\n\n// Static copy of AreEqualOrBothNil from GDataObject.m, so that using\n// GDataXMLNode does not require pulling in all of GData.\nstatic BOOL AreEqualOrBothNilPrivate(id obj1, id obj2) {\n  if (obj1 == obj2) {\n    return YES;\n  }\n  if (obj1 && obj2) {\n    return [obj1 isEqual:obj2];\n  }\n  return NO;\n}\n\n\n// convert NSString* to xmlChar*\n//\n// the \"Get\" part implies that ownership remains with str\n\nstatic xmlChar* GDataGetXMLString(NSString *str) {\n  xmlChar* result = (xmlChar *)[str UTF8String];\n  return result;\n}\n\n// Make a fake qualified name we use as local name internally in libxml\n// data structures when there's no actual namespace node available to point to\n// from an element or attribute node\n//\n// Returns an autoreleased NSString*\n\nstatic NSString *GDataFakeQNameForURIAndName(NSString *theURI, NSString *name) {\n\n  NSString *localName = [GDataXMLNode localNameForName:name];\n  NSString *fakeQName = [NSString stringWithFormat:@\"{%@}:%@\",\n                         theURI, localName];\n  return fakeQName;\n}\n\n\n// libxml2 offers xmlSplitQName2, but that searches forwards. Since we may\n// be searching for a whole URI shoved in as a prefix, like\n//   {http://foo}:name\n// we'll search for the prefix in backwards from the end of the qualified name\n//\n// returns a copy of qname as the local name if there's no prefix\nstatic xmlChar *SplitQNameReverse(const xmlChar *qname, xmlChar **prefix) {\n\n  // search backwards for a colon\n  int qnameLen = xmlStrlen(qname);\n  for (int idx = qnameLen - 1; idx >= 0; idx--) {\n\n    if (qname[idx] == ':') {\n\n      // found the prefix; copy the prefix, if requested\n      if (prefix != NULL) {\n        if (idx > 0) {\n          *prefix = xmlStrsub(qname, 0, idx);\n        } else {\n          *prefix = NULL;\n        }\n      }\n\n      if (idx < qnameLen - 1) {\n        // return a copy of the local name\n        xmlChar *localName = xmlStrsub(qname, idx + 1, qnameLen - idx - 1);\n        return localName;\n      } else {\n        return NULL;\n      }\n    }\n  }\n\n  // no colon found, so the qualified name is the local name\n  xmlChar *qnameCopy = xmlStrdup(qname);\n  return qnameCopy;\n}\n\n@interface GDataXMLNode (PrivateMethods)\n\n// consuming a node implies it will later be freed when the instance is\n// dealloc'd; borrowing it implies that ownership and disposal remain the\n// job of the supplier of the node\n\n+ (id)nodeConsumingXMLNode:(xmlNodePtr)theXMLNode;\n- (id)initConsumingXMLNode:(xmlNodePtr)theXMLNode;\n\n+ (id)nodeBorrowingXMLNode:(xmlNodePtr)theXMLNode;\n- (id)initBorrowingXMLNode:(xmlNodePtr)theXMLNode;\n\n// getters of the underlying node\n- (xmlNodePtr)XMLNode;\n- (xmlNodePtr)XMLNodeCopy;\n\n// search for an underlying attribute\n- (GDataXMLNode *)attributeForXMLNode:(xmlAttrPtr)theXMLNode;\n\n// return an NSString for an xmlChar*, using our strings cache in the\n// document\n- (NSString *)stringFromXMLString:(const xmlChar *)chars;\n\n// setter/getter of the dealloc flag for the underlying node\n- (BOOL)shouldFreeXMLNode;\n- (void)setShouldFreeXMLNode:(BOOL)flag;\n\n@end\n\n@interface GDataXMLElement (PrivateMethods)\n\n+ (void)fixUpNamespacesForNode:(xmlNodePtr)nodeToFix\n            graftingToTreeNode:(xmlNodePtr)graftPointNode;\n@end\n\n@implementation GDataXMLNode\n\n+ (void)load {\n  xmlInitParser();\n}\n\n// Note on convenience methods for making stand-alone element and\n// attribute nodes:\n//\n// Since we're making a node from scratch, we don't\n// have any namespace info.  So the namespace prefix, if\n// any, will just be slammed into the node name.\n// We'll rely on the -addChild method below to remove\n// the namespace prefix and replace it with a proper ns\n// pointer.\n\n+ (GDataXMLElement *)elementWithName:(NSString *)name {\n\n  xmlNodePtr theNewNode = xmlNewNode(NULL, // namespace\n                                     GDataGetXMLString(name));\n  if (theNewNode) {\n    // succeeded\n    return [self nodeConsumingXMLNode:theNewNode];\n  }\n  return nil;\n}\n\n+ (GDataXMLElement *)elementWithName:(NSString *)name stringValue:(NSString *)value {\n\n  xmlNodePtr theNewNode = xmlNewNode(NULL, // namespace\n                                     GDataGetXMLString(name));\n  if (theNewNode) {\n\n    xmlNodePtr textNode = xmlNewText(GDataGetXMLString(value));\n    if (textNode) {\n\n      xmlNodePtr temp = xmlAddChild(theNewNode, textNode);\n      if (temp) {\n        // succeeded\n        return [self nodeConsumingXMLNode:theNewNode];\n      }\n    }\n\n    // failed; free the node and any children\n    xmlFreeNode(theNewNode);\n  }\n  return nil;\n}\n\n+ (GDataXMLElement *)elementWithName:(NSString *)name URI:(NSString *)theURI {\n\n  // since we don't know a prefix yet, shove in the whole URI; we'll look for\n  // a proper namespace ptr later when addChild calls fixUpNamespacesForNode\n\n  NSString *fakeQName = GDataFakeQNameForURIAndName(theURI, name);\n\n  xmlNodePtr theNewNode = xmlNewNode(NULL, // namespace\n                                     GDataGetXMLString(fakeQName));\n  if (theNewNode) {\n      return [self nodeConsumingXMLNode:theNewNode];\n  }\n  return nil;\n}\n\n+ (id)attributeWithName:(NSString *)name stringValue:(NSString *)value {\n\n  xmlChar *xmlName = GDataGetXMLString(name);\n  xmlChar *xmlValue = GDataGetXMLString(value);\n\n  xmlAttrPtr theNewAttr = xmlNewProp(NULL, // parent node for the attr\n                                     xmlName, xmlValue);\n  if (theNewAttr) {\n    return [self nodeConsumingXMLNode:(xmlNodePtr) theNewAttr];\n  }\n\n  return nil;\n}\n\n+ (id)attributeWithName:(NSString *)name URI:(NSString *)attributeURI stringValue:(NSString *)value {\n\n  // since we don't know a prefix yet, shove in the whole URI; we'll look for\n  // a proper namespace ptr later when addChild calls fixUpNamespacesForNode\n\n  NSString *fakeQName = GDataFakeQNameForURIAndName(attributeURI, name);\n\n  xmlChar *xmlName = GDataGetXMLString(fakeQName);\n  xmlChar *xmlValue = GDataGetXMLString(value);\n\n  xmlAttrPtr theNewAttr = xmlNewProp(NULL, // parent node for the attr\n                                     xmlName, xmlValue);\n  if (theNewAttr) {\n    return [self nodeConsumingXMLNode:(xmlNodePtr) theNewAttr];\n  }\n\n  return nil;\n}\n\n+ (id)textWithStringValue:(NSString *)value {\n\n  xmlNodePtr theNewText = xmlNewText(GDataGetXMLString(value));\n  if (theNewText) {\n    return [self nodeConsumingXMLNode:theNewText];\n  }\n  return nil;\n}\n\n+ (id)namespaceWithName:(NSString *)name stringValue:(NSString *)value {\n\n  xmlChar *href = GDataGetXMLString(value);\n  xmlChar *prefix;\n\n  if ([name length] > 0) {\n    prefix = GDataGetXMLString(name);\n  } else {\n    // default namespace is represented by a nil prefix\n    prefix = nil;\n  }\n\n  xmlNsPtr theNewNs = xmlNewNs(NULL, // parent node\n                               href, prefix);\n  if (theNewNs) {\n    return [self nodeConsumingXMLNode:(xmlNodePtr) theNewNs];\n  }\n  return nil;\n}\n\n+ (id)nodeConsumingXMLNode:(xmlNodePtr)theXMLNode {\n  Class theClass;\n\n  if (theXMLNode->type == XML_ELEMENT_NODE) {\n    theClass = [GDataXMLElement class];\n  } else {\n    theClass = [GDataXMLNode class];\n  }\n  return [[[theClass alloc] initConsumingXMLNode:theXMLNode] autorelease];\n}\n\n- (id)initConsumingXMLNode:(xmlNodePtr)theXMLNode {\n  self = [super init];\n  if (self) {\n    xmlNode_ = theXMLNode;\n    shouldFreeXMLNode_ = YES;\n  }\n  return self;\n}\n\n+ (id)nodeBorrowingXMLNode:(xmlNodePtr)theXMLNode {\n  Class theClass;\n  if (theXMLNode->type == XML_ELEMENT_NODE) {\n    theClass = [GDataXMLElement class];\n  } else {\n    theClass = [GDataXMLNode class];\n  }\n\n  return [[[theClass alloc] initBorrowingXMLNode:theXMLNode] autorelease];\n}\n\n- (id)initBorrowingXMLNode:(xmlNodePtr)theXMLNode {\n  self = [super init];\n  if (self) {\n    xmlNode_ = theXMLNode;\n    shouldFreeXMLNode_ = NO;\n  }\n  return self;\n}\n\n- (void)releaseCachedValues {\n\n  [cachedName_ release];\n  cachedName_ = nil;\n\n  [cachedChildren_ release];\n  cachedChildren_ = nil;\n\n  [cachedAttributes_ release];\n  cachedAttributes_ = nil;\n}\n\n\n// convert xmlChar* to NSString*\n//\n// returns an autoreleased NSString*, from the current node's document strings\n// cache if possible\n- (NSString *)stringFromXMLString:(const xmlChar *)chars {\n\n#if DEBUG\n  NSCAssert(chars != NULL, @\"GDataXMLNode sees an unexpected empty string\");\n#endif\n  if (chars == NULL) return nil;\n\n  CFMutableDictionaryRef cacheDict = NULL;\n\n  NSString *result = nil;\n\n  if (xmlNode_ != NULL\n    && (xmlNode_->type == XML_ELEMENT_NODE\n        || xmlNode_->type == XML_ATTRIBUTE_NODE\n        || xmlNode_->type == XML_TEXT_NODE)) {\n    // there is no xmlDocPtr in XML_NAMESPACE_DECL nodes,\n    // so we can't cache the text of those\n\n    // look for a strings cache in the document\n    //\n    // the cache is in the document's user-defined _private field\n\n    if (xmlNode_->doc != NULL) {\n\n      cacheDict = xmlNode_->doc->_private;\n\n      if (cacheDict) {\n\n        // this document has a strings cache\n        result = (NSString *) CFDictionaryGetValue(cacheDict, chars);\n        if (result) {\n          // we found the xmlChar string in the cache; return the previously\n          // allocated NSString, rather than allocate a new one\n          return result;\n        }\n      }\n    }\n  }\n\n  // allocate a new NSString for this xmlChar*\n  result = [NSString stringWithUTF8String:(const char *) chars];\n  if (cacheDict) {\n    // save the string in the document's string cache\n    CFDictionarySetValue(cacheDict, chars, result);\n  }\n\n  return result;\n}\n\n- (void)dealloc {\n\n  if (xmlNode_ && shouldFreeXMLNode_) {\n    xmlFreeNode(xmlNode_);\n    xmlNode_ = NULL;\n  }\n\n  [self releaseCachedValues];\n  [super dealloc];\n}\n\n#pragma mark -\n\n- (void)setStringValue:(NSString *)str {\n  if (xmlNode_ != NULL && str != nil) {\n\n    if (xmlNode_->type == XML_NAMESPACE_DECL) {\n\n      // for a namespace node, the value is the namespace URI\n      xmlNsPtr nsNode = (xmlNsPtr)xmlNode_;\n\n      if (nsNode->href != NULL) xmlFree((char *)nsNode->href);\n\n      nsNode->href = xmlStrdup(GDataGetXMLString(str));\n\n    } else {\n\n      // attribute or element node\n\n      // do we need to call xmlEncodeSpecialChars?\n      xmlNodeSetContent(xmlNode_, GDataGetXMLString(str));\n    }\n  }\n}\n\n- (NSString *)stringValue {\n\n  NSString *str = nil;\n\n  if (xmlNode_ != NULL) {\n\n    if (xmlNode_->type == XML_NAMESPACE_DECL) {\n\n      // for a namespace node, the value is the namespace URI\n      xmlNsPtr nsNode = (xmlNsPtr)xmlNode_;\n\n      str = [self stringFromXMLString:(nsNode->href)];\n\n    } else {\n\n      // attribute or element node\n      xmlChar* chars = xmlNodeGetContent(xmlNode_);\n      if (chars) {\n\n        str = [self stringFromXMLString:chars];\n\n        xmlFree(chars);\n      }\n    }\n  }\n  return str;\n}\n\n- (NSString *)XMLString {\n\n  NSString *str = nil;\n\n  if (xmlNode_ != NULL) {\n\n    xmlBufferPtr buff = xmlBufferCreate();\n    if (buff) {\n\n      xmlDocPtr doc = NULL;\n      int level = 0;\n      int format = 0;\n\n      int result = xmlNodeDump(buff, doc, xmlNode_, level, format);\n\n      if (result > -1) {\n        str = [[[NSString alloc] initWithBytes:(xmlBufferContent(buff))\n                                        length:(xmlBufferLength(buff))\n                                      encoding:NSUTF8StringEncoding] autorelease];\n      }\n      xmlBufferFree(buff);\n    }\n  }\n\n  // remove leading and trailing whitespace\n  NSCharacterSet *ws = [NSCharacterSet whitespaceAndNewlineCharacterSet];\n  NSString *trimmed = [str stringByTrimmingCharactersInSet:ws];\n  return trimmed;\n}\n\n- (NSString *)localName {\n  NSString *str = nil;\n\n  if (xmlNode_ != NULL) {\n\n    str = [self stringFromXMLString:(xmlNode_->name)];\n\n    // if this is part of a detached subtree, str may have a prefix in it\n    str = [[self class] localNameForName:str];\n  }\n  return str;\n}\n\n- (NSString *)prefix {\n\n  NSString *str = nil;\n\n  if (xmlNode_ != NULL) {\n\n    // the default namespace's prefix is an empty string, though libxml\n    // represents it as NULL for ns->prefix\n    str = @\"\";\n\n    if (xmlNode_->ns != NULL && xmlNode_->ns->prefix != NULL) {\n      str = [self stringFromXMLString:(xmlNode_->ns->prefix)];\n    }\n  }\n  return str;\n}\n\n- (NSString *)URI {\n\n  NSString *str = nil;\n\n  if (xmlNode_ != NULL) {\n\n    if (xmlNode_->ns != NULL && xmlNode_->ns->href != NULL) {\n      str = [self stringFromXMLString:(xmlNode_->ns->href)];\n    }\n  }\n  return str;\n}\n\n- (NSString *)qualifiedName {\n  // internal utility\n\n  NSString *str = nil;\n\n  if (xmlNode_ != NULL) {\n    if (xmlNode_->type == XML_NAMESPACE_DECL) {\n\n      // name of a namespace node\n      xmlNsPtr nsNode = (xmlNsPtr)xmlNode_;\n\n      // null is the default namespace; one is the loneliest number\n      if (nsNode->prefix == NULL) {\n        str = @\"\";\n      }\n      else {\n        str = [self stringFromXMLString:(nsNode->prefix)];\n      }\n\n    } else if (xmlNode_->ns != NULL && xmlNode_->ns->prefix != NULL) {\n\n      // name of a non-namespace node\n\n      // has a prefix\n      char *qname;\n      if (asprintf(&qname, \"%s:%s\", (const char *)xmlNode_->ns->prefix,\n                   xmlNode_->name) != -1) {\n        str = [self stringFromXMLString:(const xmlChar *)qname];\n        free(qname);\n      }\n    } else {\n      // lacks a prefix\n      str = [self stringFromXMLString:(xmlNode_->name)];\n    }\n  }\n\n  return str;\n}\n\n- (NSString *)name {\n\n  if (cachedName_ != nil) {\n    return cachedName_;\n  }\n\n  NSString *str = [self qualifiedName];\n\n  cachedName_ = [str retain];\n\n  return str;\n}\n\n+ (NSString *)localNameForName:(NSString *)name {\n  if (name != nil) {\n\n    NSRange range = [name rangeOfString:@\":\"];\n    if (range.location != NSNotFound) {\n\n      // found a colon\n      if (range.location + 1 < [name length]) {\n        NSString *localName = [name substringFromIndex:(range.location + 1)];\n        return localName;\n      }\n    }\n  }\n  return name;\n}\n\n+ (NSString *)prefixForName:(NSString *)name {\n  if (name != nil) {\n\n    NSRange range = [name rangeOfString:@\":\"];\n    if (range.location != NSNotFound) {\n\n      NSString *prefix = [name substringToIndex:(range.location)];\n      return prefix;\n    }\n  }\n  return nil;\n}\n\n- (NSUInteger)childCount {\n\n  if (cachedChildren_ != nil) {\n    return [cachedChildren_ count];\n  }\n\n  if (xmlNode_ != NULL) {\n\n    unsigned int count = 0;\n\n    xmlNodePtr currChild = xmlNode_->children;\n\n    while (currChild != NULL) {\n      ++count;\n      currChild = currChild->next;\n    }\n    return count;\n  }\n  return 0;\n}\n\n- (NSArray *)children {\n\n  if (cachedChildren_ != nil) {\n    return cachedChildren_;\n  }\n\n  NSMutableArray *array = nil;\n\n  if (xmlNode_ != NULL) {\n\n    xmlNodePtr currChild = xmlNode_->children;\n\n    while (currChild != NULL) {\n      GDataXMLNode *node = [GDataXMLNode nodeBorrowingXMLNode:currChild];\n\n      if (array == nil) {\n        array = [NSMutableArray arrayWithObject:node];\n      } else {\n        [array addObject:node];\n      }\n\n      currChild = currChild->next;\n    }\n\n    cachedChildren_ = [array retain];\n  }\n  return array;\n}\n\n- (GDataXMLNode *)childAtIndex:(unsigned)index {\n\n  NSArray *children = [self children];\n\n  if ([children count] > index) {\n\n    return [children objectAtIndex:index];\n  }\n  return nil;\n}\n\n- (GDataXMLNodeKind)kind {\n  if (xmlNode_ != NULL) {\n    xmlElementType nodeType = xmlNode_->type;\n    switch (nodeType) {\n      case XML_ELEMENT_NODE:         return GDataXMLElementKind;\n      case XML_ATTRIBUTE_NODE:       return GDataXMLAttributeKind;\n      case XML_TEXT_NODE:            return GDataXMLTextKind;\n      case XML_CDATA_SECTION_NODE:   return GDataXMLTextKind;\n      case XML_ENTITY_REF_NODE:      return GDataXMLEntityDeclarationKind;\n      case XML_ENTITY_NODE:          return GDataXMLEntityDeclarationKind;\n      case XML_PI_NODE:              return GDataXMLProcessingInstructionKind;\n      case XML_COMMENT_NODE:         return GDataXMLCommentKind;\n      case XML_DOCUMENT_NODE:        return GDataXMLDocumentKind;\n      case XML_DOCUMENT_TYPE_NODE:   return GDataXMLDocumentKind;\n      case XML_DOCUMENT_FRAG_NODE:   return GDataXMLDocumentKind;\n      case XML_NOTATION_NODE:        return GDataXMLNotationDeclarationKind;\n      case XML_HTML_DOCUMENT_NODE:   return GDataXMLDocumentKind;\n      case XML_DTD_NODE:             return GDataXMLDTDKind;\n      case XML_ELEMENT_DECL:         return GDataXMLElementDeclarationKind;\n      case XML_ATTRIBUTE_DECL:       return GDataXMLAttributeDeclarationKind;\n      case XML_ENTITY_DECL:          return GDataXMLEntityDeclarationKind;\n      case XML_NAMESPACE_DECL:       return GDataXMLNamespaceKind;\n      case XML_XINCLUDE_START:       return GDataXMLProcessingInstructionKind;\n      case XML_XINCLUDE_END:         return GDataXMLProcessingInstructionKind;\n      case XML_DOCB_DOCUMENT_NODE:   return GDataXMLDocumentKind;\n    }\n  }\n  return GDataXMLInvalidKind;\n}\n\n- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error {\n  // call through with no explicit namespace dictionary; that will register the\n  // root node's namespaces\n  return [self nodesForXPath:xpath namespaces:nil error:error];\n}\n\n- (NSArray *)nodesForXPath:(NSString *)xpath\n                namespaces:(NSDictionary *)namespaces\n                     error:(NSError **)error {\n\n  NSMutableArray *array = nil;\n  NSInteger errorCode = -1;\n  NSDictionary *errorInfo = nil;\n\n  // xmlXPathNewContext requires a doc for its context, but if our elements\n  // are created from GDataXMLElement's initWithXMLString there may not be\n  // a document. (We may later decide that we want to stuff the doc used\n  // there into a GDataXMLDocument and retain it, but we don't do that now.)\n  //\n  // We'll temporarily make a document to use for the xpath context.\n\n  xmlDocPtr tempDoc = NULL;\n  xmlNodePtr topParent = NULL;\n\n  if (xmlNode_->doc == NULL) {\n    tempDoc = xmlNewDoc(NULL);\n    if (tempDoc) {\n      // find the topmost node of the current tree to make the root of\n      // our temporary document\n      topParent = xmlNode_;\n      while (topParent->parent != NULL) {\n        topParent = topParent->parent;\n      }\n      xmlDocSetRootElement(tempDoc, topParent);\n    }\n  }\n\n  if (xmlNode_ != NULL && xmlNode_->doc != NULL) {\n\n    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(xmlNode_->doc);\n    if (xpathCtx) {\n      // anchor at our current node\n      xpathCtx->node = xmlNode_;\n\n      // if a namespace dictionary was provided, register its contents\n      if (namespaces) {\n        // the dictionary keys are prefixes; the values are URIs\n        for (NSString *prefix in namespaces) {\n          NSString *uri = [namespaces objectForKey:prefix];\n\n          xmlChar *prefixChars = (xmlChar *) [prefix UTF8String];\n          xmlChar *uriChars = (xmlChar *) [uri UTF8String];\n          int result = xmlXPathRegisterNs(xpathCtx, prefixChars, uriChars);\n          if (result != 0) {\n#if DEBUG\n            NSCAssert1(result == 0, @\"GDataXMLNode XPath namespace %@ issue\",\n                      prefix);\n#endif\n          }\n        }\n      } else {\n        // no namespace dictionary was provided\n        //\n        // register the namespaces of this node, if it's an element, or of\n        // this node's root element, if it's a document\n        xmlNodePtr nsNodePtr = xmlNode_;\n        if (xmlNode_->type == XML_DOCUMENT_NODE) {\n          nsNodePtr = xmlDocGetRootElement((xmlDocPtr) xmlNode_);\n        }\n\n        // step through the namespaces, if any, and register each with the\n        // xpath context\n        if (nsNodePtr != NULL) {\n          for (xmlNsPtr nsPtr = nsNodePtr->ns; nsPtr != NULL; nsPtr = nsPtr->next) {\n\n            // default namespace is nil in the tree, but there's no way to\n            // register a default namespace, so we'll register a fake one,\n            // _def_ns\n            const xmlChar* prefix = nsPtr->prefix;\n            if (prefix == NULL) {\n              prefix = (xmlChar*) kGDataXMLXPathDefaultNamespacePrefix;\n            }\n\n            int result = xmlXPathRegisterNs(xpathCtx, prefix, nsPtr->href);\n            if (result != 0) {\n#if DEBUG\n              NSCAssert1(result == 0, @\"GDataXMLNode XPath namespace %@ issue\",\n                        prefix);\n#endif\n            }\n          }\n        }\n      }\n\n      // now evaluate the path\n      xmlXPathObjectPtr xpathObj;\n      xpathObj = xmlXPathEval(GDataGetXMLString(xpath), xpathCtx);\n      if (xpathObj) {\n\n        // we have some result from the search\n        array = [NSMutableArray array];\n\n        xmlNodeSetPtr nodeSet = xpathObj->nodesetval;\n        if (nodeSet) {\n\n          // add each node in the result set to our array\n          for (int index = 0; index < nodeSet->nodeNr; index++) {\n\n            xmlNodePtr currNode = nodeSet->nodeTab[index];\n\n            GDataXMLNode *node = [GDataXMLNode nodeBorrowingXMLNode:currNode];\n            if (node) {\n              [array addObject:node];\n            }\n          }\n        }\n        xmlXPathFreeObject(xpathObj);\n      } else {\n        // provide an error for failed evaluation\n        const char *msg = xpathCtx->lastError.str1;\n        errorCode = xpathCtx->lastError.code;\n        if (msg) {\n          NSString *errStr = [NSString stringWithUTF8String:msg];\n          errorInfo = [NSDictionary dictionaryWithObject:errStr\n                                                  forKey:@\"error\"];\n        }\n      }\n\n      xmlXPathFreeContext(xpathCtx);\n    }\n  } else {\n    // not a valid node for using XPath\n    errorInfo = [NSDictionary dictionaryWithObject:@\"invalid node\"\n                                            forKey:@\"error\"];\n  }\n\n  if (array == nil && error != nil) {\n    *error = [NSError errorWithDomain:@\"com.google.GDataXML\"\n                                 code:errorCode\n                             userInfo:errorInfo];\n  }\n\n  if (tempDoc != NULL) {\n    xmlUnlinkNode(topParent);\n    xmlSetTreeDoc(topParent, NULL);\n    xmlFreeDoc(tempDoc);\n  }\n  return array;\n}\n\n- (NSString *)description {\n  int nodeType = (xmlNode_ ? (int)xmlNode_->type : -1);\n\n  return [NSString stringWithFormat:@\"%@ %p: {type:%d name:%@ xml:\\\"%@\\\"}\",\n          [self class], self, nodeType, [self name], [self XMLString]];\n}\n\n- (id)copyWithZone:(NSZone *)zone {\n\n  xmlNodePtr nodeCopy = [self XMLNodeCopy];\n\n  if (nodeCopy != NULL) {\n    return [[[self class] alloc] initConsumingXMLNode:nodeCopy];\n  }\n  return nil;\n}\n\n- (BOOL)isEqual:(GDataXMLNode *)other {\n  if (self == other) return YES;\n  if (![other isKindOfClass:[GDataXMLNode class]]) return NO;\n\n  return [self XMLNode] == [other XMLNode]\n  || ([self kind] == [other kind]\n      && AreEqualOrBothNilPrivate([self name], [other name])\n      && [[self children] count] == [[other children] count]);\n\n}\n\n- (NSUInteger)hash {\n  return (NSUInteger) (void *) [GDataXMLNode class];\n}\n\n- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {\n  return [super methodSignatureForSelector:selector];\n}\n\n#pragma mark -\n\n- (xmlNodePtr)XMLNodeCopy {\n  if (xmlNode_ != NULL) {\n\n    // Note: libxml will create a new copy of namespace nodes (xmlNs records)\n    // and attach them to this copy in order to keep namespaces within this\n    // node subtree copy value.\n\n    xmlNodePtr nodeCopy = xmlCopyNode(xmlNode_, 1); // 1 = recursive\n    return nodeCopy;\n  }\n  return NULL;\n}\n\n- (xmlNodePtr)XMLNode {\n  return xmlNode_;\n}\n\n- (BOOL)shouldFreeXMLNode {\n  return shouldFreeXMLNode_;\n}\n\n- (void)setShouldFreeXMLNode:(BOOL)flag {\n  shouldFreeXMLNode_ = flag;\n}\n\n@end\n\n\n\n@implementation GDataXMLElement\n\n- (id)initWithXMLString:(NSString *)str error:(NSError **)error {\n  self = [super init];\n  if (self) {\n\n    const char *utf8Str = [str UTF8String];\n    // NOTE: We are assuming a string length that fits into an int\n    xmlDocPtr doc = xmlReadMemory(utf8Str, (int)strlen(utf8Str), NULL, // URL\n                                  NULL, // encoding\n                                  kGDataXMLParseOptions);\n    if (doc == NULL) {\n      if (error) {\n        // TODO(grobbins) use xmlSetGenericErrorFunc to capture error\n      }\n    } else {\n      // copy the root node from the doc\n      xmlNodePtr root = xmlDocGetRootElement(doc);\n      if (root) {\n        xmlNode_ = xmlCopyNode(root, 1); // 1: recursive\n        shouldFreeXMLNode_ = YES;\n      }\n      xmlFreeDoc(doc);\n    }\n\n\n    if (xmlNode_ == NULL) {\n      // failure\n      if (error) {\n        *error = [NSError errorWithDomain:@\"com.google.GDataXML\"\n                                     code:-1\n                                 userInfo:nil];\n      }\n      [self release];\n      return nil;\n    }\n  }\n  return self;\n}\n\n- (NSArray *)namespaces {\n\n  NSMutableArray *array = nil;\n\n  if (xmlNode_ != NULL && xmlNode_->nsDef != NULL) {\n\n    xmlNsPtr currNS = xmlNode_->nsDef;\n    while (currNS != NULL) {\n\n      // add this prefix/URI to the list, unless it's the implicit xml prefix\n      if (!xmlStrEqual(currNS->prefix, (const xmlChar *) \"xml\")) {\n        GDataXMLNode *node = [GDataXMLNode nodeBorrowingXMLNode:(xmlNodePtr) currNS];\n\n        if (array == nil) {\n          array = [NSMutableArray arrayWithObject:node];\n        } else {\n          [array addObject:node];\n        }\n      }\n\n      currNS = currNS->next;\n    }\n  }\n  return array;\n}\n\n- (void)setNamespaces:(NSArray *)namespaces {\n\n  if (xmlNode_ != NULL) {\n\n    [self releaseCachedValues];\n\n    // remove previous namespaces\n    if (xmlNode_->nsDef) {\n      xmlFreeNsList(xmlNode_->nsDef);\n      xmlNode_->nsDef = NULL;\n    }\n\n    // add a namespace for each object in the array\n    NSEnumerator *enumerator = [namespaces objectEnumerator];\n    GDataXMLNode *namespaceNode;\n    while ((namespaceNode = [enumerator nextObject]) != nil) {\n\n      xmlNsPtr ns = (xmlNsPtr) [namespaceNode XMLNode];\n      if (ns) {\n        (void)xmlNewNs(xmlNode_, ns->href, ns->prefix);\n      }\n    }\n\n    // we may need to fix this node's own name; the graft point is where\n    // the namespace search starts, so that points to this node too\n    [[self class] fixUpNamespacesForNode:xmlNode_\n                      graftingToTreeNode:xmlNode_];\n  }\n}\n\n- (void)addNamespace:(GDataXMLNode *)aNamespace {\n\n  if (xmlNode_ != NULL) {\n\n    [self releaseCachedValues];\n\n    xmlNsPtr ns = (xmlNsPtr) [aNamespace XMLNode];\n    if (ns) {\n      (void)xmlNewNs(xmlNode_, ns->href, ns->prefix);\n\n      // we may need to fix this node's own name; the graft point is where\n      // the namespace search starts, so that points to this node too\n      [[self class] fixUpNamespacesForNode:xmlNode_\n                        graftingToTreeNode:xmlNode_];\n    }\n  }\n}\n\n- (void)addChild:(GDataXMLNode *)child {\n  if ([child kind] == GDataXMLAttributeKind) {\n    [self addAttribute:child];\n    return;\n  }\n\n  if (xmlNode_ != NULL) {\n\n    [self releaseCachedValues];\n\n    xmlNodePtr childNodeCopy = [child XMLNodeCopy];\n    if (childNodeCopy) {\n\n      xmlNodePtr resultNode = xmlAddChild(xmlNode_, childNodeCopy);\n      if (resultNode == NULL) {\n\n        // failed to add\n        xmlFreeNode(childNodeCopy);\n\n      } else {\n        // added this child subtree successfully; see if it has\n        // previously-unresolved namespace prefixes that can now be fixed up\n        [[self class] fixUpNamespacesForNode:childNodeCopy\n                          graftingToTreeNode:xmlNode_];\n      }\n    }\n  }\n}\n\n- (void)removeChild:(GDataXMLNode *)child {\n  // this is safe for attributes too\n  if (xmlNode_ != NULL) {\n\n    [self releaseCachedValues];\n\n    xmlNodePtr node = [child XMLNode];\n\n    xmlUnlinkNode(node);\n\n    // if the child node was borrowing its xmlNodePtr, then we need to\n    // explicitly free it, since there is probably no owning object that will\n    // free it on dealloc\n    if (![child shouldFreeXMLNode]) {\n      xmlFreeNode(node);\n    }\n  }\n}\n\n- (NSArray *)elementsForName:(NSString *)name {\n\n  NSString *desiredName = name;\n\n  if (xmlNode_ != NULL) {\n\n    NSString *prefix = [[self class] prefixForName:desiredName];\n    if (prefix) {\n\n      xmlChar* desiredPrefix = GDataGetXMLString(prefix);\n\n      xmlNsPtr foundNS = xmlSearchNs(xmlNode_->doc, xmlNode_, desiredPrefix);\n      if (foundNS) {\n\n        // we found a namespace; fall back on elementsForLocalName:URI:\n        // to get the elements\n        NSString *desiredURI = [self stringFromXMLString:(foundNS->href)];\n        NSString *localName = [[self class] localNameForName:desiredName];\n\n        NSArray *nsArray = [self elementsForLocalName:localName URI:desiredURI];\n        return nsArray;\n      }\n    }\n\n    // no namespace found for the node's prefix; try an exact match\n    // for the name argument, including any prefix\n    NSMutableArray *array = nil;\n\n    // walk our list of cached child nodes\n    NSArray *children = [self children];\n\n    for (GDataXMLNode *child in children) {\n\n      xmlNodePtr currNode = [child XMLNode];\n\n      // find all children which are elements with the desired name\n      if (currNode->type == XML_ELEMENT_NODE) {\n\n        NSString *qName = [child name];\n        if ([qName isEqual:name]) {\n\n          if (array == nil) {\n            array = [NSMutableArray arrayWithObject:child];\n          } else {\n            [array addObject:child];\n          }\n        }\n      }\n    }\n    return array;\n  }\n  return nil;\n}\n\n- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI {\n\n  NSMutableArray *array = nil;\n\n  if (xmlNode_ != NULL && xmlNode_->children != NULL) {\n\n    xmlChar* desiredNSHref = GDataGetXMLString(URI);\n    xmlChar* requestedLocalName = GDataGetXMLString(localName);\n    xmlChar* expectedLocalName = requestedLocalName;\n\n    // resolve the URI at the parent level, since usually children won't\n    // have their own namespace definitions, and we don't want to try to\n    // resolve it once for every child\n    xmlNsPtr foundParentNS = xmlSearchNsByHref(xmlNode_->doc, xmlNode_, desiredNSHref);\n    if (foundParentNS == NULL) {\n      NSString *fakeQName = GDataFakeQNameForURIAndName(URI, localName);\n      expectedLocalName = GDataGetXMLString(fakeQName);\n    }\n\n    NSArray *children = [self children];\n\n    for (GDataXMLNode *child in children) {\n\n      xmlNodePtr currChildPtr = [child XMLNode];\n\n      // find all children which are elements with the desired name and\n      // namespace, or with the prefixed name and a null namespace\n      if (currChildPtr->type == XML_ELEMENT_NODE) {\n\n        // normally, we can assume the resolution done for the parent will apply\n        // to the child, as most children do not define their own namespaces\n        xmlNsPtr childLocalNS = foundParentNS;\n        xmlChar* childDesiredLocalName = expectedLocalName;\n\n        if (currChildPtr->nsDef != NULL) {\n          // this child has its own namespace definitons; do a fresh resolve\n          // of the namespace starting from the child, and see if it differs\n          // from the resolve done starting from the parent.  If the resolve\n          // finds a different namespace, then override the desired local\n          // name just for this child.\n          childLocalNS = xmlSearchNsByHref(xmlNode_->doc, currChildPtr, desiredNSHref);\n          if (childLocalNS != foundParentNS) {\n\n            // this child does indeed have a different namespace resolution\n            // result than was found for its parent\n            if (childLocalNS == NULL) {\n              // no namespace found\n              NSString *fakeQName = GDataFakeQNameForURIAndName(URI, localName);\n              childDesiredLocalName = GDataGetXMLString(fakeQName);\n            } else {\n              // a namespace was found; use the original local name requested,\n              // not a faked one expected from resolving the parent\n              childDesiredLocalName = requestedLocalName;\n            }\n          }\n        }\n\n        // check if this child's namespace and local name are what we're\n        // seeking\n        if (currChildPtr->ns == childLocalNS\n            && currChildPtr->name != NULL\n            && xmlStrEqual(currChildPtr->name, childDesiredLocalName)) {\n\n          if (array == nil) {\n            array = [NSMutableArray arrayWithObject:child];\n          } else {\n            [array addObject:child];\n          }\n        }\n      }\n    }\n    // we return nil, not an empty array, according to docs\n  }\n  return array;\n}\n\n- (NSArray *)attributes {\n\n  if (cachedAttributes_ != nil) {\n    return cachedAttributes_;\n  }\n\n  NSMutableArray *array = nil;\n\n  if (xmlNode_ != NULL && xmlNode_->properties != NULL) {\n\n    xmlAttrPtr prop = xmlNode_->properties;\n    while (prop != NULL) {\n\n      GDataXMLNode *node = [GDataXMLNode nodeBorrowingXMLNode:(xmlNodePtr) prop];\n      if (array == nil) {\n        array = [NSMutableArray arrayWithObject:node];\n      } else {\n        [array addObject:node];\n      }\n\n      prop = prop->next;\n    }\n\n    cachedAttributes_ = [array retain];\n  }\n  return array;\n}\n\n- (void)addAttribute:(GDataXMLNode *)attribute {\n\n  if (xmlNode_ != NULL) {\n\n    [self releaseCachedValues];\n\n    xmlAttrPtr attrPtr = (xmlAttrPtr) [attribute XMLNode];\n    if (attrPtr) {\n\n      // ignore this if an attribute with the name is already present,\n      // similar to NSXMLNode's addAttribute\n      xmlAttrPtr oldAttr;\n\n      if (attrPtr->ns == NULL) {\n        oldAttr = xmlHasProp(xmlNode_, attrPtr->name);\n      } else {\n        oldAttr = xmlHasNsProp(xmlNode_, attrPtr->name, attrPtr->ns->href);\n      }\n\n      if (oldAttr == NULL) {\n\n        xmlNsPtr newPropNS = NULL;\n\n        // if this attribute has a namespace, search for a matching namespace\n        // on the node we're adding to\n        if (attrPtr->ns != NULL) {\n\n          newPropNS = xmlSearchNsByHref(xmlNode_->doc, xmlNode_, attrPtr->ns->href);\n          if (newPropNS == NULL) {\n            // make a new namespace on the parent node, and use that for the\n            // new attribute\n            newPropNS = xmlNewNs(xmlNode_, attrPtr->ns->href, attrPtr->ns->prefix);\n          }\n        }\n\n        // copy the attribute onto this node\n        xmlChar *value = xmlNodeGetContent((xmlNodePtr) attrPtr);\n        xmlAttrPtr newProp = xmlNewNsProp(xmlNode_, newPropNS, attrPtr->name, value);\n        if (newProp != NULL) {\n          // we made the property, so clean up the property's namespace\n\n          [[self class] fixUpNamespacesForNode:(xmlNodePtr)newProp\n                            graftingToTreeNode:xmlNode_];\n        }\n\n        if (value != NULL) {\n          xmlFree(value);\n        }\n      }\n    }\n  }\n}\n\n- (GDataXMLNode *)attributeForXMLNode:(xmlAttrPtr)theXMLNode {\n  // search the cached attributes list for the GDataXMLNode with\n  // the underlying xmlAttrPtr\n  NSArray *attributes = [self attributes];\n\n  for (GDataXMLNode *attr in attributes) {\n\n    if (theXMLNode == (xmlAttrPtr) [attr XMLNode]) {\n      return attr;\n    }\n  }\n\n  return nil;\n}\n\n- (GDataXMLNode *)attributeForName:(NSString *)name {\n\n  if (xmlNode_ != NULL) {\n\n    xmlAttrPtr attrPtr = xmlHasProp(xmlNode_, GDataGetXMLString(name));\n    if (attrPtr == NULL) {\n\n      // can we guarantee that xmlAttrPtrs always have the ns ptr and never\n      // a namespace as part of the actual attribute name?\n\n      // split the name and its prefix, if any\n      xmlNsPtr ns = NULL;\n      NSString *prefix = [[self class] prefixForName:name];\n      if (prefix) {\n\n        // find the namespace for this prefix, and search on its URI to find\n        // the xmlNsPtr\n        name = [[self class] localNameForName:name];\n        ns = xmlSearchNs(xmlNode_->doc, xmlNode_, GDataGetXMLString(prefix));\n      }\n\n      const xmlChar* nsURI = ((ns != NULL) ? ns->href : NULL);\n      attrPtr = xmlHasNsProp(xmlNode_, GDataGetXMLString(name), nsURI);\n    }\n\n    if (attrPtr) {\n      GDataXMLNode *attr = [self attributeForXMLNode:attrPtr];\n      return attr;\n    }\n  }\n  return nil;\n}\n\n- (GDataXMLNode *)attributeForLocalName:(NSString *)localName\n                                    URI:(NSString *)attributeURI {\n\n  if (xmlNode_ != NULL) {\n\n    const xmlChar* name = GDataGetXMLString(localName);\n    const xmlChar* nsURI = GDataGetXMLString(attributeURI);\n\n    xmlAttrPtr attrPtr = xmlHasNsProp(xmlNode_, name, nsURI);\n\n    if (attrPtr == NULL) {\n      // if the attribute is in a tree lacking the proper namespace,\n      // the local name may include the full URI as a prefix\n      NSString *fakeQName = GDataFakeQNameForURIAndName(attributeURI, localName);\n      const xmlChar* xmlFakeQName = GDataGetXMLString(fakeQName);\n\n      attrPtr = xmlHasProp(xmlNode_, xmlFakeQName);\n    }\n\n    if (attrPtr) {\n      GDataXMLNode *attr = [self attributeForXMLNode:attrPtr];\n      return attr;\n    }\n  }\n  return nil;\n}\n\n- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI {\n\n  if (xmlNode_ != NULL) {\n\n    xmlChar* desiredNSHref = GDataGetXMLString(namespaceURI);\n\n    xmlNsPtr foundNS = xmlSearchNsByHref(xmlNode_->doc, xmlNode_, desiredNSHref);\n    if (foundNS) {\n\n      // we found the namespace\n      if (foundNS->prefix != NULL) {\n        NSString *prefix = [self stringFromXMLString:(foundNS->prefix)];\n        return prefix;\n      } else {\n        // empty prefix is default namespace\n        return @\"\";\n      }\n    }\n  }\n  return nil;\n}\n\n#pragma mark Namespace fixup routines\n\n+ (void)deleteNamespacePtr:(xmlNsPtr)namespaceToDelete\n               fromXMLNode:(xmlNodePtr)node {\n\n  // utilty routine to remove a namespace pointer from an element's\n  // namespace definition list.  This is just removing the nsPtr\n  // from the singly-linked list, the node's namespace definitions.\n  xmlNsPtr currNS = node->nsDef;\n  xmlNsPtr prevNS = NULL;\n\n  while (currNS != NULL) {\n    xmlNsPtr nextNS = currNS->next;\n\n    if (namespaceToDelete == currNS) {\n\n      // found it; delete it from the head of the node's ns definition list\n      // or from the next field of the previous namespace\n\n      if (prevNS != NULL) prevNS->next = nextNS;\n      else node->nsDef = nextNS;\n\n      xmlFreeNs(currNS);\n      return;\n    }\n    prevNS = currNS;\n    currNS = nextNS;\n  }\n}\n\n+ (void)fixQualifiedNamesForNode:(xmlNodePtr)nodeToFix\n              graftingToTreeNode:(xmlNodePtr)graftPointNode {\n\n  // Replace prefix-in-name with proper namespace pointers\n  //\n  // This is an inner routine for fixUpNamespacesForNode:\n  //\n  // see if this node's name lacks a namespace and is qualified, and if so,\n  // see if we can resolve the prefix against the parent\n  //\n  // The prefix may either be normal, \"gd:foo\", or a URI\n  // \"{http://blah.com/}:foo\"\n\n  if (nodeToFix->ns == NULL) {\n    xmlNsPtr foundNS = NULL;\n\n    xmlChar* prefix = NULL;\n    xmlChar* localName = SplitQNameReverse(nodeToFix->name, &prefix);\n    if (localName != NULL) {\n      if (prefix != NULL) {\n\n        // if the prefix is wrapped by { and } then it's a URI\n        int prefixLen = xmlStrlen(prefix);\n        if (prefixLen > 2\n            && prefix[0] == '{'\n            && prefix[prefixLen - 1] == '}') {\n\n          // search for the namespace by URI\n          xmlChar* uri = xmlStrsub(prefix, 1, prefixLen - 2);\n\n          if (uri != NULL) {\n            foundNS = xmlSearchNsByHref(graftPointNode->doc, graftPointNode, uri);\n\n            xmlFree(uri);\n          }\n        }\n      }\n\n      if (foundNS == NULL) {\n        // search for the namespace by prefix, even if the prefix is nil\n        // (nil prefix means to search for the default namespace)\n        foundNS = xmlSearchNs(graftPointNode->doc, graftPointNode, prefix);\n      }\n\n      if (foundNS != NULL) {\n        // we found a namespace, so fix the ns pointer and the local name\n        xmlSetNs(nodeToFix, foundNS);\n        xmlNodeSetName(nodeToFix, localName);\n      }\n\n      if (prefix != NULL) {\n        xmlFree(prefix);\n        prefix = NULL;\n      }\n\n      xmlFree(localName);\n    }\n  }\n}\n\n+ (void)fixDuplicateNamespacesForNode:(xmlNodePtr)nodeToFix\n                   graftingToTreeNode:(xmlNodePtr)graftPointNode\n             namespaceSubstitutionMap:(NSMutableDictionary *)nsMap {\n\n  // Duplicate namespace removal\n  //\n  // This is an inner routine for fixUpNamespacesForNode:\n  //\n  // If any of this node's namespaces are already defined at the graft point\n  // level, add that namespace to the map of namespace substitutions\n  // so it will be replaced in the children below the nodeToFix, and\n  // delete the namespace record\n\n  if (nodeToFix->type == XML_ELEMENT_NODE) {\n\n    // step through the namespaces defined on this node\n    xmlNsPtr definedNS = nodeToFix->nsDef;\n    while (definedNS != NULL) {\n\n      // see if this namespace is already defined higher in the tree,\n      // with both the same URI and the same prefix; if so, add a mapping for\n      // it\n      xmlNsPtr foundNS = xmlSearchNsByHref(graftPointNode->doc, graftPointNode,\n                                           definedNS->href);\n      if (foundNS != NULL\n          && foundNS != definedNS\n          && xmlStrEqual(definedNS->prefix, foundNS->prefix)) {\n\n        // store a mapping from this defined nsPtr to the one found higher\n        // in the tree\n        [nsMap setObject:[NSValue valueWithPointer:foundNS]\n                  forKey:[NSValue valueWithPointer:definedNS]];\n\n        // remove this namespace from the ns definition list of this node;\n        // all child elements and attributes referencing this namespace\n        // now have a dangling pointer and must be updated (that is done later\n        // in this method)\n        //\n        // before we delete this namespace, move our pointer to the\n        // next one\n        xmlNsPtr nsToDelete = definedNS;\n        definedNS = definedNS->next;\n\n        [self deleteNamespacePtr:nsToDelete fromXMLNode:nodeToFix];\n\n      } else {\n        // this namespace wasn't a duplicate; move to the next\n        definedNS = definedNS->next;\n      }\n    }\n  }\n\n  // if this node's namespace is one we deleted, update it to point\n  // to someplace better\n  if (nodeToFix->ns != NULL) {\n\n    NSValue *currNS = [NSValue valueWithPointer:nodeToFix->ns];\n    NSValue *replacementNS = [nsMap objectForKey:currNS];\n\n    if (replacementNS != nil) {\n      xmlNsPtr replaceNSPtr = (xmlNsPtr)[replacementNS pointerValue];\n\n      xmlSetNs(nodeToFix, replaceNSPtr);\n    }\n  }\n}\n\n\n\n+ (void)fixUpNamespacesForNode:(xmlNodePtr)nodeToFix\n            graftingToTreeNode:(xmlNodePtr)graftPointNode\n      namespaceSubstitutionMap:(NSMutableDictionary *)nsMap {\n\n  // This is the inner routine for fixUpNamespacesForNode:graftingToTreeNode:\n  //\n  // This routine fixes two issues:\n  //\n  // Because we can create nodes with qualified names before adding\n  // them to the tree that declares the namespace for the prefix,\n  // we need to set the node namespaces after adding them to the tree.\n  //\n  // Because libxml adds namespaces to nodes when it copies them,\n  // we want to remove redundant namespaces after adding them to\n  // a tree.\n  //\n  // If only the Mac's libxml had xmlDOMWrapReconcileNamespaces, it could do\n  // namespace cleanup for us\n\n  // We only care about fixing names of elements and attributes\n  if (nodeToFix->type != XML_ELEMENT_NODE\n      && nodeToFix->type != XML_ATTRIBUTE_NODE) return;\n\n  // Do the fixes\n  [self fixQualifiedNamesForNode:nodeToFix\n              graftingToTreeNode:graftPointNode];\n\n  [self fixDuplicateNamespacesForNode:nodeToFix\n                   graftingToTreeNode:graftPointNode\n             namespaceSubstitutionMap:nsMap];\n\n  if (nodeToFix->type == XML_ELEMENT_NODE) {\n\n    // when fixing element nodes, recurse for each child element and\n    // for each attribute\n    xmlNodePtr currChild = nodeToFix->children;\n    while (currChild != NULL) {\n      [self fixUpNamespacesForNode:currChild\n                graftingToTreeNode:graftPointNode\n          namespaceSubstitutionMap:nsMap];\n      currChild = currChild->next;\n    }\n\n    xmlAttrPtr currProp = nodeToFix->properties;\n    while (currProp != NULL) {\n      [self fixUpNamespacesForNode:(xmlNodePtr)currProp\n                graftingToTreeNode:graftPointNode\n          namespaceSubstitutionMap:nsMap];\n      currProp = currProp->next;\n    }\n  }\n}\n\n+ (void)fixUpNamespacesForNode:(xmlNodePtr)nodeToFix\n            graftingToTreeNode:(xmlNodePtr)graftPointNode {\n\n  // allocate the namespace map that will be passed\n  // down on recursive calls\n  NSMutableDictionary *nsMap = [NSMutableDictionary dictionary];\n\n  [self fixUpNamespacesForNode:nodeToFix\n            graftingToTreeNode:graftPointNode\n      namespaceSubstitutionMap:nsMap];\n}\n\n@end\n\n\n@interface GDataXMLDocument (PrivateMethods)\n- (void)addStringsCacheToDoc;\n@end\n\n@implementation GDataXMLDocument\n\n- (id)initWithXMLString:(NSString *)str options:(unsigned int)mask error:(NSError **)error {\n\n  NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];\n  GDataXMLDocument *doc = [self initWithData:data options:mask error:error];\n  return doc;\n}\n\n- (id)initWithData:(NSData *)data options:(unsigned int)mask error:(NSError **)error {\n\n  self = [super init];\n  if (self) {\n\n    const char *baseURL = NULL;\n    const char *encoding = NULL;\n\n    // NOTE: We are assuming [data length] fits into an int.\n    xmlDoc_ = xmlReadMemory((const char*)[data bytes], (int)[data length], baseURL, encoding,\n                            kGDataXMLParseOptions); // TODO(grobbins) map option values\n    if (xmlDoc_ == NULL) {\n      if (error) {\n       *error = [NSError errorWithDomain:@\"com.google.GDataXML\"\n                                    code:-1\n                                userInfo:nil];\n        // TODO(grobbins) use xmlSetGenericErrorFunc to capture error\n      }\n      [self release];\n      return nil;\n    } else {\n      if (error) *error = NULL;\n\n      [self addStringsCacheToDoc];\n    }\n  }\n\n  return self;\n}\n\n- (id)initWithRootElement:(GDataXMLElement *)element {\n\n  self = [super init];\n  if (self) {\n\n    xmlDoc_ = xmlNewDoc(NULL);\n\n    (void) xmlDocSetRootElement(xmlDoc_, [element XMLNodeCopy]);\n\n    [self addStringsCacheToDoc];\n  }\n\n  return self;\n}\n\n- (void)addStringsCacheToDoc {\n  // utility routine for init methods\n\n#if DEBUG\n  NSCAssert(xmlDoc_ != NULL && xmlDoc_->_private == NULL,\n            @\"GDataXMLDocument cache creation problem\");\n#endif\n\n  // add a strings cache as private data for the document\n  //\n  // we'll use plain C pointers (xmlChar*) as the keys, and NSStrings\n  // as the values\n  CFIndex capacity = 0; // no limit\n\n  CFDictionaryKeyCallBacks keyCallBacks = {\n    0, // version\n    StringCacheKeyRetainCallBack,\n    StringCacheKeyReleaseCallBack,\n    StringCacheKeyCopyDescriptionCallBack,\n    StringCacheKeyEqualCallBack,\n    StringCacheKeyHashCallBack\n  };\n\n  CFMutableDictionaryRef dict = CFDictionaryCreateMutable(\n    kCFAllocatorDefault, capacity,\n    &keyCallBacks, &kCFTypeDictionaryValueCallBacks);\n\n  // we'll use the user-defined _private field for our cache\n  xmlDoc_->_private = dict;\n}\n\n- (NSString *)description {\n  return [NSString stringWithFormat:@\"%@ %p\", [self class], self];\n}\n\n- (void)dealloc {\n  if (xmlDoc_ != NULL) {\n    // release the strings cache\n    //\n    // since it's a CF object, were anyone to use this in a GC environment,\n    // this would need to be released in a finalize method, too\n    if (xmlDoc_->_private != NULL) {\n      CFRelease(xmlDoc_->_private);\n    }\n\n    xmlFreeDoc(xmlDoc_);\n  }\n  [super dealloc];\n}\n\n#pragma mark -\n\n- (GDataXMLElement *)rootElement {\n  GDataXMLElement *element = nil;\n\n  if (xmlDoc_ != NULL) {\n    xmlNodePtr rootNode = xmlDocGetRootElement(xmlDoc_);\n    if (rootNode) {\n      element = [GDataXMLElement nodeBorrowingXMLNode:rootNode];\n    }\n  }\n  return element;\n}\n\n- (NSData *)XMLData {\n\n  if (xmlDoc_ != NULL) {\n    xmlChar *buffer = NULL;\n    int bufferSize = 0;\n\n    xmlDocDumpMemory(xmlDoc_, &buffer, &bufferSize);\n\n    if (buffer) {\n      NSData *data = [NSData dataWithBytes:buffer\n                                    length:bufferSize];\n      xmlFree(buffer);\n      return data;\n    }\n  }\n  return nil;\n}\n\n- (void)setVersion:(NSString *)version {\n\n  if (xmlDoc_ != NULL) {\n    if (xmlDoc_->version != NULL) {\n      // version is a const char* so we must cast\n      xmlFree((char *) xmlDoc_->version);\n      xmlDoc_->version = NULL;\n    }\n\n    if (version != nil) {\n      xmlDoc_->version = xmlStrdup(GDataGetXMLString(version));\n    }\n  }\n}\n\n- (void)setCharacterEncoding:(NSString *)encoding {\n\n  if (xmlDoc_ != NULL) {\n    if (xmlDoc_->encoding != NULL) {\n      // version is a const char* so we must cast\n      xmlFree((char *) xmlDoc_->encoding);\n      xmlDoc_->encoding = NULL;\n    }\n\n    if (encoding != nil) {\n      xmlDoc_->encoding = xmlStrdup(GDataGetXMLString(encoding));\n    }\n  }\n}\n\n- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error {\n  return [self nodesForXPath:xpath namespaces:nil error:error];\n}\n\n- (NSArray *)nodesForXPath:(NSString *)xpath\n                namespaces:(NSDictionary *)namespaces\n                     error:(NSError **)error {\n  if (xmlDoc_ != NULL) {\n    GDataXMLNode *docNode = [GDataXMLElement nodeBorrowingXMLNode:(xmlNodePtr)xmlDoc_];\n    NSArray *array = [docNode nodesForXPath:xpath\n                                 namespaces:namespaces\n                                      error:error];\n    return array;\n  }\n  return nil;\n}\n\n@end\n\n//\n// Dictionary key callbacks for our C-string to NSString cache dictionary\n//\nstatic const void *StringCacheKeyRetainCallBack(CFAllocatorRef allocator, const void *str) {\n  // copy the key\n  xmlChar* key = xmlStrdup(str);\n  return key;\n}\n\nstatic void StringCacheKeyReleaseCallBack(CFAllocatorRef allocator, const void *str) {\n  // free the key\n  char *chars = (char *)str;\n  xmlFree((char *) chars);\n}\n\nstatic CFStringRef StringCacheKeyCopyDescriptionCallBack(const void *str) {\n  // make a CFString from the key\n  CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorDefault,\n                                                (const char *)str,\n                                                kCFStringEncodingUTF8);\n  return cfStr;\n}\n\nstatic Boolean StringCacheKeyEqualCallBack(const void *str1, const void *str2) {\n  // compare the key strings\n  if (str1 == str2) return true;\n\n  int result = xmlStrcmp(str1, str2);\n  return (result == 0);\n}\n\nstatic CFHashCode StringCacheKeyHashCallBack(const void *str) {\n\n  // dhb hash, per http://www.cse.yorku.ca/~oz/hash.html\n  CFHashCode hash = 5381;\n  int c;\n  const char *chars = (const char *)str;\n\n  while ((c = *chars++) != 0) {\n    hash = ((hash << 5) + hash) + c;\n  }\n  return hash;\n}\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Comment/DoubanEntryComment.h",
    "content": "//\n//  DoubanEntryComment.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 3/23/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYCOMMENT_DEFINE_GLOBALS\n\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanCommentsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\n@interface DoubanEntryComment : GDataEntryBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Comment/DoubanEntryComment.m",
    "content": "//\n//  DoubanEntryComment.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 3/23/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYCOMMENT_DEFINE_GLOBALS 1\n\n#import \"DoubanDefines.h\"\n#import \"DoubanEntryComment.h\"\n\n@implementation DoubanEntryComment\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryComment;\n}\n\n\n- (void)addExtensionDeclarations {\n\t[super addExtensionDeclarations];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanCommentsDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Comment/DoubanFeedComment.h",
    "content": "//\n//  DoubanFeedComment.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 3/23/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n#import \"DoubanEntryComment.h\"\n\n@interface DoubanFeedComment : GDataFeedBase\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Comment/DoubanFeedComment.m",
    "content": "//\n//  DoubanFeedComment.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 3/23/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedComment.h\"\n\n@implementation DoubanFeedComment\n\n+ (NSString *)standardFeedKind {\n\treturn @\"coments\"; //kDoubanCommentFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryComment class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanCommentsDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanEntryCity.h",
    "content": "//\n//  DoubanEntryCity.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-27.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYCITY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanCityDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\n@class DoubanUID;\n@interface DoubanEntryCity : GDataEntryBase\n\n@property (nonatomic, copy) NSString  *name;\n@property (nonatomic, copy) NSString  *uid;\n@property (nonatomic, readonly) BOOL  isHabitable;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanEntryCity.m",
    "content": "//\n//  DoubanEntryCity.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-27.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYCITY_DEFINE_GLOBALS 1\n\n#import \"DoubanEntryCity.h\"\n#import \"DoubanDefines.h\"\n#import \"DoubanAttribute.h\"\n#import \"DoubanUID.h\"\n\n#import \"GDataEntryBase+Extension.h\"\n\n\n@implementation DoubanEntryCity\n\n@dynamic name;\n@dynamic uid;\n@dynamic isHabitable;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryCityCategory;\n}\n\n\n- (void)addExtensionDeclarations {\t\n\t[super addExtensionDeclarations];\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:[DoubanAttribute class], \n                                              [DoubanUID class], nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanCityDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (void)setName:(NSString *)theName {\n  DoubanAttribute *attr = [[[DoubanAttribute alloc] init] autorelease];\n  [attr setName:@\"name\"];\n  [attr setContent:theName];\n  [self setObject:attr forExtensionClass:[DoubanAttribute class]];\n}\n\n\n- (NSString *)name {\n\tDoubanAttribute *attr = [self attributeForName:@\"name\"];\n\tif (attr) {\n\t\treturn [attr content];\n\t}\n\treturn 0;\n}\n\n\n- (NSString *)uid {\n  DoubanUID* uid = (DoubanUID *)[self objectForExtensionClass:[DoubanUID class]];\n  if (uid) {\n    return [uid content];\n  }\n  return nil;\n}\n\n\n- (void)setUid:(NSString *)theUid {\n  DoubanUID *uid = [[[DoubanUID alloc] init] autorelease];\n  [uid setContent:theUid];\n  [self setObject:uid forExtensionClass:[DoubanUID class]];\n}\n\n\n- (BOOL)isHabitable {\n\tDoubanAttribute *attr = [self attributeForName:@\"habitable\"];  \n\tif (attr) {\n    NSString * result = [attr content];\n\t\tif ([result isEqualToString:@\"True\"]) {\n      return true;\n    }\n\t}\n\treturn false;\n}\n\n\n- (BOOL)isEqual:(id)object {\n  if (self == object) {\n    return YES;\n  }\n  if ([object isKindOfClass:[self class]]) {\n    if (![[self uid] isEqualToString:[(DoubanEntryCity *)object uid]]) \n      return NO;\n      \n    return YES;\n  }\n  return NO;\n}\n\n\n- (NSUInteger)hash {\n  return [[self uid] hash];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanEntryEvent.h",
    "content": "//\n//  DoubanEntryEvent.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYEVENT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanEventsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\nextern NSString * const kParticipatedStr;\nextern NSString * const kWishedStr;\nextern NSString * const kArrivedStr;\n\n\n@class DoubanEntryEventCategory;\n@class DoubanLocation;\n@class GDataWhere;\n@class GDataWhen;\n@interface DoubanEntryEvent : GDataEntryBase\n\n@property (nonatomic, readonly) NSInteger  eventId;\n@property (nonatomic, readonly) GDataWhere *where;\n@property (nonatomic, readonly) GDataWhen  *when;\n@property (nonatomic, readonly) DoubanLocation *location;\n@property (nonatomic, readonly) DoubanEntryEventCategory *eventCategory;\n@property (nonatomic, readonly) GDataLink   *imageLink;\n@property (nonatomic, readonly) GDataLink   *imageMobileLink;\n@property (nonatomic, readonly) GDataLink   *imageLargeLink;\n@property (nonatomic, readonly) GDataLink   *iconLink;\n@property (nonatomic, readonly) NSInteger   albumId;\n\n@property (nonatomic, readonly) NSInteger   participantsCount;\n@property (nonatomic, readonly) NSInteger   wishersCount;\n@property (nonatomic, retain)   NSDate      *participateDate;\n@property (nonatomic, copy)     NSString    *status;\n\n@property (nonatomic, readonly) float       geoLatitude;\n@property (nonatomic, readonly) float       geoLongitude;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanEntryEvent.m",
    "content": "//\n//  DoubanEntryEvent.m\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYEVENT_DEFINE_GLOBALS 1\n\n#import \"GDataWhen.h\"\n#import \"GDataWhere.h\"\n#import \"DoubanEntryEvent.h\"\n#import \"DoubanEntryEventCategory.h\"\n\n#import \"DoubanDefines.h\"\n#import \"DoubanAttribute.h\"\n#import \"DoubanLocation.h\"\n#import \"GeorssPoint.h\"\n\n#import \"GDataEntryBase+Extension.h\"\n\n\n@implementation DoubanEntryEvent\n\nNSString * const kParticipatedStr = @\"participate\";\nNSString * const kWishedStr = @\"wish\";\nNSString * const kArrivedStr = @\"arrive\";\n\n\nstatic NSString * const kEventAllCategoryTerm = @\"http://www.douban.com/2007#event.all\";\nstatic NSString * const kEventDramaCategoryTerm = @\"http://www.douban.com/2007#event.drama\";\nstatic NSString * const kEventMusicCategoryTerm = @\"http://www.douban.com/2007#event.music\";\nstatic NSString * const kEventExhibitionCategoryTerm = @\"http://www.douban.com/2007#event.exhibition\";\nstatic NSString * const kEventSportsCategoryTerm = @\"http://www.douban.com/2007#event.sports\";\nstatic NSString * const kEventPartyCategoryTerm = @\"http://www.douban.com/2007#event.party\";\nstatic NSString * const kEventCommonwealCategoryTerm = @\"http://www.douban.com/2007#event.commonweal\";\nstatic NSString * const kEventTravelCategoryTerm = @\"http://www.douban.com/2007#event.travel\";\nstatic NSString * const kEventFilmCategoryTerm = @\"http://www.douban.com/2007#event.film\";\nstatic NSString * const kEventSalonCategoryTerm = @\"http://www.douban.com/2007#event.salon\";\nstatic NSString * const kEventOthersCategoryTerm = @\"http://www.douban.com/2007#event.others\";\n\n\nstatic NSString * const kEventAllCategoryName = @\"类型\";\nstatic NSString * const kEventDramaCategoryName = @\"戏剧/曲艺\";\nstatic NSString * const kEventMusicCategoryName = @\"音乐/演出\";\nstatic NSString * const kEventExhibitionCategoryName = @\"展览\";\nstatic NSString * const kEventSportsCategoryName = @\"体育\";\nstatic NSString * const kEventPartyCategoryName = @\"生活/聚会\";\nstatic NSString * const kEventCommonwealCategoryName = @\"公益\";\nstatic NSString * const kEventTravelCategoryName = @\"旅行\";\nstatic NSString * const kEventFilmCategoryName = @\"电影\";\nstatic NSString * const kEventSalonCategoryName = @\"讲座/沙龙\";\nstatic NSString * const kEventOthersCategoryName = @\"其他\";\n\n@dynamic when;\n@dynamic where;\n@dynamic location;\n@dynamic eventCategory;\n@dynamic imageLink;\n@dynamic imageMobileLink;\n@dynamic imageLargeLink;\n@dynamic iconLink;\n@dynamic albumId;\n@dynamic participantsCount;\n@dynamic wishersCount;\n@dynamic participateDate;\n@dynamic status;\n@dynamic geoLatitude;\n@dynamic geoLongitude;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryEvent;\n}\n\n\n- (void)addExtensionDeclarations {\n\t\n\t[super addExtensionDeclarations];\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n\t\t\t\t\t\t\t\t   childClasses:[DoubanAttribute class], \n                                [GDataWhere class], \n                                [GDataWhen class], \n                                [DoubanLocation class], \n                                [GeorssPoint class], nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanEventsDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (NSInteger)eventId {\n  return [[[self identifier] lastPathComponent] integerValue];\n}\n\n- (GDataWhen *)when {\n\treturn [self objectForExtensionClass:[GDataWhen class]];\n}\n\n\n- (GDataWhere *)where {\n\treturn [self objectForExtensionClass:[GDataWhere class]];\n}\n\n\n- (DoubanLocation *)location {\n\treturn [self objectForExtensionClass:[DoubanLocation class]];\n}\n\n\n- (GDataLink *)imageLink {\n\treturn [self linkWithRelAttributeValue:@\"image\"];\n}\n\n\n- (GDataLink *)imageMobileLink {\n\treturn [self linkWithRelAttributeValue:@\"image-lmobile\"];\n}\n\n\n- (GDataLink *)imageLargeLink {\n\treturn [self linkWithRelAttributeValue:@\"image-hlarge\"];\n}\n\n\n\n- (GDataLink *)iconLink {\n\treturn [self linkWithRelAttributeValue:@\"icon\"];\n}\n\n\n- (DoubanEntryEventCategory *)eventCategory {\n  NSArray *categories = [self categories];\n  GDataCategory *category = [categories objectAtIndex:0];\n  NSString *categoryTerm = [category term];\n\n  DoubanEntryEventCategory *eventCategory = [[[DoubanEntryEventCategory alloc] init] autorelease];\n  if  ([categoryTerm isEqualToString:kEventDramaCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventDramaCategoryTitle];\n    [eventCategory setName:kEventDramaCategoryName];\n  }\n  else if ([categoryTerm isEqualToString:kEventMusicCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventMusicCategoryTitle];\n    [eventCategory setName:kEventMusicCategoryName];  \n  }\n  else if ([categoryTerm isEqualToString:kEventExhibitionCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventExhibitionCategoryTitle];\n    [eventCategory setName:kEventExhibitionCategoryName];\n  }\n  else if ([categoryTerm isEqualToString:kEventSportsCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventSportsCategoryTitle];\n    [eventCategory setName:kEventSportsCategoryName];    \n  }\n  else if ([categoryTerm isEqualToString:kEventPartyCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventPartyCategoryTitle];\n    [eventCategory setName:kEventPartyCategoryName];    \n  }\n  else if ([categoryTerm isEqualToString:kEventCommonwealCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventCommonwealCategoryTitle];\n    [eventCategory setName:kEventCommonwealCategoryName];    \n  }\n  else if ([categoryTerm isEqualToString:kEventTravelCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventTravelCategoryTitle];\n    [eventCategory setName:kEventTravelCategoryName];\n  }\n  else if ([categoryTerm isEqualToString:kEventFilmCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventFilmCategoryTitle];\n    [eventCategory setName:kEventFilmCategoryName];    \n  }  \n  else if ([categoryTerm isEqualToString:kEventSalonCategoryTerm]) {\n    [eventCategory setTitleWithString:kEventSalonCategoryTitle];\n    [eventCategory setName:kEventSalonCategoryName];    \n  }  \n  else {\n    [eventCategory setTitleWithString:kEventOthersCategoryTitle];\n    [eventCategory setName:kEventOthersCategoryName];    \n  }\n  \n  return eventCategory;\n}\n\n\n- (NSInteger)albumId {\n\tDoubanAttribute *attr = [self attributeForName:@\"album\"];\n\tif (attr) {\n\t\treturn [[attr content] integerValue];\n\t}\n\treturn 0;\n}\n\n\n- (NSInteger)participantsCount {\n\tDoubanAttribute *attr = [self attributeForName:@\"participants\"];\n\tif (attr) {\n\t\treturn [[attr content] integerValue];\n\t}\n\treturn 0;\n}\n\n\n- (NSInteger)wishersCount {\n\tDoubanAttribute *attr = [self attributeForName:@\"wishers\"];\n\tif (attr) {\n\t\treturn [[attr content] integerValue];\n\t}\n\treturn 0;\n}\n\n\n- (NSDate *)participateDate {\n\tDoubanAttribute *attr = [self attributeForName:@\"participate_date\"];\n\tif (attr) {\n\t\tNSString *dateStr = [attr content];\n    \n    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];\n    [dateFormatter setDateFormat:@\"yyyy-MM-dd\"];\n\n    NSDate *date = [dateFormatter dateFromString:dateStr];\n    \n    NSTimeZone *zone = [NSTimeZone systemTimeZone];\n    NSInteger interval = [zone secondsFromGMTForDate: date];\n    NSDate *localeDate = [date  dateByAddingTimeInterval: interval]; \n    \n    return localeDate;\n\t}\n  return nil;\n}\n\n\n- (void)setParticipateDate:(NSDate *)participateDate {\n\n  NSString *content = nil;\n  if (participateDate) {\n    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];\n    [dateFormatter setDateFormat:@\"yyyy-MM-dd\"];    \n    NSTimeZone *zone = [NSTimeZone localTimeZone];\n    [dateFormatter setTimeZone:zone];\n    \n    content = [dateFormatter stringFromDate:participateDate];\n  }\n\n  DoubanAttribute *attr = [self attributeForName:@\"participate_date\"];\n  if (attr) {\n    [attr setContent:content]; \n  }\n  else {\n    DoubanAttribute *newAttr = [[[DoubanAttribute alloc] init] autorelease];\n    [newAttr setName:@\"participate_date\"];\n    [newAttr setContent:content];\n    \n    NSArray *attrs = [self doubanAttributes];\n    NSMutableArray *array = [NSMutableArray arrayWithArray:attrs];\n    [array addObject:newAttr];\n    [self setObjects:array forExtensionClass:[DoubanAttribute class]];\n  }\n}\n\n\n- (NSString *)status {\n  DoubanAttribute *attr = [self attributeForName:@\"status\"];\n\tif (attr) {\n\t\treturn [attr content];\n\t}\n  return nil;\n}\n\n\n- (void)setStatus:(NSString *)content {\n  DoubanAttribute *attr = [self attributeForName:@\"status\"];\n  if (attr) {\n   [attr setContent:content]; \n  }\n  else {\n    DoubanAttribute *newAttr = [[[DoubanAttribute alloc] init] autorelease];\n    [newAttr setName:@\"status\"];\n    [newAttr setContent:content];\n    \n    NSArray *attrs = [self doubanAttributes];\n    NSMutableArray *array = [NSMutableArray arrayWithArray:attrs];\n    [array addObject:newAttr];\n    [self setObjects:array forExtensionClass:[DoubanAttribute class]];\n  }\n}\n\n\n- (float)geoLatitude {\n  GeorssPoint *georssPoint = [self objectForExtensionClass:[GeorssPoint class]];\n  return [georssPoint geoLatitude];\n}\n\n\n- (float)geoLongitude {\n  GeorssPoint *georssPoint = [self objectForExtensionClass:[GeorssPoint class]];\n  return [georssPoint geoLongitude];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanEntryEventCategory.h",
    "content": "//\n//  DoubanEntryEventCategory.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-26.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANEVENTCATEGORY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanEventCategoriesDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\n@interface DoubanEntryEventCategory : GDataEntryBase\n\nextern NSString * const kEventAllCategoryTitle;\nextern NSString * const kEventDramaCategoryTitle;\nextern NSString * const kEventMusicCategoryTitle;\nextern NSString * const kEventExhibitionCategoryTitle;\nextern NSString * const kEventSportsCategoryTitle;\nextern NSString * const kEventPartyCategoryTitle;\nextern NSString * const kEventCommonwealCategoryTitle;\nextern NSString * const kEventTravelCategoryTitle;\nextern NSString * const kEventFilmCategoryTitle;\nextern NSString * const kEventSalonCategoryTitle;\nextern NSString * const kEventOthersCategoryTitle;\n\n\n@property (nonatomic, readonly) NSInteger eventsCount;\n@property (nonatomic, copy)     NSString  *name;\n@property (nonatomic, readonly) GDataLink *coverLink;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanEntryEventCategory.m",
    "content": "//\n//  DoubanEntryEventCategory.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-26.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#define DOUBANEVENTCATEGORY_DEFINE_GLOBALS 1\n\n#import \"DoubanEntryEventCategory.h\"\n#import \"DoubanDefines.h\"\n#import \"DoubanAttribute.h\"\n\n#import \"GDataEntryBase+Extension.h\"\n\n\n@implementation DoubanEntryEventCategory\n\n\nNSString * const kEventAllCategoryTitle = @\"all\";\nNSString * const kEventDramaCategoryTitle = @\"drama\";\nNSString * const kEventMusicCategoryTitle = @\"music\";\nNSString * const kEventExhibitionCategoryTitle = @\"exhibition\";\nNSString * const kEventSportsCategoryTitle = @\"sports\";\nNSString * const kEventPartyCategoryTitle = @\"party\";\nNSString * const kEventCommonwealCategoryTitle = @\"commonweal\";\nNSString * const kEventTravelCategoryTitle = @\"travel\";\nNSString * const kEventFilmCategoryTitle = @\"film\";\nNSString * const kEventSalonCategoryTitle = @\"salon\";\nNSString * const kEventOthersCategoryTitle = @\"others\";\n\n\n@dynamic eventsCount;\n@dynamic name;\n@dynamic coverLink;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryEventCategory;\n}\n\n\n- (void)addExtensionDeclarations {\n\t\n\t[super addExtensionDeclarations];\t\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:[DoubanAttribute class], nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanEventCategoriesDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (NSInteger)eventsCount {\n\tDoubanAttribute *attr = [self attributeForName:@\"event_count\"];\n\tif (attr) {\n\t\treturn [[attr content] integerValue];\n\t}\n\treturn 0;\n}\n\n\n- (NSString *)name {\n  DoubanAttribute *attr = [self attributeForName:@\"cname\"];\n\tif (attr) {\n\t\treturn [attr content];\n\t}\n  return nil;\n}\n\n\n- (void)setName:(NSString *)content {\n  DoubanAttribute *attr = [[[DoubanAttribute alloc] init] autorelease];\n  [attr setName:@\"cname\"];\n  [attr setContent:content];\n  [self setObject:attr forExtensionClass:[DoubanAttribute class]];\n}\n\n\n- (GDataLink *)coverLink {\n\treturn [self linkWithRelAttributeValue:@\"event\"];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanFeedCity.h",
    "content": "//\n//  DoubanFeedCity.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-27.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedCity : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanFeedCity.m",
    "content": "//\n//  DoubanFeedCity.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-27.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedCity.h\"\n#import \"DoubanEntryCity.h\"\n\n\n@implementation DoubanFeedCity\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"cities\"; //kGDataCategoryCitiesFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryCity class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanCityDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanFeedEvent.h",
    "content": "//\n//  DoubanFeedEvent.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedEvent : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanFeedEvent.m",
    "content": "//\n//  DoubanFeedEvent.m\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedEvent.h\"\n#import \"DoubanEntryEvent.h\"\n\n\n@implementation DoubanFeedEvent\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"events\"; //kGDataCategoryEventsFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryEvent class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanEventsDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanFeedEventCategory.h",
    "content": "//\n//  DoubanFeedEventCategory.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-26.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedEventCategory : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Event/DoubanFeedEventCategory.m",
    "content": "//\n//  DoubanFeedEventCategory.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-26.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedEventCategory.h\"\n#import \"DoubanEntryEventCategory.h\"\n\n\n@implementation DoubanFeedEventCategory\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"categories\"; //kGDataCategoryEventCategoriesFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryEventCategory class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanEventCategoriesDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/GDataAtomAuthor+Extension.h",
    "content": "//\n//  GDataAtomAuthor+Extension.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataBaseElements.h\"\n\n\n@class GDataLink;\n@interface GDataAtomAuthor (Extension)\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/GDataAtomAuthor+Extension.m",
    "content": "//\n//  GDataAtomAuthor+Extension.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataAtomAuthor+Extension.h\"\n#import \"GDataLink.h\"\n\n\n@implementation GDataAtomAuthor (Extension)\n\n\n- (NSArray *)links {\n  NSArray *links = [self objectsForExtensionClass:[GDataLink class]];\n  return links;\n}\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel {\n  \n  return [GDataLink linkWithRel:rel\n                           type:nil\n                      fromLinks:[self links]];\n}\n\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/GDataEntryBase+Extension.h",
    "content": "//\n// GDataEntryBase+Extension.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/16/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataEntryBase.h\"\n\n@class DoubanAttribute;\n@class GDataAtomAuthor;\n@interface GDataEntryBase (Extension)\n\n- (NSArray *)doubanAttributes;\n\n- (DoubanAttribute *)attributeForName:(NSString *)attributeName;\n\n- (GDataAtomAuthor *)theFirstAuthor;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/GDataEntryBase+Extension.m",
    "content": "//\n//  GDataEntryBase+Extension.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/16/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase+Extension.h\"\n#import \"DoubanDefines.h\"\n#import \"DoubanAttribute.h\"\n#import \"GDataBaseElements.h\"\n\n\n@implementation GDataEntryBase (Extension)\n\n\n- (NSArray *)doubanAttributes {\n\treturn [self objectsForExtensionClass:[DoubanAttribute class]];\n}\n\n\n- (DoubanAttribute *)attributeForName:(NSString *)attributeName {\n\tDoubanAttribute *attr = nil;\n\tfor(id _attr in [self doubanAttributes]) {\n\t\tif([[_attr name] isEqualToString:attributeName]){\n\t\t\tattr = _attr;\n\t\t\tbreak;\n\t\t}\n\t}\n  return attr;\n}\n\n\n- (GDataAtomAuthor *)theFirstAuthor {\n  NSArray *authors = [self authors];\n  if (authors) {\n    GDataAtomAuthor *author = (GDataAtomAuthor *)[authors objectAtIndex:0];\n    return author;\n  }\n  return nil;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Miniblog/DoubanEntryMiniblog.h",
    "content": "//\n//  DoubanEntryMiniblog.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-9.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYMINIBLOG_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanMiniblogsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\ntypedef enum {\n  MINIBLOG_SAYING_CATEGORY,\n  MINIBLOG_BOOK_CATEGORY,\n  MINIBLOG_MAGAZINE_CATEGORY,\n  MINIBLOG_MOVIE_CATEGORY,\n  MINIBLOG_TV_CATEGORY,\n  MINIBLOG_MUSIC_CATEGORY,\n  \n  MINIBLOG_PLACE_CATEGORY,  \n  MINIBLOG_GROUP_CATEGORY,\n  MINIBLOG_EVENT_CATEGORY,\n  \n  MINIBLOG_SITE_CATEGORY,\n  MINIBLOG_RECOMMENDATION_CATEGORY,  \n  \n  MINIBLOG_NOTE_CATEGORY,  \n  MINIBLOG_BLOG_CATEGORY,  \n  MINIBLOG_PHOTO_CATEGORY,\n  MINIBLOG_CONTACT_CATEGORY,\n  \n  MINIBLOG_PLAZA_CATEGORY,\n  MINIBLOG_SIGNATURE_CATEGORY,\n\n} MiniblogCategory;\n\n@interface DoubanEntryMiniblog : GDataEntryBase\n\n@property (nonatomic, readonly) MiniblogCategory miniblogCategory;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Miniblog/DoubanEntryMiniblog.m",
    "content": "//\n//  DoubanEntryMiniblog.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-9.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYMINIBLOG_DEFINE_GLOBALS 1\n\n#import \"DoubanEntryMiniblog.h\"\n#import \"DoubanDefines.h\"\n\n\n@implementation DoubanEntryMiniblog\n\nstatic NSString * const kMiniblogSayingCategoryTerm = @\"http://www.douban.com/2007#miniblog.saying\";\n\nstatic NSString * const kMiniblogBookCategoryTerm = @\"http://www.douban.com/2007#miniblog.book\";\nstatic NSString * const kMiniblogMagazineCategoryTerm = @\"http://www.douban.com/2007#miniblog.magazine\";\nstatic NSString * const kMiniblogMovieCategoryTerm = @\"http://www.douban.com/2007#miniblog.movie\";\nstatic NSString * const kMiniblogTvCategoryTerm = @\"http://www.douban.com/2007#miniblog.tv\";\nstatic NSString * const kMiniblogMusicCategoryTerm = @\"http://www.douban.com/2007#miniblog.music\";\n\nstatic NSString * const kMiniblogPlaceCategoryTerm = @\"http://www.douban.com/2007#miniblog.place\";\nstatic NSString * const kMiniblogGroupCategoryTerm = @\"http://www.douban.com/2007#miniblog.group\";\nstatic NSString * const kMiniblogEventCategoryTerm = @\"http://www.douban.com/2007#miniblog.event\";\n\nstatic NSString * const kMiniblogSiteCategoryTerm = @\"http://www.douban.com/2007#miniblog.site\";\nstatic NSString * const kMiniblogRecommendationCategoryTerm = @\"http://www.douban.com/2007#miniblog.recommendation\";\nstatic NSString * const kMiniblogNoteCategoryTerm = @\"http://www.douban.com/2007#miniblog.note\";\nstatic NSString * const kMiniblogBlogCategoryTerm = @\"http://www.douban.com/2007#miniblog.blog\";\nstatic NSString * const kMiniblogPhotoCategoryTerm = @\"http://www.douban.com/2007#miniblog.photo\";\nstatic NSString * const kMiniblogContactCategoryTerm = @\"http://www.douban.com/2007#miniblog.contact\";\nstatic NSString * const kMiniblogPlazaCategoryTerm = @\"http://www.douban.com/2007#miniblog.plaza\";\nstatic NSString * const kMiniblogSignatureCategoryTerm = @\"http://www.douban.com/2007#miniblog.signature\";\n\n\n@dynamic miniblogCategory;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryMiniblog;\n}\n\n\n- (void)addExtensionDeclarations {\n\t[super addExtensionDeclarations];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanMiniblogsDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (MiniblogCategory)miniblogCategory {\n  NSArray *categories = [self categories];\n  GDataCategory *category = [categories objectAtIndex:0];\n  NSString *categoryTerm = [category term];\n  \n if ([categoryTerm isEqualToString:kMiniblogBookCategoryTerm]) {\n    return MINIBLOG_BOOK_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogMagazineCategoryTerm]) {\n    return MINIBLOG_MAGAZINE_CATEGORY;\n  }  \n  else if ([categoryTerm isEqualToString:kMiniblogMovieCategoryTerm]) {\n    return MINIBLOG_MOVIE_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogTvCategoryTerm]) {\n    return MINIBLOG_TV_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogMusicCategoryTerm]) {\n    return MINIBLOG_MUSIC_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogPlaceCategoryTerm]) {\n    return MINIBLOG_PLACE_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogGroupCategoryTerm]) {\n    return MINIBLOG_GROUP_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogEventCategoryTerm]) {\n    return MINIBLOG_EVENT_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogSiteCategoryTerm]) {\n    return MINIBLOG_SITE_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogRecommendationCategoryTerm]) {\n    return MINIBLOG_RECOMMENDATION_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogNoteCategoryTerm]) {\n    return MINIBLOG_NOTE_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogBlogCategoryTerm]) {\n    return MINIBLOG_BLOG_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogContactCategoryTerm]) {\n    return MINIBLOG_CONTACT_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogPlazaCategoryTerm]) {\n    return MINIBLOG_PLAZA_CATEGORY;\n  }\n  else if ([categoryTerm isEqualToString:kMiniblogSignatureCategoryTerm]) {\n    return MINIBLOG_SIGNATURE_CATEGORY;\n  }  \n  else {\n    return MINIBLOG_SAYING_CATEGORY;\n  }\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Miniblog/DoubanFeedMiniblog.h",
    "content": "//\n//  DoubanFeedMiniblog.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-9.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedMiniblog : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Miniblog/DoubanFeedMiniblog.m",
    "content": "//\n//  DoubanFeedMiniblog.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-9.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedMiniblog.h\"\n#import \"DoubanEntryMiniblog.h\"\n\n\n@implementation DoubanFeedMiniblog\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"miniblogs\"; //kGDataCategoryMiniblogsFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryMiniblog class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanMiniblogsDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/People/DoubanEntryPeople.h",
    "content": "//\n//  DoubanEntryEvent.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYPEOPLE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanPeoplesDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class DoubanLocation;\n@class DoubanUID;\n@class DoubanSignature;\n@interface DoubanEntryPeople : GDataEntryBase\n\n@property (nonatomic, readonly) DoubanLocation  *location;\n@property (nonatomic, readonly) DoubanUID       *uid;\n@property (nonatomic, readonly) DoubanSignature *signature;\n@property (nonatomic, readonly) GDataLink       *iconLink;\n@property (nonatomic, readonly) GDataLink       *homePage;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/People/DoubanEntryPeople.m",
    "content": "//\n//  DoubanEntryPeople.m\n//  douban-objective-c\n//\n//  Created by py on 3/23/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYPEOPLE_DEFINE_GLOBALS 1\n\n#import \"DoubanEntryPeople.h\"\n\n#import \"DoubanDefines.h\"\n#import \"DoubanAttribute.h\"\n\n#import \"DoubanLocation.h\"\n#import \"DoubanUID.h\"\n#import \"DoubanSignature.h\"\n\n@implementation DoubanEntryPeople\n\n@dynamic location;\n@dynamic uid;\n@dynamic signature;\n@dynamic iconLink;\n@dynamic homePage;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryPeople;\n}\n\n\n- (void)addExtensionDeclarations {\t\n\t[super addExtensionDeclarations];\t\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:[DoubanUID class], \n                                              [DoubanSignature class], \n                                              [DoubanLocation class], nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanPeoplesDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (DoubanLocation *)location {\n\treturn [self objectForExtensionClass:[DoubanLocation class]];\n}\n\n\n- (DoubanUID *)uid {\n\treturn [self objectForExtensionClass:[DoubanUID class]];\n}\n\n\n- (DoubanSignature *)signature {\n\treturn [self objectForExtensionClass:[DoubanSignature class]];\n}\n\n\n- (GDataLink *)iconLink {\n\treturn [self linkWithRelAttributeValue:@\"icon\"];\n}\n\n\n- (GDataLink *)homePage {\n\treturn [self linkWithRelAttributeValue:@\"homepage\"];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/People/DoubanFeedPeople.h",
    "content": "//\n//  DoubanFeedPeople.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-15.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedPeople : GDataFeedBase\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/People/DoubanFeedPeople.m",
    "content": "//\n//  DoubanFeedPeople.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-15.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedPeople.h\"\n#import \"DoubanEntryPeople.h\"\n\n@implementation DoubanFeedPeople\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"peoples\"; //kGDataCategoryPeoplesFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryPeople class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanPeoplesDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanEntryAlbum.h",
    "content": "//\n//  DoubanEntryAlbum.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/31/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYALBUM_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanAlbumsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataAtomAuthor;\n@interface DoubanEntryAlbum : GDataEntryBase\n\n@property (nonatomic, readonly) GDataAtomAuthor *author;\n@property (nonatomic, readonly) GDataLink       *imageLink;\n@property (nonatomic, readonly) GDataLink       *thumbLink;\n@property (nonatomic, readonly) GDataLink       *albumCoverLink;\n\n@property (nonatomic, readonly) NSInteger       size;\n@property (nonatomic, readonly) NSString        *privacy;\n@property (nonatomic, readonly) NSInteger       recsCount;\n@property (nonatomic, readonly) NSInteger       likedCount;\n@property (nonatomic, readonly) NSInteger       albumId;\n@property (nonatomic, readonly) NSInteger       authorId;\n@property (nonatomic, readonly) BOOL            liked;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanEntryAlbum.m",
    "content": "//\n//  DoubanEntryAlbum.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/31/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYALBUM_DEFINE_GLOBALS 1\n\n#import \"DoubanEntryAlbum.h\"\n#import \"DoubanAttribute.h\"\n#import \"DoubanDefines.h\"\n\n#import \"GDataBaseElements.h\"\n#import \"GDataEntryBase+Extension.h\"\n\n\n@implementation DoubanEntryAlbum\n\n@dynamic author;\n@dynamic imageLink;\n@dynamic thumbLink;\n@dynamic albumCoverLink;\n\n@dynamic size;\n@dynamic privacy;\n@dynamic recsCount;\n@dynamic likedCount;\n@dynamic albumId;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryAlbum;\n}\n\n\n- (void)addExtensionDeclarations {\n\t[super addExtensionDeclarations];\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:[DoubanAttribute class], nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanAlbumsDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (GDataAtomAuthor *)author {\n  return [self theFirstAuthor];\n}\n\n- (GDataLink *)imageLink {\n\treturn [self linkWithRelAttributeValue:@\"image\"];\n}\n\n\n- (GDataLink *)thumbLink {\n\treturn [self linkWithRelAttributeValue:@\"cover_thumb\"];\n}\n\n\n- (GDataLink *)albumCoverLink {\n\treturn [self linkWithRelAttributeValue:@\"cover\"];\n}\n\n\n- (NSInteger)size {\n  DoubanAttribute *attr = [self attributeForName:@\"size\"];\n\tif(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSString *)privacy {\n  DoubanAttribute *attr = [self attributeForName:@\"privacy\"];\n\tif(attr){\n    return [attr content];\n  }\n\treturn 0;\n}\n\n\n- (NSInteger)recsCount {\n  DoubanAttribute *attr = [self attributeForName:@\"recs_count\"];\n\tif(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSInteger)likedCount {\n  DoubanAttribute *attr = [self attributeForName:@\"liked_count\"];\n\tif(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n- (BOOL)liked{\n  DoubanAttribute *attr = [self attributeForName:@\"liked\"];\n\tif(attr){\n    return [[attr content] boolValue];\n  }\n\treturn NO;\n}\n\n\n- (NSInteger)albumId {\n  return [[[self identifier] lastPathComponent] integerValue];\n}\n\n\n- (NSInteger)authorId {\n  return [[self.author.URI lastPathComponent] integerValue];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanEntryPhoto.h",
    "content": "//\n//  DoubanEntryPhoto.h\n//  douban-objective-c\n//\n//  Created by py on 4/6/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYPHOTO_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanPhotosDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataAtomAuthor;\n@interface DoubanEntryPhoto : GDataEntryBase {\n\n}\n\n@property (nonatomic, readonly) GDataAtomAuthor *author;\n@property (nonatomic, readonly) GDataLink       *imageLink;\n@property (nonatomic, readonly) GDataLink       *thumbLink;\n@property (nonatomic, readonly) GDataLink       *albumCoverLink;\n@property (nonatomic, readonly) GDataLink       *iconLink;\n\n@property (nonatomic, readonly) NSInteger       commentsCount;\n@property (nonatomic, readonly) NSInteger       recsCount;\n@property (nonatomic, readonly) NSInteger       likedCount;\n@property (nonatomic, readonly) NSInteger       position;\n@property (nonatomic, readonly) NSInteger       photoId;\n@property (nonatomic, readonly) NSInteger       nextPhotoId;\n@property (nonatomic, readonly) NSInteger       prevPhotoId;\n@property (nonatomic, readonly) NSInteger       albumId;\n@property (nonatomic, readonly) NSString        *albumTitle;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanEntryPhoto.m",
    "content": "//\n//  DoubanEntryPhoto.m\n//  douban-objective-c\n//\n//  Created by py on 4/6/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYPHOTO_DEFINE_GLOBALS 1\n\n#import \"DoubanEntryPhoto.h\"\n#import \"DoubanAttribute.h\"\n#import \"DoubanDefines.h\"\n\n#import \"GDataBaseElements.h\"\n#import \"GDataEntryBase+Extension.h\"\n\n\n@implementation DoubanEntryPhoto\n\n@dynamic author;\n@dynamic imageLink;\n@dynamic thumbLink;\n@dynamic iconLink;\n@dynamic albumCoverLink;\n\n@dynamic commentsCount;\n@dynamic recsCount;\n@dynamic position;\n@dynamic nextPhotoId;\n@dynamic prevPhotoId;\n@dynamic albumId;\n@dynamic albumTitle;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryPhoto;\n}\n\n\n- (void)addExtensionDeclarations {\n\t[super addExtensionDeclarations];\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:[DoubanAttribute class], nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanPhotosDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (GDataAtomAuthor *)author {\n  return [self theFirstAuthor];\n}\n\n- (GDataLink *)imageLink {\n\treturn [self linkWithRelAttributeValue:@\"image\"];\n}\n\n\n- (GDataLink *)thumbLink {\n\treturn [self linkWithRelAttributeValue:@\"thumb\"];\n}\n\n\n- (GDataLink *)iconLink {\n\treturn [self linkWithRelAttributeValue:@\"icon\"];\n}\n\n\n- (GDataLink *)albumCoverLink {\n\treturn [self linkWithRelAttributeValue:@\"cover\"];\n}\n\n\n- (NSInteger)commentsCount {\n  DoubanAttribute *attr = [self attributeForName:@\"comments_count\"];\n\tif(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSInteger)recsCount {\n  DoubanAttribute *attr = [self attributeForName:@\"recs_count\"];\n\tif(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n- (NSInteger)likedCount {\n  DoubanAttribute *attr = [self attributeForName:@\"liked_count\"];\n\tif(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSInteger)position {\n  DoubanAttribute *attr = [self attributeForName:@\"position\"];\n  if(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSInteger)photoId {\n  return [[[self identifier] lastPathComponent] integerValue];\n}\n\n\n- (NSInteger)nextPhotoId {\n  DoubanAttribute *attr = [self attributeForName:@\"next_photo\"];\n\tif(attr){\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSInteger)prevPhotoId {\n  DoubanAttribute *attr = [self attributeForName:@\"prev_photo\"];\n\tif(attr) {\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSInteger)albumId {\t\n  DoubanAttribute *attr = [self attributeForName:@\"album\"];\n if(attr) {\n    return [[attr content] integerValue];\n  }\n\treturn 0;\n}\n\n\n- (NSString *)albumTitle {\n  DoubanAttribute *attr = [self attributeForName:@\"album_title\"];\n  if(attr) {\n    return [attr content];\t\t\n  }\n\treturn nil;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanFeedAlbum.h",
    "content": "//\n//  DoubanFeedAlbum.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/31/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedAlbum : GDataFeedBase\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanFeedAlbum.m",
    "content": "//\n//  DoubanFeedAlbum.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/31/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedAlbum.h\"\n#import \"DoubanEntryAlbum.h\"\n\n\n@implementation DoubanFeedAlbum\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"albums\"; //kGDataCategoryAlbumsFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryAlbum class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanAlbumsDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanFeedPhoto.h",
    "content": "//\n//  DoubanFeedPhoto.h\n//  douban-objective-c\n//\n//  Created by py on 4/6/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedPhoto : GDataFeedBase\n\n\n@end"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Photo/DoubanFeedPhoto.m",
    "content": "//\n//  DoubanFeedPhoto.m\n//  douban-objective-c\n//\n//  Created by py on 4/6/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedPhoto.h\"\n#import \"DoubanEntryPhoto.h\"\n\n\n@implementation DoubanFeedPhoto\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"photos\"; //kGDataCategoryPhotosFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryPhoto class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanPhotosDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Recommendation/DoubanEntryRecommendation.h",
    "content": "//\n//  DoubanEntryRecommendation.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYRECOMMENDATION_DEFINE_GLOBALS\n\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanRecommendationsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@interface DoubanEntryRecommendation : GDataEntryBase\n\n@property (nonatomic, readonly) NSString *category;\n@property (nonatomic, readonly) NSString *comment;\n@property (nonatomic, readonly) NSInteger commentsCount;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Recommendation/DoubanEntryRecommendation.m",
    "content": "//\n//  DoubanEntryRecommendation.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#define DOUBANENTRYRECOMMENDATION_DEFINE_GLOBALS 1\n\n#import \"DoubanEntryRecommendation.h\"\n#import \"DoubanDefines.h\"\n#import \"DoubanAttribute.h\"\n#import \"GDataEntryBase+Extension.h\"\n\n\n@implementation DoubanEntryRecommendation\n\n@dynamic category;\n@dynamic comment;\n@dynamic commentsCount;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryRecommendation;\n}\n\n\n- (void)addExtensionDeclarations {\n\t[super addExtensionDeclarations];\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:[DoubanAttribute class], nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanRecommendationsDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (NSString *)category {\n\tDoubanAttribute *attr = [self attributeForName:@\"category\"];\n\tif (attr) {\n\t\treturn [attr content];\n\t}\n\treturn nil;\n}\n\n\n- (NSString *)comment {\n\tDoubanAttribute *attr = [self attributeForName:@\"comment\"];\n\tif (attr) {\n\t\treturn [attr content];\n\t}\n\treturn nil;\n}\n\n\n- (NSInteger)commentsCount {\n\tDoubanAttribute *attr = [self attributeForName:@\"comments_count\"];\n\tif (attr) {\n\t\treturn [[attr content] integerValue];\n\t}\n\treturn 0;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Recommendation/DoubanFeedRecommendation.h",
    "content": "//\n//  DoubanFeedRecommendation.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedRecommendation : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Recommendation/DoubanFeedRecommendation.m",
    "content": "//\n//  DoubanFeedRecommendation.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedRecommendation.h\"\n#import \"DoubanEntryRecommendation.h\"\n\n@implementation DoubanFeedRecommendation\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"recommendations\"; //kGDataCategoryRecommendationsFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryRecommendation class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanRecommendationsDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Review/DoubanEntryReview.h",
    "content": "//\n//  DoubanEntryReview.h\n//  douban-objective-c\n//\n//  Created by py on 3/26/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYREVIEW_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanReviewsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataRating;\n@interface DoubanEntryReview : GDataEntryBase\n\n@property (nonatomic, retain) GDataRating *rating;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Review/DoubanEntryReview.m",
    "content": "//\n//  DoubanEntryReview.m\n//  douban-objective-c\n//\n//  Created by py on 3/26/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n\n#define DOUBANENTRYREVIEW_DEFINE_GLOBALS 1\n\n#import \"GDataRating.h\"\n#import \"DoubanDefines.h\"\n#import \"DoubanEntryReview.h\"\n\n#import \"DoubanAttribute.h\"\n\n@implementation DoubanEntryReview\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategoryReview;\n}\n\n\n- (void)addExtensionDeclarations {\n\t[super addExtensionDeclarations];\t\n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n\t\t\t\t\t\t\t\t   childClasses:[GDataRating class],\n\t\t\t\t\t\t\t\t\t\t\t\t[DoubanAttribute class],nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanReviewsDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (GDataRating *)rating {\n\treturn [self objectForExtensionClass:[GDataRating class]];\n}\n\n\n- (void)setRating:(GDataRating *)obj {\n\t[self setObject:obj forExtensionClass:[GDataRating class]];\n}\n\n\n@end"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Review/DoubanFeedReview.h",
    "content": "//\n//  DoubanFeedReview.h\n//  douban-objective-c\n//\n//  Created by py on 3/26/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedReview : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Review/DoubanFeedReview.m",
    "content": "//\n//  DoubanFeedReview.m\n//  douban-objective-c\n//\n//  Created by py on 3/26/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedReview.h\"\n#import \"DoubanEntryReview.h\"\n\n\n@implementation DoubanFeedReview\n\n\n+ (NSString *)standardFeedKind {\n\treturn @\"reviews\"; //kGDataCategoryReviesFeed;\n}\n\n\n- (Class)classForEntries {\n\treturn [DoubanEntryReview class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanReviewsDefaultServiceVersion;\n}\n\n\n@end"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Subject/DoubanEntrySubject.h",
    "content": "//\n//  DoubanEntrySubject.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-4.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n\n#import \"GDataEntryBase.h\"\n\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYSUBJECT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanSubjectsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataRating;\n@class GDataLink;\n@class DoubanTag;\n@interface DoubanEntrySubject : GDataEntryBase\n\n@property (nonatomic, retain) GDataRating  *rating;\n@property (nonatomic, retain) NSArray      *tags;\n\n@property (nonatomic, readonly) GDataLink  *imageLink;\n@property (nonatomic, readonly) NSString   *publisher; \n@property (nonatomic, readonly) NSString   *publishDate;\n@property (nonatomic, readonly) NSString   *isbn;\n@property (nonatomic, readonly) NSString   *price;\n@property (nonatomic, readonly) NSArray    *translators;\n\n- (void)addTag:(DoubanTag *)obj;\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Subject/DoubanEntrySubject.m",
    "content": "//\n//  DoubanEntrySubject.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-4.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n\n#define DOUBANENTRYSUBJECT_DEFINE_GLOBALS 1\n\n#import \"DoubanEntrySubject.h\"\n#import \"DoubanDefines.h\"\n\n#import \"GDataEntryBase+Extension.h\"\n#import \"GDataRating.h\"\n#import \"DoubanAttribute.h\"\n#import \"DoubanTag.h\"\n\n@implementation DoubanEntrySubject\n\n@dynamic rating;\n@dynamic tags;\n@dynamic imageLink;\n@dynamic publisher;\n@dynamic publishDate;\n@dynamic isbn;\n@dynamic price;\n@dynamic translators;\n\n\n+ (NSString *)standardEntryKind {\n\treturn kDoubanCategorySubject;\n}\n\n\n- (void)addExtensionDeclarations {\n\t[super addExtensionDeclarations];  \n\tClass entryClass = [self class];\n\t[self addExtensionDeclarationForParentClass:entryClass\n                                 childClasses:[GDataRating class],[DoubanAttribute class],\n                                              [DoubanTag class],nil];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n\treturn kDoubanSubjectsDefaultServiceVersion;\n}\n\n\n#pragma mark - Extensions\n\n- (GDataRating *)rating {\n\treturn [self objectForExtensionClass:[GDataRating class]];\n}\n\n\n- (void)setRating:(GDataRating *)obj {\n\t[self setObject:obj forExtensionClass:[GDataRating class]];\n}\n\n\n- (NSArray *)tags {\n\treturn [self objectsForExtensionClass:[DoubanTag class]];\n}\n\n\n- (void)setTags:(NSArray *)tag {\n\t[self setObjects:tag forExtensionClass:[DoubanTag class]];\n}\n\n\n- (void)addTag:(DoubanTag *)obj {\n\t[self addObject:obj forExtensionClass:[DoubanTag class]];\n}\n\n\n- (GDataLink *)imageLink {\n  return [self linkWithRelAttributeValue:@\"image\"];\n}\n\n\n- (NSString*)publisher {\n  DoubanAttribute *attr = [self attributeForName:@\"publisher\"];\n  if (attr) {\n    return [attr content];\n  }\n  return nil;\n}\n\n\n- (NSString *)publishDate {\n  DoubanAttribute *attr = [self attributeForName:@\"pubdate\"];\n  if (attr) {\n    return [attr content];\n  }\n  return nil;\n}\n\n\n- (NSString *)isbn {\n  DoubanAttribute *attr = [self attributeForName:@\"isbn10\"];\n\tif (attr) {\n    return [attr content];\n  }\n  return nil;\n}\n\n\n- (NSString *)price {  \n  DoubanAttribute *attr = [self attributeForName:@\"price\"];\n\tif (attr) {\n\t\treturn [attr content];\n\t}\n  return nil;\n}\n\n\n- (NSArray *)translators {\n\tNSMutableArray * _translators = [[[NSMutableArray alloc] init ] autorelease];\n\tfor (id attr in [self attributes]) {\n\t\tif ([[attr name] isEqualToString:@\"translators\"]) {\n\t\t\t[_translators addObject:[attr content]];\n\t\t}\n\t}\n\treturn _translators;\n}\n\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Subject/DoubanFeedSubject.h",
    "content": "//\n//  DoubanFeedSubject.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-7.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedSubject : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Clients/Subject/DoubanFeedSubject.m",
    "content": "//\n//  DoubanFeedSubject.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-7.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanFeedSubject.h\"\n#import \"DoubanEntrySubject.h\"\n\n@implementation DoubanFeedSubject\n\n\n+ (NSString *)standardFeedKind {\n  return @\"subjects\"; //kGDataCategorySubjectsVolume;\n}\n\n\n- (Class)classForEntries {\n  return [DoubanEntrySubject class];\n}\n\n\n+ (NSString *)defaultServiceVersion {\n  return kDoubanSubjectsDefaultServiceVersion;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/DoubanDefines.h",
    "content": "//\n//  DoubanDefines.h\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Apple Inc. All rights reserved.\n//\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBAN_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanCategorySubject  _INITIALIZE_AS(@\"http://www.douban.com/2007#subject\");\n_EXTERN NSString* const kDoubanCategoryMiniblog  _INITIALIZE_AS(@\"http://www.douban.com/2007#miniblog\");\n_EXTERN NSString* const kDoubanCategoryRecommendation  _INITIALIZE_AS(@\"http://www.douban.com/2007#recommendation\");\n\n_EXTERN NSString* const kDoubanCategoryComment  _INITIALIZE_AS(@\"http://www.douban.com/2007#comment\");\n\n_EXTERN NSString* const kDoubanCategoryReview  _INITIALIZE_AS(@\"http://www.douban.com/2007#review\");\n_EXTERN NSString* const kDoubanCategoryEvent  _INITIALIZE_AS(@\"http://www.douban.com/2007#event\");\n_EXTERN NSString* const kDoubanCategoryPeople  _INITIALIZE_AS(@\"http://www.douban.com/2007#people\");\n_EXTERN NSString* const kDoubanCategoryPhoto  _INITIALIZE_AS(@\"http://www.douban.com/2007#photo\");\n_EXTERN NSString* const kDoubanCategoryAlbum  _INITIALIZE_AS(@\"http://www.douban.com/2007#album\");\n\n_EXTERN NSString* const kDoubanCategoryEventCategory  _INITIALIZE_AS(@\"http://www.douban.com/2007#category\");\n_EXTERN NSString* const kDoubanCategoryCityCategory _INITIALIZE_AS(@\"http://www.douban.com/2007#city\");\n\n_EXTERN NSString* const kDoubanNamespace _INITIALIZE_AS(@\"http://www.douban.com/xmlns/\");\n_EXTERN NSString* const kDoubanNamespacePrefix _INITIALIZE_AS(@\"db\");\n\n_EXTERN NSString* const kAtomNamespace _INITIALIZE_AS(@\"http://www.w3.org/2005/Atom\");\n_EXTERN NSString* const kAtomNamespacePrefix _INITIALIZE_AS(@\"ns0\");\n\n_EXTERN NSString* const kGeorssNamespace _INITIALIZE_AS(@\"http://www.georss.org/georss\");\n_EXTERN NSString* const kGeorssNamespacePrefix _INITIALIZE_AS(@\"georess\");\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/DoubanDefines.m",
    "content": "//\n//  DoubanDefines.m\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 __MyCompanyName__. All rights reserved.\n//\n\n#define DOUBAN_DEFINE_GLOBALS 1\n\n#import \"DoubanDefines.h\"\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanAttribute.h",
    "content": "//\n//  DoubanAttribute.h\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Apple Inc. All rights reserved.\n//\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanAttribute : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanAttribute.m",
    "content": "//\n//  DoubanAttribute.m\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Apple Inc. All rights reserved.\n//\n\n#import \"DoubanDefines.h\"\n#import \"DoubanAttribute.h\"\n\nstatic NSString* const kNameAttr = @\"name\";\nstatic NSString* const kContentAttr = @\"content\";\n\n@implementation DoubanAttribute\n\n\n+ (NSString *)extensionElementURI       { return kDoubanNamespace; }\n+ (NSString *)extensionElementPrefix    { return kDoubanNamespacePrefix; }\n+ (NSString *)extensionElementLocalName { return @\"attribute\"; }\n\n- (void)addParseDeclarations {\n\tNSArray *attrs = [NSArray arrayWithObjects:\n\t\t\t\t\t  kNameAttr, kContentAttr, nil];\n\n\t[self addLocalAttributeDeclarations:attrs];\n\t[self addContentValueDeclaration];\n}\n\n\n- (NSString *)content {\n\treturn [self contentStringValue];\n}\n\n\n- (void)setContent:(NSString *)str {\n\t[self setContentStringValue:str];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanLocation.h",
    "content": "//\n//  DoubanLocation.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban.inc All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanLocation : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)identity;\n\n- (void)setIdentity:(NSString *)str;\n\n- (NSString *)uid;\n\n- (void)setUid:(NSString *)str;\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanLocation.m",
    "content": "//\n//  DoubanLocation.m\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 __MyCompanyName__. All rights reserved.\n//\n\n#import \"DoubanDefines.h\"\n#import \"DoubanLocation.h\"\n\nstatic NSString* const kIdentityAttr = @\"id\";\nstatic NSString* const kNIdentifyAttr = @\"n_id\";\n\n@implementation DoubanLocation\n\n\n+ (NSString *)extensionElementURI       { return kDoubanNamespace; }\n+ (NSString *)extensionElementPrefix    { return kDoubanNamespacePrefix; }\n+ (NSString *)extensionElementLocalName { return @\"location\"; }\n\n- (void)addParseDeclarations {\n\tNSArray *attrs = [NSArray arrayWithObjects:\n\t\t\t\t\t  kIdentityAttr, kNIdentifyAttr, nil];\n\t\n\t[self addLocalAttributeDeclarations:attrs];\n\t[self addContentValueDeclaration];\n}\n\n\n- (NSString *)identity {\n\treturn [self stringValueForAttribute:kIdentityAttr];\n}\n\n\n- (void)setIdentity:(NSString *)str {\n\t[self setStringValue:str forAttribute:kIdentityAttr];\n}\n\n\n- (NSString *)uid {\n\treturn [self stringValueForAttribute:kIdentityAttr];\n}\n\n\n- (void)setUid:(NSString *)str {\n\t[self setStringValue:str forAttribute:kIdentityAttr];\n}\n\n- (NSString *)content {\n\treturn [self contentStringValue];\n}\n\n\n- (void)setContent:(NSString *)str {\n\t[self setContentStringValue:str];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanSignature.h",
    "content": "//\n//  DoubanSignature.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-15.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanSignature : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n- (void)setContent:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanSignature.m",
    "content": "//\n//  DoubanSignature.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-15.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanDefines.h\"\n#import \"DoubanSignature.h\"\n\nstatic NSString* const kContentAttr = @\"content\";\n\n@implementation DoubanSignature\n\n\n+ (NSString *)extensionElementURI       { return kDoubanNamespace; }\n+ (NSString *)extensionElementPrefix    { return kDoubanNamespacePrefix; }\n+ (NSString *)extensionElementLocalName { return @\"signature\"; }\n\n\n- (void)addParseDeclarations {\n\tNSArray *attrs = [NSArray arrayWithObjects:\n                    kContentAttr, nil];\n  \n\t[self addLocalAttributeDeclarations:attrs];\n\t[self addContentValueDeclaration];\n}\n\n\n- (NSString *)content {\n\treturn [self contentStringValue];\n}\n\n\n- (void)setContent:(NSString *)str {\n\t[self setContentStringValue:str];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanTag.h",
    "content": "//\n//  DoubanTag.h\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanTag : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)name;\n\n- (void)setName:(NSString *)str;\n\n- (NSNumber *)count;\n\n- (void)setCount:(NSNumber *)num;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanTag.m",
    "content": "//\n//  DoubanTag.m\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Apple Inc. All rights reserved.\n//\n\n#import \"DoubanDefines.h\"\n#import \"DoubanTag.h\"\n\nstatic NSString* const kNameAttr = @\"name\";\nstatic NSString* const kCountAttr = @\"count\";\n\n@implementation DoubanTag\n\n\n+ (NSString *)extensionElementURI       { return kDoubanNamespace; }\n+ (NSString *)extensionElementPrefix    { return kDoubanNamespacePrefix; }\n+ (NSString *)extensionElementLocalName { return @\"tag\"; }\n\n- (void)addParseDeclarations {\n\tNSArray *attrs = [NSArray arrayWithObjects:\n\t\t\t\t\t  kCountAttr, kNameAttr, nil];\n\n\t[self addLocalAttributeDeclarations:attrs];\n\t[self addContentValueDeclaration];\n}\n\n\n- (NSString *)name {\n  return [self stringValueForAttribute:kNameAttr];\n}\n\n\n- (void)setName:(NSString *)str {\n  [self setStringValue:str forAttribute:kNameAttr];\n}\n\n\n- (NSNumber *)count {\n  return [self intNumberForAttribute:kCountAttr];\n}\n\n\n- (void)setCount:(NSNumber *)num {\n  [self setStringValue:[num stringValue] forAttribute:kCountAttr];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanUID.h",
    "content": "//\n//  DoubanUID.h\n//  douban-objective-c\n//\n//  Created by py on 3/23/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanUID : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/DoubanUID.m",
    "content": "//\n//  DoubanUID.m\n//  douban-objective-c\n//\n//  Created by py on 3/23/10.\n//  Copyright 2010 __MyCompanyName__. All rights reserved.\n//\n\n\n#import \"DoubanDefines.h\"\n#import \"DoubanUID.h\"\n\nstatic NSString* const kContentAttr = @\"content\";\n\n@implementation DoubanUID\n\n\n+ (NSString *)extensionElementURI       { return kDoubanNamespace; }\n+ (NSString *)extensionElementPrefix    { return kDoubanNamespacePrefix; }\n+ (NSString *)extensionElementLocalName { return @\"uid\"; }\n\n- (void)addParseDeclarations {\n\tNSArray *attrs = [NSArray arrayWithObjects:\n\t\t\t\t\t  kContentAttr, nil];\n\n\t[self addLocalAttributeDeclarations:attrs];\n\t[self addContentValueDeclaration];\n}\n\n\n- (NSString *)content {\n\treturn [self contentStringValue];\n}\n\n\n- (void)setContent:(NSString *)str {\n\t[self setContentStringValue:str];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/GeorssPoint.h",
    "content": "//\n//  GeorssPoint.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface GeorssPoint : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n- (float) geoLatitude;\n\n- (float) geoLongitude;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model/GDataDoubanWrapper/Elements/GeorssPoint.m",
    "content": "//\n//  GeorssPoint.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GeorssPoint.h\"\n#import \"DoubanDefines.h\"\n\nstatic NSString* const kContentAttr = @\"content\";\n\n@implementation GeorssPoint\n\n\n+ (NSString *)extensionElementURI       { return kGeorssNamespace; }\n+ (NSString *)extensionElementPrefix    { return kGeorssNamespacePrefix; }\n+ (NSString *)extensionElementLocalName { return @\"point\"; }\n\n- (void)addParseDeclarations {\n\tNSArray *attrs = [NSArray arrayWithObjects:\n                    kContentAttr, nil];\n  \n\t[self addLocalAttributeDeclarations:attrs];\n\t[self addContentValueDeclaration];\n}\n\n\n- (NSString *)content {\n\treturn [self contentStringValue];\n}\n\n\n- (void)setContent:(NSString *)str {\n\t[self setContentStringValue:str];\n}\n\n\n- (float) geoLatitude {\n  NSString *content = [self content];\n  NSArray *array = [content componentsSeparatedByString:@\" \"];\n  if ([array count] == 2) {\n    return [[array objectAtIndex:0] floatValue];\n  }\n  return 0;\n}\n\n\n- (float) geoLongitude {\n  NSString *content = [self content];\n  NSArray *array = [content componentsSeparatedByString:@\" \"];\n  if ([array count] == 2) {\n    return [[array objectAtIndex:1] floatValue];\n  }\n  return 0;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUAnnotation.h",
    "content": "//\n//  DOUAnnotation.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#import \"DOUObject.h\"\n\n@interface DOUAnnotation : DOUObject\n\n@property (nonatomic, copy) NSString *chapter;\n@property (nonatomic, copy) NSString *book_id;\n@property (nonatomic, copy) NSString *time;\n@property (nonatomic, copy) NSString *abstract;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUAnnotation.m",
    "content": "//\n//  DOUAnnotation.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUAnnotation.h\"\n\n@implementation DOUAnnotation\n\n@dynamic chapter;\n@dynamic book_id;\n@dynamic time;\n@dynamic abstract;\n\n- (NSString *)chapter {\n    return [self.dictionary objectForKey:@\"chapter\"];\n}\n\n\n- (NSString *)book_id {\n    return [self.dictionary objectForKey:@\"book_id\"];\n}\n\n- (NSString *)time {\n    return [self.dictionary objectForKey:@\"time\"];\n}\n\n\n- (NSString *)abstract {\n    return [self.dictionary objectForKey:@\"abstract\"];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUAnnotationArray.h",
    "content": "//\n//  DOUAnnotationArray.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUAnnotationArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUAnnotationArray.m",
    "content": "//\n//  DOUAnnotationArray.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUAnnotationArray.h\"\n\n#import \"DOUAnnotation.h\"\n\n@implementation DOUAnnotationArray\n\n+ (Class)objectClass {\n    return [DOUAnnotation class];\n}\n\n+ (NSString *)objectName {\n    return @\"annotations\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUBook.h",
    "content": "//\n//  DOUBook.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUBook : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *subTitle;\n@property (nonatomic, copy) NSString *rating;\n@property (nonatomic, copy) NSString *numRaters;\n@property (nonatomic, copy) NSString *average;\n@property (nonatomic, copy) NSString *ISBN10;\n@property (nonatomic, copy) NSString *ISBN13;\n\n@property (nonatomic, copy) NSString *publisher;\n@property (nonatomic, copy) NSString *publishDateStr;\n@property (nonatomic, retain) NSDate *publishDate;\n\n@property (nonatomic, copy) NSString *image;\n@property (nonatomic, copy) NSString *largeImage;\n@property (nonatomic, copy) NSString *smallImage;\n@property (nonatomic, copy) NSString *mediumImage;\n\n@property (nonatomic, copy) NSString *authorIntro;\n@property (nonatomic, copy) NSString *summary;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUBook.m",
    "content": "//\n//  DOUBook.m\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUBook.h\"\n#import \"DOUObject+Utils.h\"\n#import \"SBJson.h\"\n\n@implementation DOUBook\n\n@dynamic identifier;\n@dynamic title;\n@dynamic subTitle;\n@dynamic rating;\n@dynamic numRaters;\n@dynamic average;\n@dynamic ISBN10;\n@dynamic ISBN13;\n\n@dynamic publisher;\n@dynamic publishDateStr;\n@dynamic publishDate;\n\n@dynamic image;\n@dynamic largeImage;\n@dynamic smallImage;\n@dynamic mediumImage;\n\n@dynamic authorIntro;\n@dynamic summary;\n\n\n- (NSString *)identifier {\n    return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSString *)subTitle {\n    return [self.dictionary objectForKey:@\"subtitle\"];\n}\n\n- (NSString *)title {\n    return [self.dictionary objectForKey:@\"title\"];\n}\n\n- (NSString *)rating {\n    return [self.dictionary objectForKey:@\"rating\"];\n}\n\n- (NSString *)numRaters {\n    NSMutableDictionary *dic = [self.dictionary objectForKey:@\"rating\"];\n    if (!dic) {\n        return nil;\n    } else {\n        return [dic objectForKey:@\"numRaters\"];\n    }\n}\n\n- (NSString *)average {\n    NSMutableDictionary *dic = [self.dictionary objectForKey:@\"rating\"];\n    if (!dic) {\n        return nil;\n    } else {\n        return [dic objectForKey:@\"average\"];\n    }\n}\n\n- (NSString *)ISBN10 {\n    return [self.dictionary objectForKey:@\"isbn10\"];\n}\n\n- (NSString *)ISBN13 {\n    return [self.dictionary objectForKey:@\"isbn13\"];\n}\n\n- (NSString *)publishDateStr {\n    return [self.dictionary objectForKey:@\"pubdate\"];\n}\n\n- (NSDate *)publishDate {\n  return [[self class] dateOfString:[self publishDateStr] dateFormat:@\"yyyy-MM\"];\n}\n\n\n- (NSString *)image{\n    return [self.dictionary objectForKey:@\"image\"];\n}\n\n- (NSString *)images{\n    return [self.dictionary objectForKey:@\"images\"];\n}\n\n- (NSString *)largeImage {\n    NSMutableDictionary *dic = [self.dictionary objectForKey:@\"images\"];\n    if (!dic) {\n        return nil;\n    } else {\n        return [dic objectForKey:@\"large\"];\n    }\n}\n\n- (NSString *)smallImage {\n    NSMutableDictionary *dic = [self.dictionary objectForKey:@\"images\"];\n    if (!dic) {\n        return nil;\n    } else {\n        return [dic objectForKey:@\"small\"];\n    }\n}\n\n- (NSString *)mediumImage {\n    NSMutableDictionary *dic = [self.dictionary objectForKey:@\"images\"];\n    if (!dic) {\n        return nil;\n    } else {\n        return [dic objectForKey:@\"medium\"];\n    }\n}\n\n\n- (NSString *)authorIntro {\n  return [self.dictionary objectForKey:@\"author_intro\"];\n}\n\n- (NSString *)summary {\n  return [self.dictionary objectForKey:@\"summary\"];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUBookArray.h",
    "content": "//\n//  DOUBookArray.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUBookArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Book/DOUBookArray.m",
    "content": "//\n//  DOUBookArray.m\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUBookArray.h\"\n#import \"DOUBook.h\"\n\n@implementation DOUBookArray\n\n+ (Class)objectClass {\n  return [DOUBook class];\n}\n\n+ (NSString *)objectName {\n  return @\"books\";\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Collection/DOUCollection.h",
    "content": "//\n//  DOUCollection.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#import \"DOUObject.h\"\n\n@interface DOUCollection : DOUObject\n\n@property (nonatomic, copy) NSString *status;\n@property (nonatomic, copy) NSString *book_id;\n@property (nonatomic, copy) NSString *tags;\n@property (nonatomic, copy) NSString *updated;\n@property (nonatomic, copy) NSString *comment;\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *user_id;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Collection/DOUCollection.m",
    "content": "//\n//  DOUCollection.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUCollection.h\"\n\n@implementation DOUCollection\n\n@dynamic status;\n@dynamic book_id;\n@dynamic tags;\n@dynamic updated;\n@dynamic comment;\n@dynamic identifier;\n@dynamic user_id;\n\n- (NSString *)status {\n    return [self.dictionary objectForKey:@\"status\"];\n}\n\n\n- (NSString *)book_id {\n    return [self.dictionary objectForKey:@\"book_id\"];\n}\n\n- (NSString *)tags {\n    return [self.dictionary objectForKey:@\"tags\"];\n}\n\n- (NSString *)updated {\n    return [self.dictionary objectForKey:@\"updated\"];\n}\n\n- (NSString *)comment {\n    return [self.dictionary objectForKey:@\"comment\"];\n}\n\n- (NSString *)identifier {\n    return [self.dictionary objectForKey:@\"identifier\"];\n}\n\n- (NSString *)user_id {\n    return [self.dictionary objectForKey:@\"user_id\"];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Collection/DOUCollectionArray.h",
    "content": "//\n//  DOUCollectionArray.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUCollectionArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Collection/DOUCollectionArray.m",
    "content": "//\n//  DOUCollectionArray.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUCollectionArray.h\"\n\n#import \"DOUCollection.h\"\n\n@implementation DOUCollectionArray\n\n+ (Class)objectClass {\n    return [DOUCollection class];\n}\n\n+ (NSString *)objectName {\n    return @\"collections\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUComment.h",
    "content": "//\n//  DOUComment.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUComment : DOUObject\n\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *content;\n\n@property (nonatomic, copy) NSString *createTimeStr; \n@property (nonatomic, retain) NSDate *createTime;\n\n@property (nonatomic, retain) DOUUser *author;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUComment.m",
    "content": "//\n//  DOUComment.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUComment.h\"\n#import \"DOUUser.h\"\n#import \"DOUObject+Utils.h\"\n\n\n@implementation DOUComment\n\n@dynamic identifier;\n@dynamic content;\n@dynamic createTimeStr;\n@dynamic createTime;\n\n@dynamic author;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n\n- (NSString *)content {\n  return [self.dictionary objectForKey:@\"content\"];\n}\n\n\n- (NSString *)createTimeStr {\n  return [self.dictionary objectForKey:@\"created\"];\n}\n\n- (NSDate *)createTime {\n  return [[self class] dateOfString:self.createTimeStr];\n}\n\n\n- (DOUUser *)author {\n  NSDictionary *dic = [self.dictionary objectForKey:@\"author\"];\n  DOUUser *user = [DOUUser objectWithDictionary:dic];\n  return user;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUCommentArray.h",
    "content": "//\n//  DOUCommentArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUCommentArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUCommentArray.m",
    "content": "//\n//  DOUCommentArray.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUCommentArray.h\"\n#import \"DOUComment.h\"\n\n@implementation DOUCommentArray\n\n+ (Class)objectClass {\n  return [DOUComment class];\n}\n\n+ (NSString *)objectName {\n  return @\"comments\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNote.h",
    "content": "//\n//  DOUNote.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUNote : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *summary;\n@property (nonatomic, retain) NSArray *content;\n@property (nonatomic, copy) NSString *privacy;\n\n@property (nonatomic, assign) BOOL    canReply;\n\n@property (nonatomic, copy) NSString *updateTimeStr;\n@property (nonatomic, retain) NSDate *updateTime;\n@property (nonatomic, copy) NSString *publishTimeStr;\n@property (nonatomic, retain) NSDate *publishTime;\n\n@property (nonatomic, assign) NSInteger recsCount;\n@property (nonatomic, assign) NSInteger likedCount;\n@property (nonatomic, assign) NSInteger commentsCount;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNote.m",
    "content": "//\n//  DOUNote.m\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUNote.h\"\n#import \"DOUObject+Utils.h\"\n\n@implementation DOUNote\n\n@dynamic identifier;\n@dynamic alt;\n@dynamic title;\n@dynamic summary;\n@dynamic content;\n@dynamic privacy;\n\n@dynamic canReply;\n\n@dynamic updateTimeStr;\n@dynamic updateTime;\n@dynamic publishTimeStr;\n@dynamic publishTime;\n\n@dynamic recsCount;\n@dynamic likedCount;\n@dynamic commentsCount;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSString *)alt {\n  return [self.dictionary objectForKey:@\"alt\"];\n}\n\n\n- (NSString *)title {\n  return [self.dictionary objectForKey:@\"title\"];\n}\n\n\n- (NSString *)summary {\n  return [self.dictionary objectForKey:@\"summary\"];\n}\n\n\n- (NSString *)content {\n  return [self.dictionary objectForKey:@\"content\"];\n}\n\n\n- (NSString *)privacy {\n  return [self.dictionary objectForKey:@\"privacy\"];\n}\n\n\n- (BOOL)canReply {\n  return [[self.dictionary objectForKey:@\"can_reply\"] boolValue];\n}\n\n\n- (NSString *)updateTimeStr {\n  return [self.dictionary objectForKey:@\"update_time\"];\n}\n\n- (NSDate *)updateTime {\n  return [[self class] dateOfString:self.updateTimeStr];\n}\n\n\n- (NSString *)publishTimeStr {\n  return [self.dictionary objectForKey:@\"publish_time\"];\n}\n\n- (NSDate *)publishTime {\n  return [[self class] dateOfString:self.publishTimeStr];\n}\n\n\n- (NSInteger)recsCount {\n  return [[self.dictionary objectForKey:@\"recs_count\"] integerValue];\n}\n\n- (NSInteger)likedCount {\n  return [[self.dictionary objectForKey:@\"liked_count\"] integerValue];\n}\n\n- (NSInteger)commentsCount {\n  return [[self.dictionary objectForKey:@\"comments_count\"] integerValue];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNoteArray.h",
    "content": "//\n//  DOUNoteArray.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUNoteArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNoteArray.m",
    "content": "//\n//  DOUNoteArray.m\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUNoteArray.h\"\n#import \"DOUNote.h\"\n\n@implementation DOUNoteArray\n\n+ (Class)objectClass {\n  return [DOUNote class];\n}\n\n+ (NSString *)objectName {\n  return @\"notes\";\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNotification.h",
    "content": "//\n//  DOUNotification.h\n//  DoubanAPIEngine\n//\n//  Created by alex zou on 12-11-6.\n//  Copyright (c) 2012年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUNotification : DOUObject\n\n@property (nonatomic, assign) NSInteger count;\n@property (nonatomic, copy) NSString *containerTitle;\n@property (nonatomic, copy) NSString *containerId;\n@property (nonatomic, copy) NSString *targetId;\n@property (nonatomic, copy) NSString *targetType;\n@property (nonatomic, copy) NSString *targetTitle;\n@property (nonatomic, copy) NSString *targetIcon;\n\n@property (nonatomic, copy) NSString *timeStr;\n@property (nonatomic, copy) NSDate *time;\n\n@property (nonatomic, copy) NSString *type;\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *cate;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNotification.m",
    "content": "//\n//  DOUNotification.m\n//  DoubanAPIEngine\n//\n//  Created by alex zou on 12-11-6.\n//  Copyright (c) 2012年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUNotification.h\"\n#import \"DOUObject+Utils.h\"\n\n\n@implementation DOUNotification\n\n@dynamic count;\n@dynamic containerTitle;\n@dynamic containerId;\n@dynamic targetId;\n@dynamic targetType;\n@dynamic time;\n@dynamic timeStr;\n@dynamic type;\n@dynamic identifier;\n@dynamic cate;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSInteger)count {\n  return [[self.dictionary objectForKey:@\"count\"] integerValue];\n}\n\n\n- (NSString *)containerTitle {\n  return [self.dictionary objectForKey:@\"container_title\"];\n}\n\n- (NSString *)containerId {\n  return [self.dictionary objectForKey:@\"container_id\"];\n}\n\n\n- (NSString *)targetId {\n  return [self.dictionary objectForKey:@\"target_id\"];\n}\n\n- (NSString *)targetType {\n  return [self.dictionary objectForKey:@\"target_type\"];\n}\n\n- (NSString *)targetTitle {\n  return [self.dictionary objectForKey:@\"target_title\"];\n}\n\n- (NSString *)targetIcon {\n  return [self.dictionary objectForKey:@\"target_icon\"];\n}\n\n\n- (NSString *)timeStr {\n  return [self.dictionary objectForKey:@\"time\"];\n}\n\n- (NSDate *)time {\n  return [[self class] dateOfString:self.timeStr];\n}\n\n\n-(NSString *)type {\n  return [self.dictionary objectForKey:@\"type\"];\n}\n\n\n-(NSString *)cate {\n  return [self.dictionary objectForKey:@\"cate\"];\n}\n\n\n- (BOOL)isEqual:(id)object {\n  if (self == object) {\n    return YES;\n  }\n  if ([object isKindOfClass:[self class]]) {\n    if (![[self identifier] isEqualToString:[(DOUNotification *)object identifier]])\n      return NO;\n    \n    return YES;\n  }\n  return NO;\n}\n\n\n- (NSUInteger)hash {\n  return [[self identifier] hash];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNotificationArray.h",
    "content": "//\n//  DouNotificationArray.h\n//  DoubanAPIEngine\n//\n//  Created by alex zou on 12-11-6.\n//  Copyright (c) 2012年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUNotificationArray : DOUObjectArray\n\n- (NSInteger)num;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUNotificationArray.m",
    "content": "//\n//  DouNotificationArray.m\n//  DoubanAPIEngine\n//\n//  Created by alex zou on 12-11-6.\n//  Copyright (c) 2012年 Douban Inc. All rights reserved.\n//\n\n#import \"DouNotificationArray.h\"\n#import \"DOUNotification.h\"\n\n@implementation DOUNotificationArray\n\n+ (Class)objectClass {\n  return [DOUNotification class];\n}\n\n+ (NSString *)objectName {\n  return @\"notifications\";\n}\n\n\n- (NSInteger)num {\n  return [[self.dictionary objectForKey:@\"num\"] integerValue];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUOnline.h",
    "content": "//\n//  DOUOnline.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUOnline : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *desc;\n@property (nonatomic, retain) NSArray *tags;\n\n@property (nonatomic, copy) NSString *createTimeStr;\n@property (nonatomic, retain) NSDate *createTime;\n@property (nonatomic, copy) NSString *beginTimeStr;\n@property (nonatomic, retain) NSDate *beginTime;\n@property (nonatomic, copy) NSString *endTimeStr;\n@property (nonatomic, retain) NSDate *endTime;\n\n\n@property (nonatomic, copy) NSString *relatedUrl;\n@property (nonatomic, copy) NSString *topic;\n\n@property (nonatomic, assign) BOOL cascadeInvite;\n\n@property (nonatomic, copy) NSString *groupId;\n@property (nonatomic, copy) NSString *albumId;\n\n@property (nonatomic, assign) NSInteger participantCount;\n@property (nonatomic, assign) NSInteger photoCount;\n@property (nonatomic, assign) NSInteger likedCount;\n@property (nonatomic, assign) NSInteger recsCount;\n\n@property (nonatomic, copy) NSString *icon;\n@property (nonatomic, copy) NSString *thumb;\n@property (nonatomic, copy) NSString *cover;\n\n@property (nonatomic, copy) NSString *image;\n\n@property (nonatomic, retain) DOUUser *owner;\n\n@property (nonatomic, assign) BOOL liked;\n@property (nonatomic, assign) BOOL participated;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUOnline.m",
    "content": "//\n//  DOUOnline.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUOnline.h\"\n#import \"DOUUser.h\"\n#import \"DOUObject+Utils.h\"\n\n\n@implementation DOUOnline\n\n@dynamic identifier;\n@dynamic alt;\n@dynamic title;\n@dynamic desc;\n@dynamic tags;\n\n@dynamic createTimeStr;\n@dynamic createTime;\n@dynamic beginTimeStr;\n@dynamic beginTime;\n@dynamic endTimeStr;\n@dynamic endTime;\n\n@dynamic relatedUrl;\n@dynamic topic;\n@dynamic cascadeInvite;\n@dynamic groupId;\n@dynamic albumId;\n\n@dynamic participantCount;\n@dynamic photoCount;\n@dynamic likedCount;\n@dynamic recsCount;\n\n@dynamic icon;\n@dynamic thumb;\n@dynamic cover;\n@dynamic image;\n\n@dynamic owner;\n\n@dynamic liked;\n@dynamic participated;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSString *)alt {\n  return [self.dictionary objectForKey:@\"alt\"];\n}\n\n\n- (NSString *)title {\n  return [self.dictionary objectForKey:@\"title\"];\n}\n\n\n- (NSString *)desc {\n  return [self.dictionary objectForKey:@\"desc\"];\n}\n\n\n- (NSArray *)tags {\n  return [self.dictionary objectForKey:@\"tags\"];\n}\n\n\n- (NSString *)createTimeStr {\n  return [self.dictionary objectForKey:@\"create_time\"];\n}\n\n\n- (NSDate *)createTime {\n  return [[self class] dateOfString:self.createTimeStr];\n}\n\n\n- (NSString *)beginTimeStr {\n  return [self.dictionary objectForKey:@\"begin_time\"];\n}\n\n\n- (NSDate *)beginTime {\n  return [[self class] dateOfString:self.beginTimeStr];\n}\n\n\n- (NSString *)endTimeStr {\n  return [self.dictionary objectForKey:@\"end_time\"];\n}\n\n\n- (NSDate *)endTime {\n  return [[self class] dateOfString:self.endTimeStr];\n}\n\n\n- (NSString *)relatedUrl {\n  return [self.dictionary objectForKey:@\"related_url\"];\n}\n\n\n- (NSString *)topic {\n  return [self.dictionary objectForKey:@\"shuo_topic\"];\n}\n\n- (BOOL)cascadeInvite {\n  return [[self.dictionary objectForKey:@\"cascade_invite\"] boolValue];\n}\n\n\n- (NSString *)groupId {\n  return [self.dictionary objectForKey:@\"group_id\"];\n}\n\n\n- (NSString *)albumId {\n  return [self.dictionary objectForKey:@\"album_id\"];\n}\n\n\n- (NSInteger)participantCount {\n  return [[self.dictionary objectForKey:@\"participant_count\"] integerValue];\n}\n\n\n- (NSInteger)photoCount {\n  return [[self.dictionary objectForKey:@\"photo_count\"] integerValue];\n}\n\n\n- (NSInteger)likedCount {\n  return  [[self.dictionary objectForKey:@\"liked_count\"] integerValue];\n}\n\n\n- (NSInteger)recsCount {\n  return  [[self.dictionary objectForKey:@\"recs_count\"] integerValue];\n}\n\n\n- (NSString *)icon {\n  return  [self.dictionary objectForKey:@\"icon\"];\n}\n\n\n- (NSString *)thumb {\n  return [self.dictionary objectForKey:@\"thumb\"];\n}\n\n\n- (NSString *)cover {\n  return  [self.dictionary objectForKey:@\"cover\"];\n}\n\n\n- (NSString *)image {\n  return [self.dictionary objectForKey:@\"image\"];\n}\n\n\n- (DOUUser *)owner {\n  NSDictionary *dic = [self.dictionary objectForKey:@\"owner\"];\n  DOUUser *user = [DOUUser objectWithDictionary:dic];\n  return user;\n}\n\n\n- (BOOL)liked {\n  return [[self.dictionary objectForKey:@\"liked\"] boolValue];\n}\n\n\n- (BOOL)participated {\n  return [[self.dictionary objectForKey:@\"participated\"] boolValue];\n}\n\n\n- (void)setParticipated:(BOOL)participated {\n  [self.dictionary setValue:[NSNumber numberWithBool:participated] forKey:@\"participated\"];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUOnlineArray.h",
    "content": "//\n//  DOUOnlineArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUOnlineArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUOnlineArray.m",
    "content": "//\n//  DOUOnlineArray.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUOnlineArray.h\"\n#import \"DOUOnline.h\"\n\n@implementation DOUOnlineArray\n\n\n+ (Class)objectClass {\n  return [DOUOnline class];\n}\n\n+ (NSString *)objectName {\n  return @\"onlines\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUUser.h",
    "content": "//\n//  DOUUser.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUUser : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *avatar;\n@property (nonatomic, copy) NSString *name;\n@property (nonatomic, copy) NSString *signature;\n@property (nonatomic, copy) NSString *alt;\n@property (nonatomic, copy) NSString *uid;\n@property (nonatomic, copy) NSString *desc;\n\n@property (nonatomic, copy) NSString *locId;\n@property (nonatomic, copy) NSString *locName;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Community/DOUUser.m",
    "content": "//\n//  DOUUser.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUUser.h\"\n\n@implementation DOUUser\n\n@dynamic identifier;\n@dynamic avatar;\n@dynamic alt;\n@dynamic name;\n@dynamic uid;\n@dynamic desc;\n@dynamic locId;\n@dynamic locName;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n\n- (NSString *)avatar {\n  return [self.dictionary objectForKey:@\"avatar\"];\n}\n\n\n- (NSString *)alt {\n  return [self.dictionary objectForKey:@\"alt\"];\n}\n\n\n- (NSString *)name {\n  return [self.dictionary objectForKey:@\"name\"];\n}\n\n\n- (NSString *)signature {\n  return [self.dictionary objectForKey:@\"signature\"];\n}\n\n\n- (NSString *)uid {\n  return [self.dictionary objectForKey:@\"uid\"];\n}\n\n\n- (NSString *)desc {\n  return [self.dictionary objectForKey:@\"desc\"];\n}\n\n\n- (NSString *)locId {\n  return [self.dictionary objectForKey:@\"loc_id\"];\n}\n\n\n- (NSString *)locName {\n  return [self.dictionary objectForKey:@\"loc_name\"];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/DOUObject+Utils.h",
    "content": "//\n//  DOUObject+Utils.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUObject (Utils)\n\n+ (NSDate *)dateOfString:(NSString *)dateString;\n\n+ (NSDate *)dateOfString:(NSString *)dateString dateFormat:(NSString *)dateFormatString;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/DOUObject+Utils.m",
    "content": "//\n//  DOUObject+Utils.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject+Utils.h\"\n\n@implementation DOUObject (Utils)\n\n+ (NSDate *)dateOfString:(NSString *)dateString {\n  return [self dateOfString:dateString dateFormat:@\"yyyy-MM-dd HH:mm:SS\"];\n}\n\n+ (NSDate *)dateOfString:(NSString *)dateString dateFormat:(NSString *)dateFormatString {\n    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];\n    [dateFormat setDateFormat:dateFormatString];\n    NSDate *date = [dateFormat dateFromString:dateString];\n    [dateFormat release];\n    return date;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/DOUObject.h",
    "content": "//\n//  DOUObject.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface DOUObject : NSObject\n\n@property (nonatomic, copy) NSString *string;\n@property (nonatomic, retain) NSMutableDictionary *dictionary;\n\n\n- (id)initWithString:(NSString *)theJsonStr;\n- (id)initWithDictionary:(NSDictionary *)theDictionary;\n\n+ (id)objectWithString:(NSString *)theJsonStr;\n+ (id)objectWithDictionary:(NSDictionary *)theDictionary;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/DOUObject.m",
    "content": "//\n//  DOUObject.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n#import \"SBJson.h\"\n\n\n@implementation DOUObject\n\n@dynamic string;\n@synthesize dictionary = dictionary_;\n\n\n- (id)init {\n  self = [super init];\n  if (self) {\n    self.dictionary = [NSMutableDictionary dictionary];\n  }\n  return  self;\n}\n\n\n- (id)initWithString:(NSString *)theJsonStr {\n  self = [super init];\n  if (self) {\n    if (!theJsonStr || [theJsonStr length] <= 0) {\n      return nil;\n    }\n\n    NSMutableDictionary *dic = (NSMutableDictionary *)[theJsonStr JSONValue]; \n    if (!dic) {\n      return nil;\n    }\n    \n    self.dictionary = dic;\n  }\n  return self;\n}\n\n\n- (id)initWithDictionary:(NSDictionary *)theDictionary {\n  self = [super init];\n  if (self) {\n    self.dictionary = [[[NSMutableDictionary alloc] initWithDictionary:theDictionary] autorelease];\n  }\n  return self;\n}\n\n\n+ (id)objectWithString:(NSString *)theJsonStr {\n  id newInstance = [[[[self class] alloc] initWithString:theJsonStr] autorelease];\n  return newInstance;\n}\n\n\n+ (id)objectWithDictionary:(NSDictionary *)theDictionary {\n  id newInstance = [[[[self class] alloc] initWithDictionary:theDictionary] autorelease];\n  return newInstance;\n}\n\n\n\n- (void)dealloc {\n  [dictionary_ release]; dictionary_ = nil;\n  [super dealloc];\n}\n\n\n- (NSString *)string {\n  if (self.dictionary) {\n    NSString *result = [self.dictionary JSONRepresentation];\n    return result;      \n  }\n  return nil;\n}\n\n\n- (void)setString:(NSString *)theJsonStr {\n  NSMutableDictionary *dic = (NSMutableDictionary *)[theJsonStr JSONValue]; \n  if (!dic) {\n    return ;\n  }\n  self.dictionary = dic;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/DOUObjectArray.h",
    "content": "//\n//  DOUObjectArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUObjectArray : DOUObject\n\n@property (nonatomic, assign) NSInteger count;\n@property (nonatomic, assign) NSInteger start;\n@property (nonatomic, assign) NSInteger total;\n\n@property (nonatomic, retain, readonly) NSArray  *objectArray;\n\n+ (Class)objectClass;\n+ (NSString *)objectName;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/DOUObjectArray.m",
    "content": "//\n//  DOUObjectArray.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@implementation DOUObjectArray\n\n@dynamic start;\n@dynamic count;\n@dynamic total;\n@dynamic objectArray;\n\n\n- (NSInteger)start {\n  return [[self.dictionary objectForKey:@\"start\"] integerValue];\n}\n\n\n- (NSInteger)count {\n  return [[self.dictionary objectForKey:@\"count\"] integerValue];\n}\n\n\n- (NSInteger)total {\n  return [[self.dictionary objectForKey:@\"total\"] integerValue];\n}\n\n\n- (NSArray*)objectArray {\n  NSString *objectName = [[self class] objectName];\n  NSMutableArray *objectArray = [NSMutableArray array];\n\n  if (objectName) {\n    NSArray *array = (NSArray *)[self.dictionary objectForKey:objectName];\n    \n    for (id dic in array) {\n      if ([dic isKindOfClass:[NSDictionary class]]) {\n      id object = [[[self class] objectClass] objectWithDictionary:dic];\n      [objectArray addObject:object];\n      }\n    }\n  }\n  \n  return objectArray;    \n}\n\n\n/**\n Overwrited by subclass \n */\n+ (Class)objectClass {\n  return nil;\n}\n\n\n/**\n Overwrited by subclass \n */\n+ (NSString *)objectName {\n  return nil;\n}\n\n\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOUEvent.h",
    "content": "//\n//  DOUEvent.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUEvent : DOUObject\n\nextern NSString * const kParticipatedStatus;\nextern NSString * const kWishedStatus;\nextern NSString * const kArrivedStatus;\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *content;\n\n@property (nonatomic, copy) NSString *beginTimeStr;\n@property (nonatomic, retain) NSDate *beginTime;\n@property (nonatomic, copy) NSString *endTimeStr;\n@property (nonatomic, retain) NSDate *endTime;\n@property (nonatomic, copy) NSString *category;\n@property (nonatomic, copy) NSString *categoryName;\n\n\n@property (nonatomic, copy) NSString *adaptUrl;\n@property (nonatomic, copy) NSString *locId;\n@property (nonatomic, copy) NSString *locName;\n@property (nonatomic, copy) NSString *address;\n\n@property (nonatomic, copy) NSString *albumId;\n\n@property (nonatomic, assign) NSInteger participantCount;\n@property (nonatomic, assign) NSInteger wisherCount;\n\n@property (nonatomic, copy) NSString *imageMobile;\n@property (nonatomic, copy) NSString *imageLarge;\n@property (nonatomic, copy) NSString *image;\n@property (nonatomic, copy) NSString *icon;\n\n@property (nonatomic, retain) DOUUser *owner;\n\n@property (nonatomic, copy) NSString    *participateDateStr;\n@property (nonatomic, retain) NSDate    *participateDate;\n@property (nonatomic, copy)   NSString  *status;\n\n@property (nonatomic, assign) float lat;\n@property (nonatomic, assign) float lng;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOUEvent.m",
    "content": "//\n//  DOUEvent.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUEvent.h\"\n#import \"DOUUser.h\"\n#import \"DOUObject+Utils.h\"\n\n\n@implementation DOUEvent\n\nNSString * const kParticipatedStatus = @\"participate\";\nNSString * const kWishedStatus = @\"wish\";\nNSString * const kArrivedStatus = @\"arrive\";\n\nstatic NSString * const kEventAllCategory = @\"all\";\nstatic NSString * const kEventDramaCategory = @\"drama\";\nstatic NSString * const kEventMusicCategory = @\"music\";\nstatic NSString * const kEventExhibitionCategory = @\"exhibition\";\nstatic NSString * const kEventSportsCategory = @\"sports\";\nstatic NSString * const kEventPartyCategory = @\"party\";\nstatic NSString * const kEventCommonwealCategory = @\"commonweal\";\nstatic NSString * const kEventTravelCategory = @\"travel\";\nstatic NSString * const kEventFilmCategory = @\"film\";\nstatic NSString * const kEventSalonCategory = @\"salon\";\nstatic NSString * const kEventOthersCategory = @\"others\";\n\nstatic NSString * const kEventAllCategoryName = @\"类型\";\nstatic NSString * const kEventDramaCategoryName = @\"戏剧/曲艺\";\nstatic NSString * const kEventMusicCategoryName = @\"音乐/演出\";\nstatic NSString * const kEventExhibitionCategoryName = @\"展览\";\nstatic NSString * const kEventSportsCategoryName = @\"体育\";\nstatic NSString * const kEventPartyCategoryName = @\"生活/聚会\";\nstatic NSString * const kEventCommonwealCategoryName = @\"公益\";\nstatic NSString * const kEventTravelCategoryName = @\"旅行\";\nstatic NSString * const kEventFilmCategoryName = @\"电影\";\nstatic NSString * const kEventSalonCategoryName = @\"讲座/沙龙\";\nstatic NSString * const kEventOthersCategoryName = @\"其他\";\n\n\n@dynamic identifier;\n@dynamic alt;\n@dynamic title;\n@dynamic content;\n\n@dynamic beginTimeStr;\n@dynamic beginTime;\n@dynamic endTimeStr;\n@dynamic endTime;\n@dynamic category;\n@dynamic categoryName;\n@dynamic adaptUrl;\n@dynamic albumId;\n\n@dynamic participantCount;\n@dynamic wisherCount;\n\n@dynamic locId;\n@dynamic locName;\n@dynamic address;\n\n@dynamic imageMobile;\n@dynamic imageLarge;\n@dynamic image;\n@dynamic icon;\n\n@dynamic owner;\n\n@dynamic participateDateStr;\n@dynamic participateDate;\n\n@dynamic status;\n\n@dynamic lat;\n@dynamic lng;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSString *)alt {\n  return [self.dictionary objectForKey:@\"alt\"];\n}\n\n\n- (NSString *)title {\n  return [self.dictionary objectForKey:@\"title\"];\n}\n\n\n- (NSString *)content {\n  return [self.dictionary objectForKey:@\"content\"];\n}\n\n\n- (NSString *)beginTimeStr {\n  return [self.dictionary objectForKey:@\"begin_time\"];\n}\n\n\n- (NSDate *)beginTime {\n  return [[self class] dateOfString:self.beginTimeStr];\n}\n\n\n- (NSString *)endTimeStr {\n  return [self.dictionary objectForKey:@\"end_time\"];\n}\n\n\n- (NSDate *)endTime {\n  return [[self class] dateOfString:self.endTimeStr];\n}\n\n\n- (NSString *)category {\n  return [self.dictionary objectForKey:@\"category\"];\n}\n\n\n- (NSString *)categoryName {\n  NSString *category = self.category;\n  NSString *categoryName = kEventAllCategoryName;\n  \n  if  ([category isEqualToString:kEventDramaCategory]) {\n    categoryName = kEventDramaCategoryName;\n  }\n  else if ([category isEqualToString:kEventMusicCategory]) {\n    categoryName = kEventMusicCategoryName;    \n  }\n  else if ([category isEqualToString:kEventExhibitionCategory]) {\n    categoryName = kEventExhibitionCategoryName;\n  }\n  else if ([category isEqualToString:kEventSportsCategory]) {\n    categoryName = kEventSportsCategoryName;\n  }\n  else if ([category isEqualToString:kEventPartyCategory]) {\n    categoryName = kEventPartyCategoryName;\n  }\n  else if ([category isEqualToString:kEventCommonwealCategory]) {\n    categoryName = kEventCommonwealCategoryName;\n  }\n  else if ([category isEqualToString:kEventTravelCategory]) {\n    categoryName = kEventTravelCategoryName;\n  }\n  else if ([category isEqualToString:kEventFilmCategory]) {\n    categoryName = kEventFilmCategoryName;\n  }  \n  else if ([category isEqualToString:kEventSalonCategory]) {\n    categoryName = kEventSalonCategoryName;\n  }  \n  \n  return categoryName;\n}\n\n\n- (NSString *)adaptUrl {\n  return [self.dictionary objectForKey:@\"adapt_url\"];\n}\n\n\n- (NSString *)albumId {\n  return [self.dictionary objectForKey:@\"album\"];\n}\n\n\n- (NSInteger)participantCount {\n  return [[self.dictionary objectForKey:@\"participant_count\"] integerValue];\n}\n\n\n- (NSInteger)wisherCount {\n  return [[self.dictionary objectForKey:@\"wisher_count\"] integerValue];\n}\n\n\n- (NSString *)locId {\n  return [self.dictionary objectForKey:@\"loc_id\"];\n}\n\n\n- (NSString *)locName {\n  return [self.dictionary objectForKey:@\"loc_name\"];\n}\n\n\n- (NSString *)address {\n  return [self.dictionary objectForKey:@\"address\"];\n}\n\n\n- (NSString *)icon {\n  return  [self.dictionary objectForKey:@\"icon\"];\n}\n\n\n- (NSString *)image {\n  return [self.dictionary objectForKey:@\"image\"];\n}\n\n\n- (NSString *)imageMobile {\n  return [self.dictionary objectForKey:@\"image_lmobile\"];\n}\n\n\n- (NSString *)imageLarge {\n  return [self.dictionary objectForKey:@\"image_hlarge\"];\n}\n\n\n- (NSString *)status {\n  return [self.dictionary objectForKey:@\"status\"];\n}\n\n\n- (void)setStatus:(NSString *)status {\n  return [self.dictionary setValue:status forKey:@\"status\"];\n}\n\n\n- (NSString *)participateDateStr {\n  return [self.dictionary objectForKey:@\"participate_date\"];\n}\n\n\n- (void)setParticipateDateStr:(NSString *)participateDateStr {\n  return [self.dictionary setValue:participateDateStr forKey:@\"participate_date\"];\n}\n\n\n- (NSDate *)participateDate {\n  if (!self.participateDateStr) {\n    return nil;\n  }\n  NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];\n  [dateFormat setDateFormat:@\"yyyy-MM-dd\"];\n  NSDate *date = [dateFormat dateFromString:self.participateDateStr];\n  [dateFormat release];\n  return date;\n}\n\n\n- (DOUUser *)owner {\n  NSDictionary *dic = [self.dictionary objectForKey:@\"owner\"];\n  DOUUser *user = [DOUUser objectWithDictionary:dic];\n  return user;\n}\n\n\n- (float)lat {\n  NSString *geo = [self.dictionary objectForKey:@\"geo\"];\n  if (geo) {\n    NSArray *words = [geo componentsSeparatedByString:@\" \"];\n    if ([words count] == 2 && [words objectAtIndex:0]) {\n      NSString *str = [words objectAtIndex:0];\n      return [str floatValue];\n    }\n  }\n  return 0;\n}\n\n\n- (float)lng {\n  NSString *geo = [self.dictionary objectForKey:@\"geo\"];\n  if (geo) {\n    NSArray *words = [geo componentsSeparatedByString:@\" \"];\n    if ([words count] == 2 && [words objectAtIndex:1]) {\n      NSString *str = [words objectAtIndex:1];\n      return [str floatValue];\n    }\n  }\n  return 0;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOUEventArray.h",
    "content": "//\n//  DOUEventArray.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUEventArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOUEventArray.m",
    "content": "//\n//  DOUEventArray.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUEventArray.h\"\n#import \"DOUEvent.h\"\n\n@implementation DOUEventArray\n\n+ (Class)objectClass {\n  return [DOUEvent class];\n}\n\n+ (NSString *)objectName {\n  return @\"events\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOULoc.h",
    "content": "//\n//  DOULoc.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 9/7/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOULoc : DOUObject\n\n@property (nonatomic, copy) NSString  *identifier;\n@property (nonatomic, copy) NSString  *parent;\n@property (nonatomic, copy) NSString  *name;\n@property (nonatomic, copy) NSString  *uid;\n@property (nonatomic, assign) BOOL  isHabitable;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOULoc.m",
    "content": "//\n//  DOULoc.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 9/7/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOULoc.h\"\n\n@implementation DOULoc\n\n@dynamic identifier;\n@dynamic parent;\n@dynamic name;\n@dynamic uid;\n@dynamic isHabitable;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (void)setIdentifier:(NSString *)identifier {\n  [self.dictionary setValue:identifier forKey:@\"id\"];\n\n}\n\n\n- (NSString *)parent {\n  return [self.dictionary objectForKey:@\"parent\"];\n}\n\n- (void)setParent:(NSString *)parent {\n  return [self.dictionary setObject:parent forKey:@\"parent\"];\n}\n\n\n- (NSString *)name {\n  return [self.dictionary objectForKey:@\"name\"];\n}\n\n-  (void)setName:(NSString *)name {\n  return [self.dictionary setObject:name forKey:@\"name\"];\n}\n\n\n- (NSString *)uid {\n  return [self.dictionary objectForKey:@\"uid\"];\n}\n\n- (void)setUid:(NSString *)uid {\n  return [self.dictionary setObject:uid forKey:@\"uid\"];\n}\n\n\n- (BOOL)isHabitable {\n  return [[self.dictionary objectForKey:@\"habitable\"] boolValue];\n}\n\n\n- (void)setIsHabitable:(BOOL)isHabitable {\n  [self.dictionary setValue:[NSNumber numberWithBool:isHabitable] forKey:@\"habitable\"];\n}\n\n\n- (BOOL)isEqual:(id)object {\n  if (self == object) {\n    return YES;\n  }\n  if ([object isKindOfClass:[self class]]) {\n    if (![[self identifier] isEqualToString:[(DOULoc *)object identifier]]) \n      return NO;\n    \n    return YES;\n  }\n  return NO;\n}\n\n\n- (NSUInteger)hash {\n  return [[self identifier] hash];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOULocArray.h",
    "content": "//\n//  DOULocArray.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 9/7/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOULocArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Event/DOULocArray.m",
    "content": "//\n//  DOULocArray.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 9/7/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOULocArray.h\"\n#import \"DOULoc.h\"\n\n@implementation DOULocArray\n\n+ (Class)objectClass {\n  return [DOULoc class];\n}\n\n+ (NSString *)objectName {\n  return @\"locs\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Movie/DOUMovie.h",
    "content": "//\n//  DOUMovie.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUMovie : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *originalTitle;\n@property (nonatomic, copy) NSString *rating;\n@property (nonatomic, copy) NSString *stars;\n\n@property (nonatomic, copy) NSString *publishTimeStr;\n@property (nonatomic, retain) NSDate *publishTime;\n\n@property (nonatomic, copy) NSString *largeImage;\n@property (nonatomic, copy) NSString *smallImage;\n@property (nonatomic, copy) NSString *mediumImage;\n\n@property (nonatomic, assign) NSInteger wishCount;\n@property (nonatomic, assign) NSInteger collectionCount;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Movie/DOUMovie.m",
    "content": "//\n//  DOUMovie.m\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUMovie.h\"\n#import \"DOUObject+Utils.h\"\n\n\n@implementation DOUMovie\n\n@dynamic identifier;\n@dynamic title;\n@dynamic originalTitle;\n@dynamic stars;\n@dynamic rating;\n\n@dynamic publishTimeStr;\n@dynamic publishTime;\n\n@dynamic largeImage;\n@dynamic smallImage;\n@dynamic mediumImage;\n\n@dynamic wishCount;\n@dynamic collectionCount;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSString *)originalTitle {\n  return [self.dictionary objectForKey:@\"orignal_title\"];\n}\n\n- (NSString *)title {\n  return [self.dictionary objectForKey:@\"title\"];\n}\n\n\n- (NSString *)stars {\n  return [self.dictionary objectForKey:@\"stars\"];\n}\n\n\n- (NSString *)rating {\n  return [self.dictionary objectForKey:@\"rating\"];\n}\n\n\n- (NSString *)publishTimeStr {\n  return [self.dictionary objectForKey:@\"pubdate\"];\n}\n\n\n- (NSDate *)publishTime {\n  return [[self class] dateOfString:self.publishTimeStr dateFormat:@\"yyyy-MM-dd\"];\n}\n\n\n- (NSString *)largeImage {\n  return [[self.dictionary objectForKey:@\"images\"] objectForKey:@\"large\"];\n}\n\n- (NSString *)smallImage {\n  return [[self.dictionary objectForKey:@\"images\"] objectForKey:@\"small\"];\n}\n\n- (NSString *)mediumImage {\n  return [[self.dictionary objectForKey:@\"images\"] objectForKey:@\"medium\"];\n}\n\n\n\n- (NSInteger)wishCount {\n  return [[self.dictionary objectForKey:@\"wish\"] integerValue];\n}\n\n- (NSInteger)collectionCount {\n  return [[self.dictionary objectForKey:@\"collection\"] integerValue];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Movie/DOUMovieArray.h",
    "content": "//\n//  DOUMovieArray.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUMovieArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Movie/DOUMovieArray.m",
    "content": "//\n//  DOUMovieArray.m\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUMovieArray.h\"\n#import \"DOUMovie.h\"\n\n@implementation DOUMovieArray\n\n+ (Class)objectClass {\n  return [DOUMovie class];\n}\n\n+ (NSString *)objectName {\n  return @\"movies\";\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Music/DOUMusic.h",
    "content": "//\n//  DOUMusic.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUMusic : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *altTitle;\n@property (nonatomic, copy) NSString *rating;\n\n@property (nonatomic, copy) NSString *publisher;\n\n@property (nonatomic, copy) NSString *publishDateStr;\n@property (nonatomic, retain) NSDate *publishDate;\n\n@property (nonatomic, copy) NSString *image;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Music/DOUMusic.m",
    "content": "//\n//  DOUMusic.m\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUMusic.h\"\n#import \"DOUObject+Utils.h\"\n\n\n@implementation DOUMusic\n\n@dynamic identifier;\n@dynamic title;\n@dynamic altTitle;\n@dynamic rating;\n\n@dynamic publisher;\n\n@dynamic publishDateStr;\n@dynamic publishDate;\n\n@dynamic image;\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSString *)altTitle {\n  return [self.dictionary objectForKey:@\"alt_title\"];\n}\n\n- (NSString *)title {\n  return [self.dictionary objectForKey:@\"title\"];\n}\n\n\n- (NSString *)publisher {\n  return [[[self.dictionary objectForKey:@\"attrs\"] objectForKey:@\"publisher\"] objectAtIndex:0];\n}\n\n\n- (NSString *)rating {\n  return [[self.dictionary objectForKey:@\"rating\"] objectForKey:@\"average\"];\n}\n\n\n- (NSString *)publishDateStr {\n  return [[[self.dictionary objectForKey:@\"attrs\"] objectForKey:@\"pubdate\"] objectAtIndex:0];\n}\n\n\n- (NSDate *)publishDate {\n  return [[self class] dateOfString:self.publishDateStr dateFormat:@\"yyyy-MM-dd\"];\n}\n\n\n- (NSString *)image {\n  return [self.dictionary objectForKey:@\"image\"];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Music/DOUMusicArray.h",
    "content": "//\n//  DOUMusicArray.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUMusicArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Music/DOUMusicArray.m",
    "content": "//\n//  DOUMusicArray.m\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUMusicArray.h\"\n#import \"DOUMusic.h\"\n\n@implementation DOUMusicArray\n\n+ (Class)objectClass {\n  return [DOUMusic class];\n}\n\n+ (NSString *)objectName {\n  return @\"musics\";\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUAlbum.h",
    "content": "//\n//  DOUAlbum.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUAlbum : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *desc;\n@property (nonatomic, copy) NSString *privacy;\n\n@property (nonatomic, copy) NSString *createTimeStr;\n@property (nonatomic, retain) NSDate *createTime;\n@property (nonatomic, copy) NSString *updateTimeStr;\n@property (nonatomic, retain) NSDate *updateTime;\n\n@property (nonatomic, assign) NSInteger size;\n@property (nonatomic, assign) NSInteger recsCount;\n@property (nonatomic, assign) NSInteger likedCount;\n\n@property (nonatomic, assign) BOOL liked;\n\n@property (nonatomic, copy) NSString *icon;\n@property (nonatomic, copy) NSString *thumb;\n@property (nonatomic, copy) NSString *cover;\n@property (nonatomic, copy) NSString *image;\n\n@property (nonatomic, retain) DOUUser *author;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUAlbum.m",
    "content": "//\n//  DOUAlbum.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUAlbum.h\"\n#import \"DOUObject+Utils.h\"\n#import \"DOUUser.h\"\n\n\n@implementation DOUAlbum\n\n@dynamic identifier;\n@dynamic alt;\n@dynamic title;\n@dynamic desc;\n@dynamic privacy;\n\n@dynamic createTimeStr;\n@dynamic createTime;\n@dynamic updateTimeStr;\n@dynamic updateTime;\n\n@dynamic size;\n@dynamic recsCount;\n@dynamic likedCount;\n\n@dynamic icon;\n@dynamic thumb;\n@dynamic cover;\n@dynamic image;\n\n@dynamic liked;\n@dynamic author;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n- (NSString *)alt {\n  return [self.dictionary objectForKey:@\"alt\"];\n}\n\n- (NSString *)title {\n  return [self.dictionary objectForKey:@\"title\"];\n}\n\n- (NSString *)desc {\n  return [self.dictionary objectForKey:@\"desc\"];\n}\n\n- (NSString *)privacy {\n  return [self.dictionary objectForKey:@\"privacy\"];\n}\n\n\n- (NSString *)createTimeStr {\n  return [self.dictionary objectForKey:@\"created\"];\n}\n\n- (NSDate *)createTime {\n  return [[self class] dateOfString:self.createTimeStr];\n}\n\n- (NSString *)updateTimeStr {\n  return [self.dictionary objectForKey:@\"updated\"];\n}\n\n- (NSDate *)updateTime {\n  return [[self class] dateOfString:self.updateTimeStr];\n}\n\n\n- (NSInteger)recsCount {\n  return [[self.dictionary objectForKey:@\"recs_count\"] integerValue];\n}\n\n- (NSInteger)likedCount {\n  return [[self.dictionary objectForKey:@\"liked_count\"] integerValue];\n}\n\n- (NSInteger)size {\n  return [[self.dictionary objectForKey:@\"size\"] integerValue];\n}\n\n\n- (NSString *)icon {\n  return  [self.dictionary objectForKey:@\"icon\"];\n}\n\n- (NSString *)thumb {\n  return [self.dictionary objectForKey:@\"thumb\"];\n}\n\n- (NSString *)cover {\n  return  [self.dictionary objectForKey:@\"cover\"];\n}\n\n- (NSString *)image {\n  return [self.dictionary objectForKey:@\"image\"];\n}\n\n\n- (DOUUser *)author {\n  NSDictionary *dic = [self.dictionary objectForKey:@\"author\"];\n  DOUUser *people = [DOUUser objectWithDictionary:dic];\n  return people;\n}\n\n\n- (BOOL)liked {\n  return [[self.dictionary objectForKey:@\"liked\"] boolValue];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUAlbumArray.h",
    "content": "//\n//  DOUAlbumArray.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUAlbumArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUAlbumArray.m",
    "content": "//\n//  DOUAlbumArray.m\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUAlbumArray.h\"\n#import \"DOUAlbum.h\"\n\n@implementation DOUAlbumArray\n\n+ (Class)objectClass {\n  return [DOUAlbum class];\n}\n\n+ (NSString *)objectName {\n  return @\"albums\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUPhoto.h",
    "content": "//\n//  DOUPhoto.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n#import <UIKit/UIKit.h>\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUPhoto : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *desc;\n@property (nonatomic, copy) NSString *alt;\n@property (nonatomic, copy) NSString *privacy;\n\n@property (nonatomic, copy) NSString *createTimeStr;\n@property (nonatomic, retain) NSDate *createTime;\n\n@property (nonatomic, assign) NSInteger recsCount; \n@property (nonatomic, assign) NSInteger likedCount; \n@property (nonatomic, assign) NSInteger commentsCount; \n\n@property (nonatomic, copy) NSString *icon;\n@property (nonatomic, copy) NSString *thumb;\n@property (nonatomic, copy) NSString *cover;\n@property (nonatomic, copy) NSString *image;\n\n@property (nonatomic, assign) NSInteger position;\n@property (nonatomic, copy) NSString *prevPhoto;\n@property (nonatomic, copy) NSString *nextPhoto;\n\n@property (nonatomic, assign) BOOL liked;\n@property (nonatomic, retain) DOUUser *author;\n\n@property (nonatomic, assign) NSString *albumId;\n@property (nonatomic, assign) NSString *albumTitle;\n\n@property (nonatomic, assign) CGSize imageSize;\n@property (nonatomic, assign) CGSize coverSize;\n@property (nonatomic, assign) CGSize thumbSize;\n@property (nonatomic, assign) CGSize iconSize;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUPhoto.m",
    "content": "//\n//  DOUPhoto.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUPhoto.h\"\n#import \"DOUObject+Utils.h\"\n#import \"DOUUser.h\"\n\n@implementation DOUPhoto\n\n@dynamic identifier;\n@dynamic alt;\n@dynamic desc;\n@dynamic privacy;\n@dynamic createTimeStr;\n@dynamic createTime;\n\n@dynamic recsCount;\n@dynamic likedCount;\n@dynamic commentsCount;\n\n@dynamic icon;\n@dynamic thumb;\n@dynamic cover;\n@dynamic image;\n\n@dynamic position;\n@dynamic prevPhoto;\n@dynamic nextPhoto;\n\n@dynamic liked;\n@dynamic author;\n\n@dynamic albumId;\n@dynamic albumTitle;\n\n@dynamic imageSize;\n@dynamic coverSize;\n@dynamic thumbSize;\n@dynamic iconSize;\n\n\n- (NSString *)identifier {\n  return [self.dictionary objectForKey:@\"id\"];\n}\n\n\n- (NSString *)alt {\n  return [self.dictionary objectForKey:@\"alt\"];\n}\n\n\n- (NSString *)desc {\n  return [self.dictionary objectForKey:@\"desc\"];\n}\n\n\n- (NSString *)privacy {\n  return [self.dictionary objectForKey:@\"privacy\"];\n}\n\n\n- (NSString *)createTimeStr {\n  return [self.dictionary objectForKey:@\"created\"];\n}\n\n- (NSDate *)createTime {\n  return [[self class] dateOfString:self.createTimeStr];\n}\n\n\n- (NSInteger)recsCount {\n  return [[self.dictionary objectForKey:@\"recs_count\"] integerValue];\n}\n\n- (NSInteger)likedCount {\n  return [[self.dictionary objectForKey:@\"liked_count\"] integerValue];\n}\n\n- (NSInteger)commentsCount {\n  return [[self.dictionary objectForKey:@\"comments_count\"] integerValue];\n}\n\n\n- (void)setCommentsCount:(NSInteger)commentsCount {\n  [self.dictionary setObject:[NSNumber numberWithInteger:commentsCount] forKey:@\"comments_count\"];\n}\n\n\n- (NSString *)icon {\n  return  [self.dictionary objectForKey:@\"icon\"];\n}\n\n- (NSString *)thumb {\n  return [self.dictionary objectForKey:@\"thumb\"];\n}\n\n- (NSString *)cover {\n  return  [self.dictionary objectForKey:@\"cover\"];\n}\n\n- (NSString *)image {\n  return [self.dictionary objectForKey:@\"image\"];\n}\n\n\n- (NSInteger)position {\n  return [[self.dictionary objectForKey:@\"position\"] integerValue];\n}\n\n- (NSString *)prevPhoto {\n  return [self.dictionary objectForKey:@\"prev_photo\"];\n}\n\n- (NSString *)nextPhoto {\n  return [self.dictionary objectForKey:@\"next_photo\"];\n}\n\n\n- (DOUUser *)author {\n  NSDictionary *dic = [self.dictionary objectForKey:@\"author\"];\n  DOUUser *user = [DOUUser objectWithDictionary:dic];\n  return user;\n}\n\n\n- (BOOL)liked {\n  return [[self.dictionary objectForKey:@\"liked\"] boolValue];\n}\n\n\n- (NSString *)albumId {\n  return [self.dictionary objectForKey:@\"album_id\"];\n}\n\n\n- (NSString *)albumTitle {\n  return [self.dictionary objectForKey:@\"album_title\"];\n}\n\n\n- (CGSize)imageSizeFor:(NSString *)tag {\n  NSDictionary *dic = [self.dictionary objectForKey:@\"sizes\"];\n  if (dic) {\n    NSArray *size = [dic objectForKey:tag];\n    CGFloat width = [[size objectAtIndex:0] floatValue];\n    CGFloat height = [[size objectAtIndex:1] floatValue];\n    return CGSizeMake(width, height);\n  }\n  return CGSizeZero;\n}\n\n\n- (CGSize)imageSize {\n  return [self imageSizeFor:@\"image\"];\n}\n\n\n- (CGSize)thumbSize {\n  return [self imageSizeFor:@\"thumb\"];  \n}\n\n\n- (CGSize)coverSize {\n  return [self imageSizeFor:@\"cover\"];  \n}\n\n\n- (CGSize)iconSize {\n  return [self imageSizeFor:@\"icon\"];  \n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUPhotoArray.h",
    "content": "//\n//  DOUPhotoArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@class DOUAlbum;\n@interface DOUPhotoArray : DOUObjectArray\n\n@property (nonatomic, copy) NSString *sortBy;\n@property (nonatomic, copy) NSString *order;\n@property (nonatomic, copy) DOUAlbum *album;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Photo/DOUPhotoArray.m",
    "content": "//\n//  DOUPhotoArray.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUPhotoArray.h\"\n#import \"DOUPhoto.h\"\n#import \"DOUAlbum.h\"\n\n\n@implementation DOUPhotoArray\n\n@dynamic sortBy;\n@dynamic order;\n@dynamic album;\n\n+ (Class)objectClass {\n  return [DOUPhoto class];\n}\n\n\n+ (NSString *)objectName {\n  return @\"photos\";\n}\n\n\n- (NSString *)sortBy {\n  return [self.dictionary objectForKey:@\"sortby\"];\n}\n\n\n- (NSString *)order {\n  return [self.dictionary objectForKey:@\"order\"];\n}\n\n\n- (DOUAlbum *)album {\n  NSDictionary *dic = [self.dictionary objectForKey:@\"album\"];\n  DOUAlbum *album = [DOUAlbum objectWithDictionary:dic];\n  return album;\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUTag.h",
    "content": "//\n//  DOUTag.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"DOUObject.h\"\n\n@interface DOUTag : DOUObject\n\n@property (nonatomic, copy) NSString *count;\n@property (nonatomic, copy) NSString *name;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUTag.m",
    "content": "//\n//  DOUTag.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUTag.h\"\n\n@implementation DOUTag\n\n@dynamic count;\n@dynamic name;\n\n- (NSString *)count {\n    return [self.dictionary objectForKey:@\"count\"];\n}\n\n\n- (NSString *)name {\n    return [self.dictionary objectForKey:@\"name\"];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUTagArray.h",
    "content": "//\n//  DOUTagArray.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUTagArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUTagArray.m",
    "content": "//\n//  DOUTagArray.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUTagArray.h\"\n\n#import \"DOUTag.h\"\n\n@implementation DOUTagArray\n\n+ (Class)objectClass {\n    return [DOUTag class];\n}\n\n+ (NSString *)objectName {\n    return @\"tags\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUUserTag.h",
    "content": "//\n//  DOUUserTag.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#import \"DOUObject.h\"\n\n@interface DOUUserTag : DOUObject\n\n@property (nonatomic, copy) NSString *count;\n@property (nonatomic, copy) NSString *title;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUUserTag.m",
    "content": "//\n//  DOUUserTag.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUUserTag.h\"\n\n@implementation DOUUserTag\n\n@dynamic count;\n@dynamic title;\n\n- (NSString *)count {\n    return [self.dictionary objectForKey:@\"count\"];\n}\n\n\n- (NSString *)name {\n    return [self.dictionary objectForKey:@\"title\"];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUUserTagArray.h",
    "content": "//\n//  DOUUserTagArray.h\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUUserTagArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Model2/Tag/DOUUserTagArray.m",
    "content": "//\n//  DOUUserTagArray.m\n//  DoubanAPICocoa\n//\n//  Created by GuoJing on 12-12-16.\n//  Copyright (c) 2012年 GuoJing. All rights reserved.\n//\n\n#import \"DOUUserTagArray.h\"\n\n#import \"DOUUserTag.h\"\n\n@implementation DOUUserTagArray\n\n+ (Class)objectClass {\n    return [DOUUserTag class];\n}\n\n+ (NSString *)objectName {\n    return @\"tags\";\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Network/DOUHttpRequest.h",
    "content": "//\n//  DOUHttpRequest.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"ASIHTTPRequest.h\"\n\n\nextern NSUInteger const kDefaultTimeoutSeconds;\n\nextern NSString * const DOUHTTPRequestErrorDomain;\n\nextern NSString * const DOUOAuthErrorDomain;\n\nextern NSString * const DOUErrorDomain;\n\n@class DOUHttpRequest;\n@class DOUQuery;\n@protocol DOUHttpRequestDelegate <NSObject>\n\n@required\n- (void)requestFinished:(DOUHttpRequest *)aRequest;\n- (void)requestFailed:(DOUHttpRequest *)aRequest;\n@end\n\n\ntypedef enum _DOUNetworkErrorType {\n  DOUConnectionFailureErrorType = 1,\n  DOURequestTimedOutErrorType = 2,\n  DOUAuthenticationErrorType = 3,\n  DOURequestCancelledErrorType = 4,\n  DOUUnableToCreateRequestErrorType = 5,\n  DOUInternalErrorWhileBuildingRequestType  = 6,\n  DOUInternalErrorWhileApplyingCredentialsType  = 7,\n\tDOUFileManagementError = 8,\n\tDOUTooMuchRedirectionErrorType = 9,\n\tDOUUnhandledExceptionError = 10,\n\tDOUCompressionError = 11\n} DOUNetworkErrorType;\n\n\n\n#if NS_BLOCKS_AVAILABLE\ntypedef void (^DOUBasicBlock)(void);\n\ntypedef void (^DOUReqBlock)(DOUHttpRequest *);\n\ntypedef void (^DOUSizeBlock)(long long size);\n#endif\n\n//\n// DOUHttpRequest is the wrapper of http request, now it's ASIHTTPRequest.\n//\n@interface DOUHttpRequest : ASIHTTPRequest\n\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL;\n\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL target:(id<DOUHttpRequestDelegate>)delegate;\n\n+ (DOUHttpRequest *)requestWithQuery:(DOUQuery *)query target:(id<DOUHttpRequestDelegate>)delegate;\n\n#if NS_BLOCKS_AVAILABLE\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL \n                     completionBlock:(DOUBasicBlock)completionHandler;\n\n+ (DOUHttpRequest *)requestWithQuery:(DOUQuery *)query \n                     completionBlock:(DOUBasicBlock)completionHandler;\n#endif\n\n+ (NSError *)adapterError:(NSError *)asiError;\n\n- (NSError *)doubanError;\n\n- (void)appendPostString:(NSString *)string;\n\n@end\n\n\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Network/DOUHttpRequest.m",
    "content": "//\n//  DOUHttpRequest.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"ASIHTTPRequest.h\"\n#import \"DOUHttpRequest.h\"\n#import \"DOUOAuth2.h\"\n#import \"DOUQuery.h\"\n\n#import \"DOUAPIConfig.h\"\n#import \"SBJson.h\"\n\n\n@implementation DOUHttpRequest\n\nNSUInteger const kDefaultTimeoutSeconds = 30;\n\n\nNSString * const DOUHTTPRequestErrorDomain = @\"DOUHTTPRequestErrorDomain\";\n\nNSString * const DOUOAuthErrorDomain = @\"DOUOAuthErrorDomain\";\n\nNSString * const DOUErrorDomain = @\"DOUErrorDomain\";\n\n\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL {\n  DOUHttpRequest *req = [[[DOUHttpRequest alloc] initWithURL:URL] autorelease];\n  req.useCookiePersistence = NO;\n  //[req setValidatesSecureCertificate:NO];\n  [req setAllowCompressedResponse:YES];// YES is the default\n  [req setTimeOutSeconds:kDefaultTimeoutSeconds];\n  return req;\n}\n\n\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL target:(id<DOUHttpRequestDelegate>)delegate {\n  DOUHttpRequest *req = [[self class] requestWithURL:URL];\n  [req setDelegate:delegate];\n  [req setDidFinishSelector:@selector(requestFinished:)];\n  [req setDidFailSelector:@selector(requestFailed:)];\n  return req;\n}\n\n\n+ (DOUHttpRequest *)requestWithQuery:(DOUQuery *)query target:(id<DOUHttpRequestDelegate>)delegate {\n  DOUHttpRequest *req = [[self class] requestWithURL:[query requestURL] target:delegate];\n  return req;\n}\n\n#if NS_BLOCKS_AVAILABLE\n\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL \n                   completionBlock:(DOUBasicBlock)completionHandler {\n  DOUHttpRequest *req = [[self class] requestWithURL:URL];\n  [req setCompletionBlock:completionHandler];\n  [req setFailedBlock:completionHandler];\n  return req;\n}\n\n\n+ (DOUHttpRequest *)requestWithQuery:(DOUQuery *)query \n                     completionBlock:(DOUBasicBlock)completionHandler {\n  DOUHttpRequest *req = [[self class] requestWithURL:[query requestURL]];\n  [req setCompletionBlock:completionHandler];\n  [req setFailedBlock:completionHandler];\n  return req;\n}\n#endif\n\n\n+ (NSError *)adapterError:(NSError *)asiError {\n  NSError *doubanError;\n  switch ([asiError code]) {\n    case ASIConnectionFailureErrorType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOUConnectionFailureErrorType \n                                    userInfo:asiError.userInfo];\n        break;\n    case ASIRequestTimedOutErrorType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOURequestTimedOutErrorType \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOUAuthenticationErrorType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOUAuthenticationErrorType \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOURequestCancelledErrorType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOURequestCancelledErrorType \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOUUnableToCreateRequestErrorType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOUUnableToCreateRequestErrorType \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOUInternalErrorWhileBuildingRequestType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOUInternalErrorWhileBuildingRequestType \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOUInternalErrorWhileApplyingCredentialsType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOUInternalErrorWhileApplyingCredentialsType \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOUFileManagementError:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOUFileManagementError \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOUTooMuchRedirectionErrorType:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain\n                                        code:DOUTooMuchRedirectionErrorType \n                                    userInfo:asiError.userInfo];\n         break;\n    case DOUUnhandledExceptionError:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain \n                                        code:DOUUnhandledExceptionError \n                                    userInfo:asiError.userInfo];\n      break;\n    case DOUCompressionError:\n      doubanError = [NSError errorWithDomain:DOUHTTPRequestErrorDomain \n                                        code:DOUCompressionError \n                                    userInfo:asiError.userInfo];\n      break;\n    default:\n      doubanError = asiError;\n      break;\n  }\n  return doubanError;\n} \n\n\n- (NSError *)doubanError {\n  NSError *asiError = [super error];\n  // handle the http error\n  if (asiError) {\n    return [[self class] adapterError:asiError];\n  }\n  \n  int statusCode = [self responseStatusCode];\n  if (statusCode == 200 || statusCode == 201 || statusCode == 202) {\n    // success\n    return nil;\n  }\n  else if (statusCode == 400) {\n    // handle the oauth error\n    NSString *response = [self responseString];\n    NSDictionary *dic = [response JSONValue];  \n    NSInteger code = 0;\n    if (dic) {\n      code = [[dic objectForKey:@\"code\"] integerValue];\n    }\n\n    if (dic) {\n      NSError *oauthError = [NSError errorWithDomain:DOUOAuthErrorDomain\n                                                code:code \n                                            userInfo:dic];\n      return oauthError;\n    }\n  }\n      \n  NSError *otherError = [NSError errorWithDomain:DOUErrorDomain\n                                            code:error.code\n                                        userInfo:nil];\n  return otherError;  \n\n}\n\n- (void)appendPostString:(NSString *)string {\n\t[super appendPostData:[string dataUsingEncoding:NSUTF8StringEncoding]];\n}\n\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Network/DOUQuery.h",
    "content": "//\n//  DOUQuery.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n//\n// DOUQuery the class by which we can define the API Request.\n//\n@interface DOUQuery : NSObject {\n @private\n  NSString     *subPath_;\n  NSDictionary *parameters_;\n  NSString     *apiBaseUrlString_;\n}\n\n@property (nonatomic, copy) NSString *subPath;\n@property (nonatomic, retain) NSDictionary *parameters;\n@property (nonatomic, copy) NSString *apiBaseUrlString;\n\n- (id)initWithSubPath:(NSString *)aSubPath parameters:(NSDictionary *)theParameters;\n\n- (NSString *)requestURLString;\n\n- (NSURL *)requestURL;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Network/DOUQuery.m",
    "content": "//\n//  DOUQuery.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUQuery.h\"\n\n\n@implementation DOUQuery\n\n@synthesize subPath = subPath_;\n@synthesize parameters = parameters_;\n@synthesize apiBaseUrlString = apiBaseUrlString_;\n\n\n- (id)initWithSubPath:(NSString *)aSubPath parameters:(NSDictionary *)theParameters {\n  self = [super init];\n  if (self) {\n    subPath_ = [aSubPath retain];\n    parameters_ = [theParameters retain];\n  }\n  return self;\n}\n\n\n- (void)dealloc {\n  [subPath_ release]; subPath_ = nil;\n  [parameters_ release]; parameters_ = nil;\n  [apiBaseUrlString_ release]; apiBaseUrlString_ = nil;\n  [super dealloc];\n}\n\n\n- (NSString *)parametersUrlString {\n  NSString *parametersUrl = @\"\";\n  NSUInteger index = 0;\n  for (id key in [parameters_ allKeys]) {\n    NSString* value = [parameters_ objectForKey:key];\n    if (index == 0) {\n      parametersUrl = [parametersUrl stringByAppendingFormat:@\"?%@=%@\", key, value];\n    }\n    else {\n      parametersUrl = [parametersUrl stringByAppendingFormat:@\"&%@=%@\", key, value];\n    }\n    ++index;\n  }\n  return parametersUrl;\n}\n\n\n- (NSString *)requestURLString {\n  NSString *url = [NSString stringWithFormat:@\"%@%@\", apiBaseUrlString_, subPath_];\n  NSString *parameterStr = [self parametersUrlString];\n  if ( parameterStr != nil && [parameterStr length] > 0 ) {\n    url = [url stringByAppendingString:parameterStr];\n  }\n  \n  return [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];\n}\n\n\n- (NSURL *)requestURL {\n  return [NSURL URLWithString:[self requestURLString]];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Network/DOUService.h",
    "content": "//\n//  DOUService.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"DOUHttpRequest.h\"\n\n\n@class ASINetworkQueue;\n@interface DOUService : NSObject {\n @private\n  ASINetworkQueue   *queue_;  \n  NSString          *apiBaseUrlString_;  \n  NSString          *clientId_;\n  NSString          *clientSecret_;\n}\n\n@property (nonatomic, copy) NSString *apiBaseUrlString;\n@property (nonatomic, copy) NSString *clientId;\n@property (nonatomic, copy) NSString *clientSecret;\n\n\n+ (DOUService *)sharedInstance;\n\n- (BOOL)isValid;\n\n- (void)addRequest:(DOUHttpRequest *)request;\n\n\n#if NS_BLOCKS_AVAILABLE\n\n- (DOUHttpRequest *)get:(DOUQuery *)query callback:(DOUReqBlock)block;\n\n- (DOUHttpRequest *)post:(DOUQuery *)query \n                postBody:(NSString *)body \n                callback:(DOUReqBlock)block;\n\n- (DOUHttpRequest *)post:(DOUQuery *)query\n               photoData:(NSData *)photoData\n             description:(NSString *)description\n                callback:(DOUReqBlock)block\n  uploadProgressDelegate:(id<ASIProgressDelegate>)progressDelegate;\n\n// v2 api post image\n- (DOUHttpRequest *)post2:(DOUQuery *)query\n                photoData:(NSData *)photoData\n              description:(NSString *)description\n                 callback:(DOUReqBlock)block\n   uploadProgressDelegate:(id<ASIProgressDelegate>)progressDelegate;\n\n\n- (DOUHttpRequest *)put:(DOUQuery *)query\n                postBody:(NSString *)body\n                callback:(DOUReqBlock)block;\n\n- (DOUHttpRequest *)delete:(DOUQuery *)query callback:(DOUReqBlock)block;\n\n#endif\n\n\n- (DOUHttpRequest *)get:(DOUQuery *)query delegate:(id<DOUHttpRequestDelegate>)delegate;\n\n- (DOUHttpRequest *)post:(DOUQuery *)query postBody:(NSString *)body delegate:(id<DOUHttpRequestDelegate>)delegate;\n\n- (DOUHttpRequest *)delete:(DOUQuery *)query delegate:(id<DOUHttpRequestDelegate>)delegate;\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/Network/DOUService.m",
    "content": "//\n//  DOUService.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUService.h\"\n#import \"DOUHTTPRequest.h\"\n#import \"DOUAPIConfig.h\"\n#import \"GDataEntryBase.h\"\n#import \"DOUOAuthService.h\"\n#import \"DOUOAuthStore.h\"\n#import \"DOUQuery.h\"\n#import \"DoubanDefines.h\"\n#import \"NSData+Base64.h\"\n\n#import \"ASINetworkQueue.h\"\n\n\n@interface DOUService ()\n\n@property (nonatomic, retain) ASINetworkQueue   *queue;\n\n- (void)addRequest:(DOUHttpRequest *)request;\n- (void)setMaxConcurrentOperationCount:(NSUInteger)maxConcurrentOperationCount;\n\n@end\n\n@implementation DOUService\n\nNSUInteger const kDefaultMaxConcurrentOperationCount = 4;\n\n@synthesize queue = queue_;\n\n@synthesize apiBaseUrlString = apiBaseUrlString_;\n@synthesize clientId = clientId_;\n@synthesize clientSecret = clientSecret_;\n\n\n- (id)init {\n  self = [super init];\n  if (self) {\n    \n  }\n  return self;\n}\n\n\n- (void)dealloc {\n  [queue_ release]; queue_ = nil;\n  [apiBaseUrlString_ release]; apiBaseUrlString_ = nil;\n  [clientId_ release]; clientId_ = nil;\n  [clientSecret_ release]; clientSecret_ = nil;\n  [super dealloc];\n}\n\n\n#pragma mark - Singleton\n\nstatic DOUService *myInstance = nil;\n\n+ (DOUService *)sharedInstance {\n  \n  @synchronized(self) {\n    if (myInstance == nil) {\n      myInstance = [[DOUService alloc] init];\n    }\n    \n  }\n  return myInstance;\n}\n\n\n+ (id)allocWithZone:(NSZone *)zone {\n  @synchronized(self) {\n    if (myInstance == nil) {\n      myInstance = [super allocWithZone:zone];\n      return myInstance;  // assignment and return on first allocation\n    }\n  }\n  return nil; \n}\n\n- (id)copyWithZone:(NSZone *)zone {\n  return self;\n}\n\n\n- (id)retain {\n  return self;\n}\n\n\n- (unsigned)retainCount {\n  return UINT_MAX;\n}\n\n\n- (oneway void)release {\n  //nothing\n}\n\n\n- (id)autorelease {\n  return self;\n}\n\n\n\n- (NSError *)executeRefreshToken {\n  DOUOAuthService *service = [DOUOAuthService sharedInstance];\n  service.authorizationURL = kTokenUrl;\n  service.clientId = self.clientId;\n  service.clientSecret = self.clientSecret;\n  return [service validateRefresh];\n}\n\n\n\n- (NSDictionary *)parseQueryString:(NSString *)query {\n  NSMutableDictionary *dict = [[[NSMutableDictionary alloc] initWithCapacity:6] autorelease];\n  NSArray *pairs = [query componentsSeparatedByString:@\"&\"];\n  \n  for (NSString *pair in pairs) {\n    NSArray *elements = [pair componentsSeparatedByString:@\"=\"];\n    NSString *key = \n    [[elements objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];\n    NSString *val = \n    [[elements objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];\n    \n    [dict setObject:val forKey:key];\n  }\n  return dict;\n}\n\n\n- (void)sign:(DOUHttpRequest *)request {\n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  if (store.accessToken && ![store hasExpired]) {\n    NSString *authValue = [NSString stringWithFormat:@\"%@ %@\", @\"Bearer\", store.accessToken];\n    //NSLog(@\"bearer:%@\", authValue);\n    [request addRequestHeader:@\"Authorization\" value:authValue];      \n  }\n  else {\n    NSString *clientId = self.clientId;\n    if (!clientId) {\n      return ;\n    }\n    \n    NSURL *url = [request url];\n    NSString *urlString = [url absoluteString];\n    NSString *query = [url query];\n    if (query) {\n      NSDictionary *parameters = [self parseQueryString:query];\n      \n      NSArray *keys = [parameters allKeys];      \n      if ([keys count]  == 0) {\n        urlString = [urlString stringByAppendingFormat:@\"?%@=%@\", @\"apikey\", clientId];\n      }\n      else {\n        urlString = [urlString stringByAppendingFormat:@\"&%@=%@\", @\"apikey\", clientId];\n      }\n    }\n    else {\n      urlString = [urlString stringByAppendingFormat:@\"?%@=%@\", @\"apikey\", clientId];  \n    }\n    \n    NSString *afterUrl = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];\n    request.url = [NSURL URLWithString:afterUrl];\n  }\n  \n}\n\n\n- (void)addRequest:(DOUHttpRequest *)request {\n  \n  if (![self queue]) {\n    [self setQueue:[[[ASINetworkQueue alloc] init] autorelease]];\n    self.queue.maxConcurrentOperationCount = kDefaultMaxConcurrentOperationCount;\n  }\n  \n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  if (store.userId != 0 && store.refreshToken && [store shouldRefreshToken]) {\n    [self executeRefreshToken];\n  }\n  \n  [self sign:request];\n\n  [[self queue] addOperation:request];\n  [[self queue] go];\n}\n\n\n- (void)setMaxConcurrentOperationCount:(NSUInteger)maxCount {\n  self.queue.maxConcurrentOperationCount = maxCount;\n}\n\n\n- (BOOL)isValid {\n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  if (store.accessToken) {\n    return ![store hasExpired];\n  }\n  return NO;\n}\n\n\n#if NS_BLOCKS_AVAILABLE\n\n- (DOUHttpRequest *)get:(DOUQuery *)query callback:(DOUReqBlock)block {\n  query.apiBaseUrlString = self.apiBaseUrlString;\n  // __block, It tells the block not to retain the request, which is important in preventing a retain-cycle,\n  // since the request will always retain the block\n  __block DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query completionBlock:^{\n    if (block != NULL) {\n      block(req);      \n    }\n  }];\n  \n  [req setRequestMethod:@\"GET\"];\n\n  [self addRequest:req];\n  return req;\n}\n\n\n- (DOUHttpRequest *)post:(DOUQuery *)query postBody:(NSString *)body callback:(DOUReqBlock)block {\n  query.apiBaseUrlString = self.apiBaseUrlString;\n  __block DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query completionBlock:^{\n    if (block != NULL) {\n      block(req);      \n    }\n  }];\n  \n  [req setRequestMethod:@\"POST\"];\n  [req addRequestHeader:@\"Content-Type\" value:@\"application/x-www-form-urlencoded; charset=UTF-8\"];      \n\n  if (body && [body length] > 0) {\n    \n    NSError *error = nil;\n    GDataXMLElement *element = [[[GDataXMLElement alloc] initWithXMLString:body error:&error] autorelease];\n    if (!error && element) {\n      // if body is XML, Content-Type must be application/atom+xml\n      [req addRequestHeader:@\"Content-Type\" value:@\"application/atom+xml\"];\n    }\n    \n    NSData *objectData = [body dataUsingEncoding:NSUTF8StringEncoding];\n    NSString *length = [NSString stringWithFormat:@\"%d\", [objectData length]];\n    [req appendPostData:objectData];\n    [req addRequestHeader:@\"Content-Length\" value:length];        \n  }\n  else {\n    [req addRequestHeader:@\"Content-Length\" value:@\"0\"];\n  }\n  \n  [req setResponseEncoding:NSUTF8StringEncoding];\n  [self addRequest:req];\n  return req;\n}\n\n\n- (DOUHttpRequest *)post2:(DOUQuery *)query \n                photoData:(NSData *)photoData\n              description:(NSString *)description\n                 callback:(DOUReqBlock)block \n   uploadProgressDelegate:(id<ASIProgressDelegate>)progressDelegate {\n  \n  query.apiBaseUrlString = self.apiBaseUrlString;\n  __block DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query completionBlock:^{\n    if (block != NULL) {\n      block(req);      \n    }\n  }];\n  \n\n  NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));\n\t\n\t// We don't bother to check if post data contains the boundary, since it's pretty unlikely that it does.\n\tCFUUIDRef uuid = CFUUIDCreate(nil);\n\tNSString *uuidString = [(NSString*)CFUUIDCreateString(nil, uuid) autorelease];\n\tCFRelease(uuid);\n\tNSString *stringBoundary = [NSString stringWithFormat:@\"0xKhTmLbOuNdArY-%@\",uuidString];\n  NSString *endItemBoundary = [NSString stringWithFormat:@\"\\r\\n--%@\\r\\n\",stringBoundary];\n\n  [req setRequestMethod:@\"POST\"];\n  [req setResponseEncoding:NSUTF8StringEncoding];\n  [req setUploadProgressDelegate:progressDelegate];\n  \n\t[req addRequestHeader:@\"Content-Type\" value:[NSString stringWithFormat:@\"multipart/form-data; charset=%@; boundary=%@\", charset, stringBoundary]];\n\t\n\t[req appendPostString:[NSString stringWithFormat:@\"--%@\\r\\n\",stringBoundary]];\n\t\n\t// Adds post data\n  [req appendPostString:[NSString stringWithFormat:@\"Content-Disposition: form-data; name=\\\"%@\\\"\\r\\n\\r\\n\", @\"desc\"]];\n  [req appendPostString:description];\n  [req appendPostString:endItemBoundary];\n\n  // Adds Post file  \n  [req appendPostString:[NSString stringWithFormat:@\"Content-Disposition: form-data; name=\\\"%@\\\"; filename=\\\"%@\\\"\\r\\n\", @\"image\", @\"image.jpeg\"]];\n  [req appendPostString:[NSString stringWithFormat:@\"Content-Type: %@\\r\\n\\r\\n\", @\"image/jpeg\"]];\n  [req appendPostData:photoData];\n  \n\t[req appendPostString:[NSString stringWithFormat:@\"\\r\\n--%@--\\r\\n\",stringBoundary]];\n  \n  // request length\n  NSData *postData = [req postBody];\n  [req addRequestHeader:@\"Content-Length\" value:[NSString stringWithFormat:@\"%d\", [postData length]]];  \n  \n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  if (store.userId != 0 && store.refreshToken && [store shouldRefreshToken]) {\n    [self executeRefreshToken];\n  }\n  \n  [self sign:req];\n  [req startAsynchronous];\n  return req;\n}\n\n\n- (DOUHttpRequest *)post:(DOUQuery *)query \n               photoData:(NSData *)photoData\n             description:(NSString *)description\n                callback:(DOUReqBlock)block \n  uploadProgressDelegate:(id<ASIProgressDelegate>)progressDelegate {\n  \n  query.apiBaseUrlString = self.apiBaseUrlString;\n  __block DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query completionBlock:^{\n    if (block != NULL) {\n      block(req);      \n    }\n  }];\n  \n  \n  NSString *boundary = [[NSProcessInfo processInfo] globallyUniqueString];\n  NSData *boundaryData   = [[NSString stringWithFormat:@\"--%@\\n\", boundary] \n                                     dataUsingEncoding:NSUTF8StringEncoding];\n\n  NSData *finalBoundaryData = [[NSString stringWithFormat:@\"\\n--%@--\", boundary]\n                                        dataUsingEncoding:NSUTF8StringEncoding]; \n\n  [req setRequestMethod:@\"POST\"];\n  [req setResponseEncoding:NSUTF8StringEncoding];\n  [req setUploadProgressDelegate:progressDelegate];\n\n  [req addRequestHeader:@\"Content-Type\" \n                  value:[NSString stringWithFormat:@\"multipart/related; boundary=\\\"%@\\\"\", boundary]];\n  [req addRequestHeader:@\"MIME-version\" value:@\"1.0\"];\n  \n  // Content XML\n  [req appendPostData:boundaryData];\n  [req appendPostData:[@\"Content-Type: application/atom+xml\\n\\n\" dataUsingEncoding:NSUTF8StringEncoding]];\n  \n  GDataEntryBase *emptyEntry = [[[GDataEntryBase alloc] init] autorelease];\n  NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:kAtomNamespace, kAtomNamespacePrefix, kDoubanNamespace, kDoubanNamespacePrefix, nil];\n  [emptyEntry addNamespaces:dic];\n  [emptyEntry addExtensionDeclarations];\n  \n  GDataEntryContent *content = [GDataEntryContent contentWithString:description];\n  [emptyEntry setContent:content];\n  NSData *descData = [[emptyEntry XMLDocument] XMLData];\n  [req appendPostData:descData];\n  [req appendPostData:boundaryData];\n  \n  // Image base64 binary\n  [req appendPostData:[@\"Content-Type: image/jpeg\\n\\n\" dataUsingEncoding:NSUTF8StringEncoding]];\n  \n  NSString *encodingStr = [photoData base64EncodedString];\n  NSData *data = [encodingStr dataUsingEncoding:NSUTF8StringEncoding];\n  [req appendPostData:data];\n  [req appendPostData:finalBoundaryData];\n\n  // request length\n  NSData *postData = [req postBody];\n  [req addRequestHeader:@\"Content-Length\" value:[NSString stringWithFormat:@\"%d\", [postData length]]];  \n  \n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  if (store.userId != 0 && store.refreshToken && [store shouldRefreshToken]) {\n    [self executeRefreshToken];\n  }\n  \n  [self sign:req];\n  //NSLog(@\"request url:%@\", [req.url absoluteString]);\n  [req startAsynchronous];\n  return req;  \n}\n\n\n- (DOUHttpRequest *)put:(DOUQuery *)query postBody:(NSString *)body callback:(DOUReqBlock)block {\n  query.apiBaseUrlString = self.apiBaseUrlString;\n  __block DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query completionBlock:^{\n    if (block != NULL) {\n      block(req);\n    }\n  }];\n  \n  [req setRequestMethod:@\"PUT\"];\n  [req addRequestHeader:@\"Content-Type\" value:@\"application/x-www-form-urlencoded; charset=UTF-8\"];\n  \n  if (body && [body length] > 0) {\n    \n    NSError *error = nil;\n    GDataXMLElement *element = [[[GDataXMLElement alloc] initWithXMLString:body error:&error] autorelease];\n    if (!error && element) {\n      // if body is XML, Content-Type must be application/atom+xml\n      [req addRequestHeader:@\"Content-Type\" value:@\"application/atom+xml\"];\n    }\n    \n    NSData *objectData = [body dataUsingEncoding:NSUTF8StringEncoding];\n    NSString *length = [NSString stringWithFormat:@\"%d\", [objectData length]];\n    [req appendPostData:objectData];\n    [req addRequestHeader:@\"Content-Length\" value:length];\n  }\n  else {\n    [req addRequestHeader:@\"Content-Length\" value:@\"0\"];\n  }\n  \n  [req setResponseEncoding:NSUTF8StringEncoding];\n  [self addRequest:req];\n  return req;\n}\n\n\n- (DOUHttpRequest *)delete:(DOUQuery *)query callback:(DOUReqBlock)block {\n  \n  query.apiBaseUrlString = self.apiBaseUrlString;\n\n  __block DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query completionBlock:^{\n    if (block != NULL) {\n      block(req);      \n    }\n  }];\n  \n  [req setRequestMethod:@\"DELETE\"];\n  [req addRequestHeader:@\"Content-Type\" value:@\"application/atom+xml\"];\n  [req addRequestHeader:@\"Content-Length\" value:@\"0\"];\n  [self addRequest:req];\n  return req;\n}\n\n\n#endif\n\n\n- (DOUHttpRequest *)get:(DOUQuery *)query delegate:(id<DOUHttpRequestDelegate>)delegate {\n  query.apiBaseUrlString = self.apiBaseUrlString;\n  DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query target:delegate];\n  \n  [req setRequestMethod:@\"GET\"];\n  [self addRequest:req];\n  return req;\n}\n\n\n- (DOUHttpRequest *)post:(DOUQuery *)query postBody:(NSString *)body delegate:(id<DOUHttpRequestDelegate>)delegate {\n  query.apiBaseUrlString = self.apiBaseUrlString;\n  DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query target:delegate];\n  \n  [req setRequestMethod:@\"POST\"];\n  [req addRequestHeader:@\"Content-Type\" value:@\"application/x-www-form-urlencoded; charset=UTF-8\"];\n  \n  if (body && [body length] > 0) {\n    \n    NSError *error = nil;\n    GDataXMLElement *element = [[[GDataXMLElement alloc] initWithXMLString:body error:&error] autorelease];\n    if (!error && element) {\n      // if body is XML, Content-Type must be application/atom+xml\n      [req addRequestHeader:@\"Content-Type\" value:@\"application/atom+xml\"];\n    }\n    \n    NSData *objectData = [body dataUsingEncoding:NSUTF8StringEncoding];\n    NSString *length = [NSString stringWithFormat:@\"%d\", [objectData length]];\n    [req appendPostData:objectData];\n    [req addRequestHeader:@\"Content-Length\" value:length];        \n  }\n  else {\n    [req addRequestHeader:@\"Content-Length\" value:@\"0\"];\n  }\n  \n  [req setResponseEncoding:NSUTF8StringEncoding];\n  [self addRequest:req];\n  return req;\n}\n\n\n- (DOUHttpRequest *)delete:(DOUQuery *)query delegate:(id<DOUHttpRequestDelegate>)delegate {\n  query.apiBaseUrlString = self.apiBaseUrlString;\n\n  DOUHttpRequest * req = [DOUHttpRequest requestWithQuery:query target:delegate];\n  [req setRequestMethod:@\"DELETE\"];\n  [req addRequestHeader:@\"Content-Type\" value:@\"application/atom+xml\"];\n  [req addRequestHeader:@\"Content-Length\" value:@\"0\"];      \n  [self addRequest:req];\n  return req;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/OAuth2/DOUOAuth2.h",
    "content": "//\n//  DOUOAuth2Client.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 31/10/2011.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\nstatic NSString * const kOAuthErrorDomain = @\"kOAuthErrorDomain\";\n\nstatic NSInteger const kOAuthErrorInvalidRequestScheme       = 100;\nstatic NSInteger const kOAuthErrorInvalidRequestMethod       = 101;\nstatic NSInteger const kOAuthErrorAccessTokenIsMissing       = 102;\nstatic NSInteger const kOAuthErrorInvalidAccessToken         = 103;\nstatic NSInteger const kOAuthErrorInvalidAPIKey              = 104;\nstatic NSInteger const kOAuthErrorAPIKeyIsBlocked            = 105;\nstatic NSInteger const kOAuthErrorAccessTokenHasExpired      = 106;\nstatic NSInteger const kOAuthErrorInvalidRequestUri          = 107; \nstatic NSInteger const kOAuthErrorInvalidCredencial          = 108;\nstatic NSInteger const kOAuthErrorInvalidCredencial2         = 109;\nstatic NSInteger const kOAuthErrorNotTrialUser               = 110;\nstatic NSInteger const kOAuthErrorRateLimitExceeded          = 111;\nstatic NSInteger const kOAuthErrorRateLimitExceeded2         = 112;\nstatic NSInteger const kOAuthErrorRequiredParameterIsMissing = 113;\nstatic NSInteger const kOAuthErrorUnsupportedGrantType       = 114;\nstatic NSInteger const kOAuthErrorUnsupportedResponseType    = 115;\nstatic NSInteger const kOAuthErrorClientSecretMismatch       = 116;\nstatic NSInteger const kOAuthErrorRedirectUriMismatch        = 117;\nstatic NSInteger const kOAuthErrorInvalidAuthorizationCode   = 118;\nstatic NSInteger const kOAuthErrorInvalidRefreshToken        = 119;\nstatic NSInteger const kOAuthErrorUsernamePasswordMismatch   = 120;\nstatic NSInteger const kOAuthErrorInvalidUser                = 121;\nstatic NSInteger const kOAuthErrorUserHasBlocked             = 122;\nstatic NSInteger const kOAuthErrorAccessTokenHasExpiredSincePasswordChanged = 123;\nstatic NSInteger const kOAuthErrorAccessTokenHasNotExpired   = 124;\nstatic NSInteger const kOAuthErrorUnknown                    = 999;\n\n\nstatic NSString * const kClientIdKey = @\"client_id\";\nstatic NSString * const kClientSecretKey = @\"client_secret\";\nstatic NSString * const kRedirectURIKey = @\"redirect_uri\";\n\nstatic NSString * const kGrantTypeKey = @\"grant_type\";\nstatic NSString * const kAccessTokenKey = @\"access_token\";\nstatic NSString * const kRefreshTokenKey = @\"refresh_token\";\n\nstatic NSString * const kExpiresInKey = @\"expires_in\";\nstatic NSString * const kScopeKey = @\"scope\";\nstatic NSString * const kStateKey = @\"state\";\n\nstatic NSString * const kUserIdKey = @\"user_id\";\nstatic NSString * const kGrantTypeAuthorizationCode = @\"authorization_code\";\nstatic NSString * const kGrantTypeRefreshToken = @\"refresh_token\";\nstatic NSString * const kGrantTypePassword = @\"password\";\n\nstatic NSString * const kUsernameKey = @\"username\";\nstatic NSString * const kPasswordKey = @\"password\";\n\n\nstatic NSString * const kDoubanUserIdKey = @\"douban_user_id\";\n\nstatic NSString * const kOAuth2ResponseType = @\"response_type\";\nstatic NSString * const kOAuth2ResponseTypeCode = @\"code\";\nstatic NSString * const kOAuth2ResponseTypeToken = @\"refresh_token\";\n\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/OAuth2/DOUOAuthService.h",
    "content": "//\n//  DOUOAuthService.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"DOUService.h\"\n\n\n@class DOUOAuthService;\n@protocol DOUOAuthServiceDelegate <NSObject>\n\n@required\n\n- (void)OAuthClient:(DOUOAuthService *)client didAcquireSuccessDictionary:(NSDictionary *)dic;\n\n- (void)OAuthClient:(DOUOAuthService *)client didFailWithError:(NSError *)error;\n\n@end\n\n\n\n@interface DOUOAuthService : NSObject {\n @private\n@private\n\tNSString *clientId_;\n  NSString *clientSecret_;\n\tNSString *authorizationCode_;\n  NSString *authorizationURL_;\n  NSString *callbackURL_;\n\n  \n  id<DOUOAuthServiceDelegate> delegate_;\n}\n\n@property (nonatomic, assign) id<DOUOAuthServiceDelegate> delegate;\n@property (nonatomic, retain) NSString *clientId;\n@property (nonatomic, retain) NSString *clientSecret;\n@property (nonatomic, retain) NSString *authorizationURL;\n@property (nonatomic, retain) NSString *callbackURL;\n@property (nonatomic, retain) NSString *authorizationCode;\n\n\n+ (id)sharedInstance;\n\n- (void)validateAuthorizationCode;\n\n- (void)validateUsername:(NSString *)username password:(NSString *)password;\n\n- (NSError *)validateRefresh;\n\n\n#if NS_BLOCKS_AVAILABLE\n\n- (void)validateUsername:(NSString *)username \n                password:(NSString *)password\n                callback:(DOUBasicBlock)block;\n\n- (void)validateAuthorizationCodeWithCallback:(DOUBasicBlock)block;\n\n#endif\n\n- (void)logout;\n\n@end\n\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/OAuth2/DOUOAuthService.m",
    "content": "//\n//  DOUOAuthRequest.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUOAuthService.h\"\n#import \"DOUOAuth2.h\"\n#import \"DOUOAUthStore.h\"\n#import \"SBJson.h\"\n#import \"ASIFormDataRequest.h\"\n\n\n@interface DOUOAuthService () <ASIHTTPRequestDelegate>\n@end\n\n\n@implementation DOUOAuthService\n\n@synthesize delegate = delegate_;\n\n@synthesize clientId = clientId_;\n@synthesize clientSecret = clientSecret_;\n@synthesize authorizationURL = authorizationURL_;\n@synthesize callbackURL = callbackURL_;\n@synthesize authorizationCode = authorizationCode_;\n\n\nstatic DOUOAuthService *myInstance = nil;\n\n+ (DOUOAuthService *)sharedInstance {\n  \n  @synchronized(self) {\n    if (myInstance == nil) {\n      myInstance = [[DOUOAuthService alloc] init];\n    }\n    \n  }\n  return myInstance;\n}\n\n\n+ (id)allocWithZone:(NSZone *)zone {\n  @synchronized(self) {\n    if (myInstance == nil) {\n      myInstance = [super allocWithZone:zone];\n      return myInstance;  // assignment and return on first allocation\n    }\n  }\n  return nil; \n}\n\n\n- (id)copyWithZone:(NSZone *)zone {\n  return self;\n}\n\n\n- (id)retain {\n  return self;\n}\n\n\n- (unsigned)retainCount {\n  return UINT_MAX;\n}\n\n\n- (oneway void)release {\n  //nothing\n}\n\n\n- (id)autorelease {\n  return self;\n}\n\n\n- (void)dealloc {\n  [clientId_ release];\n  [clientSecret_ release];\n  [authorizationCode_ release];\n  [callbackURL_ release];\n  [authorizationURL_ release];\n  [super dealloc];\n}\n\n\n\n\n\n#pragma mark - Auth2 actions\n\n- (ASIFormDataRequest *)formRequest {\n  NSURL *URL = [NSURL URLWithString:authorizationURL_];\n  ASIFormDataRequest *req = [ASIFormDataRequest requestWithURL:URL];\n  [req setRequestMethod:@\"POST\"];\n  [req setValidatesSecureCertificate:NO];\n  [req setAllowCompressedResponse:YES]; // YES is the default\n  [req setTimeOutSeconds:kDefaultTimeoutSeconds];\n  \n  [req setPostValue:self.clientId forKey:kClientIdKey];\n  [req setPostValue:self.clientSecret forKey:kClientSecretKey];\n  [req setPostValue:self.callbackURL forKey:kRedirectURIKey];\n  \n  return req;\n}\n\n\n- (void)validateAuthorizationCode {\n  ASIFormDataRequest *req = [self formRequest];\n  [req setDelegate:self];\n  [req setPostValue:@\"authorization_code\" forKey:kGrantTypeKey]; \n  [req setPostValue:self.authorizationCode forKey:kOAuth2ResponseTypeCode];\n  [req startAsynchronous];\n}\n\n\n- (void)validateUsername:(NSString *)username password:(NSString *)password {  \n  ASIFormDataRequest *req = [self formRequest];\n  [req setDelegate:self];\n\n  [req setPostValue:kGrantTypePassword forKey:kGrantTypeKey];  \n  [req setPostValue:username forKey:kUsernameKey];\n  [req setPostValue:password forKey:kPasswordKey];\n\n  [req startAsynchronous];\n}\n\n\n- (NSError *)validateRefresh {\n  ASIFormDataRequest *req = [self formRequest];\n  [req setPostValue:kGrantTypeRefreshToken forKey:kGrantTypeKey];\n  \n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  NSString *refreshToken = store.refreshToken;\n  [req setPostValue:refreshToken forKey:kOAuth2ResponseTypeToken];\n  [req startSynchronous];\n  \n  NSError *error = [req error];\n  if (!error) {\n    NSString* responseStr = [req responseString];\n    NSDictionary *dic = [responseStr JSONValue];\n    DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n    [store updateWithSuccessDictionary:dic];\n  }\n  \n  return error;\n}\n\n\n- (void)requestFailed:(ASIHTTPRequest *)req {\n  NSError *error = nil;\n  \n  NSError *asiError = [req error];\n  // handle the http error\n  if (asiError) {\n     error = [DOUHttpRequest adapterError:asiError];\n  }\n\n  // handle the oauth error\n  int statusCode = [req responseStatusCode];\n  if (statusCode >= 400 && statusCode <= 403) {\n    NSString *response = [req responseString];\n    NSDictionary *dic = [response JSONValue];  \n    if (dic) {\n      NSInteger code = [[dic objectForKey:@\"code\"] integerValue];\n      error = [NSError errorWithDomain:DOUOAuthErrorDomain\n                                  code:code \n                              userInfo:dic];\n    }\n  }\n\n  if ([delegate_ respondsToSelector:@selector(OAuthClient:didFailWithError:)]) {\n    [delegate_ OAuthClient:self didFailWithError:error];\n  }\n \n}\n\n\n- (void)requestFinished:(ASIHTTPRequest *)req {\n  NSError *error = nil;\n\n  NSError *asiError = [req error];\n  if (asiError) {\n    error = [DOUHttpRequest adapterError:asiError];\n  }\n  \n  // handle the oauth error\n  int statusCode = [req responseStatusCode];\n  if (statusCode >= 400 && statusCode <= 403) {\n    NSString *response = [req responseString];\n    NSDictionary *dic = [response JSONValue];  \n    if (dic) {\n      NSInteger code = [[dic objectForKey:@\"code\"] integerValue];\n      error = [NSError errorWithDomain:DOUOAuthErrorDomain\n                                  code:code \n                              userInfo:dic];\n    }\n  }\n  \n  // Error\n  if (error) {\n    if ([delegate_ respondsToSelector:@selector(OAuthClient:didFailWithError:)]) {\n      [delegate_ OAuthClient:self didFailWithError:error];\n      return ;\n    }\n  }\n  \n  // Success\n  NSString *response = [req responseString];\n  NSLog(@\"login success:%@\", response);\n  NSDictionary *dic = [response JSONValue];\n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  [store updateWithSuccessDictionary:dic];\n  \n  if ([delegate_ respondsToSelector:@selector(OAuthClient:didAcquireSuccessDictionary:)]) {\n    [delegate_ OAuthClient:self didAcquireSuccessDictionary:dic];\n  }\n}\n \n\n\n\n#if NS_BLOCKS_AVAILABLE\n\n- (void)validateUsername:(NSString *)username\n                password:(NSString *)password \n                callback:(DOUBasicBlock)block {\n  ASIFormDataRequest *req = [self formRequest];\n  \n  [req setDelegate:self];\n\n  [req setPostValue:@\"password\" forKey:kGrantTypeKey];  \n  [req setPostValue:username forKey:kUsernameKey];\n  [req setPostValue:password forKey:kPasswordKey];\n  [req setCompletionBlock:block];\n  [req setFailedBlock:block];\n  \n  [req startAsynchronous];\n}\n\n\n- (void)validateAuthorizationCodeWithCallback:(DOUBasicBlock)block {\n  ASIFormDataRequest *req = [self formRequest];\n  [req setDelegate:self];\n  [req setPostValue:@\"authorization_code\" forKey:kGrantTypeKey]; \n  [req setPostValue:self.authorizationCode forKey:kOAuth2ResponseTypeCode];\n\n  [req setCompletionBlock:block];\n  [req setFailedBlock:block];\n  \n  [req startAsynchronous];\n}\n\n\n#endif\n\n\n\n- (void)logout {\n  DOUOAuthStore *store = [DOUOAuthStore sharedInstance];\n  [store clear];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/OAuth2/DOUOAuthStore.h",
    "content": "//\n//  DOUOAuthStore.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface DOUOAuthStore : NSObject {\n @private  \n  NSString   *accessToken_;\n  NSString   *refreshToken_;\n  NSDate     *expiresIn_;\n  int        userId_;\n}\n\n\n@property (nonatomic, copy, readonly) NSString *accessToken;\n@property (nonatomic, copy, readonly) NSString *refreshToken;\n@property (nonatomic, copy, readonly) NSDate *expiresIn;\n\n@property (nonatomic, assign, readonly) int userId;\n\n+ (id)sharedInstance;\n\n\n- (void)updateWithSuccessDictionary:(NSDictionary *)dic;\n\n- (BOOL)hasExpired;\n\n// refresh token one day before token is expired.\n- (BOOL)shouldRefreshToken;\n\n- (void)save;\n\n- (void)clear;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine/Sources/OAuth2/DOUOAuthStore.m",
    "content": "//\n//  DOUOAuth2Consumer.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUOAuthStore.h\"\n#import \"DOUOAuth2.h\"\n#import \"SBJson.h\"\n\n\n@interface DOUOAuthStore ()\n@property (nonatomic, copy) NSString *accessToken;\n@property (nonatomic, copy) NSString *refreshToken;\n@property (nonatomic, copy) NSDate *expiresIn;\n@property (nonatomic, assign) int userId;\n@end\n\n\n@implementation DOUOAuthStore\n\nstatic NSString *kUserDefaultsAccessTokenKey = @\"douban_userdefaults_access_token\";\nstatic NSString *kUserDefaultsRefreshTokenKey = @\"douban_userdefaults_refresh_token\";\nstatic NSString *kUserDefaultsExpiresInKey = @\"douban_userdefaults_expires_in\";\nstatic NSString *kUserDefaultsUserIdKey = @\"douban_userdefaults_user_id\";\n\n@synthesize accessToken  = accessToken_;\n@synthesize refreshToken = refreshToken_;\n@synthesize expiresIn = expiresIn_;\n@synthesize userId = userId_;\n\n\n- (id)init {\n\tself = [super init];\n\tif( self ) {\n    [self updateWithUserDefaults];\n\t}\n\treturn self;\n}\n\n\n#pragma mark - Singleton\n\nstatic DOUOAuthStore *myInstance = nil;\n\n+ (DOUOAuthStore *)sharedInstance {\n  \n  @synchronized(self) {\n    if (myInstance == nil) {\n      myInstance = [[DOUOAuthStore alloc] init];\n    }\n    \n  }\n  return myInstance;\n}\n\n\n+ (id)allocWithZone:(NSZone *)zone {\n  @synchronized(self) {\n    if (myInstance == nil) {\n      myInstance = [super allocWithZone:zone];\n      return myInstance;  // assignment and return on first allocation\n    }\n  }\n  return nil; \n}\n\n\n- (id)copyWithZone:(NSZone *)zone {\n  return self;\n}\n\n\n- (id)retain {\n  return self;\n}\n\n\n- (unsigned)retainCount {\n  return UINT_MAX;\n}\n\n\n- (oneway void)release {\n  //nothing\n}\n\n\n- (id)autorelease {\n  return self;\n}\n\n- (void)dealloc {\n  [accessToken_ release];\taccessToken_ = nil;\n\t[refreshToken_ release]; refreshToken_ = nil;\n  [expiresIn_ release]; expiresIn_ = nil;\n\t[super dealloc];\n}\n\n\n- (void)updateWithSuccessDictionary:(NSDictionary *)dic {\n\n  self.accessToken = [dic objectForKey:kAccessTokenKey];\n  self.refreshToken = [dic objectForKey:kRefreshTokenKey];\n  \n  NSUInteger expiresSecond = [[dic objectForKey:kExpiresInKey] integerValue];\n  self.expiresIn = [[NSDate date] dateByAddingTimeInterval:expiresSecond];\n  self.userId = [[dic objectForKey:kDoubanUserIdKey] intValue];\n  [self save];\n}\n\n\n- (BOOL)hasExpired {\n  NSDate *now = [NSDate date];\n  NSDate *thirtyMinutesBeforeExpires = [self.expiresIn dateByAddingTimeInterval:-1800];\n  if([now compare:thirtyMinutesBeforeExpires] == NSOrderedAscending) {\n\t\treturn NO;\n\t}\n\telse {\n\t\treturn YES;\n\t}\n}\n\n\n- (BOOL)shouldRefreshToken {\n  NSDate *now = [NSDate date];\n  NSDate *oneDayBeforeExpires = [self.expiresIn dateByAddingTimeInterval:-86400];\n  if([now compare:oneDayBeforeExpires] == NSOrderedAscending) {\n\t\treturn NO;\n\t}\n\telse{\n\t\treturn YES;\n\t}\n\n}\n\n\n- (void)save {\n  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];\n  [userDefaults setObject:accessToken_ forKey:kUserDefaultsAccessTokenKey];\n  [userDefaults setObject:refreshToken_ forKey:kUserDefaultsRefreshTokenKey];\n  [userDefaults setObject:expiresIn_ forKey:kUserDefaultsExpiresInKey];\n  [userDefaults setInteger:userId_ forKey:kUserDefaultsUserIdKey];\n  [userDefaults synchronize];\n}\n\n\n- (void)clear {\n  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];\n  [userDefaults removeObjectForKey:kUserDefaultsAccessTokenKey];\n  [userDefaults removeObjectForKey:kUserDefaultsRefreshTokenKey];\n  [userDefaults removeObjectForKey:kUserDefaultsExpiresInKey];\n  [userDefaults removeObjectForKey:kUserDefaultsUserIdKey];\n  [userDefaults synchronize];\n}\n\n\n- (NSString *)accessToken {\n  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];\n  self.accessToken = [userDefaults stringForKey:kUserDefaultsAccessTokenKey];\n  //NSLog(@\"token:%@\", accessToken_);\n  return accessToken_;\n}\n\n\n- (NSString *)refreshToken {\n  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];\n  self.refreshToken = [userDefaults stringForKey:kUserDefaultsRefreshTokenKey];\n  return refreshToken_;\n}\n\n\n- (NSDate *)expiresIn {\n  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];\n  self.expiresIn = [userDefaults objectForKey:kUserDefaultsExpiresInKey];\n  return expiresIn_;\n}\n\n\n- (int)userId {\n  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];\n  self.userId = [[userDefaults objectForKey:kUserDefaultsUserIdKey] intValue];\n  return userId_;\n}\n\n\n- (void)updateWithUserDefaults {\n  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];\n  self.accessToken = [userDefaults stringForKey:kUserDefaultsAccessTokenKey];\n  self.refreshToken = [userDefaults stringForKey:kUserDefaultsRefreshTokenKey];\n  self.expiresIn = [userDefaults objectForKey:kUserDefaultsExpiresInKey];\n  self.userId = [[userDefaults objectForKey:kUserDefaultsUserIdKey] intValue];\n}\n\n\n- (NSString*)description {\n  return [NSString stringWithFormat:@\"%@\\r\\ntoken = %@\\r\\nexpiry = %@\",[super description], accessToken_, expiresIn_];\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngine.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXAggregateTarget section */\n\t\tD820CFA7166E03FC0067C5A5 /* libDoubanApiEngine */ = {\n\t\t\tisa = PBXAggregateTarget;\n\t\t\tbuildConfigurationList = D820CFAA166E03FC0067C5A5 /* Build configuration list for PBXAggregateTarget \"libDoubanApiEngine\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tD820CFAE166E04230067C5A5 /* ShellScript */,\n\t\t\t\tD820CFAF166E044C0067C5A5 /* ShellScript */,\n\t\t\t\tD820CFB0166E04AA0067C5A5 /* CopyFiles */,\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tD820CFAD166E04170067C5A5 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = libDoubanApiEngine;\n\t\t\tproductName = libDoubanApiEngine;\n\t\t};\n/* End PBXAggregateTarget section */\n\n/* Begin PBXBuildFile section */\n\t\t1A3451DA167887E90097FEF5 /* DOUBookArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A3451D6167887E90097FEF5 /* DOUBookArray.m */; };\n\t\t1A3451DB167887E90097FEF5 /* DOUBookArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A3451D7167887E90097FEF5 /* DOUBookArray.h */; };\n\t\t1A3451DC167887E90097FEF5 /* DOUBook.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A3451D8167887E90097FEF5 /* DOUBook.m */; };\n\t\t1A3451DD167887E90097FEF5 /* DOUBook.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A3451D9167887E90097FEF5 /* DOUBook.h */; };\n\t\t1A3451E2167887F80097FEF5 /* DOUMusicArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A3451DE167887F80097FEF5 /* DOUMusicArray.m */; };\n\t\t1A3451E3167887F80097FEF5 /* DOUMusicArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A3451DF167887F80097FEF5 /* DOUMusicArray.h */; };\n\t\t1A3451E4167887F80097FEF5 /* DOUMusic.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A3451E0167887F80097FEF5 /* DOUMusic.m */; };\n\t\t1A3451E5167887F80097FEF5 /* DOUMusic.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A3451E1167887F80097FEF5 /* DOUMusic.h */; };\n\t\t1A3451E8167889060097FEF5 /* MusicArray.json in Resources */ = {isa = PBXBuildFile; fileRef = 1A3451E6167889060097FEF5 /* MusicArray.json */; };\n\t\t1A3451E9167889060097FEF5 /* BookArray.json in Resources */ = {isa = PBXBuildFile; fileRef = 1A3451E7167889060097FEF5 /* BookArray.json */; };\n\t\t1A3451EC167889140097FEF5 /* DOUMusicTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A3451EA167889140097FEF5 /* DOUMusicTests.m */; };\n\t\t1A3451ED167889140097FEF5 /* DOUBookTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A3451EB167889140097FEF5 /* DOUBookTests.m */; };\n\t\tD800D53C146907B2009F64FD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D53B146907B2009F64FD /* Foundation.framework */; };\n\t\tD800D54A146907B2009F64FD /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D549146907B2009F64FD /* SenTestingKit.framework */; };\n\t\tD800D54D146907B2009F64FD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D53B146907B2009F64FD /* Foundation.framework */; };\n\t\tD800D550146907B2009F64FD /* libDoubanAPIEngine.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D538146907B2009F64FD /* libDoubanAPIEngine.a */; settings = {ATTRIBUTES = (Required, ); }; };\n\t\tD800D556146907B2009F64FD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D800D554146907B2009F64FD /* InfoPlist.strings */; };\n\t\tD800D559146907B2009F64FD /* DoubanAPIEngineTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D558146907B2009F64FD /* DoubanAPIEngineTests.m */; };\n\t\tD800D56D146908AF009F64FD /* DOUAPIEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D563146908AF009F64FD /* DOUAPIEngine.h */; };\n\t\tD800D56E146908AF009F64FD /* DOUHttpRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D565146908AF009F64FD /* DOUHttpRequest.h */; };\n\t\tD800D56F146908AF009F64FD /* DOUHttpRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D566146908AF009F64FD /* DOUHttpRequest.m */; };\n\t\tD800D570146908AF009F64FD /* DOUOAuth2.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D568146908AF009F64FD /* DOUOAuth2.h */; };\n\t\tD800D5C9146908FD009F64FD /* ASIAuthenticationDialog.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D577146908FD009F64FD /* ASIAuthenticationDialog.h */; };\n\t\tD800D5CA146908FD009F64FD /* ASIAuthenticationDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D578146908FD009F64FD /* ASIAuthenticationDialog.m */; };\n\t\tD800D5CB146908FD009F64FD /* ASICacheDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D579146908FD009F64FD /* ASICacheDelegate.h */; };\n\t\tD800D5CC146908FD009F64FD /* ASIDataCompressor.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D57A146908FD009F64FD /* ASIDataCompressor.h */; };\n\t\tD800D5CD146908FD009F64FD /* ASIDataCompressor.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D57B146908FD009F64FD /* ASIDataCompressor.m */; };\n\t\tD800D5CE146908FD009F64FD /* ASIDataDecompressor.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D57C146908FD009F64FD /* ASIDataDecompressor.h */; };\n\t\tD800D5CF146908FD009F64FD /* ASIDataDecompressor.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D57D146908FD009F64FD /* ASIDataDecompressor.m */; };\n\t\tD800D5D0146908FD009F64FD /* ASIDownloadCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D57E146908FD009F64FD /* ASIDownloadCache.h */; };\n\t\tD800D5D1146908FD009F64FD /* ASIDownloadCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D57F146908FD009F64FD /* ASIDownloadCache.m */; };\n\t\tD800D5D2146908FD009F64FD /* ASIFormDataRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D580146908FD009F64FD /* ASIFormDataRequest.h */; };\n\t\tD800D5D3146908FD009F64FD /* ASIFormDataRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D581146908FD009F64FD /* ASIFormDataRequest.m */; };\n\t\tD800D5D4146908FD009F64FD /* ASIHTTPRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D582146908FD009F64FD /* ASIHTTPRequest.h */; };\n\t\tD800D5D5146908FD009F64FD /* ASIHTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D583146908FD009F64FD /* ASIHTTPRequest.m */; };\n\t\tD800D5D6146908FD009F64FD /* ASIHTTPRequestConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D584146908FD009F64FD /* ASIHTTPRequestConfig.h */; };\n\t\tD800D5D7146908FD009F64FD /* ASIHTTPRequestDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D585146908FD009F64FD /* ASIHTTPRequestDelegate.h */; };\n\t\tD800D5D8146908FD009F64FD /* ASIInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D586146908FD009F64FD /* ASIInputStream.h */; };\n\t\tD800D5D9146908FD009F64FD /* ASIInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D587146908FD009F64FD /* ASIInputStream.m */; };\n\t\tD800D5DA146908FD009F64FD /* ASINetworkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D588146908FD009F64FD /* ASINetworkQueue.h */; };\n\t\tD800D5DB146908FD009F64FD /* ASINetworkQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D589146908FD009F64FD /* ASINetworkQueue.m */; };\n\t\tD800D5DC146908FD009F64FD /* ASIProgressDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D58A146908FD009F64FD /* ASIProgressDelegate.h */; };\n\t\tD800D5DD146908FD009F64FD /* ASIWebPageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D58C146908FD009F64FD /* ASIWebPageRequest.h */; };\n\t\tD800D5DE146908FD009F64FD /* ASIWebPageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D58D146908FD009F64FD /* ASIWebPageRequest.m */; };\n\t\tD800D5DF146908FD009F64FD /* ASICloudFilesCDNRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D58F146908FD009F64FD /* ASICloudFilesCDNRequest.h */; };\n\t\tD800D5E0146908FD009F64FD /* ASICloudFilesCDNRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D590146908FD009F64FD /* ASICloudFilesCDNRequest.m */; };\n\t\tD800D5E1146908FD009F64FD /* ASICloudFilesContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D591146908FD009F64FD /* ASICloudFilesContainer.h */; };\n\t\tD800D5E2146908FD009F64FD /* ASICloudFilesContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D592146908FD009F64FD /* ASICloudFilesContainer.m */; };\n\t\tD800D5E3146908FD009F64FD /* ASICloudFilesContainerRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D593146908FD009F64FD /* ASICloudFilesContainerRequest.h */; };\n\t\tD800D5E4146908FD009F64FD /* ASICloudFilesContainerRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D594146908FD009F64FD /* ASICloudFilesContainerRequest.m */; };\n\t\tD800D5E5146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D595146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.h */; };\n\t\tD800D5E6146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D596146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.m */; };\n\t\tD800D5E7146908FD009F64FD /* ASICloudFilesObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D597146908FD009F64FD /* ASICloudFilesObject.h */; };\n\t\tD800D5E8146908FD009F64FD /* ASICloudFilesObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D598146908FD009F64FD /* ASICloudFilesObject.m */; };\n\t\tD800D5E9146908FD009F64FD /* ASICloudFilesObjectRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D599146908FD009F64FD /* ASICloudFilesObjectRequest.h */; };\n\t\tD800D5EA146908FD009F64FD /* ASICloudFilesObjectRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D59A146908FD009F64FD /* ASICloudFilesObjectRequest.m */; };\n\t\tD800D5EB146908FD009F64FD /* ASICloudFilesRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D59B146908FD009F64FD /* ASICloudFilesRequest.h */; };\n\t\tD800D5EC146908FD009F64FD /* ASICloudFilesRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D59C146908FD009F64FD /* ASICloudFilesRequest.m */; };\n\t\tD800D5ED146908FD009F64FD /* ASINSXMLParserCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D59E146908FD009F64FD /* ASINSXMLParserCompat.h */; };\n\t\tD800D5EE146908FD009F64FD /* ASIS3Bucket.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D59F146908FD009F64FD /* ASIS3Bucket.h */; };\n\t\tD800D5EF146908FD009F64FD /* ASIS3Bucket.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5A0146908FD009F64FD /* ASIS3Bucket.m */; };\n\t\tD800D5F0146908FD009F64FD /* ASIS3BucketObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5A1146908FD009F64FD /* ASIS3BucketObject.h */; };\n\t\tD800D5F1146908FD009F64FD /* ASIS3BucketObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5A2146908FD009F64FD /* ASIS3BucketObject.m */; };\n\t\tD800D5F2146908FD009F64FD /* ASIS3BucketRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5A3146908FD009F64FD /* ASIS3BucketRequest.h */; };\n\t\tD800D5F3146908FD009F64FD /* ASIS3BucketRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5A4146908FD009F64FD /* ASIS3BucketRequest.m */; };\n\t\tD800D5F4146908FD009F64FD /* ASIS3ObjectRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5A5146908FD009F64FD /* ASIS3ObjectRequest.h */; };\n\t\tD800D5F5146908FD009F64FD /* ASIS3ObjectRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5A6146908FD009F64FD /* ASIS3ObjectRequest.m */; };\n\t\tD800D5F6146908FD009F64FD /* ASIS3Request.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5A7146908FD009F64FD /* ASIS3Request.h */; };\n\t\tD800D5F7146908FD009F64FD /* ASIS3Request.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5A8146908FD009F64FD /* ASIS3Request.m */; };\n\t\tD800D5F8146908FD009F64FD /* ASIS3ServiceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5A9146908FD009F64FD /* ASIS3ServiceRequest.h */; };\n\t\tD800D5F9146908FD009F64FD /* ASIS3ServiceRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5AA146908FD009F64FD /* ASIS3ServiceRequest.m */; };\n\t\tD800D5FA146908FD009F64FD /* NSObject+SBJson.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5AD146908FD009F64FD /* NSObject+SBJson.h */; };\n\t\tD800D5FB146908FD009F64FD /* NSObject+SBJson.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5AE146908FD009F64FD /* NSObject+SBJson.m */; };\n\t\tD800D5FC146908FD009F64FD /* SBJson.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5AF146908FD009F64FD /* SBJson.h */; };\n\t\tD800D5FD146908FD009F64FD /* SBJsonParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5B0146908FD009F64FD /* SBJsonParser.h */; };\n\t\tD800D5FE146908FD009F64FD /* SBJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5B1146908FD009F64FD /* SBJsonParser.m */; };\n\t\tD800D5FF146908FD009F64FD /* SBJsonStreamParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5B2146908FD009F64FD /* SBJsonStreamParser.h */; };\n\t\tD800D600146908FD009F64FD /* SBJsonStreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5B3146908FD009F64FD /* SBJsonStreamParser.m */; };\n\t\tD800D601146908FD009F64FD /* SBJsonStreamParserAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5B4146908FD009F64FD /* SBJsonStreamParserAccumulator.h */; };\n\t\tD800D602146908FD009F64FD /* SBJsonStreamParserAccumulator.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5B5146908FD009F64FD /* SBJsonStreamParserAccumulator.m */; };\n\t\tD800D603146908FD009F64FD /* SBJsonStreamParserAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5B6146908FD009F64FD /* SBJsonStreamParserAdapter.h */; };\n\t\tD800D604146908FD009F64FD /* SBJsonStreamParserAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5B7146908FD009F64FD /* SBJsonStreamParserAdapter.m */; };\n\t\tD800D605146908FD009F64FD /* SBJsonStreamParserState.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5B8146908FD009F64FD /* SBJsonStreamParserState.h */; };\n\t\tD800D606146908FD009F64FD /* SBJsonStreamParserState.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5B9146908FD009F64FD /* SBJsonStreamParserState.m */; };\n\t\tD800D607146908FD009F64FD /* SBJsonStreamWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5BA146908FD009F64FD /* SBJsonStreamWriter.h */; };\n\t\tD800D608146908FD009F64FD /* SBJsonStreamWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5BB146908FD009F64FD /* SBJsonStreamWriter.m */; };\n\t\tD800D609146908FD009F64FD /* SBJsonStreamWriterAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5BC146908FD009F64FD /* SBJsonStreamWriterAccumulator.h */; };\n\t\tD800D60A146908FD009F64FD /* SBJsonStreamWriterAccumulator.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5BD146908FD009F64FD /* SBJsonStreamWriterAccumulator.m */; };\n\t\tD800D60B146908FD009F64FD /* SBJsonStreamWriterState.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5BE146908FD009F64FD /* SBJsonStreamWriterState.h */; };\n\t\tD800D60C146908FD009F64FD /* SBJsonStreamWriterState.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5BF146908FD009F64FD /* SBJsonStreamWriterState.m */; };\n\t\tD800D60D146908FD009F64FD /* SBJsonTokeniser.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5C0146908FD009F64FD /* SBJsonTokeniser.h */; };\n\t\tD800D60E146908FD009F64FD /* SBJsonTokeniser.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5C1146908FD009F64FD /* SBJsonTokeniser.m */; };\n\t\tD800D60F146908FD009F64FD /* SBJsonUTF8Stream.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5C2146908FD009F64FD /* SBJsonUTF8Stream.h */; };\n\t\tD800D610146908FD009F64FD /* SBJsonUTF8Stream.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5C3146908FD009F64FD /* SBJsonUTF8Stream.m */; };\n\t\tD800D611146908FD009F64FD /* SBJsonWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5C4146908FD009F64FD /* SBJsonWriter.h */; };\n\t\tD800D612146908FD009F64FD /* SBJsonWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5C5146908FD009F64FD /* SBJsonWriter.m */; };\n\t\tD800D613146908FD009F64FD /* Reachability.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D5C7146908FD009F64FD /* Reachability.h */; };\n\t\tD800D614146908FD009F64FD /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D5C8146908FD009F64FD /* Reachability.m */; };\n\t\tD800D6161469092C009F64FD /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D6151469092C009F64FD /* libxml2.dylib */; };\n\t\tD800D626146909C2009F64FD /* DOUAPIConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = D800D624146909C2009F64FD /* DOUAPIConfig.h */; };\n\t\tD800D627146909C2009F64FD /* DOUAPIConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = D800D625146909C2009F64FD /* DOUAPIConfig.m */; };\n\t\tD800D71914690B3F009F64FD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D71814690B3F009F64FD /* UIKit.framework */; };\n\t\tD800D71B14690B6E009F64FD /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D71A14690B6E009F64FD /* CFNetwork.framework */; };\n\t\tD800D72014690D32009F64FD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D71F14690D32009F64FD /* Security.framework */; };\n\t\tD800D72514690E2E009F64FD /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D72414690E2D009F64FD /* MobileCoreServices.framework */; };\n\t\tD800D72914690E53009F64FD /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D72814690E53009F64FD /* SystemConfiguration.framework */; };\n\t\tD800D72B14690E6F009F64FD /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D72A14690E6F009F64FD /* libz.dylib */; };\n\t\tD800D737146910D5009F64FD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D71814690B3F009F64FD /* UIKit.framework */; };\n\t\tD800D739146910DF009F64FD /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D6151469092C009F64FD /* libxml2.dylib */; };\n\t\tD800D73A146910F5009F64FD /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D71A14690B6E009F64FD /* CFNetwork.framework */; };\n\t\tD800D73B14691108009F64FD /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D72814690E53009F64FD /* SystemConfiguration.framework */; };\n\t\tD800D73D14691130009F64FD /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D72414690E2D009F64FD /* MobileCoreServices.framework */; };\n\t\tD800D73E14691140009F64FD /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D72A14690E6F009F64FD /* libz.dylib */; };\n\t\tD820CFB1166E05390067C5A5 /* DOUAPIConfig.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D624146909C2009F64FD /* DOUAPIConfig.h */; };\n\t\tD820CFB2166E05390067C5A5 /* DOUAPIEngine.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D563146908AF009F64FD /* DOUAPIEngine.h */; };\n\t\tD820CFB3166E05390067C5A5 /* DOUService.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D858E04C14C3DA9100335280 /* DOUService.h */; };\n\t\tD820CFB4166E05390067C5A5 /* DOUQuery.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D858E04414C3AC0D00335280 /* DOUQuery.h */; };\n\t\tD820CFB5166E05390067C5A5 /* DOUHttpRequest.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D565146908AF009F64FD /* DOUHttpRequest.h */; };\n\t\tD820CFB6166E05390067C5A5 /* DOUOAuthService.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D882160C15889C5F004B4AD4 /* DOUOAuthService.h */; };\n\t\tD820CFB7166E05390067C5A5 /* DOUOAuthStore.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D882160E15889C5F004B4AD4 /* DOUOAuthStore.h */; };\n\t\tD820CFB8166E05390067C5A5 /* DOUOAuth2.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D568146908AF009F64FD /* DOUOAuth2.h */; };\n\t\tD820CFB9166E05390067C5A5 /* DOUEvent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D89A6A99162D384100954BC4 /* DOUEvent.h */; };\n\t\tD820CFBA166E05390067C5A5 /* DOUEventArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D89A6A9B162D384100954BC4 /* DOUEventArray.h */; };\n\t\tD820CFBB166E05390067C5A5 /* DOULoc.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D89A6A9D162D384100954BC4 /* DOULoc.h */; };\n\t\tD820CFBC166E05390067C5A5 /* DOULocArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D89A6A9F162D384100954BC4 /* DOULocArray.h */; };\n\t\tD820CFBD166E05390067C5A5 /* DOUAlbum.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B3315C3F0230006FAFE /* DOUAlbum.h */; };\n\t\tD820CFBE166E05390067C5A5 /* DOUPhoto.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B3515C3F0230006FAFE /* DOUPhoto.h */; };\n\t\tD820CFBF166E05390067C5A5 /* DOUPhotoArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B3715C3F0230006FAFE /* DOUPhotoArray.h */; };\n\t\tD820CFC0166E05390067C5A5 /* DOUUser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D89A6A94162D37EE00954BC4 /* DOUUser.h */; };\n\t\tD820CFC1166E05390067C5A5 /* DOUComment.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4C7715C3F14E0006FAFE /* DOUComment.h */; };\n\t\tD820CFC2166E05390067C5A5 /* DOUCommentArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4C7915C3F14E0006FAFE /* DOUCommentArray.h */; };\n\t\tD820CFC3166E05390067C5A5 /* DOUObject+Utils.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B1315C3EF600006FAFE /* DOUObject+Utils.h */; };\n\t\tD820CFC4166E05390067C5A5 /* DOUOnline.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B2A15C3EFE70006FAFE /* DOUOnline.h */; };\n\t\tD820CFC5166E05390067C5A5 /* DOUOnlineArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B2C15C3EFE70006FAFE /* DOUOnlineArray.h */; };\n\t\tD820CFC6166E05390067C5A5 /* DOUObject.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B1115C3EF600006FAFE /* DOUObject.h */; };\n\t\tD820CFC7166E05390067C5A5 /* DOUObjectArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B1515C3EF600006FAFE /* DOUObjectArray.h */; };\n\t\tD820CFDC166E068E0067C5A5 /* ASIProgressDelegate.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D58A146908FD009F64FD /* ASIProgressDelegate.h */; };\n\t\tD820CFDD166E0A520067C5A5 /* ASIHTTPRequest.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D582146908FD009F64FD /* ASIHTTPRequest.h */; };\n\t\tD820CFDE166E0B330067C5A5 /* ASICacheDelegate.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D579146908FD009F64FD /* ASICacheDelegate.h */; };\n\t\tD820CFDF166E0B330067C5A5 /* ASIHTTPRequestConfig.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D584146908FD009F64FD /* ASIHTTPRequestConfig.h */; };\n\t\tD820CFE0166E0B330067C5A5 /* ASIHTTPRequestDelegate.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D800D585146908FD009F64FD /* ASIHTTPRequestDelegate.h */; };\n\t\tD858E04614C3AC0D00335280 /* DOUQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = D858E04414C3AC0D00335280 /* DOUQuery.h */; };\n\t\tD858E04714C3AC0D00335280 /* DOUQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = D858E04514C3AC0D00335280 /* DOUQuery.m */; };\n\t\tD858E04E14C3DA9100335280 /* DOUService.h in Headers */ = {isa = PBXBuildFile; fileRef = D858E04C14C3DA9100335280 /* DOUService.h */; };\n\t\tD858E04F14C3DA9100335280 /* DOUService.m in Sources */ = {isa = PBXBuildFile; fileRef = D858E04D14C3DA9100335280 /* DOUService.m */; };\n\t\tD8695E8F167AD59000EFFF41 /* DOUNotification.h in Headers */ = {isa = PBXBuildFile; fileRef = D8695E8B167AD59000EFFF41 /* DOUNotification.h */; };\n\t\tD8695E90167AD59000EFFF41 /* DOUNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = D8695E8C167AD59000EFFF41 /* DOUNotification.m */; };\n\t\tD8695E91167AD59000EFFF41 /* DOUNotificationArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D8695E8D167AD59000EFFF41 /* DOUNotificationArray.h */; };\n\t\tD8695E92167AD59000EFFF41 /* DOUNotificationArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D8695E8E167AD59000EFFF41 /* DOUNotificationArray.m */; };\n\t\tD8695EBD167AFBCE00EFFF41 /* DOUBook.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A3451D9167887E90097FEF5 /* DOUBook.h */; };\n\t\tD8695EBE167AFBCE00EFFF41 /* DOUBookArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A3451D7167887E90097FEF5 /* DOUBookArray.h */; };\n\t\tD8695EBF167AFBCE00EFFF41 /* DOUMusic.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A3451E1167887F80097FEF5 /* DOUMusic.h */; };\n\t\tD8695EC0167AFBCE00EFFF41 /* DOUMusicArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A3451DF167887F80097FEF5 /* DOUMusicArray.h */; };\n\t\tD8695EC1167AFBCE00EFFF41 /* DOUAlbumArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D88800BB166F5BF500DAFFC4 /* DOUAlbumArray.h */; };\n\t\tD87D4B2315C3EF600006FAFE /* DOUObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B1115C3EF600006FAFE /* DOUObject.h */; };\n\t\tD87D4B2415C3EF600006FAFE /* DOUObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B1215C3EF600006FAFE /* DOUObject.m */; };\n\t\tD87D4B2515C3EF600006FAFE /* DOUObject+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B1315C3EF600006FAFE /* DOUObject+Utils.h */; };\n\t\tD87D4B2615C3EF600006FAFE /* DOUObject+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B1415C3EF600006FAFE /* DOUObject+Utils.m */; };\n\t\tD87D4B2715C3EF600006FAFE /* DOUObjectArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B1515C3EF600006FAFE /* DOUObjectArray.h */; };\n\t\tD87D4B2815C3EF600006FAFE /* DOUObjectArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B1615C3EF600006FAFE /* DOUObjectArray.m */; };\n\t\tD87D4B2E15C3EFE70006FAFE /* DOUOnline.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B2A15C3EFE70006FAFE /* DOUOnline.h */; };\n\t\tD87D4B2F15C3EFE70006FAFE /* DOUOnline.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B2B15C3EFE70006FAFE /* DOUOnline.m */; };\n\t\tD87D4B3015C3EFE70006FAFE /* DOUOnlineArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B2C15C3EFE70006FAFE /* DOUOnlineArray.h */; };\n\t\tD87D4B3115C3EFE70006FAFE /* DOUOnlineArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B2D15C3EFE70006FAFE /* DOUOnlineArray.m */; };\n\t\tD87D4B3915C3F0230006FAFE /* DOUAlbum.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B3315C3F0230006FAFE /* DOUAlbum.h */; };\n\t\tD87D4B3A15C3F0230006FAFE /* DOUAlbum.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B3415C3F0230006FAFE /* DOUAlbum.m */; };\n\t\tD87D4B3B15C3F0230006FAFE /* DOUPhoto.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B3515C3F0230006FAFE /* DOUPhoto.h */; };\n\t\tD87D4B3C15C3F0230006FAFE /* DOUPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B3615C3F0230006FAFE /* DOUPhoto.m */; };\n\t\tD87D4B3D15C3F0230006FAFE /* DOUPhotoArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B3715C3F0230006FAFE /* DOUPhotoArray.h */; };\n\t\tD87D4B3E15C3F0230006FAFE /* DOUPhotoArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B3815C3F0230006FAFE /* DOUPhotoArray.m */; };\n\t\tD87D4BE115C3F0430006FAFE /* GDataEntryBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B4115C3F0420006FAFE /* GDataEntryBase.h */; };\n\t\tD87D4BE215C3F0430006FAFE /* GDataEntryBase.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B4215C3F0420006FAFE /* GDataEntryBase.m */; };\n\t\tD87D4BE315C3F0430006FAFE /* GDataFeedBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B4315C3F0420006FAFE /* GDataFeedBase.h */; };\n\t\tD87D4BE415C3F0430006FAFE /* GDataFeedBase.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B4415C3F0420006FAFE /* GDataFeedBase.m */; };\n\t\tD87D4BE515C3F0430006FAFE /* GDataObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B4515C3F0420006FAFE /* GDataObject.h */; };\n\t\tD87D4BE615C3F0430006FAFE /* GDataObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B4615C3F0420006FAFE /* GDataObject.m */; };\n\t\tD87D4BE715C3F0430006FAFE /* GDataAtomPubControl.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B4815C3F0420006FAFE /* GDataAtomPubControl.h */; };\n\t\tD87D4BE815C3F0430006FAFE /* GDataAtomPubControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B4915C3F0420006FAFE /* GDataAtomPubControl.m */; };\n\t\tD87D4BE915C3F0430006FAFE /* GDataBaseElements.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B4A15C3F0420006FAFE /* GDataBaseElements.h */; };\n\t\tD87D4BEA15C3F0430006FAFE /* GDataBaseElements.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B4B15C3F0420006FAFE /* GDataBaseElements.m */; };\n\t\tD87D4BEB15C3F0430006FAFE /* GDataBatchID.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B4C15C3F0420006FAFE /* GDataBatchID.h */; };\n\t\tD87D4BEC15C3F0430006FAFE /* GDataBatchID.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B4D15C3F0420006FAFE /* GDataBatchID.m */; };\n\t\tD87D4BED15C3F0430006FAFE /* GDataBatchInterrupted.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B4E15C3F0420006FAFE /* GDataBatchInterrupted.h */; };\n\t\tD87D4BEE15C3F0430006FAFE /* GDataBatchInterrupted.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B4F15C3F0420006FAFE /* GDataBatchInterrupted.m */; };\n\t\tD87D4BEF15C3F0430006FAFE /* GDataBatchOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5015C3F0420006FAFE /* GDataBatchOperation.h */; };\n\t\tD87D4BF015C3F0430006FAFE /* GDataBatchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B5115C3F0420006FAFE /* GDataBatchOperation.m */; };\n\t\tD87D4BF115C3F0430006FAFE /* GDataBatchStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5215C3F0420006FAFE /* GDataBatchStatus.h */; };\n\t\tD87D4BF215C3F0430006FAFE /* GDataBatchStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B5315C3F0420006FAFE /* GDataBatchStatus.m */; };\n\t\tD87D4BF315C3F0430006FAFE /* GDataCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5415C3F0420006FAFE /* GDataCategory.h */; };\n\t\tD87D4BF415C3F0430006FAFE /* GDataCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B5515C3F0420006FAFE /* GDataCategory.m */; };\n\t\tD87D4BF515C3F0430006FAFE /* GDataComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5615C3F0420006FAFE /* GDataComment.h */; };\n\t\tD87D4BF615C3F0430006FAFE /* GDataComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B5715C3F0420006FAFE /* GDataComment.m */; };\n\t\tD87D4BF715C3F0430006FAFE /* GDataCustomProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5815C3F0420006FAFE /* GDataCustomProperty.h */; };\n\t\tD87D4BF815C3F0430006FAFE /* GDataCustomProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B5915C3F0420006FAFE /* GDataCustomProperty.m */; };\n\t\tD87D4BF915C3F0430006FAFE /* GDataDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5A15C3F0420006FAFE /* GDataDateTime.h */; };\n\t\tD87D4BFA15C3F0430006FAFE /* GDataDateTime.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B5B15C3F0420006FAFE /* GDataDateTime.m */; };\n\t\tD87D4BFB15C3F0430006FAFE /* GDataDeleted.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5C15C3F0420006FAFE /* GDataDeleted.h */; };\n\t\tD87D4BFC15C3F0430006FAFE /* GDataDeleted.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B5D15C3F0420006FAFE /* GDataDeleted.m */; };\n\t\tD87D4BFD15C3F0430006FAFE /* GDataElements.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5E15C3F0420006FAFE /* GDataElements.h */; };\n\t\tD87D4BFE15C3F0430006FAFE /* GDataEmail.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B5F15C3F0420006FAFE /* GDataEmail.h */; };\n\t\tD87D4BFF15C3F0430006FAFE /* GDataEmail.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6015C3F0420006FAFE /* GDataEmail.m */; };\n\t\tD87D4C0015C3F0430006FAFE /* GDataEntryContent.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6115C3F0420006FAFE /* GDataEntryContent.h */; };\n\t\tD87D4C0115C3F0430006FAFE /* GDataEntryContent.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6215C3F0420006FAFE /* GDataEntryContent.m */; };\n\t\tD87D4C0215C3F0430006FAFE /* GDataEntryLink.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6315C3F0420006FAFE /* GDataEntryLink.h */; };\n\t\tD87D4C0315C3F0430006FAFE /* GDataEntryLink.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6415C3F0420006FAFE /* GDataEntryLink.m */; };\n\t\tD87D4C0415C3F0430006FAFE /* GDataExtendedProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6515C3F0420006FAFE /* GDataExtendedProperty.h */; };\n\t\tD87D4C0515C3F0430006FAFE /* GDataExtendedProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6615C3F0420006FAFE /* GDataExtendedProperty.m */; };\n\t\tD87D4C0615C3F0430006FAFE /* GDataFeedLink.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6715C3F0420006FAFE /* GDataFeedLink.h */; };\n\t\tD87D4C0715C3F0430006FAFE /* GDataFeedLink.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6815C3F0420006FAFE /* GDataFeedLink.m */; };\n\t\tD87D4C0815C3F0430006FAFE /* GDataGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6915C3F0420006FAFE /* GDataGenerator.h */; };\n\t\tD87D4C0915C3F0430006FAFE /* GDataGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6A15C3F0420006FAFE /* GDataGenerator.m */; };\n\t\tD87D4C0A15C3F0430006FAFE /* GDataGeoPt.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6B15C3F0420006FAFE /* GDataGeoPt.h */; };\n\t\tD87D4C0B15C3F0430006FAFE /* GDataGeoPt.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6C15C3F0420006FAFE /* GDataGeoPt.m */; };\n\t\tD87D4C0C15C3F0430006FAFE /* GDataIM.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6D15C3F0420006FAFE /* GDataIM.h */; };\n\t\tD87D4C0D15C3F0430006FAFE /* GDataIM.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B6E15C3F0420006FAFE /* GDataIM.m */; };\n\t\tD87D4C0E15C3F0430006FAFE /* GDataLink.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B6F15C3F0420006FAFE /* GDataLink.h */; };\n\t\tD87D4C0F15C3F0430006FAFE /* GDataLink.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7015C3F0420006FAFE /* GDataLink.m */; };\n\t\tD87D4C1015C3F0430006FAFE /* GDataMoney.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7115C3F0420006FAFE /* GDataMoney.h */; };\n\t\tD87D4C1115C3F0430006FAFE /* GDataMoney.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7215C3F0420006FAFE /* GDataMoney.m */; };\n\t\tD87D4C1215C3F0430006FAFE /* GDataName.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7315C3F0420006FAFE /* GDataName.h */; };\n\t\tD87D4C1315C3F0430006FAFE /* GDataName.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7415C3F0420006FAFE /* GDataName.m */; };\n\t\tD87D4C1415C3F0430006FAFE /* GDataOrganization.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7515C3F0420006FAFE /* GDataOrganization.h */; };\n\t\tD87D4C1515C3F0430006FAFE /* GDataOrganization.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7615C3F0420006FAFE /* GDataOrganization.m */; };\n\t\tD87D4C1615C3F0430006FAFE /* GDataOrganizationName.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7715C3F0420006FAFE /* GDataOrganizationName.h */; };\n\t\tD87D4C1715C3F0430006FAFE /* GDataOrganizationName.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7815C3F0420006FAFE /* GDataOrganizationName.m */; };\n\t\tD87D4C1815C3F0430006FAFE /* GDataPerson.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7915C3F0420006FAFE /* GDataPerson.h */; };\n\t\tD87D4C1915C3F0430006FAFE /* GDataPerson.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7A15C3F0420006FAFE /* GDataPerson.m */; };\n\t\tD87D4C1A15C3F0430006FAFE /* GDataPhoneNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7B15C3F0420006FAFE /* GDataPhoneNumber.h */; };\n\t\tD87D4C1B15C3F0430006FAFE /* GDataPhoneNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7C15C3F0420006FAFE /* GDataPhoneNumber.m */; };\n\t\tD87D4C1C15C3F0430006FAFE /* GDataPostalAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7D15C3F0420006FAFE /* GDataPostalAddress.h */; };\n\t\tD87D4C1D15C3F0430006FAFE /* GDataPostalAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B7E15C3F0420006FAFE /* GDataPostalAddress.m */; };\n\t\tD87D4C1E15C3F0430006FAFE /* GDataRating.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B7F15C3F0420006FAFE /* GDataRating.h */; };\n\t\tD87D4C1F15C3F0430006FAFE /* GDataRating.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8015C3F0420006FAFE /* GDataRating.m */; };\n\t\tD87D4C2015C3F0430006FAFE /* GDataStructuredPostalAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8115C3F0420006FAFE /* GDataStructuredPostalAddress.h */; };\n\t\tD87D4C2115C3F0430006FAFE /* GDataStructuredPostalAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8215C3F0420006FAFE /* GDataStructuredPostalAddress.m */; };\n\t\tD87D4C2215C3F0430006FAFE /* GDataTextConstruct.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8315C3F0420006FAFE /* GDataTextConstruct.h */; };\n\t\tD87D4C2315C3F0430006FAFE /* GDataTextConstruct.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8415C3F0420006FAFE /* GDataTextConstruct.m */; };\n\t\tD87D4C2415C3F0430006FAFE /* GDataValueConstruct.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8515C3F0420006FAFE /* GDataValueConstruct.h */; };\n\t\tD87D4C2515C3F0430006FAFE /* GDataValueConstruct.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8615C3F0420006FAFE /* GDataValueConstruct.m */; };\n\t\tD87D4C2615C3F0430006FAFE /* GDataWhen.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8715C3F0420006FAFE /* GDataWhen.h */; };\n\t\tD87D4C2715C3F0430006FAFE /* GDataWhen.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8815C3F0420006FAFE /* GDataWhen.m */; };\n\t\tD87D4C2815C3F0430006FAFE /* GDataWhere.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8915C3F0420006FAFE /* GDataWhere.h */; };\n\t\tD87D4C2915C3F0430006FAFE /* GDataWhere.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8A15C3F0420006FAFE /* GDataWhere.m */; };\n\t\tD87D4C2A15C3F0430006FAFE /* GDataWho.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8B15C3F0420006FAFE /* GDataWho.h */; };\n\t\tD87D4C2B15C3F0430006FAFE /* GDataWho.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8C15C3F0420006FAFE /* GDataWho.m */; };\n\t\tD87D4C2C15C3F0430006FAFE /* GDataDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8D15C3F0420006FAFE /* GDataDefines.h */; };\n\t\tD87D4C2D15C3F0430006FAFE /* GDataUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B8E15C3F0420006FAFE /* GDataUtilities.h */; };\n\t\tD87D4C2E15C3F0430006FAFE /* GDataUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B8F15C3F0420006FAFE /* GDataUtilities.m */; };\n\t\tD87D4C2F15C3F0430006FAFE /* GTMGatherInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B9115C3F0420006FAFE /* GTMGatherInputStream.h */; };\n\t\tD87D4C3015C3F0430006FAFE /* GTMGatherInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B9215C3F0420006FAFE /* GTMGatherInputStream.m */; };\n\t\tD87D4C3115C3F0430006FAFE /* GTMMIMEDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B9315C3F0420006FAFE /* GTMMIMEDocument.h */; };\n\t\tD87D4C3215C3F0430006FAFE /* GTMMIMEDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B9415C3F0420006FAFE /* GTMMIMEDocument.m */; };\n\t\tD87D4C3315C3F0430006FAFE /* GDataXMLNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B9615C3F0420006FAFE /* GDataXMLNode.h */; };\n\t\tD87D4C3415C3F0430006FAFE /* GDataXMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B9715C3F0420006FAFE /* GDataXMLNode.m */; };\n\t\tD87D4C3515C3F0430006FAFE /* DoubanEntryComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B9B15C3F0420006FAFE /* DoubanEntryComment.h */; };\n\t\tD87D4C3615C3F0430006FAFE /* DoubanEntryComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B9C15C3F0420006FAFE /* DoubanEntryComment.m */; };\n\t\tD87D4C3715C3F0430006FAFE /* DoubanFeedComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4B9D15C3F0420006FAFE /* DoubanFeedComment.h */; };\n\t\tD87D4C3815C3F0430006FAFE /* DoubanFeedComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4B9E15C3F0420006FAFE /* DoubanFeedComment.m */; };\n\t\tD87D4C3915C3F0430006FAFE /* DoubanEntryCity.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BA015C3F0420006FAFE /* DoubanEntryCity.h */; };\n\t\tD87D4C3A15C3F0430006FAFE /* DoubanEntryCity.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BA115C3F0420006FAFE /* DoubanEntryCity.m */; };\n\t\tD87D4C3B15C3F0430006FAFE /* DoubanEntryEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BA215C3F0420006FAFE /* DoubanEntryEvent.h */; };\n\t\tD87D4C3C15C3F0430006FAFE /* DoubanEntryEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BA315C3F0420006FAFE /* DoubanEntryEvent.m */; };\n\t\tD87D4C3D15C3F0430006FAFE /* DoubanEntryEventCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BA415C3F0420006FAFE /* DoubanEntryEventCategory.h */; };\n\t\tD87D4C3E15C3F0430006FAFE /* DoubanEntryEventCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BA515C3F0420006FAFE /* DoubanEntryEventCategory.m */; };\n\t\tD87D4C3F15C3F0430006FAFE /* DoubanFeedCity.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BA615C3F0420006FAFE /* DoubanFeedCity.h */; };\n\t\tD87D4C4015C3F0430006FAFE /* DoubanFeedCity.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BA715C3F0420006FAFE /* DoubanFeedCity.m */; };\n\t\tD87D4C4115C3F0430006FAFE /* DoubanFeedEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BA815C3F0420006FAFE /* DoubanFeedEvent.h */; };\n\t\tD87D4C4215C3F0430006FAFE /* DoubanFeedEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BA915C3F0420006FAFE /* DoubanFeedEvent.m */; };\n\t\tD87D4C4315C3F0430006FAFE /* DoubanFeedEventCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BAA15C3F0420006FAFE /* DoubanFeedEventCategory.h */; };\n\t\tD87D4C4415C3F0430006FAFE /* DoubanFeedEventCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BAB15C3F0420006FAFE /* DoubanFeedEventCategory.m */; };\n\t\tD87D4C4515C3F0430006FAFE /* GDataAtomAuthor+Extension.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BAC15C3F0420006FAFE /* GDataAtomAuthor+Extension.h */; };\n\t\tD87D4C4615C3F0430006FAFE /* GDataAtomAuthor+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BAD15C3F0420006FAFE /* GDataAtomAuthor+Extension.m */; };\n\t\tD87D4C4715C3F0430006FAFE /* GDataEntryBase+Extension.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BAE15C3F0420006FAFE /* GDataEntryBase+Extension.h */; };\n\t\tD87D4C4815C3F0430006FAFE /* GDataEntryBase+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BAF15C3F0420006FAFE /* GDataEntryBase+Extension.m */; };\n\t\tD87D4C4915C3F0430006FAFE /* DoubanEntryMiniblog.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BB115C3F0420006FAFE /* DoubanEntryMiniblog.h */; };\n\t\tD87D4C4A15C3F0430006FAFE /* DoubanEntryMiniblog.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BB215C3F0420006FAFE /* DoubanEntryMiniblog.m */; };\n\t\tD87D4C4B15C3F0430006FAFE /* DoubanFeedMiniblog.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BB315C3F0420006FAFE /* DoubanFeedMiniblog.h */; };\n\t\tD87D4C4C15C3F0430006FAFE /* DoubanFeedMiniblog.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BB415C3F0420006FAFE /* DoubanFeedMiniblog.m */; };\n\t\tD87D4C4D15C3F0430006FAFE /* DoubanEntryPeople.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BB615C3F0420006FAFE /* DoubanEntryPeople.h */; };\n\t\tD87D4C4E15C3F0430006FAFE /* DoubanEntryPeople.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BB715C3F0420006FAFE /* DoubanEntryPeople.m */; };\n\t\tD87D4C4F15C3F0430006FAFE /* DoubanFeedPeople.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BB815C3F0420006FAFE /* DoubanFeedPeople.h */; };\n\t\tD87D4C5015C3F0430006FAFE /* DoubanFeedPeople.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BB915C3F0420006FAFE /* DoubanFeedPeople.m */; };\n\t\tD87D4C5115C3F0430006FAFE /* DoubanEntryAlbum.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BBB15C3F0420006FAFE /* DoubanEntryAlbum.h */; };\n\t\tD87D4C5215C3F0430006FAFE /* DoubanEntryAlbum.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BBC15C3F0420006FAFE /* DoubanEntryAlbum.m */; };\n\t\tD87D4C5315C3F0430006FAFE /* DoubanEntryPhoto.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BBD15C3F0420006FAFE /* DoubanEntryPhoto.h */; };\n\t\tD87D4C5415C3F0430006FAFE /* DoubanEntryPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BBE15C3F0420006FAFE /* DoubanEntryPhoto.m */; };\n\t\tD87D4C5515C3F0430006FAFE /* DoubanFeedAlbum.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BBF15C3F0420006FAFE /* DoubanFeedAlbum.h */; };\n\t\tD87D4C5615C3F0430006FAFE /* DoubanFeedAlbum.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BC015C3F0420006FAFE /* DoubanFeedAlbum.m */; };\n\t\tD87D4C5715C3F0430006FAFE /* DoubanFeedPhoto.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BC115C3F0420006FAFE /* DoubanFeedPhoto.h */; };\n\t\tD87D4C5815C3F0430006FAFE /* DoubanFeedPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BC215C3F0420006FAFE /* DoubanFeedPhoto.m */; };\n\t\tD87D4C5915C3F0430006FAFE /* DoubanEntryRecommendation.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BC415C3F0420006FAFE /* DoubanEntryRecommendation.h */; };\n\t\tD87D4C5A15C3F0430006FAFE /* DoubanEntryRecommendation.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BC515C3F0420006FAFE /* DoubanEntryRecommendation.m */; };\n\t\tD87D4C5B15C3F0430006FAFE /* DoubanFeedRecommendation.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BC615C3F0430006FAFE /* DoubanFeedRecommendation.h */; };\n\t\tD87D4C5C15C3F0430006FAFE /* DoubanFeedRecommendation.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BC715C3F0430006FAFE /* DoubanFeedRecommendation.m */; };\n\t\tD87D4C5D15C3F0430006FAFE /* DoubanEntryReview.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BC915C3F0430006FAFE /* DoubanEntryReview.h */; };\n\t\tD87D4C5E15C3F0430006FAFE /* DoubanEntryReview.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BCA15C3F0430006FAFE /* DoubanEntryReview.m */; };\n\t\tD87D4C5F15C3F0430006FAFE /* DoubanFeedReview.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BCB15C3F0430006FAFE /* DoubanFeedReview.h */; };\n\t\tD87D4C6015C3F0430006FAFE /* DoubanFeedReview.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BCC15C3F0430006FAFE /* DoubanFeedReview.m */; };\n\t\tD87D4C6115C3F0430006FAFE /* DoubanEntrySubject.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BCE15C3F0430006FAFE /* DoubanEntrySubject.h */; };\n\t\tD87D4C6215C3F0430006FAFE /* DoubanEntrySubject.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BCF15C3F0430006FAFE /* DoubanEntrySubject.m */; };\n\t\tD87D4C6315C3F0430006FAFE /* DoubanFeedSubject.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BD015C3F0430006FAFE /* DoubanFeedSubject.h */; };\n\t\tD87D4C6415C3F0430006FAFE /* DoubanFeedSubject.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BD115C3F0430006FAFE /* DoubanFeedSubject.m */; };\n\t\tD87D4C6515C3F0430006FAFE /* DoubanDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BD215C3F0430006FAFE /* DoubanDefines.h */; };\n\t\tD87D4C6615C3F0430006FAFE /* DoubanDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BD315C3F0430006FAFE /* DoubanDefines.m */; };\n\t\tD87D4C6715C3F0430006FAFE /* DoubanAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BD515C3F0430006FAFE /* DoubanAttribute.h */; };\n\t\tD87D4C6815C3F0430006FAFE /* DoubanAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BD615C3F0430006FAFE /* DoubanAttribute.m */; };\n\t\tD87D4C6915C3F0430006FAFE /* DoubanLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BD715C3F0430006FAFE /* DoubanLocation.h */; };\n\t\tD87D4C6A15C3F0430006FAFE /* DoubanLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BD815C3F0430006FAFE /* DoubanLocation.m */; };\n\t\tD87D4C6B15C3F0430006FAFE /* DoubanSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BD915C3F0430006FAFE /* DoubanSignature.h */; };\n\t\tD87D4C6C15C3F0430006FAFE /* DoubanSignature.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BDA15C3F0430006FAFE /* DoubanSignature.m */; };\n\t\tD87D4C6D15C3F0430006FAFE /* DoubanTag.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BDB15C3F0430006FAFE /* DoubanTag.h */; };\n\t\tD87D4C6E15C3F0430006FAFE /* DoubanTag.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BDC15C3F0430006FAFE /* DoubanTag.m */; };\n\t\tD87D4C6F15C3F0430006FAFE /* DoubanUID.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BDD15C3F0430006FAFE /* DoubanUID.h */; };\n\t\tD87D4C7015C3F0430006FAFE /* DoubanUID.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BDE15C3F0430006FAFE /* DoubanUID.m */; };\n\t\tD87D4C7115C3F0430006FAFE /* GeorssPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4BDF15C3F0430006FAFE /* GeorssPoint.h */; };\n\t\tD87D4C7215C3F0430006FAFE /* GeorssPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4BE015C3F0430006FAFE /* GeorssPoint.m */; };\n\t\tD87D4C7515C3F11C0006FAFE /* NSData+Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4C7315C3F11C0006FAFE /* NSData+Base64.h */; };\n\t\tD87D4C7615C3F11C0006FAFE /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C7415C3F11C0006FAFE /* NSData+Base64.m */; };\n\t\tD87D4C7D15C3F14E0006FAFE /* DOUComment.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4C7715C3F14E0006FAFE /* DOUComment.h */; };\n\t\tD87D4C7E15C3F14E0006FAFE /* DOUComment.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C7815C3F14E0006FAFE /* DOUComment.m */; };\n\t\tD87D4C7F15C3F14E0006FAFE /* DOUCommentArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D87D4C7915C3F14E0006FAFE /* DOUCommentArray.h */; };\n\t\tD87D4C8015C3F14E0006FAFE /* DOUCommentArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C7A15C3F14E0006FAFE /* DOUCommentArray.m */; };\n\t\tD87D4C8D15C3F2A70006FAFE /* DoubanCityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8515C3F2A70006FAFE /* DoubanCityTests.m */; };\n\t\tD87D4C8E15C3F2A70006FAFE /* DoubanCommentTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8615C3F2A70006FAFE /* DoubanCommentTests.m */; };\n\t\tD87D4C8F15C3F2A70006FAFE /* DoubanEventCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8715C3F2A70006FAFE /* DoubanEventCategoryTests.m */; };\n\t\tD87D4C9015C3F2A70006FAFE /* DoubanEventTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8815C3F2A70006FAFE /* DoubanEventTests.m */; };\n\t\tD87D4C9115C3F2A70006FAFE /* DoubanMiniblogTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8915C3F2A70006FAFE /* DoubanMiniblogTests.m */; };\n\t\tD87D4C9215C3F2A70006FAFE /* DoubanPeopleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8A15C3F2A70006FAFE /* DoubanPeopleTests.m */; };\n\t\tD87D4C9315C3F2A70006FAFE /* DoubanPhotoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8B15C3F2A70006FAFE /* DoubanPhotoTests.m */; };\n\t\tD87D4C9415C3F2A70006FAFE /* DoubanSubjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4C8C15C3F2A70006FAFE /* DoubanSubjectTests.m */; };\n\t\tD87D4CA715C3F4850006FAFE /* DoubanEntryCity.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9715C3F4850006FAFE /* DoubanEntryCity.xml */; };\n\t\tD87D4CA815C3F4850006FAFE /* DoubanEntryEvent.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9815C3F4850006FAFE /* DoubanEntryEvent.xml */; };\n\t\tD87D4CA915C3F4850006FAFE /* DoubanEntryMiniblog.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9915C3F4850006FAFE /* DoubanEntryMiniblog.xml */; };\n\t\tD87D4CAA15C3F4850006FAFE /* DoubanEntryPeople.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9A15C3F4850006FAFE /* DoubanEntryPeople.xml */; };\n\t\tD87D4CAB15C3F4850006FAFE /* DoubanEntryPhoto.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9B15C3F4850006FAFE /* DoubanEntryPhoto.xml */; };\n\t\tD87D4CAC15C3F4850006FAFE /* DoubanEntryRecommendation.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9C15C3F4850006FAFE /* DoubanEntryRecommendation.xml */; };\n\t\tD87D4CAD15C3F4850006FAFE /* DoubanEntrySubject.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9D15C3F4850006FAFE /* DoubanEntrySubject.xml */; };\n\t\tD87D4CAE15C3F4850006FAFE /* DoubanFeedCity.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9E15C3F4850006FAFE /* DoubanFeedCity.xml */; };\n\t\tD87D4CAF15C3F4850006FAFE /* DoubanFeedComment.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4C9F15C3F4850006FAFE /* DoubanFeedComment.xml */; };\n\t\tD87D4CB015C3F4850006FAFE /* DoubanFeedEvent.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CA015C3F4850006FAFE /* DoubanFeedEvent.xml */; };\n\t\tD87D4CB115C3F4850006FAFE /* DoubanFeedEventCategory.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CA115C3F4850006FAFE /* DoubanFeedEventCategory.xml */; };\n\t\tD87D4CB215C3F4850006FAFE /* DoubanFeedMiniblog.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CA215C3F4850006FAFE /* DoubanFeedMiniblog.xml */; };\n\t\tD87D4CB315C3F4850006FAFE /* DoubanFeedPeople.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CA315C3F4850006FAFE /* DoubanFeedPeople.xml */; };\n\t\tD87D4CB415C3F4850006FAFE /* DoubanFeedPhoto.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CA415C3F4850006FAFE /* DoubanFeedPhoto.xml */; };\n\t\tD87D4CB515C3F4850006FAFE /* DoubanFeedRecommendation.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CA515C3F4850006FAFE /* DoubanFeedRecommendation.xml */; };\n\t\tD87D4CB615C3F4850006FAFE /* DoubanFeedSubject.xml in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CA615C3F4850006FAFE /* DoubanFeedSubject.xml */; };\n\t\tD87D4CBD15C3F5580006FAFE /* Album.json in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CB715C3F5580006FAFE /* Album.json */; };\n\t\tD87D4CBE15C3F5580006FAFE /* CommentArray.json in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CB815C3F5580006FAFE /* CommentArray.json */; };\n\t\tD87D4CBF15C3F5580006FAFE /* Online.json in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CB915C3F5580006FAFE /* Online.json */; };\n\t\tD87D4CC015C3F5580006FAFE /* OnlineArray.json in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CBA15C3F5580006FAFE /* OnlineArray.json */; };\n\t\tD87D4CC115C3F5580006FAFE /* Photo.json in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CBB15C3F5580006FAFE /* Photo.json */; };\n\t\tD87D4CC215C3F5580006FAFE /* PhotoArray.json in Resources */ = {isa = PBXBuildFile; fileRef = D87D4CBC15C3F5580006FAFE /* PhotoArray.json */; };\n\t\tD87D4CC615C3F56D0006FAFE /* DOUCommentTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4CC315C3F56D0006FAFE /* DOUCommentTests.m */; };\n\t\tD87D4CC715C3F56D0006FAFE /* DOUOnlineTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4CC415C3F56D0006FAFE /* DOUOnlineTests.m */; };\n\t\tD87D4CC815C3F56D0006FAFE /* DOUPhotoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D87D4CC515C3F56D0006FAFE /* DOUPhotoTests.m */; };\n\t\tD882161015889C5F004B4AD4 /* DOUOAuthService.h in Headers */ = {isa = PBXBuildFile; fileRef = D882160C15889C5F004B4AD4 /* DOUOAuthService.h */; };\n\t\tD882161115889C5F004B4AD4 /* DOUOAuthService.m in Sources */ = {isa = PBXBuildFile; fileRef = D882160D15889C5F004B4AD4 /* DOUOAuthService.m */; };\n\t\tD882161215889C5F004B4AD4 /* DOUOAuthStore.h in Headers */ = {isa = PBXBuildFile; fileRef = D882160E15889C5F004B4AD4 /* DOUOAuthStore.h */; };\n\t\tD882161315889C5F004B4AD4 /* DOUOAuthStore.m in Sources */ = {isa = PBXBuildFile; fileRef = D882160F15889C5F004B4AD4 /* DOUOAuthStore.m */; };\n\t\tD882161915889DDE004B4AD4 /* DOUOAuthServiceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D882161415889DDE004B4AD4 /* DOUOAuthServiceTests.m */; };\n\t\tD882161B15889DDE004B4AD4 /* DOUTestResponseLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = D882161815889DDE004B4AD4 /* DOUTestResponseLoader.m */; };\n\t\tD888006F166EE73300DAFFC4 /* DoubanEntryComment.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B9B15C3F0420006FAFE /* DoubanEntryComment.h */; };\n\t\tD8880070166EE73300DAFFC4 /* DoubanFeedComment.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B9D15C3F0420006FAFE /* DoubanFeedComment.h */; };\n\t\tD8880071166EE73300DAFFC4 /* DoubanEntryCity.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BA015C3F0420006FAFE /* DoubanEntryCity.h */; };\n\t\tD8880072166EE73300DAFFC4 /* DoubanEntryEvent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BA215C3F0420006FAFE /* DoubanEntryEvent.h */; };\n\t\tD8880073166EE73300DAFFC4 /* DoubanEntryEventCategory.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BA415C3F0420006FAFE /* DoubanEntryEventCategory.h */; };\n\t\tD8880074166EE73300DAFFC4 /* DoubanFeedCity.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BA615C3F0420006FAFE /* DoubanFeedCity.h */; };\n\t\tD8880075166EE73300DAFFC4 /* DoubanFeedEvent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BA815C3F0420006FAFE /* DoubanFeedEvent.h */; };\n\t\tD8880076166EE73300DAFFC4 /* DoubanFeedEventCategory.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BAA15C3F0420006FAFE /* DoubanFeedEventCategory.h */; };\n\t\tD8880077166EE73300DAFFC4 /* DoubanEntryMiniblog.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BB115C3F0420006FAFE /* DoubanEntryMiniblog.h */; };\n\t\tD8880078166EE73300DAFFC4 /* DoubanFeedMiniblog.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BB315C3F0420006FAFE /* DoubanFeedMiniblog.h */; };\n\t\tD8880079166EE73300DAFFC4 /* DoubanEntryPeople.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BB615C3F0420006FAFE /* DoubanEntryPeople.h */; };\n\t\tD888007A166EE73300DAFFC4 /* DoubanFeedPeople.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BB815C3F0420006FAFE /* DoubanFeedPeople.h */; };\n\t\tD888007B166EE73300DAFFC4 /* DoubanEntryAlbum.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BBB15C3F0420006FAFE /* DoubanEntryAlbum.h */; };\n\t\tD888007C166EE73300DAFFC4 /* DoubanEntryPhoto.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BBD15C3F0420006FAFE /* DoubanEntryPhoto.h */; };\n\t\tD888007D166EE73300DAFFC4 /* DoubanFeedAlbum.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BBF15C3F0420006FAFE /* DoubanFeedAlbum.h */; };\n\t\tD888007E166EE73300DAFFC4 /* DoubanFeedPhoto.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BC115C3F0420006FAFE /* DoubanFeedPhoto.h */; };\n\t\tD888007F166EE73300DAFFC4 /* DoubanEntryRecommendation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BC415C3F0420006FAFE /* DoubanEntryRecommendation.h */; };\n\t\tD8880080166EE73300DAFFC4 /* DoubanFeedRecommendation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BC615C3F0430006FAFE /* DoubanFeedRecommendation.h */; };\n\t\tD8880081166EE73300DAFFC4 /* DoubanEntryReview.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BC915C3F0430006FAFE /* DoubanEntryReview.h */; };\n\t\tD8880082166EE73300DAFFC4 /* DoubanFeedReview.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BCB15C3F0430006FAFE /* DoubanFeedReview.h */; };\n\t\tD8880083166EE73300DAFFC4 /* DoubanEntrySubject.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BCE15C3F0430006FAFE /* DoubanEntrySubject.h */; };\n\t\tD8880084166EE73300DAFFC4 /* DoubanFeedSubject.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BD015C3F0430006FAFE /* DoubanFeedSubject.h */; };\n\t\tD8880085166EE73300DAFFC4 /* DoubanDefines.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BD215C3F0430006FAFE /* DoubanDefines.h */; };\n\t\tD8880086166EE73300DAFFC4 /* DoubanAttribute.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BD515C3F0430006FAFE /* DoubanAttribute.h */; };\n\t\tD8880087166EE73300DAFFC4 /* DoubanLocation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BD715C3F0430006FAFE /* DoubanLocation.h */; };\n\t\tD8880088166EE73300DAFFC4 /* DoubanSignature.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BD915C3F0430006FAFE /* DoubanSignature.h */; };\n\t\tD8880089166EE73300DAFFC4 /* DoubanTag.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BDB15C3F0430006FAFE /* DoubanTag.h */; };\n\t\tD888008A166EE73300DAFFC4 /* DoubanUID.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BDD15C3F0430006FAFE /* DoubanUID.h */; };\n\t\tD888008B166EE73300DAFFC4 /* GeorssPoint.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4BDF15C3F0430006FAFE /* GeorssPoint.h */; };\n\t\tD888008D166EEAB900DAFFC4 /* GDataEntryBase.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B4115C3F0420006FAFE /* GDataEntryBase.h */; };\n\t\tD888008E166EEAB900DAFFC4 /* GDataFeedBase.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B4315C3F0420006FAFE /* GDataFeedBase.h */; };\n\t\tD888008F166EEAB900DAFFC4 /* GDataObject.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B4515C3F0420006FAFE /* GDataObject.h */; };\n\t\tD8880090166EEC3100DAFFC4 /* GDataAtomPubControl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B4815C3F0420006FAFE /* GDataAtomPubControl.h */; };\n\t\tD8880091166EEC3100DAFFC4 /* GDataBaseElements.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B4A15C3F0420006FAFE /* GDataBaseElements.h */; };\n\t\tD8880092166EEC3100DAFFC4 /* GDataBatchID.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B4C15C3F0420006FAFE /* GDataBatchID.h */; };\n\t\tD8880093166EEC3100DAFFC4 /* GDataBatchInterrupted.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B4E15C3F0420006FAFE /* GDataBatchInterrupted.h */; };\n\t\tD8880094166EEC3100DAFFC4 /* GDataBatchOperation.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5015C3F0420006FAFE /* GDataBatchOperation.h */; };\n\t\tD8880095166EEC3100DAFFC4 /* GDataBatchStatus.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5215C3F0420006FAFE /* GDataBatchStatus.h */; };\n\t\tD8880096166EEC3100DAFFC4 /* GDataCategory.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5415C3F0420006FAFE /* GDataCategory.h */; };\n\t\tD8880097166EEC3100DAFFC4 /* GDataComment.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5615C3F0420006FAFE /* GDataComment.h */; };\n\t\tD8880098166EEC3100DAFFC4 /* GDataCustomProperty.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5815C3F0420006FAFE /* GDataCustomProperty.h */; };\n\t\tD8880099166EEC3100DAFFC4 /* GDataDateTime.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5A15C3F0420006FAFE /* GDataDateTime.h */; };\n\t\tD888009A166EEC3100DAFFC4 /* GDataDeleted.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5C15C3F0420006FAFE /* GDataDeleted.h */; };\n\t\tD888009B166EEC3100DAFFC4 /* GDataElements.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5E15C3F0420006FAFE /* GDataElements.h */; };\n\t\tD888009C166EEC3100DAFFC4 /* GDataEmail.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B5F15C3F0420006FAFE /* GDataEmail.h */; };\n\t\tD888009D166EEC3100DAFFC4 /* GDataEntryContent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6115C3F0420006FAFE /* GDataEntryContent.h */; };\n\t\tD888009E166EEC3100DAFFC4 /* GDataEntryLink.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6315C3F0420006FAFE /* GDataEntryLink.h */; };\n\t\tD888009F166EEC3100DAFFC4 /* GDataExtendedProperty.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6515C3F0420006FAFE /* GDataExtendedProperty.h */; };\n\t\tD88800A0166EEC3100DAFFC4 /* GDataFeedLink.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6715C3F0420006FAFE /* GDataFeedLink.h */; };\n\t\tD88800A1166EEC3100DAFFC4 /* GDataGenerator.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6915C3F0420006FAFE /* GDataGenerator.h */; };\n\t\tD88800A2166EEC3100DAFFC4 /* GDataGeoPt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6B15C3F0420006FAFE /* GDataGeoPt.h */; };\n\t\tD88800A3166EEC3100DAFFC4 /* GDataIM.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6D15C3F0420006FAFE /* GDataIM.h */; };\n\t\tD88800A4166EEC3100DAFFC4 /* GDataLink.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B6F15C3F0420006FAFE /* GDataLink.h */; };\n\t\tD88800A5166EEC3100DAFFC4 /* GDataMoney.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7115C3F0420006FAFE /* GDataMoney.h */; };\n\t\tD88800A6166EEC3100DAFFC4 /* GDataName.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7315C3F0420006FAFE /* GDataName.h */; };\n\t\tD88800A7166EEC3100DAFFC4 /* GDataOrganization.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7515C3F0420006FAFE /* GDataOrganization.h */; };\n\t\tD88800A8166EEC3100DAFFC4 /* GDataOrganizationName.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7715C3F0420006FAFE /* GDataOrganizationName.h */; };\n\t\tD88800A9166EEC3100DAFFC4 /* GDataPerson.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7915C3F0420006FAFE /* GDataPerson.h */; };\n\t\tD88800AA166EEC3100DAFFC4 /* GDataPhoneNumber.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7B15C3F0420006FAFE /* GDataPhoneNumber.h */; };\n\t\tD88800AB166EEC3100DAFFC4 /* GDataPostalAddress.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7D15C3F0420006FAFE /* GDataPostalAddress.h */; };\n\t\tD88800AC166EEC3100DAFFC4 /* GDataRating.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B7F15C3F0420006FAFE /* GDataRating.h */; };\n\t\tD88800AD166EEC3100DAFFC4 /* GDataStructuredPostalAddress.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8115C3F0420006FAFE /* GDataStructuredPostalAddress.h */; };\n\t\tD88800AE166EEC3100DAFFC4 /* GDataTextConstruct.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8315C3F0420006FAFE /* GDataTextConstruct.h */; };\n\t\tD88800AF166EEC3100DAFFC4 /* GDataValueConstruct.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8515C3F0420006FAFE /* GDataValueConstruct.h */; };\n\t\tD88800B0166EEC3100DAFFC4 /* GDataWhen.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8715C3F0420006FAFE /* GDataWhen.h */; };\n\t\tD88800B1166EEC3100DAFFC4 /* GDataWhere.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8915C3F0420006FAFE /* GDataWhere.h */; };\n\t\tD88800B2166EEC3100DAFFC4 /* GDataWho.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8B15C3F0420006FAFE /* GDataWho.h */; };\n\t\tD88800B3166EEC3100DAFFC4 /* GDataDefines.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8D15C3F0420006FAFE /* GDataDefines.h */; };\n\t\tD88800B4166EEC3100DAFFC4 /* GDataUtilities.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B8E15C3F0420006FAFE /* GDataUtilities.h */; };\n\t\tD88800B5166EEC3100DAFFC4 /* GTMGatherInputStream.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B9115C3F0420006FAFE /* GTMGatherInputStream.h */; };\n\t\tD88800B6166EEC3100DAFFC4 /* GTMMIMEDocument.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B9315C3F0420006FAFE /* GTMMIMEDocument.h */; };\n\t\tD88800B7166EEC3100DAFFC4 /* GDataXMLNode.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87D4B9615C3F0420006FAFE /* GDataXMLNode.h */; };\n\t\tD88800BD166F5BF600DAFFC4 /* DOUAlbumArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D88800BB166F5BF500DAFFC4 /* DOUAlbumArray.h */; };\n\t\tD88800BE166F5BF600DAFFC4 /* DOUAlbumArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D88800BC166F5BF600DAFFC4 /* DOUAlbumArray.m */; };\n\t\tD88800C7166F5D4F00DAFFC4 /* DOUNote.h in Headers */ = {isa = PBXBuildFile; fileRef = D88800C5166F5D4E00DAFFC4 /* DOUNote.h */; };\n\t\tD88800C8166F5D4F00DAFFC4 /* DOUNote.m in Sources */ = {isa = PBXBuildFile; fileRef = D88800C6166F5D4F00DAFFC4 /* DOUNote.m */; };\n\t\tD88800CA166F603F00DAFFC4 /* Note.json in Resources */ = {isa = PBXBuildFile; fileRef = D88800C9166F603F00DAFFC4 /* Note.json */; };\n\t\tD88800CC166F609300DAFFC4 /* DOUNoteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D88800CB166F609300DAFFC4 /* DOUNoteTests.m */; };\n\t\tD88800CF166F63B600DAFFC4 /* DOUNoteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D88800CD166F63B400DAFFC4 /* DOUNoteArray.h */; };\n\t\tD88800D0166F63B600DAFFC4 /* DOUNoteArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D88800CE166F63B500DAFFC4 /* DOUNoteArray.m */; };\n\t\tD88800D2166F654100DAFFC4 /* MovieArray.json in Resources */ = {isa = PBXBuildFile; fileRef = D88800D1166F654100DAFFC4 /* MovieArray.json */; };\n\t\tD88800D4166F65A200DAFFC4 /* DOUMovieTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D88800D3166F65A200DAFFC4 /* DOUMovieTests.m */; };\n\t\tD88800D7166F65CA00DAFFC4 /* DOUMovie.h in Headers */ = {isa = PBXBuildFile; fileRef = D88800D5166F65CA00DAFFC4 /* DOUMovie.h */; };\n\t\tD88800D8166F65CA00DAFFC4 /* DOUMovie.m in Sources */ = {isa = PBXBuildFile; fileRef = D88800D6166F65CA00DAFFC4 /* DOUMovie.m */; };\n\t\tD88800DB166F65E400DAFFC4 /* DOUMovieArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D88800D9166F65E400DAFFC4 /* DOUMovieArray.h */; };\n\t\tD88800DC166F65E400DAFFC4 /* DOUMovieArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D88800DA166F65E400DAFFC4 /* DOUMovieArray.m */; };\n\t\tD88800DD166F6AD000DAFFC4 /* DOUMovie.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D88800D5166F65CA00DAFFC4 /* DOUMovie.h */; };\n\t\tD88800DE166F6AD000DAFFC4 /* DOUMovieArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D88800D9166F65E400DAFFC4 /* DOUMovieArray.h */; };\n\t\tD88800DF166F6AD000DAFFC4 /* DOUNote.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D88800C5166F5D4E00DAFFC4 /* DOUNote.h */; };\n\t\tD88800E0166F6AD000DAFFC4 /* DOUNoteArray.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D88800CD166F63B400DAFFC4 /* DOUNoteArray.h */; };\n\t\tD88EAEFD14691D0800A4DE43 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D88EAEFC14691D0800A4DE43 /* CoreGraphics.framework */; };\n\t\tD88EAEFE14691D2F00A4DE43 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D800D71F14690D32009F64FD /* Security.framework */; };\n\t\tD88EAEFF14691D5B00A4DE43 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D88EAEFC14691D0800A4DE43 /* CoreGraphics.framework */; };\n\t\tD89A2A5615ECA3360027C0B0 /* Event.json in Resources */ = {isa = PBXBuildFile; fileRef = D89A2A5515ECA3360027C0B0 /* Event.json */; };\n\t\tD89A6A96162D37EE00954BC4 /* DOUUser.h in Headers */ = {isa = PBXBuildFile; fileRef = D89A6A94162D37EE00954BC4 /* DOUUser.h */; };\n\t\tD89A6A97162D37EE00954BC4 /* DOUUser.m in Sources */ = {isa = PBXBuildFile; fileRef = D89A6A95162D37EE00954BC4 /* DOUUser.m */; };\n\t\tD89A6AA1162D384100954BC4 /* DOUEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = D89A6A99162D384100954BC4 /* DOUEvent.h */; };\n\t\tD89A6AA2162D384100954BC4 /* DOUEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = D89A6A9A162D384100954BC4 /* DOUEvent.m */; };\n\t\tD89A6AA3162D384100954BC4 /* DOUEventArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D89A6A9B162D384100954BC4 /* DOUEventArray.h */; };\n\t\tD89A6AA4162D384100954BC4 /* DOUEventArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D89A6A9C162D384100954BC4 /* DOUEventArray.m */; };\n\t\tD89A6AA5162D384100954BC4 /* DOULoc.h in Headers */ = {isa = PBXBuildFile; fileRef = D89A6A9D162D384100954BC4 /* DOULoc.h */; };\n\t\tD89A6AA6162D384100954BC4 /* DOULoc.m in Sources */ = {isa = PBXBuildFile; fileRef = D89A6A9E162D384100954BC4 /* DOULoc.m */; };\n\t\tD89A6AA7162D384100954BC4 /* DOULocArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D89A6A9F162D384100954BC4 /* DOULocArray.h */; };\n\t\tD89A6AA8162D384100954BC4 /* DOULocArray.m in Sources */ = {isa = PBXBuildFile; fileRef = D89A6AA0162D384100954BC4 /* DOULocArray.m */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tD800D54E146907B2009F64FD /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = D800D52F146907B2009F64FD /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = D800D537146907B2009F64FD;\n\t\t\tremoteInfo = DoubanAPIEngine;\n\t\t};\n\t\tD820CFAC166E04170067C5A5 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = D800D52F146907B2009F64FD /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = D800D537146907B2009F64FD;\n\t\t\tremoteInfo = DoubanAPIEngine;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\tD820CFB0166E04AA0067C5A5 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal/${PRODUCT_NAME}.framework/Versions/A/Headers\";\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t\tD8695EBD167AFBCE00EFFF41 /* DOUBook.h in CopyFiles */,\n\t\t\t\tD8695EBE167AFBCE00EFFF41 /* DOUBookArray.h in CopyFiles */,\n\t\t\t\tD8695EBF167AFBCE00EFFF41 /* DOUMusic.h in CopyFiles */,\n\t\t\t\tD8695EC0167AFBCE00EFFF41 /* DOUMusicArray.h in CopyFiles */,\n\t\t\t\tD8695EC1167AFBCE00EFFF41 /* DOUAlbumArray.h in CopyFiles */,\n\t\t\t\tD88800DD166F6AD000DAFFC4 /* DOUMovie.h in CopyFiles */,\n\t\t\t\tD88800DE166F6AD000DAFFC4 /* DOUMovieArray.h in CopyFiles */,\n\t\t\t\tD88800DF166F6AD000DAFFC4 /* DOUNote.h in CopyFiles */,\n\t\t\t\tD88800E0166F6AD000DAFFC4 /* DOUNoteArray.h in CopyFiles */,\n\t\t\t\tD8880090166EEC3100DAFFC4 /* GDataAtomPubControl.h in CopyFiles */,\n\t\t\t\tD8880091166EEC3100DAFFC4 /* GDataBaseElements.h in CopyFiles */,\n\t\t\t\tD8880092166EEC3100DAFFC4 /* GDataBatchID.h in CopyFiles */,\n\t\t\t\tD8880093166EEC3100DAFFC4 /* GDataBatchInterrupted.h in CopyFiles */,\n\t\t\t\tD8880094166EEC3100DAFFC4 /* GDataBatchOperation.h in CopyFiles */,\n\t\t\t\tD8880095166EEC3100DAFFC4 /* GDataBatchStatus.h in CopyFiles */,\n\t\t\t\tD8880096166EEC3100DAFFC4 /* GDataCategory.h in CopyFiles */,\n\t\t\t\tD8880097166EEC3100DAFFC4 /* GDataComment.h in CopyFiles */,\n\t\t\t\tD8880098166EEC3100DAFFC4 /* GDataCustomProperty.h in CopyFiles */,\n\t\t\t\tD8880099166EEC3100DAFFC4 /* GDataDateTime.h in CopyFiles */,\n\t\t\t\tD888009A166EEC3100DAFFC4 /* GDataDeleted.h in CopyFiles */,\n\t\t\t\tD888009B166EEC3100DAFFC4 /* GDataElements.h in CopyFiles */,\n\t\t\t\tD888009C166EEC3100DAFFC4 /* GDataEmail.h in CopyFiles */,\n\t\t\t\tD888009D166EEC3100DAFFC4 /* GDataEntryContent.h in CopyFiles */,\n\t\t\t\tD888009E166EEC3100DAFFC4 /* GDataEntryLink.h in CopyFiles */,\n\t\t\t\tD888009F166EEC3100DAFFC4 /* GDataExtendedProperty.h in CopyFiles */,\n\t\t\t\tD88800A0166EEC3100DAFFC4 /* GDataFeedLink.h in CopyFiles */,\n\t\t\t\tD88800A1166EEC3100DAFFC4 /* GDataGenerator.h in CopyFiles */,\n\t\t\t\tD88800A2166EEC3100DAFFC4 /* GDataGeoPt.h in CopyFiles */,\n\t\t\t\tD88800A3166EEC3100DAFFC4 /* GDataIM.h in CopyFiles */,\n\t\t\t\tD88800A4166EEC3100DAFFC4 /* GDataLink.h in CopyFiles */,\n\t\t\t\tD88800A5166EEC3100DAFFC4 /* GDataMoney.h in CopyFiles */,\n\t\t\t\tD88800A6166EEC3100DAFFC4 /* GDataName.h in CopyFiles */,\n\t\t\t\tD88800A7166EEC3100DAFFC4 /* GDataOrganization.h in CopyFiles */,\n\t\t\t\tD88800A8166EEC3100DAFFC4 /* GDataOrganizationName.h in CopyFiles */,\n\t\t\t\tD88800A9166EEC3100DAFFC4 /* GDataPerson.h in CopyFiles */,\n\t\t\t\tD88800AA166EEC3100DAFFC4 /* GDataPhoneNumber.h in CopyFiles */,\n\t\t\t\tD88800AB166EEC3100DAFFC4 /* GDataPostalAddress.h in CopyFiles */,\n\t\t\t\tD88800AC166EEC3100DAFFC4 /* GDataRating.h in CopyFiles */,\n\t\t\t\tD88800AD166EEC3100DAFFC4 /* GDataStructuredPostalAddress.h in CopyFiles */,\n\t\t\t\tD88800AE166EEC3100DAFFC4 /* GDataTextConstruct.h in CopyFiles */,\n\t\t\t\tD88800AF166EEC3100DAFFC4 /* GDataValueConstruct.h in CopyFiles */,\n\t\t\t\tD88800B0166EEC3100DAFFC4 /* GDataWhen.h in CopyFiles */,\n\t\t\t\tD88800B1166EEC3100DAFFC4 /* GDataWhere.h in CopyFiles */,\n\t\t\t\tD88800B2166EEC3100DAFFC4 /* GDataWho.h in CopyFiles */,\n\t\t\t\tD88800B3166EEC3100DAFFC4 /* GDataDefines.h in CopyFiles */,\n\t\t\t\tD88800B4166EEC3100DAFFC4 /* GDataUtilities.h in CopyFiles */,\n\t\t\t\tD88800B5166EEC3100DAFFC4 /* GTMGatherInputStream.h in CopyFiles */,\n\t\t\t\tD88800B6166EEC3100DAFFC4 /* GTMMIMEDocument.h in CopyFiles */,\n\t\t\t\tD88800B7166EEC3100DAFFC4 /* GDataXMLNode.h in CopyFiles */,\n\t\t\t\tD888008D166EEAB900DAFFC4 /* GDataEntryBase.h in CopyFiles */,\n\t\t\t\tD888008E166EEAB900DAFFC4 /* GDataFeedBase.h in CopyFiles */,\n\t\t\t\tD888008F166EEAB900DAFFC4 /* GDataObject.h in CopyFiles */,\n\t\t\t\tD888006F166EE73300DAFFC4 /* DoubanEntryComment.h in CopyFiles */,\n\t\t\t\tD8880070166EE73300DAFFC4 /* DoubanFeedComment.h in CopyFiles */,\n\t\t\t\tD8880071166EE73300DAFFC4 /* DoubanEntryCity.h in CopyFiles */,\n\t\t\t\tD8880072166EE73300DAFFC4 /* DoubanEntryEvent.h in CopyFiles */,\n\t\t\t\tD8880073166EE73300DAFFC4 /* DoubanEntryEventCategory.h in CopyFiles */,\n\t\t\t\tD8880074166EE73300DAFFC4 /* DoubanFeedCity.h in CopyFiles */,\n\t\t\t\tD8880075166EE73300DAFFC4 /* DoubanFeedEvent.h in CopyFiles */,\n\t\t\t\tD8880076166EE73300DAFFC4 /* DoubanFeedEventCategory.h in CopyFiles */,\n\t\t\t\tD8880077166EE73300DAFFC4 /* DoubanEntryMiniblog.h in CopyFiles */,\n\t\t\t\tD8880078166EE73300DAFFC4 /* DoubanFeedMiniblog.h in CopyFiles */,\n\t\t\t\tD8880079166EE73300DAFFC4 /* DoubanEntryPeople.h in CopyFiles */,\n\t\t\t\tD888007A166EE73300DAFFC4 /* DoubanFeedPeople.h in CopyFiles */,\n\t\t\t\tD888007B166EE73300DAFFC4 /* DoubanEntryAlbum.h in CopyFiles */,\n\t\t\t\tD888007C166EE73300DAFFC4 /* DoubanEntryPhoto.h in CopyFiles */,\n\t\t\t\tD888007D166EE73300DAFFC4 /* DoubanFeedAlbum.h in CopyFiles */,\n\t\t\t\tD888007E166EE73300DAFFC4 /* DoubanFeedPhoto.h in CopyFiles */,\n\t\t\t\tD888007F166EE73300DAFFC4 /* DoubanEntryRecommendation.h in CopyFiles */,\n\t\t\t\tD8880080166EE73300DAFFC4 /* DoubanFeedRecommendation.h in CopyFiles */,\n\t\t\t\tD8880081166EE73300DAFFC4 /* DoubanEntryReview.h in CopyFiles */,\n\t\t\t\tD8880082166EE73300DAFFC4 /* DoubanFeedReview.h in CopyFiles */,\n\t\t\t\tD8880083166EE73300DAFFC4 /* DoubanEntrySubject.h in CopyFiles */,\n\t\t\t\tD8880084166EE73300DAFFC4 /* DoubanFeedSubject.h in CopyFiles */,\n\t\t\t\tD8880085166EE73300DAFFC4 /* DoubanDefines.h in CopyFiles */,\n\t\t\t\tD8880086166EE73300DAFFC4 /* DoubanAttribute.h in CopyFiles */,\n\t\t\t\tD8880087166EE73300DAFFC4 /* DoubanLocation.h in CopyFiles */,\n\t\t\t\tD8880088166EE73300DAFFC4 /* DoubanSignature.h in CopyFiles */,\n\t\t\t\tD8880089166EE73300DAFFC4 /* DoubanTag.h in CopyFiles */,\n\t\t\t\tD888008A166EE73300DAFFC4 /* DoubanUID.h in CopyFiles */,\n\t\t\t\tD888008B166EE73300DAFFC4 /* GeorssPoint.h in CopyFiles */,\n\t\t\t\tD820CFDE166E0B330067C5A5 /* ASICacheDelegate.h in CopyFiles */,\n\t\t\t\tD820CFDF166E0B330067C5A5 /* ASIHTTPRequestConfig.h in CopyFiles */,\n\t\t\t\tD820CFE0166E0B330067C5A5 /* ASIHTTPRequestDelegate.h in CopyFiles */,\n\t\t\t\tD820CFDD166E0A520067C5A5 /* ASIHTTPRequest.h in CopyFiles */,\n\t\t\t\tD820CFDC166E068E0067C5A5 /* ASIProgressDelegate.h in CopyFiles */,\n\t\t\t\tD820CFB1166E05390067C5A5 /* DOUAPIConfig.h in CopyFiles */,\n\t\t\t\tD820CFB2166E05390067C5A5 /* DOUAPIEngine.h in CopyFiles */,\n\t\t\t\tD820CFB3166E05390067C5A5 /* DOUService.h in CopyFiles */,\n\t\t\t\tD820CFB4166E05390067C5A5 /* DOUQuery.h in CopyFiles */,\n\t\t\t\tD820CFB5166E05390067C5A5 /* DOUHttpRequest.h in CopyFiles */,\n\t\t\t\tD820CFB6166E05390067C5A5 /* DOUOAuthService.h in CopyFiles */,\n\t\t\t\tD820CFB7166E05390067C5A5 /* DOUOAuthStore.h in CopyFiles */,\n\t\t\t\tD820CFB8166E05390067C5A5 /* DOUOAuth2.h in CopyFiles */,\n\t\t\t\tD820CFB9166E05390067C5A5 /* DOUEvent.h in CopyFiles */,\n\t\t\t\tD820CFBA166E05390067C5A5 /* DOUEventArray.h in CopyFiles */,\n\t\t\t\tD820CFBB166E05390067C5A5 /* DOULoc.h in CopyFiles */,\n\t\t\t\tD820CFBC166E05390067C5A5 /* DOULocArray.h in CopyFiles */,\n\t\t\t\tD820CFBD166E05390067C5A5 /* DOUAlbum.h in CopyFiles */,\n\t\t\t\tD820CFBE166E05390067C5A5 /* DOUPhoto.h in CopyFiles */,\n\t\t\t\tD820CFBF166E05390067C5A5 /* DOUPhotoArray.h in CopyFiles */,\n\t\t\t\tD820CFC0166E05390067C5A5 /* DOUUser.h in CopyFiles */,\n\t\t\t\tD820CFC1166E05390067C5A5 /* DOUComment.h in CopyFiles */,\n\t\t\t\tD820CFC2166E05390067C5A5 /* DOUCommentArray.h in CopyFiles */,\n\t\t\t\tD820CFC3166E05390067C5A5 /* DOUObject+Utils.h in CopyFiles */,\n\t\t\t\tD820CFC4166E05390067C5A5 /* DOUOnline.h in CopyFiles */,\n\t\t\t\tD820CFC5166E05390067C5A5 /* DOUOnlineArray.h in CopyFiles */,\n\t\t\t\tD820CFC6166E05390067C5A5 /* DOUObject.h in CopyFiles */,\n\t\t\t\tD820CFC7166E05390067C5A5 /* DOUObjectArray.h in CopyFiles */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1A3451D6167887E90097FEF5 /* DOUBookArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUBookArray.m; sourceTree = \"<group>\"; };\n\t\t1A3451D7167887E90097FEF5 /* DOUBookArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUBookArray.h; sourceTree = \"<group>\"; };\n\t\t1A3451D8167887E90097FEF5 /* DOUBook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUBook.m; sourceTree = \"<group>\"; };\n\t\t1A3451D9167887E90097FEF5 /* DOUBook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUBook.h; sourceTree = \"<group>\"; };\n\t\t1A3451DE167887F80097FEF5 /* DOUMusicArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUMusicArray.m; sourceTree = \"<group>\"; };\n\t\t1A3451DF167887F80097FEF5 /* DOUMusicArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUMusicArray.h; sourceTree = \"<group>\"; };\n\t\t1A3451E0167887F80097FEF5 /* DOUMusic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUMusic.m; sourceTree = \"<group>\"; };\n\t\t1A3451E1167887F80097FEF5 /* DOUMusic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUMusic.h; sourceTree = \"<group>\"; };\n\t\t1A3451E6167889060097FEF5 /* MusicArray.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MusicArray.json; sourceTree = \"<group>\"; };\n\t\t1A3451E7167889060097FEF5 /* BookArray.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = BookArray.json; sourceTree = \"<group>\"; };\n\t\t1A3451EA167889140097FEF5 /* DOUMusicTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DOUMusicTests.m; path = Model2/DOUMusicTests.m; sourceTree = \"<group>\"; };\n\t\t1A3451EB167889140097FEF5 /* DOUBookTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DOUBookTests.m; path = Model2/DOUBookTests.m; sourceTree = \"<group>\"; };\n\t\tD800D538146907B2009F64FD /* libDoubanAPIEngine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDoubanAPIEngine.a; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tD800D53B146907B2009F64FD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };\n\t\tD800D53F146907B2009F64FD /* DoubanAPIEngine-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"DoubanAPIEngine-Prefix.pch\"; sourceTree = \"<group>\"; };\n\t\tD800D548146907B2009F64FD /* DoubanAPIEngineTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubanAPIEngineTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tD800D549146907B2009F64FD /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };\n\t\tD800D553146907B2009F64FD /* DoubanAPIEngineTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = \"DoubanAPIEngineTests-Info.plist\"; sourceTree = \"<group>\"; };\n\t\tD800D555146907B2009F64FD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n\t\tD800D558146907B2009F64FD /* DoubanAPIEngineTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DoubanAPIEngineTests.m; sourceTree = \"<group>\"; };\n\t\tD800D563146908AF009F64FD /* DOUAPIEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUAPIEngine.h; sourceTree = \"<group>\"; };\n\t\tD800D565146908AF009F64FD /* DOUHttpRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUHttpRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D566146908AF009F64FD /* DOUHttpRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUHttpRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D568146908AF009F64FD /* DOUOAuth2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUOAuth2.h; sourceTree = \"<group>\"; };\n\t\tD800D577146908FD009F64FD /* ASIAuthenticationDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIAuthenticationDialog.h; sourceTree = \"<group>\"; };\n\t\tD800D578146908FD009F64FD /* ASIAuthenticationDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIAuthenticationDialog.m; sourceTree = \"<group>\"; };\n\t\tD800D579146908FD009F64FD /* ASICacheDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICacheDelegate.h; sourceTree = \"<group>\"; };\n\t\tD800D57A146908FD009F64FD /* ASIDataCompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIDataCompressor.h; sourceTree = \"<group>\"; };\n\t\tD800D57B146908FD009F64FD /* ASIDataCompressor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIDataCompressor.m; sourceTree = \"<group>\"; };\n\t\tD800D57C146908FD009F64FD /* ASIDataDecompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIDataDecompressor.h; sourceTree = \"<group>\"; };\n\t\tD800D57D146908FD009F64FD /* ASIDataDecompressor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIDataDecompressor.m; sourceTree = \"<group>\"; };\n\t\tD800D57E146908FD009F64FD /* ASIDownloadCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIDownloadCache.h; sourceTree = \"<group>\"; };\n\t\tD800D57F146908FD009F64FD /* ASIDownloadCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIDownloadCache.m; sourceTree = \"<group>\"; };\n\t\tD800D580146908FD009F64FD /* ASIFormDataRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIFormDataRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D581146908FD009F64FD /* ASIFormDataRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIFormDataRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D582146908FD009F64FD /* ASIHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIHTTPRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D583146908FD009F64FD /* ASIHTTPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIHTTPRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D584146908FD009F64FD /* ASIHTTPRequestConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIHTTPRequestConfig.h; sourceTree = \"<group>\"; };\n\t\tD800D585146908FD009F64FD /* ASIHTTPRequestDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIHTTPRequestDelegate.h; sourceTree = \"<group>\"; };\n\t\tD800D586146908FD009F64FD /* ASIInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIInputStream.h; sourceTree = \"<group>\"; };\n\t\tD800D587146908FD009F64FD /* ASIInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIInputStream.m; sourceTree = \"<group>\"; };\n\t\tD800D588146908FD009F64FD /* ASINetworkQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASINetworkQueue.h; sourceTree = \"<group>\"; };\n\t\tD800D589146908FD009F64FD /* ASINetworkQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASINetworkQueue.m; sourceTree = \"<group>\"; };\n\t\tD800D58A146908FD009F64FD /* ASIProgressDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIProgressDelegate.h; sourceTree = \"<group>\"; };\n\t\tD800D58C146908FD009F64FD /* ASIWebPageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIWebPageRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D58D146908FD009F64FD /* ASIWebPageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIWebPageRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D58F146908FD009F64FD /* ASICloudFilesCDNRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICloudFilesCDNRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D590146908FD009F64FD /* ASICloudFilesCDNRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASICloudFilesCDNRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D591146908FD009F64FD /* ASICloudFilesContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICloudFilesContainer.h; sourceTree = \"<group>\"; };\n\t\tD800D592146908FD009F64FD /* ASICloudFilesContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASICloudFilesContainer.m; sourceTree = \"<group>\"; };\n\t\tD800D593146908FD009F64FD /* ASICloudFilesContainerRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICloudFilesContainerRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D594146908FD009F64FD /* ASICloudFilesContainerRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASICloudFilesContainerRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D595146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICloudFilesContainerXMLParserDelegate.h; sourceTree = \"<group>\"; };\n\t\tD800D596146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASICloudFilesContainerXMLParserDelegate.m; sourceTree = \"<group>\"; };\n\t\tD800D597146908FD009F64FD /* ASICloudFilesObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICloudFilesObject.h; sourceTree = \"<group>\"; };\n\t\tD800D598146908FD009F64FD /* ASICloudFilesObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASICloudFilesObject.m; sourceTree = \"<group>\"; };\n\t\tD800D599146908FD009F64FD /* ASICloudFilesObjectRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICloudFilesObjectRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D59A146908FD009F64FD /* ASICloudFilesObjectRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASICloudFilesObjectRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D59B146908FD009F64FD /* ASICloudFilesRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASICloudFilesRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D59C146908FD009F64FD /* ASICloudFilesRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASICloudFilesRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D59E146908FD009F64FD /* ASINSXMLParserCompat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASINSXMLParserCompat.h; sourceTree = \"<group>\"; };\n\t\tD800D59F146908FD009F64FD /* ASIS3Bucket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIS3Bucket.h; sourceTree = \"<group>\"; };\n\t\tD800D5A0146908FD009F64FD /* ASIS3Bucket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIS3Bucket.m; sourceTree = \"<group>\"; };\n\t\tD800D5A1146908FD009F64FD /* ASIS3BucketObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIS3BucketObject.h; sourceTree = \"<group>\"; };\n\t\tD800D5A2146908FD009F64FD /* ASIS3BucketObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIS3BucketObject.m; sourceTree = \"<group>\"; };\n\t\tD800D5A3146908FD009F64FD /* ASIS3BucketRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIS3BucketRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D5A4146908FD009F64FD /* ASIS3BucketRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIS3BucketRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D5A5146908FD009F64FD /* ASIS3ObjectRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIS3ObjectRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D5A6146908FD009F64FD /* ASIS3ObjectRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIS3ObjectRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D5A7146908FD009F64FD /* ASIS3Request.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIS3Request.h; sourceTree = \"<group>\"; };\n\t\tD800D5A8146908FD009F64FD /* ASIS3Request.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIS3Request.m; sourceTree = \"<group>\"; };\n\t\tD800D5A9146908FD009F64FD /* ASIS3ServiceRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIS3ServiceRequest.h; sourceTree = \"<group>\"; };\n\t\tD800D5AA146908FD009F64FD /* ASIS3ServiceRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIS3ServiceRequest.m; sourceTree = \"<group>\"; };\n\t\tD800D5AD146908FD009F64FD /* NSObject+SBJson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"NSObject+SBJson.h\"; sourceTree = \"<group>\"; };\n\t\tD800D5AE146908FD009F64FD /* NSObject+SBJson.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"NSObject+SBJson.m\"; sourceTree = \"<group>\"; };\n\t\tD800D5AF146908FD009F64FD /* SBJson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJson.h; sourceTree = \"<group>\"; };\n\t\tD800D5B0146908FD009F64FD /* SBJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonParser.h; sourceTree = \"<group>\"; };\n\t\tD800D5B1146908FD009F64FD /* SBJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonParser.m; sourceTree = \"<group>\"; };\n\t\tD800D5B2146908FD009F64FD /* SBJsonStreamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonStreamParser.h; sourceTree = \"<group>\"; };\n\t\tD800D5B3146908FD009F64FD /* SBJsonStreamParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonStreamParser.m; sourceTree = \"<group>\"; };\n\t\tD800D5B4146908FD009F64FD /* SBJsonStreamParserAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonStreamParserAccumulator.h; sourceTree = \"<group>\"; };\n\t\tD800D5B5146908FD009F64FD /* SBJsonStreamParserAccumulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonStreamParserAccumulator.m; sourceTree = \"<group>\"; };\n\t\tD800D5B6146908FD009F64FD /* SBJsonStreamParserAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonStreamParserAdapter.h; sourceTree = \"<group>\"; };\n\t\tD800D5B7146908FD009F64FD /* SBJsonStreamParserAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonStreamParserAdapter.m; sourceTree = \"<group>\"; };\n\t\tD800D5B8146908FD009F64FD /* SBJsonStreamParserState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonStreamParserState.h; sourceTree = \"<group>\"; };\n\t\tD800D5B9146908FD009F64FD /* SBJsonStreamParserState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonStreamParserState.m; sourceTree = \"<group>\"; };\n\t\tD800D5BA146908FD009F64FD /* SBJsonStreamWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonStreamWriter.h; sourceTree = \"<group>\"; };\n\t\tD800D5BB146908FD009F64FD /* SBJsonStreamWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonStreamWriter.m; sourceTree = \"<group>\"; };\n\t\tD800D5BC146908FD009F64FD /* SBJsonStreamWriterAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonStreamWriterAccumulator.h; sourceTree = \"<group>\"; };\n\t\tD800D5BD146908FD009F64FD /* SBJsonStreamWriterAccumulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonStreamWriterAccumulator.m; sourceTree = \"<group>\"; };\n\t\tD800D5BE146908FD009F64FD /* SBJsonStreamWriterState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonStreamWriterState.h; sourceTree = \"<group>\"; };\n\t\tD800D5BF146908FD009F64FD /* SBJsonStreamWriterState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonStreamWriterState.m; sourceTree = \"<group>\"; };\n\t\tD800D5C0146908FD009F64FD /* SBJsonTokeniser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonTokeniser.h; sourceTree = \"<group>\"; };\n\t\tD800D5C1146908FD009F64FD /* SBJsonTokeniser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonTokeniser.m; sourceTree = \"<group>\"; };\n\t\tD800D5C2146908FD009F64FD /* SBJsonUTF8Stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonUTF8Stream.h; sourceTree = \"<group>\"; };\n\t\tD800D5C3146908FD009F64FD /* SBJsonUTF8Stream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonUTF8Stream.m; sourceTree = \"<group>\"; };\n\t\tD800D5C4146908FD009F64FD /* SBJsonWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonWriter.h; sourceTree = \"<group>\"; };\n\t\tD800D5C5146908FD009F64FD /* SBJsonWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonWriter.m; sourceTree = \"<group>\"; };\n\t\tD800D5C7146908FD009F64FD /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = \"<group>\"; };\n\t\tD800D5C8146908FD009F64FD /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = \"<group>\"; };\n\t\tD800D6151469092C009F64FD /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };\n\t\tD800D624146909C2009F64FD /* DOUAPIConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUAPIConfig.h; sourceTree = \"<group>\"; };\n\t\tD800D625146909C2009F64FD /* DOUAPIConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUAPIConfig.m; sourceTree = \"<group>\"; };\n\t\tD800D71814690B3F009F64FD /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };\n\t\tD800D71A14690B6E009F64FD /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };\n\t\tD800D71F14690D32009F64FD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };\n\t\tD800D72414690E2D009F64FD /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };\n\t\tD800D72814690E53009F64FD /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };\n\t\tD800D72A14690E6F009F64FD /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };\n\t\tD858E04414C3AC0D00335280 /* DOUQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUQuery.h; sourceTree = \"<group>\"; };\n\t\tD858E04514C3AC0D00335280 /* DOUQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUQuery.m; sourceTree = \"<group>\"; };\n\t\tD858E04C14C3DA9100335280 /* DOUService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUService.h; sourceTree = \"<group>\"; };\n\t\tD858E04D14C3DA9100335280 /* DOUService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUService.m; sourceTree = \"<group>\"; };\n\t\tD8695E8B167AD59000EFFF41 /* DOUNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUNotification.h; sourceTree = \"<group>\"; };\n\t\tD8695E8C167AD59000EFFF41 /* DOUNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUNotification.m; sourceTree = \"<group>\"; };\n\t\tD8695E8D167AD59000EFFF41 /* DOUNotificationArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUNotificationArray.h; sourceTree = \"<group>\"; };\n\t\tD8695E8E167AD59000EFFF41 /* DOUNotificationArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUNotificationArray.m; sourceTree = \"<group>\"; };\n\t\tD87D4B1115C3EF600006FAFE /* DOUObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUObject.h; sourceTree = \"<group>\"; };\n\t\tD87D4B1215C3EF600006FAFE /* DOUObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUObject.m; sourceTree = \"<group>\"; };\n\t\tD87D4B1315C3EF600006FAFE /* DOUObject+Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"DOUObject+Utils.h\"; sourceTree = \"<group>\"; };\n\t\tD87D4B1415C3EF600006FAFE /* DOUObject+Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"DOUObject+Utils.m\"; sourceTree = \"<group>\"; };\n\t\tD87D4B1515C3EF600006FAFE /* DOUObjectArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUObjectArray.h; sourceTree = \"<group>\"; };\n\t\tD87D4B1615C3EF600006FAFE /* DOUObjectArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUObjectArray.m; sourceTree = \"<group>\"; };\n\t\tD87D4B2A15C3EFE70006FAFE /* DOUOnline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUOnline.h; sourceTree = \"<group>\"; };\n\t\tD87D4B2B15C3EFE70006FAFE /* DOUOnline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUOnline.m; sourceTree = \"<group>\"; };\n\t\tD87D4B2C15C3EFE70006FAFE /* DOUOnlineArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUOnlineArray.h; sourceTree = \"<group>\"; };\n\t\tD87D4B2D15C3EFE70006FAFE /* DOUOnlineArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUOnlineArray.m; sourceTree = \"<group>\"; };\n\t\tD87D4B3315C3F0230006FAFE /* DOUAlbum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUAlbum.h; sourceTree = \"<group>\"; };\n\t\tD87D4B3415C3F0230006FAFE /* DOUAlbum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUAlbum.m; sourceTree = \"<group>\"; };\n\t\tD87D4B3515C3F0230006FAFE /* DOUPhoto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUPhoto.h; sourceTree = \"<group>\"; };\n\t\tD87D4B3615C3F0230006FAFE /* DOUPhoto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUPhoto.m; sourceTree = \"<group>\"; };\n\t\tD87D4B3715C3F0230006FAFE /* DOUPhotoArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUPhotoArray.h; sourceTree = \"<group>\"; };\n\t\tD87D4B3815C3F0230006FAFE /* DOUPhotoArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUPhotoArray.m; sourceTree = \"<group>\"; };\n\t\tD87D4B4115C3F0420006FAFE /* GDataEntryBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataEntryBase.h; sourceTree = \"<group>\"; };\n\t\tD87D4B4215C3F0420006FAFE /* GDataEntryBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataEntryBase.m; sourceTree = \"<group>\"; };\n\t\tD87D4B4315C3F0420006FAFE /* GDataFeedBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataFeedBase.h; sourceTree = \"<group>\"; };\n\t\tD87D4B4415C3F0420006FAFE /* GDataFeedBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataFeedBase.m; sourceTree = \"<group>\"; };\n\t\tD87D4B4515C3F0420006FAFE /* GDataObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataObject.h; sourceTree = \"<group>\"; };\n\t\tD87D4B4615C3F0420006FAFE /* GDataObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataObject.m; sourceTree = \"<group>\"; };\n\t\tD87D4B4815C3F0420006FAFE /* GDataAtomPubControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataAtomPubControl.h; sourceTree = \"<group>\"; };\n\t\tD87D4B4915C3F0420006FAFE /* GDataAtomPubControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataAtomPubControl.m; sourceTree = \"<group>\"; };\n\t\tD87D4B4A15C3F0420006FAFE /* GDataBaseElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataBaseElements.h; sourceTree = \"<group>\"; };\n\t\tD87D4B4B15C3F0420006FAFE /* GDataBaseElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataBaseElements.m; sourceTree = \"<group>\"; };\n\t\tD87D4B4C15C3F0420006FAFE /* GDataBatchID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataBatchID.h; sourceTree = \"<group>\"; };\n\t\tD87D4B4D15C3F0420006FAFE /* GDataBatchID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataBatchID.m; sourceTree = \"<group>\"; };\n\t\tD87D4B4E15C3F0420006FAFE /* GDataBatchInterrupted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataBatchInterrupted.h; sourceTree = \"<group>\"; };\n\t\tD87D4B4F15C3F0420006FAFE /* GDataBatchInterrupted.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataBatchInterrupted.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5015C3F0420006FAFE /* GDataBatchOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataBatchOperation.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5115C3F0420006FAFE /* GDataBatchOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataBatchOperation.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5215C3F0420006FAFE /* GDataBatchStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataBatchStatus.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5315C3F0420006FAFE /* GDataBatchStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataBatchStatus.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5415C3F0420006FAFE /* GDataCategory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataCategory.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5515C3F0420006FAFE /* GDataCategory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataCategory.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5615C3F0420006FAFE /* GDataComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataComment.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5715C3F0420006FAFE /* GDataComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataComment.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5815C3F0420006FAFE /* GDataCustomProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataCustomProperty.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5915C3F0420006FAFE /* GDataCustomProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataCustomProperty.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5A15C3F0420006FAFE /* GDataDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataDateTime.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5B15C3F0420006FAFE /* GDataDateTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataDateTime.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5C15C3F0420006FAFE /* GDataDeleted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataDeleted.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5D15C3F0420006FAFE /* GDataDeleted.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataDeleted.m; sourceTree = \"<group>\"; };\n\t\tD87D4B5E15C3F0420006FAFE /* GDataElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataElements.h; sourceTree = \"<group>\"; };\n\t\tD87D4B5F15C3F0420006FAFE /* GDataEmail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataEmail.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6015C3F0420006FAFE /* GDataEmail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataEmail.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6115C3F0420006FAFE /* GDataEntryContent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataEntryContent.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6215C3F0420006FAFE /* GDataEntryContent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataEntryContent.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6315C3F0420006FAFE /* GDataEntryLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataEntryLink.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6415C3F0420006FAFE /* GDataEntryLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataEntryLink.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6515C3F0420006FAFE /* GDataExtendedProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataExtendedProperty.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6615C3F0420006FAFE /* GDataExtendedProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataExtendedProperty.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6715C3F0420006FAFE /* GDataFeedLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataFeedLink.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6815C3F0420006FAFE /* GDataFeedLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataFeedLink.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6915C3F0420006FAFE /* GDataGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataGenerator.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6A15C3F0420006FAFE /* GDataGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataGenerator.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6B15C3F0420006FAFE /* GDataGeoPt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataGeoPt.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6C15C3F0420006FAFE /* GDataGeoPt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataGeoPt.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6D15C3F0420006FAFE /* GDataIM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataIM.h; sourceTree = \"<group>\"; };\n\t\tD87D4B6E15C3F0420006FAFE /* GDataIM.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataIM.m; sourceTree = \"<group>\"; };\n\t\tD87D4B6F15C3F0420006FAFE /* GDataLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataLink.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7015C3F0420006FAFE /* GDataLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataLink.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7115C3F0420006FAFE /* GDataMoney.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataMoney.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7215C3F0420006FAFE /* GDataMoney.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataMoney.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7315C3F0420006FAFE /* GDataName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataName.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7415C3F0420006FAFE /* GDataName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataName.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7515C3F0420006FAFE /* GDataOrganization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataOrganization.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7615C3F0420006FAFE /* GDataOrganization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataOrganization.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7715C3F0420006FAFE /* GDataOrganizationName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataOrganizationName.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7815C3F0420006FAFE /* GDataOrganizationName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataOrganizationName.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7915C3F0420006FAFE /* GDataPerson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataPerson.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7A15C3F0420006FAFE /* GDataPerson.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataPerson.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7B15C3F0420006FAFE /* GDataPhoneNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataPhoneNumber.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7C15C3F0420006FAFE /* GDataPhoneNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataPhoneNumber.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7D15C3F0420006FAFE /* GDataPostalAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataPostalAddress.h; sourceTree = \"<group>\"; };\n\t\tD87D4B7E15C3F0420006FAFE /* GDataPostalAddress.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataPostalAddress.m; sourceTree = \"<group>\"; };\n\t\tD87D4B7F15C3F0420006FAFE /* GDataRating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataRating.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8015C3F0420006FAFE /* GDataRating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataRating.m; sourceTree = \"<group>\"; };\n\t\tD87D4B8115C3F0420006FAFE /* GDataStructuredPostalAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataStructuredPostalAddress.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8215C3F0420006FAFE /* GDataStructuredPostalAddress.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataStructuredPostalAddress.m; sourceTree = \"<group>\"; };\n\t\tD87D4B8315C3F0420006FAFE /* GDataTextConstruct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataTextConstruct.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8415C3F0420006FAFE /* GDataTextConstruct.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataTextConstruct.m; sourceTree = \"<group>\"; };\n\t\tD87D4B8515C3F0420006FAFE /* GDataValueConstruct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataValueConstruct.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8615C3F0420006FAFE /* GDataValueConstruct.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataValueConstruct.m; sourceTree = \"<group>\"; };\n\t\tD87D4B8715C3F0420006FAFE /* GDataWhen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataWhen.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8815C3F0420006FAFE /* GDataWhen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataWhen.m; sourceTree = \"<group>\"; };\n\t\tD87D4B8915C3F0420006FAFE /* GDataWhere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataWhere.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8A15C3F0420006FAFE /* GDataWhere.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataWhere.m; sourceTree = \"<group>\"; };\n\t\tD87D4B8B15C3F0420006FAFE /* GDataWho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataWho.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8C15C3F0420006FAFE /* GDataWho.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataWho.m; sourceTree = \"<group>\"; };\n\t\tD87D4B8D15C3F0420006FAFE /* GDataDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataDefines.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8E15C3F0420006FAFE /* GDataUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataUtilities.h; sourceTree = \"<group>\"; };\n\t\tD87D4B8F15C3F0420006FAFE /* GDataUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataUtilities.m; sourceTree = \"<group>\"; };\n\t\tD87D4B9115C3F0420006FAFE /* GTMGatherInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMGatherInputStream.h; sourceTree = \"<group>\"; };\n\t\tD87D4B9215C3F0420006FAFE /* GTMGatherInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMGatherInputStream.m; sourceTree = \"<group>\"; };\n\t\tD87D4B9315C3F0420006FAFE /* GTMMIMEDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMMIMEDocument.h; sourceTree = \"<group>\"; };\n\t\tD87D4B9415C3F0420006FAFE /* GTMMIMEDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMMIMEDocument.m; sourceTree = \"<group>\"; };\n\t\tD87D4B9615C3F0420006FAFE /* GDataXMLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDataXMLNode.h; sourceTree = \"<group>\"; };\n\t\tD87D4B9715C3F0420006FAFE /* GDataXMLNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GDataXMLNode.m; sourceTree = \"<group>\"; };\n\t\tD87D4B9B15C3F0420006FAFE /* DoubanEntryComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryComment.h; sourceTree = \"<group>\"; };\n\t\tD87D4B9C15C3F0420006FAFE /* DoubanEntryComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryComment.m; sourceTree = \"<group>\"; };\n\t\tD87D4B9D15C3F0420006FAFE /* DoubanFeedComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedComment.h; sourceTree = \"<group>\"; };\n\t\tD87D4B9E15C3F0420006FAFE /* DoubanFeedComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedComment.m; sourceTree = \"<group>\"; };\n\t\tD87D4BA015C3F0420006FAFE /* DoubanEntryCity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryCity.h; sourceTree = \"<group>\"; };\n\t\tD87D4BA115C3F0420006FAFE /* DoubanEntryCity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryCity.m; sourceTree = \"<group>\"; };\n\t\tD87D4BA215C3F0420006FAFE /* DoubanEntryEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryEvent.h; sourceTree = \"<group>\"; };\n\t\tD87D4BA315C3F0420006FAFE /* DoubanEntryEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryEvent.m; sourceTree = \"<group>\"; };\n\t\tD87D4BA415C3F0420006FAFE /* DoubanEntryEventCategory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryEventCategory.h; sourceTree = \"<group>\"; };\n\t\tD87D4BA515C3F0420006FAFE /* DoubanEntryEventCategory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryEventCategory.m; sourceTree = \"<group>\"; };\n\t\tD87D4BA615C3F0420006FAFE /* DoubanFeedCity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedCity.h; sourceTree = \"<group>\"; };\n\t\tD87D4BA715C3F0420006FAFE /* DoubanFeedCity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedCity.m; sourceTree = \"<group>\"; };\n\t\tD87D4BA815C3F0420006FAFE /* DoubanFeedEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedEvent.h; sourceTree = \"<group>\"; };\n\t\tD87D4BA915C3F0420006FAFE /* DoubanFeedEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedEvent.m; sourceTree = \"<group>\"; };\n\t\tD87D4BAA15C3F0420006FAFE /* DoubanFeedEventCategory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedEventCategory.h; sourceTree = \"<group>\"; };\n\t\tD87D4BAB15C3F0420006FAFE /* DoubanFeedEventCategory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedEventCategory.m; sourceTree = \"<group>\"; };\n\t\tD87D4BAC15C3F0420006FAFE /* GDataAtomAuthor+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"GDataAtomAuthor+Extension.h\"; sourceTree = \"<group>\"; };\n\t\tD87D4BAD15C3F0420006FAFE /* GDataAtomAuthor+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"GDataAtomAuthor+Extension.m\"; sourceTree = \"<group>\"; };\n\t\tD87D4BAE15C3F0420006FAFE /* GDataEntryBase+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"GDataEntryBase+Extension.h\"; sourceTree = \"<group>\"; };\n\t\tD87D4BAF15C3F0420006FAFE /* GDataEntryBase+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"GDataEntryBase+Extension.m\"; sourceTree = \"<group>\"; };\n\t\tD87D4BB115C3F0420006FAFE /* DoubanEntryMiniblog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryMiniblog.h; sourceTree = \"<group>\"; };\n\t\tD87D4BB215C3F0420006FAFE /* DoubanEntryMiniblog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryMiniblog.m; sourceTree = \"<group>\"; };\n\t\tD87D4BB315C3F0420006FAFE /* DoubanFeedMiniblog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedMiniblog.h; sourceTree = \"<group>\"; };\n\t\tD87D4BB415C3F0420006FAFE /* DoubanFeedMiniblog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedMiniblog.m; sourceTree = \"<group>\"; };\n\t\tD87D4BB615C3F0420006FAFE /* DoubanEntryPeople.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryPeople.h; sourceTree = \"<group>\"; };\n\t\tD87D4BB715C3F0420006FAFE /* DoubanEntryPeople.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryPeople.m; sourceTree = \"<group>\"; };\n\t\tD87D4BB815C3F0420006FAFE /* DoubanFeedPeople.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedPeople.h; sourceTree = \"<group>\"; };\n\t\tD87D4BB915C3F0420006FAFE /* DoubanFeedPeople.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedPeople.m; sourceTree = \"<group>\"; };\n\t\tD87D4BBB15C3F0420006FAFE /* DoubanEntryAlbum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryAlbum.h; sourceTree = \"<group>\"; };\n\t\tD87D4BBC15C3F0420006FAFE /* DoubanEntryAlbum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryAlbum.m; sourceTree = \"<group>\"; };\n\t\tD87D4BBD15C3F0420006FAFE /* DoubanEntryPhoto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryPhoto.h; sourceTree = \"<group>\"; };\n\t\tD87D4BBE15C3F0420006FAFE /* DoubanEntryPhoto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryPhoto.m; sourceTree = \"<group>\"; };\n\t\tD87D4BBF15C3F0420006FAFE /* DoubanFeedAlbum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedAlbum.h; sourceTree = \"<group>\"; };\n\t\tD87D4BC015C3F0420006FAFE /* DoubanFeedAlbum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedAlbum.m; sourceTree = \"<group>\"; };\n\t\tD87D4BC115C3F0420006FAFE /* DoubanFeedPhoto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedPhoto.h; sourceTree = \"<group>\"; };\n\t\tD87D4BC215C3F0420006FAFE /* DoubanFeedPhoto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedPhoto.m; sourceTree = \"<group>\"; };\n\t\tD87D4BC415C3F0420006FAFE /* DoubanEntryRecommendation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryRecommendation.h; sourceTree = \"<group>\"; };\n\t\tD87D4BC515C3F0420006FAFE /* DoubanEntryRecommendation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryRecommendation.m; sourceTree = \"<group>\"; };\n\t\tD87D4BC615C3F0430006FAFE /* DoubanFeedRecommendation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedRecommendation.h; sourceTree = \"<group>\"; };\n\t\tD87D4BC715C3F0430006FAFE /* DoubanFeedRecommendation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedRecommendation.m; sourceTree = \"<group>\"; };\n\t\tD87D4BC915C3F0430006FAFE /* DoubanEntryReview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntryReview.h; sourceTree = \"<group>\"; };\n\t\tD87D4BCA15C3F0430006FAFE /* DoubanEntryReview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntryReview.m; sourceTree = \"<group>\"; };\n\t\tD87D4BCB15C3F0430006FAFE /* DoubanFeedReview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedReview.h; sourceTree = \"<group>\"; };\n\t\tD87D4BCC15C3F0430006FAFE /* DoubanFeedReview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedReview.m; sourceTree = \"<group>\"; };\n\t\tD87D4BCE15C3F0430006FAFE /* DoubanEntrySubject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanEntrySubject.h; sourceTree = \"<group>\"; };\n\t\tD87D4BCF15C3F0430006FAFE /* DoubanEntrySubject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEntrySubject.m; sourceTree = \"<group>\"; };\n\t\tD87D4BD015C3F0430006FAFE /* DoubanFeedSubject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanFeedSubject.h; sourceTree = \"<group>\"; };\n\t\tD87D4BD115C3F0430006FAFE /* DoubanFeedSubject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanFeedSubject.m; sourceTree = \"<group>\"; };\n\t\tD87D4BD215C3F0430006FAFE /* DoubanDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanDefines.h; sourceTree = \"<group>\"; };\n\t\tD87D4BD315C3F0430006FAFE /* DoubanDefines.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanDefines.m; sourceTree = \"<group>\"; };\n\t\tD87D4BD515C3F0430006FAFE /* DoubanAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanAttribute.h; sourceTree = \"<group>\"; };\n\t\tD87D4BD615C3F0430006FAFE /* DoubanAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanAttribute.m; sourceTree = \"<group>\"; };\n\t\tD87D4BD715C3F0430006FAFE /* DoubanLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanLocation.h; sourceTree = \"<group>\"; };\n\t\tD87D4BD815C3F0430006FAFE /* DoubanLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanLocation.m; sourceTree = \"<group>\"; };\n\t\tD87D4BD915C3F0430006FAFE /* DoubanSignature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanSignature.h; sourceTree = \"<group>\"; };\n\t\tD87D4BDA15C3F0430006FAFE /* DoubanSignature.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanSignature.m; sourceTree = \"<group>\"; };\n\t\tD87D4BDB15C3F0430006FAFE /* DoubanTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanTag.h; sourceTree = \"<group>\"; };\n\t\tD87D4BDC15C3F0430006FAFE /* DoubanTag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanTag.m; sourceTree = \"<group>\"; };\n\t\tD87D4BDD15C3F0430006FAFE /* DoubanUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanUID.h; sourceTree = \"<group>\"; };\n\t\tD87D4BDE15C3F0430006FAFE /* DoubanUID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanUID.m; sourceTree = \"<group>\"; };\n\t\tD87D4BDF15C3F0430006FAFE /* GeorssPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeorssPoint.h; sourceTree = \"<group>\"; };\n\t\tD87D4BE015C3F0430006FAFE /* GeorssPoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeorssPoint.m; sourceTree = \"<group>\"; };\n\t\tD87D4C7315C3F11C0006FAFE /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = \"NSData+Base64.h\"; path = \"Base64/NSData+Base64.h\"; sourceTree = \"<group>\"; };\n\t\tD87D4C7415C3F11C0006FAFE /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = \"NSData+Base64.m\"; path = \"Base64/NSData+Base64.m\"; sourceTree = \"<group>\"; };\n\t\tD87D4C7715C3F14E0006FAFE /* DOUComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUComment.h; sourceTree = \"<group>\"; };\n\t\tD87D4C7815C3F14E0006FAFE /* DOUComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUComment.m; sourceTree = \"<group>\"; };\n\t\tD87D4C7915C3F14E0006FAFE /* DOUCommentArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUCommentArray.h; sourceTree = \"<group>\"; };\n\t\tD87D4C7A15C3F14E0006FAFE /* DOUCommentArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUCommentArray.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8515C3F2A70006FAFE /* DoubanCityTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanCityTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8615C3F2A70006FAFE /* DoubanCommentTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanCommentTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8715C3F2A70006FAFE /* DoubanEventCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEventCategoryTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8815C3F2A70006FAFE /* DoubanEventTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanEventTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8915C3F2A70006FAFE /* DoubanMiniblogTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanMiniblogTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8A15C3F2A70006FAFE /* DoubanPeopleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanPeopleTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8B15C3F2A70006FAFE /* DoubanPhotoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanPhotoTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C8C15C3F2A70006FAFE /* DoubanSubjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanSubjectTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4C9715C3F4850006FAFE /* DoubanEntryCity.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanEntryCity.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9815C3F4850006FAFE /* DoubanEntryEvent.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanEntryEvent.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9915C3F4850006FAFE /* DoubanEntryMiniblog.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanEntryMiniblog.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9A15C3F4850006FAFE /* DoubanEntryPeople.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanEntryPeople.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9B15C3F4850006FAFE /* DoubanEntryPhoto.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanEntryPhoto.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9C15C3F4850006FAFE /* DoubanEntryRecommendation.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanEntryRecommendation.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9D15C3F4850006FAFE /* DoubanEntrySubject.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanEntrySubject.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9E15C3F4850006FAFE /* DoubanFeedCity.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedCity.xml; sourceTree = \"<group>\"; };\n\t\tD87D4C9F15C3F4850006FAFE /* DoubanFeedComment.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedComment.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CA015C3F4850006FAFE /* DoubanFeedEvent.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedEvent.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CA115C3F4850006FAFE /* DoubanFeedEventCategory.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedEventCategory.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CA215C3F4850006FAFE /* DoubanFeedMiniblog.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedMiniblog.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CA315C3F4850006FAFE /* DoubanFeedPeople.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedPeople.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CA415C3F4850006FAFE /* DoubanFeedPhoto.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedPhoto.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CA515C3F4850006FAFE /* DoubanFeedRecommendation.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedRecommendation.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CA615C3F4850006FAFE /* DoubanFeedSubject.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DoubanFeedSubject.xml; sourceTree = \"<group>\"; };\n\t\tD87D4CB715C3F5580006FAFE /* Album.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Album.json; sourceTree = \"<group>\"; };\n\t\tD87D4CB815C3F5580006FAFE /* CommentArray.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CommentArray.json; sourceTree = \"<group>\"; };\n\t\tD87D4CB915C3F5580006FAFE /* Online.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Online.json; sourceTree = \"<group>\"; };\n\t\tD87D4CBA15C3F5580006FAFE /* OnlineArray.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = OnlineArray.json; sourceTree = \"<group>\"; };\n\t\tD87D4CBB15C3F5580006FAFE /* Photo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Photo.json; sourceTree = \"<group>\"; };\n\t\tD87D4CBC15C3F5580006FAFE /* PhotoArray.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = PhotoArray.json; sourceTree = \"<group>\"; };\n\t\tD87D4CC315C3F56D0006FAFE /* DOUCommentTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DOUCommentTests.m; path = Model2/DOUCommentTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4CC415C3F56D0006FAFE /* DOUOnlineTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DOUOnlineTests.m; path = Model2/DOUOnlineTests.m; sourceTree = \"<group>\"; };\n\t\tD87D4CC515C3F56D0006FAFE /* DOUPhotoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DOUPhotoTests.m; path = Model2/DOUPhotoTests.m; sourceTree = \"<group>\"; };\n\t\tD882160C15889C5F004B4AD4 /* DOUOAuthService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUOAuthService.h; sourceTree = \"<group>\"; };\n\t\tD882160D15889C5F004B4AD4 /* DOUOAuthService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUOAuthService.m; sourceTree = \"<group>\"; };\n\t\tD882160E15889C5F004B4AD4 /* DOUOAuthStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUOAuthStore.h; sourceTree = \"<group>\"; };\n\t\tD882160F15889C5F004B4AD4 /* DOUOAuthStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUOAuthStore.m; sourceTree = \"<group>\"; };\n\t\tD882161415889DDE004B4AD4 /* DOUOAuthServiceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUOAuthServiceTests.m; sourceTree = \"<group>\"; };\n\t\tD882161715889DDE004B4AD4 /* DOUTestResponseLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUTestResponseLoader.h; sourceTree = \"<group>\"; };\n\t\tD882161815889DDE004B4AD4 /* DOUTestResponseLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUTestResponseLoader.m; sourceTree = \"<group>\"; };\n\t\tD88800BB166F5BF500DAFFC4 /* DOUAlbumArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUAlbumArray.h; sourceTree = \"<group>\"; };\n\t\tD88800BC166F5BF600DAFFC4 /* DOUAlbumArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUAlbumArray.m; sourceTree = \"<group>\"; };\n\t\tD88800C5166F5D4E00DAFFC4 /* DOUNote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUNote.h; sourceTree = \"<group>\"; };\n\t\tD88800C6166F5D4F00DAFFC4 /* DOUNote.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUNote.m; sourceTree = \"<group>\"; };\n\t\tD88800C9166F603F00DAFFC4 /* Note.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Note.json; sourceTree = \"<group>\"; };\n\t\tD88800CB166F609300DAFFC4 /* DOUNoteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DOUNoteTests.m; path = Model2/DOUNoteTests.m; sourceTree = \"<group>\"; };\n\t\tD88800CD166F63B400DAFFC4 /* DOUNoteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUNoteArray.h; sourceTree = \"<group>\"; };\n\t\tD88800CE166F63B500DAFFC4 /* DOUNoteArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUNoteArray.m; sourceTree = \"<group>\"; };\n\t\tD88800D1166F654100DAFFC4 /* MovieArray.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MovieArray.json; sourceTree = \"<group>\"; };\n\t\tD88800D3166F65A200DAFFC4 /* DOUMovieTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DOUMovieTests.m; path = Model2/DOUMovieTests.m; sourceTree = \"<group>\"; };\n\t\tD88800D5166F65CA00DAFFC4 /* DOUMovie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUMovie.h; sourceTree = \"<group>\"; };\n\t\tD88800D6166F65CA00DAFFC4 /* DOUMovie.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUMovie.m; sourceTree = \"<group>\"; };\n\t\tD88800D9166F65E400DAFFC4 /* DOUMovieArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUMovieArray.h; sourceTree = \"<group>\"; };\n\t\tD88800DA166F65E400DAFFC4 /* DOUMovieArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUMovieArray.m; sourceTree = \"<group>\"; };\n\t\tD88EAEFC14691D0800A4DE43 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };\n\t\tD89A2A5515ECA3360027C0B0 /* Event.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Event.json; sourceTree = \"<group>\"; };\n\t\tD89A6A94162D37EE00954BC4 /* DOUUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUUser.h; sourceTree = \"<group>\"; };\n\t\tD89A6A95162D37EE00954BC4 /* DOUUser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUUser.m; sourceTree = \"<group>\"; };\n\t\tD89A6A99162D384100954BC4 /* DOUEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUEvent.h; sourceTree = \"<group>\"; };\n\t\tD89A6A9A162D384100954BC4 /* DOUEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUEvent.m; sourceTree = \"<group>\"; };\n\t\tD89A6A9B162D384100954BC4 /* DOUEventArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOUEventArray.h; sourceTree = \"<group>\"; };\n\t\tD89A6A9C162D384100954BC4 /* DOUEventArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOUEventArray.m; sourceTree = \"<group>\"; };\n\t\tD89A6A9D162D384100954BC4 /* DOULoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOULoc.h; sourceTree = \"<group>\"; };\n\t\tD89A6A9E162D384100954BC4 /* DOULoc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOULoc.m; sourceTree = \"<group>\"; };\n\t\tD89A6A9F162D384100954BC4 /* DOULocArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOULocArray.h; sourceTree = \"<group>\"; };\n\t\tD89A6AA0162D384100954BC4 /* DOULocArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DOULocArray.m; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tD800D535146907B2009F64FD /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD800D72514690E2E009F64FD /* MobileCoreServices.framework in Frameworks */,\n\t\t\t\tD800D72914690E53009F64FD /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\tD800D72014690D32009F64FD /* Security.framework in Frameworks */,\n\t\t\t\tD800D71B14690B6E009F64FD /* CFNetwork.framework in Frameworks */,\n\t\t\t\tD800D72B14690E6F009F64FD /* libz.dylib in Frameworks */,\n\t\t\t\tD800D6161469092C009F64FD /* libxml2.dylib in Frameworks */,\n\t\t\t\tD800D71914690B3F009F64FD /* UIKit.framework in Frameworks */,\n\t\t\t\tD800D53C146907B2009F64FD /* Foundation.framework in Frameworks */,\n\t\t\t\tD88EAEFD14691D0800A4DE43 /* CoreGraphics.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tD800D544146907B2009F64FD /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD800D73D14691130009F64FD /* MobileCoreServices.framework in Frameworks */,\n\t\t\t\tD800D73B14691108009F64FD /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\tD88EAEFE14691D2F00A4DE43 /* Security.framework in Frameworks */,\n\t\t\t\tD800D73A146910F5009F64FD /* CFNetwork.framework in Frameworks */,\n\t\t\t\tD800D73E14691140009F64FD /* libz.dylib in Frameworks */,\n\t\t\t\tD800D739146910DF009F64FD /* libxml2.dylib in Frameworks */,\n\t\t\t\tD800D737146910D5009F64FD /* UIKit.framework in Frameworks */,\n\t\t\t\tD800D54D146907B2009F64FD /* Foundation.framework in Frameworks */,\n\t\t\t\tD88EAEFF14691D5B00A4DE43 /* CoreGraphics.framework in Frameworks */,\n\t\t\t\tD800D54A146907B2009F64FD /* SenTestingKit.framework in Frameworks */,\n\t\t\t\tD800D550146907B2009F64FD /* libDoubanAPIEngine.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\tD800D52D146907B2009F64FD = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D53D146907B2009F64FD /* DoubanAPIEngine */,\n\t\t\t\tD800D551146907B2009F64FD /* DoubanAPIEngineTests */,\n\t\t\t\tD800D53A146907B2009F64FD /* Frameworks */,\n\t\t\t\tD800D539146907B2009F64FD /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D539146907B2009F64FD /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D538146907B2009F64FD /* libDoubanAPIEngine.a */,\n\t\t\t\tD800D548146907B2009F64FD /* DoubanAPIEngineTests.octest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D53A146907B2009F64FD /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D6151469092C009F64FD /* libxml2.dylib */,\n\t\t\t\tD800D72A14690E6F009F64FD /* libz.dylib */,\n\t\t\t\tD800D72414690E2D009F64FD /* MobileCoreServices.framework */,\n\t\t\t\tD800D72814690E53009F64FD /* SystemConfiguration.framework */,\n\t\t\t\tD800D71F14690D32009F64FD /* Security.framework */,\n\t\t\t\tD800D71A14690B6E009F64FD /* CFNetwork.framework */,\n\t\t\t\tD800D71814690B3F009F64FD /* UIKit.framework */,\n\t\t\t\tD800D53B146907B2009F64FD /* Foundation.framework */,\n\t\t\t\tD88EAEFC14691D0800A4DE43 /* CoreGraphics.framework */,\n\t\t\t\tD800D549146907B2009F64FD /* SenTestingKit.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D53D146907B2009F64FD /* DoubanAPIEngine */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D562146908AF009F64FD /* Sources */,\n\t\t\t\tD800D575146908FD009F64FD /* OtherSources */,\n\t\t\t\tD800D53E146907B2009F64FD /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = DoubanAPIEngine;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D53E146907B2009F64FD /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D53F146907B2009F64FD /* DoubanAPIEngine-Prefix.pch */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D551146907B2009F64FD /* DoubanAPIEngineTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD882161615889DDE004B4AD4 /* Testing */,\n\t\t\t\tD88EAF3514692D9400A4DE43 /* Resources */,\n\t\t\t\tD882161415889DDE004B4AD4 /* DOUOAuthServiceTests.m */,\n\t\t\t\tD800D558146907B2009F64FD /* DoubanAPIEngineTests.m */,\n\t\t\t\tD87D4C8315C3F2700006FAFE /* Model */,\n\t\t\t\tD87D4C8415C3F2760006FAFE /* Model2 */,\n\t\t\t\tD800D552146907B2009F64FD /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = DoubanAPIEngineTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D552146907B2009F64FD /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D553146907B2009F64FD /* DoubanAPIEngineTests-Info.plist */,\n\t\t\t\tD800D554146907B2009F64FD /* InfoPlist.strings */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D562146908AF009F64FD /* Sources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D624146909C2009F64FD /* DOUAPIConfig.h */,\n\t\t\t\tD800D625146909C2009F64FD /* DOUAPIConfig.m */,\n\t\t\t\tD800D563146908AF009F64FD /* DOUAPIEngine.h */,\n\t\t\t\tD800D564146908AF009F64FD /* Network */,\n\t\t\t\tD800D567146908AF009F64FD /* OAuth2 */,\n\t\t\t\tD87D4B0115C3EF2F0006FAFE /* Model */,\n\t\t\t\tD87D4B0315C3EF350006FAFE /* Model2 */,\n\t\t\t);\n\t\t\tpath = Sources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D564146908AF009F64FD /* Network */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD858E04C14C3DA9100335280 /* DOUService.h */,\n\t\t\t\tD858E04D14C3DA9100335280 /* DOUService.m */,\n\t\t\t\tD858E04414C3AC0D00335280 /* DOUQuery.h */,\n\t\t\t\tD858E04514C3AC0D00335280 /* DOUQuery.m */,\n\t\t\t\tD800D565146908AF009F64FD /* DOUHttpRequest.h */,\n\t\t\t\tD800D566146908AF009F64FD /* DOUHttpRequest.m */,\n\t\t\t);\n\t\t\tpath = Network;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D567146908AF009F64FD /* OAuth2 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD882160C15889C5F004B4AD4 /* DOUOAuthService.h */,\n\t\t\t\tD882160D15889C5F004B4AD4 /* DOUOAuthService.m */,\n\t\t\t\tD882160E15889C5F004B4AD4 /* DOUOAuthStore.h */,\n\t\t\t\tD882160F15889C5F004B4AD4 /* DOUOAuthStore.m */,\n\t\t\t\tD800D568146908AF009F64FD /* DOUOAuth2.h */,\n\t\t\t);\n\t\t\tpath = OAuth2;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D575146908FD009F64FD /* OtherSources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8CFD43C151C742700CCC311 /* Base64 */,\n\t\t\t\tD800D576146908FD009F64FD /* ASIHTTPRequest */,\n\t\t\t\tD800D5AC146908FD009F64FD /* JSON */,\n\t\t\t\tD800D5C6146908FD009F64FD /* Reachability */,\n\t\t\t);\n\t\t\tpath = OtherSources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D576146908FD009F64FD /* ASIHTTPRequest */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D577146908FD009F64FD /* ASIAuthenticationDialog.h */,\n\t\t\t\tD800D578146908FD009F64FD /* ASIAuthenticationDialog.m */,\n\t\t\t\tD800D579146908FD009F64FD /* ASICacheDelegate.h */,\n\t\t\t\tD800D57A146908FD009F64FD /* ASIDataCompressor.h */,\n\t\t\t\tD800D57B146908FD009F64FD /* ASIDataCompressor.m */,\n\t\t\t\tD800D57C146908FD009F64FD /* ASIDataDecompressor.h */,\n\t\t\t\tD800D57D146908FD009F64FD /* ASIDataDecompressor.m */,\n\t\t\t\tD800D57E146908FD009F64FD /* ASIDownloadCache.h */,\n\t\t\t\tD800D57F146908FD009F64FD /* ASIDownloadCache.m */,\n\t\t\t\tD800D580146908FD009F64FD /* ASIFormDataRequest.h */,\n\t\t\t\tD800D581146908FD009F64FD /* ASIFormDataRequest.m */,\n\t\t\t\tD800D582146908FD009F64FD /* ASIHTTPRequest.h */,\n\t\t\t\tD800D583146908FD009F64FD /* ASIHTTPRequest.m */,\n\t\t\t\tD800D584146908FD009F64FD /* ASIHTTPRequestConfig.h */,\n\t\t\t\tD800D585146908FD009F64FD /* ASIHTTPRequestDelegate.h */,\n\t\t\t\tD800D586146908FD009F64FD /* ASIInputStream.h */,\n\t\t\t\tD800D587146908FD009F64FD /* ASIInputStream.m */,\n\t\t\t\tD800D588146908FD009F64FD /* ASINetworkQueue.h */,\n\t\t\t\tD800D589146908FD009F64FD /* ASINetworkQueue.m */,\n\t\t\t\tD800D58A146908FD009F64FD /* ASIProgressDelegate.h */,\n\t\t\t\tD800D58B146908FD009F64FD /* ASIWebPageRequest */,\n\t\t\t\tD800D58E146908FD009F64FD /* CloudFiles */,\n\t\t\t\tD800D59D146908FD009F64FD /* S3 */,\n\t\t\t\tD800D5AB146908FD009F64FD /* Tests */,\n\t\t\t);\n\t\t\tpath = ASIHTTPRequest;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D58B146908FD009F64FD /* ASIWebPageRequest */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D58C146908FD009F64FD /* ASIWebPageRequest.h */,\n\t\t\t\tD800D58D146908FD009F64FD /* ASIWebPageRequest.m */,\n\t\t\t);\n\t\t\tpath = ASIWebPageRequest;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D58E146908FD009F64FD /* CloudFiles */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D58F146908FD009F64FD /* ASICloudFilesCDNRequest.h */,\n\t\t\t\tD800D590146908FD009F64FD /* ASICloudFilesCDNRequest.m */,\n\t\t\t\tD800D591146908FD009F64FD /* ASICloudFilesContainer.h */,\n\t\t\t\tD800D592146908FD009F64FD /* ASICloudFilesContainer.m */,\n\t\t\t\tD800D593146908FD009F64FD /* ASICloudFilesContainerRequest.h */,\n\t\t\t\tD800D594146908FD009F64FD /* ASICloudFilesContainerRequest.m */,\n\t\t\t\tD800D595146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.h */,\n\t\t\t\tD800D596146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.m */,\n\t\t\t\tD800D597146908FD009F64FD /* ASICloudFilesObject.h */,\n\t\t\t\tD800D598146908FD009F64FD /* ASICloudFilesObject.m */,\n\t\t\t\tD800D599146908FD009F64FD /* ASICloudFilesObjectRequest.h */,\n\t\t\t\tD800D59A146908FD009F64FD /* ASICloudFilesObjectRequest.m */,\n\t\t\t\tD800D59B146908FD009F64FD /* ASICloudFilesRequest.h */,\n\t\t\t\tD800D59C146908FD009F64FD /* ASICloudFilesRequest.m */,\n\t\t\t);\n\t\t\tpath = CloudFiles;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D59D146908FD009F64FD /* S3 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D59E146908FD009F64FD /* ASINSXMLParserCompat.h */,\n\t\t\t\tD800D59F146908FD009F64FD /* ASIS3Bucket.h */,\n\t\t\t\tD800D5A0146908FD009F64FD /* ASIS3Bucket.m */,\n\t\t\t\tD800D5A1146908FD009F64FD /* ASIS3BucketObject.h */,\n\t\t\t\tD800D5A2146908FD009F64FD /* ASIS3BucketObject.m */,\n\t\t\t\tD800D5A3146908FD009F64FD /* ASIS3BucketRequest.h */,\n\t\t\t\tD800D5A4146908FD009F64FD /* ASIS3BucketRequest.m */,\n\t\t\t\tD800D5A5146908FD009F64FD /* ASIS3ObjectRequest.h */,\n\t\t\t\tD800D5A6146908FD009F64FD /* ASIS3ObjectRequest.m */,\n\t\t\t\tD800D5A7146908FD009F64FD /* ASIS3Request.h */,\n\t\t\t\tD800D5A8146908FD009F64FD /* ASIS3Request.m */,\n\t\t\t\tD800D5A9146908FD009F64FD /* ASIS3ServiceRequest.h */,\n\t\t\t\tD800D5AA146908FD009F64FD /* ASIS3ServiceRequest.m */,\n\t\t\t);\n\t\t\tpath = S3;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D5AB146908FD009F64FD /* Tests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tpath = Tests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D5AC146908FD009F64FD /* JSON */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D5AD146908FD009F64FD /* NSObject+SBJson.h */,\n\t\t\t\tD800D5AE146908FD009F64FD /* NSObject+SBJson.m */,\n\t\t\t\tD800D5AF146908FD009F64FD /* SBJson.h */,\n\t\t\t\tD800D5B0146908FD009F64FD /* SBJsonParser.h */,\n\t\t\t\tD800D5B1146908FD009F64FD /* SBJsonParser.m */,\n\t\t\t\tD800D5B2146908FD009F64FD /* SBJsonStreamParser.h */,\n\t\t\t\tD800D5B3146908FD009F64FD /* SBJsonStreamParser.m */,\n\t\t\t\tD800D5B4146908FD009F64FD /* SBJsonStreamParserAccumulator.h */,\n\t\t\t\tD800D5B5146908FD009F64FD /* SBJsonStreamParserAccumulator.m */,\n\t\t\t\tD800D5B6146908FD009F64FD /* SBJsonStreamParserAdapter.h */,\n\t\t\t\tD800D5B7146908FD009F64FD /* SBJsonStreamParserAdapter.m */,\n\t\t\t\tD800D5B8146908FD009F64FD /* SBJsonStreamParserState.h */,\n\t\t\t\tD800D5B9146908FD009F64FD /* SBJsonStreamParserState.m */,\n\t\t\t\tD800D5BA146908FD009F64FD /* SBJsonStreamWriter.h */,\n\t\t\t\tD800D5BB146908FD009F64FD /* SBJsonStreamWriter.m */,\n\t\t\t\tD800D5BC146908FD009F64FD /* SBJsonStreamWriterAccumulator.h */,\n\t\t\t\tD800D5BD146908FD009F64FD /* SBJsonStreamWriterAccumulator.m */,\n\t\t\t\tD800D5BE146908FD009F64FD /* SBJsonStreamWriterState.h */,\n\t\t\t\tD800D5BF146908FD009F64FD /* SBJsonStreamWriterState.m */,\n\t\t\t\tD800D5C0146908FD009F64FD /* SBJsonTokeniser.h */,\n\t\t\t\tD800D5C1146908FD009F64FD /* SBJsonTokeniser.m */,\n\t\t\t\tD800D5C2146908FD009F64FD /* SBJsonUTF8Stream.h */,\n\t\t\t\tD800D5C3146908FD009F64FD /* SBJsonUTF8Stream.m */,\n\t\t\t\tD800D5C4146908FD009F64FD /* SBJsonWriter.h */,\n\t\t\t\tD800D5C5146908FD009F64FD /* SBJsonWriter.m */,\n\t\t\t);\n\t\t\tpath = JSON;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD800D5C6146908FD009F64FD /* Reachability */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D5C7146908FD009F64FD /* Reachability.h */,\n\t\t\t\tD800D5C8146908FD009F64FD /* Reachability.m */,\n\t\t\t);\n\t\t\tpath = Reachability;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B0115C3EF2F0006FAFE /* Model */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B3F15C3F0420006FAFE /* GData */,\n\t\t\t\tD87D4B9815C3F0420006FAFE /* GDataDoubanWrapper */,\n\t\t\t);\n\t\t\tname = Model;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B0315C3EF350006FAFE /* Model2 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD88800C0166F5C3000DAFFC4 /* Book */,\n\t\t\t\tD88800C1166F5C3700DAFFC4 /* Movie */,\n\t\t\t\tD88800C2166F5C4300DAFFC4 /* Music */,\n\t\t\t\tD89A6A98162D384100954BC4 /* Event */,\n\t\t\t\tD87D4B3215C3F00C0006FAFE /* Photo */,\n\t\t\t\tD87D4B2915C3EFBF0006FAFE /* Community */,\n\t\t\t\tD87D4B1315C3EF600006FAFE /* DOUObject+Utils.h */,\n\t\t\t\tD87D4B1415C3EF600006FAFE /* DOUObject+Utils.m */,\n\t\t\t\tD87D4B1115C3EF600006FAFE /* DOUObject.h */,\n\t\t\t\tD87D4B1215C3EF600006FAFE /* DOUObject.m */,\n\t\t\t\tD87D4B1515C3EF600006FAFE /* DOUObjectArray.h */,\n\t\t\t\tD87D4B1615C3EF600006FAFE /* DOUObjectArray.m */,\n\t\t\t);\n\t\t\tpath = Model2;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B2915C3EFBF0006FAFE /* Community */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD89A6A94162D37EE00954BC4 /* DOUUser.h */,\n\t\t\t\tD89A6A95162D37EE00954BC4 /* DOUUser.m */,\n\t\t\t\tD87D4C7715C3F14E0006FAFE /* DOUComment.h */,\n\t\t\t\tD87D4C7815C3F14E0006FAFE /* DOUComment.m */,\n\t\t\t\tD87D4C7915C3F14E0006FAFE /* DOUCommentArray.h */,\n\t\t\t\tD87D4C7A15C3F14E0006FAFE /* DOUCommentArray.m */,\n\t\t\t\tD87D4B2A15C3EFE70006FAFE /* DOUOnline.h */,\n\t\t\t\tD87D4B2B15C3EFE70006FAFE /* DOUOnline.m */,\n\t\t\t\tD87D4B2C15C3EFE70006FAFE /* DOUOnlineArray.h */,\n\t\t\t\tD87D4B2D15C3EFE70006FAFE /* DOUOnlineArray.m */,\n\t\t\t\tD88800C5166F5D4E00DAFFC4 /* DOUNote.h */,\n\t\t\t\tD88800C6166F5D4F00DAFFC4 /* DOUNote.m */,\n\t\t\t\tD88800CD166F63B400DAFFC4 /* DOUNoteArray.h */,\n\t\t\t\tD88800CE166F63B500DAFFC4 /* DOUNoteArray.m */,\n\t\t\t\tD8695E8B167AD59000EFFF41 /* DOUNotification.h */,\n\t\t\t\tD8695E8C167AD59000EFFF41 /* DOUNotification.m */,\n\t\t\t\tD8695E8D167AD59000EFFF41 /* DOUNotificationArray.h */,\n\t\t\t\tD8695E8E167AD59000EFFF41 /* DOUNotificationArray.m */,\n\t\t\t);\n\t\t\tpath = Community;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B3215C3F00C0006FAFE /* Photo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B3315C3F0230006FAFE /* DOUAlbum.h */,\n\t\t\t\tD87D4B3415C3F0230006FAFE /* DOUAlbum.m */,\n\t\t\t\tD88800BB166F5BF500DAFFC4 /* DOUAlbumArray.h */,\n\t\t\t\tD88800BC166F5BF600DAFFC4 /* DOUAlbumArray.m */,\n\t\t\t\tD87D4B3515C3F0230006FAFE /* DOUPhoto.h */,\n\t\t\t\tD87D4B3615C3F0230006FAFE /* DOUPhoto.m */,\n\t\t\t\tD87D4B3715C3F0230006FAFE /* DOUPhotoArray.h */,\n\t\t\t\tD87D4B3815C3F0230006FAFE /* DOUPhotoArray.m */,\n\t\t\t);\n\t\t\tpath = Photo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B3F15C3F0420006FAFE /* GData */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B4015C3F0420006FAFE /* BaseClasses */,\n\t\t\t\tD87D4B4715C3F0420006FAFE /* Elements */,\n\t\t\t\tD87D4B8D15C3F0420006FAFE /* GDataDefines.h */,\n\t\t\t\tD87D4B8E15C3F0420006FAFE /* GDataUtilities.h */,\n\t\t\t\tD87D4B8F15C3F0420006FAFE /* GDataUtilities.m */,\n\t\t\t\tD87D4B9015C3F0420006FAFE /* HTTPFetcher */,\n\t\t\t\tD87D4B9515C3F0420006FAFE /* XMLSupport */,\n\t\t\t);\n\t\t\tname = GData;\n\t\t\tpath = Model/GData;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B4015C3F0420006FAFE /* BaseClasses */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B4115C3F0420006FAFE /* GDataEntryBase.h */,\n\t\t\t\tD87D4B4215C3F0420006FAFE /* GDataEntryBase.m */,\n\t\t\t\tD87D4B4315C3F0420006FAFE /* GDataFeedBase.h */,\n\t\t\t\tD87D4B4415C3F0420006FAFE /* GDataFeedBase.m */,\n\t\t\t\tD87D4B4515C3F0420006FAFE /* GDataObject.h */,\n\t\t\t\tD87D4B4615C3F0420006FAFE /* GDataObject.m */,\n\t\t\t);\n\t\t\tpath = BaseClasses;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B4715C3F0420006FAFE /* Elements */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B4815C3F0420006FAFE /* GDataAtomPubControl.h */,\n\t\t\t\tD87D4B4915C3F0420006FAFE /* GDataAtomPubControl.m */,\n\t\t\t\tD87D4B4A15C3F0420006FAFE /* GDataBaseElements.h */,\n\t\t\t\tD87D4B4B15C3F0420006FAFE /* GDataBaseElements.m */,\n\t\t\t\tD87D4B4C15C3F0420006FAFE /* GDataBatchID.h */,\n\t\t\t\tD87D4B4D15C3F0420006FAFE /* GDataBatchID.m */,\n\t\t\t\tD87D4B4E15C3F0420006FAFE /* GDataBatchInterrupted.h */,\n\t\t\t\tD87D4B4F15C3F0420006FAFE /* GDataBatchInterrupted.m */,\n\t\t\t\tD87D4B5015C3F0420006FAFE /* GDataBatchOperation.h */,\n\t\t\t\tD87D4B5115C3F0420006FAFE /* GDataBatchOperation.m */,\n\t\t\t\tD87D4B5215C3F0420006FAFE /* GDataBatchStatus.h */,\n\t\t\t\tD87D4B5315C3F0420006FAFE /* GDataBatchStatus.m */,\n\t\t\t\tD87D4B5415C3F0420006FAFE /* GDataCategory.h */,\n\t\t\t\tD87D4B5515C3F0420006FAFE /* GDataCategory.m */,\n\t\t\t\tD87D4B5615C3F0420006FAFE /* GDataComment.h */,\n\t\t\t\tD87D4B5715C3F0420006FAFE /* GDataComment.m */,\n\t\t\t\tD87D4B5815C3F0420006FAFE /* GDataCustomProperty.h */,\n\t\t\t\tD87D4B5915C3F0420006FAFE /* GDataCustomProperty.m */,\n\t\t\t\tD87D4B5A15C3F0420006FAFE /* GDataDateTime.h */,\n\t\t\t\tD87D4B5B15C3F0420006FAFE /* GDataDateTime.m */,\n\t\t\t\tD87D4B5C15C3F0420006FAFE /* GDataDeleted.h */,\n\t\t\t\tD87D4B5D15C3F0420006FAFE /* GDataDeleted.m */,\n\t\t\t\tD87D4B5E15C3F0420006FAFE /* GDataElements.h */,\n\t\t\t\tD87D4B5F15C3F0420006FAFE /* GDataEmail.h */,\n\t\t\t\tD87D4B6015C3F0420006FAFE /* GDataEmail.m */,\n\t\t\t\tD87D4B6115C3F0420006FAFE /* GDataEntryContent.h */,\n\t\t\t\tD87D4B6215C3F0420006FAFE /* GDataEntryContent.m */,\n\t\t\t\tD87D4B6315C3F0420006FAFE /* GDataEntryLink.h */,\n\t\t\t\tD87D4B6415C3F0420006FAFE /* GDataEntryLink.m */,\n\t\t\t\tD87D4B6515C3F0420006FAFE /* GDataExtendedProperty.h */,\n\t\t\t\tD87D4B6615C3F0420006FAFE /* GDataExtendedProperty.m */,\n\t\t\t\tD87D4B6715C3F0420006FAFE /* GDataFeedLink.h */,\n\t\t\t\tD87D4B6815C3F0420006FAFE /* GDataFeedLink.m */,\n\t\t\t\tD87D4B6915C3F0420006FAFE /* GDataGenerator.h */,\n\t\t\t\tD87D4B6A15C3F0420006FAFE /* GDataGenerator.m */,\n\t\t\t\tD87D4B6B15C3F0420006FAFE /* GDataGeoPt.h */,\n\t\t\t\tD87D4B6C15C3F0420006FAFE /* GDataGeoPt.m */,\n\t\t\t\tD87D4B6D15C3F0420006FAFE /* GDataIM.h */,\n\t\t\t\tD87D4B6E15C3F0420006FAFE /* GDataIM.m */,\n\t\t\t\tD87D4B6F15C3F0420006FAFE /* GDataLink.h */,\n\t\t\t\tD87D4B7015C3F0420006FAFE /* GDataLink.m */,\n\t\t\t\tD87D4B7115C3F0420006FAFE /* GDataMoney.h */,\n\t\t\t\tD87D4B7215C3F0420006FAFE /* GDataMoney.m */,\n\t\t\t\tD87D4B7315C3F0420006FAFE /* GDataName.h */,\n\t\t\t\tD87D4B7415C3F0420006FAFE /* GDataName.m */,\n\t\t\t\tD87D4B7515C3F0420006FAFE /* GDataOrganization.h */,\n\t\t\t\tD87D4B7615C3F0420006FAFE /* GDataOrganization.m */,\n\t\t\t\tD87D4B7715C3F0420006FAFE /* GDataOrganizationName.h */,\n\t\t\t\tD87D4B7815C3F0420006FAFE /* GDataOrganizationName.m */,\n\t\t\t\tD87D4B7915C3F0420006FAFE /* GDataPerson.h */,\n\t\t\t\tD87D4B7A15C3F0420006FAFE /* GDataPerson.m */,\n\t\t\t\tD87D4B7B15C3F0420006FAFE /* GDataPhoneNumber.h */,\n\t\t\t\tD87D4B7C15C3F0420006FAFE /* GDataPhoneNumber.m */,\n\t\t\t\tD87D4B7D15C3F0420006FAFE /* GDataPostalAddress.h */,\n\t\t\t\tD87D4B7E15C3F0420006FAFE /* GDataPostalAddress.m */,\n\t\t\t\tD87D4B7F15C3F0420006FAFE /* GDataRating.h */,\n\t\t\t\tD87D4B8015C3F0420006FAFE /* GDataRating.m */,\n\t\t\t\tD87D4B8115C3F0420006FAFE /* GDataStructuredPostalAddress.h */,\n\t\t\t\tD87D4B8215C3F0420006FAFE /* GDataStructuredPostalAddress.m */,\n\t\t\t\tD87D4B8315C3F0420006FAFE /* GDataTextConstruct.h */,\n\t\t\t\tD87D4B8415C3F0420006FAFE /* GDataTextConstruct.m */,\n\t\t\t\tD87D4B8515C3F0420006FAFE /* GDataValueConstruct.h */,\n\t\t\t\tD87D4B8615C3F0420006FAFE /* GDataValueConstruct.m */,\n\t\t\t\tD87D4B8715C3F0420006FAFE /* GDataWhen.h */,\n\t\t\t\tD87D4B8815C3F0420006FAFE /* GDataWhen.m */,\n\t\t\t\tD87D4B8915C3F0420006FAFE /* GDataWhere.h */,\n\t\t\t\tD87D4B8A15C3F0420006FAFE /* GDataWhere.m */,\n\t\t\t\tD87D4B8B15C3F0420006FAFE /* GDataWho.h */,\n\t\t\t\tD87D4B8C15C3F0420006FAFE /* GDataWho.m */,\n\t\t\t);\n\t\t\tpath = Elements;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B9015C3F0420006FAFE /* HTTPFetcher */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B9115C3F0420006FAFE /* GTMGatherInputStream.h */,\n\t\t\t\tD87D4B9215C3F0420006FAFE /* GTMGatherInputStream.m */,\n\t\t\t\tD87D4B9315C3F0420006FAFE /* GTMMIMEDocument.h */,\n\t\t\t\tD87D4B9415C3F0420006FAFE /* GTMMIMEDocument.m */,\n\t\t\t);\n\t\t\tpath = HTTPFetcher;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B9515C3F0420006FAFE /* XMLSupport */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B9615C3F0420006FAFE /* GDataXMLNode.h */,\n\t\t\t\tD87D4B9715C3F0420006FAFE /* GDataXMLNode.m */,\n\t\t\t);\n\t\t\tpath = XMLSupport;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B9815C3F0420006FAFE /* GDataDoubanWrapper */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B9915C3F0420006FAFE /* Clients */,\n\t\t\t\tD87D4BD215C3F0430006FAFE /* DoubanDefines.h */,\n\t\t\t\tD87D4BD315C3F0430006FAFE /* DoubanDefines.m */,\n\t\t\t\tD87D4BD415C3F0430006FAFE /* Elements */,\n\t\t\t);\n\t\t\tname = GDataDoubanWrapper;\n\t\t\tpath = Model/GDataDoubanWrapper;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B9915C3F0420006FAFE /* Clients */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B9A15C3F0420006FAFE /* Comment */,\n\t\t\t\tD87D4B9F15C3F0420006FAFE /* Event */,\n\t\t\t\tD87D4BAC15C3F0420006FAFE /* GDataAtomAuthor+Extension.h */,\n\t\t\t\tD87D4BAD15C3F0420006FAFE /* GDataAtomAuthor+Extension.m */,\n\t\t\t\tD87D4BAE15C3F0420006FAFE /* GDataEntryBase+Extension.h */,\n\t\t\t\tD87D4BAF15C3F0420006FAFE /* GDataEntryBase+Extension.m */,\n\t\t\t\tD87D4BB015C3F0420006FAFE /* Miniblog */,\n\t\t\t\tD87D4BB515C3F0420006FAFE /* People */,\n\t\t\t\tD87D4BBA15C3F0420006FAFE /* Photo */,\n\t\t\t\tD87D4BC315C3F0420006FAFE /* Recommendation */,\n\t\t\t\tD87D4BC815C3F0430006FAFE /* Review */,\n\t\t\t\tD87D4BCD15C3F0430006FAFE /* Subject */,\n\t\t\t);\n\t\t\tpath = Clients;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B9A15C3F0420006FAFE /* Comment */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4B9B15C3F0420006FAFE /* DoubanEntryComment.h */,\n\t\t\t\tD87D4B9C15C3F0420006FAFE /* DoubanEntryComment.m */,\n\t\t\t\tD87D4B9D15C3F0420006FAFE /* DoubanFeedComment.h */,\n\t\t\t\tD87D4B9E15C3F0420006FAFE /* DoubanFeedComment.m */,\n\t\t\t);\n\t\t\tpath = Comment;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4B9F15C3F0420006FAFE /* Event */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BA015C3F0420006FAFE /* DoubanEntryCity.h */,\n\t\t\t\tD87D4BA115C3F0420006FAFE /* DoubanEntryCity.m */,\n\t\t\t\tD87D4BA215C3F0420006FAFE /* DoubanEntryEvent.h */,\n\t\t\t\tD87D4BA315C3F0420006FAFE /* DoubanEntryEvent.m */,\n\t\t\t\tD87D4BA415C3F0420006FAFE /* DoubanEntryEventCategory.h */,\n\t\t\t\tD87D4BA515C3F0420006FAFE /* DoubanEntryEventCategory.m */,\n\t\t\t\tD87D4BA615C3F0420006FAFE /* DoubanFeedCity.h */,\n\t\t\t\tD87D4BA715C3F0420006FAFE /* DoubanFeedCity.m */,\n\t\t\t\tD87D4BA815C3F0420006FAFE /* DoubanFeedEvent.h */,\n\t\t\t\tD87D4BA915C3F0420006FAFE /* DoubanFeedEvent.m */,\n\t\t\t\tD87D4BAA15C3F0420006FAFE /* DoubanFeedEventCategory.h */,\n\t\t\t\tD87D4BAB15C3F0420006FAFE /* DoubanFeedEventCategory.m */,\n\t\t\t);\n\t\t\tpath = Event;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4BB015C3F0420006FAFE /* Miniblog */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BB115C3F0420006FAFE /* DoubanEntryMiniblog.h */,\n\t\t\t\tD87D4BB215C3F0420006FAFE /* DoubanEntryMiniblog.m */,\n\t\t\t\tD87D4BB315C3F0420006FAFE /* DoubanFeedMiniblog.h */,\n\t\t\t\tD87D4BB415C3F0420006FAFE /* DoubanFeedMiniblog.m */,\n\t\t\t);\n\t\t\tpath = Miniblog;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4BB515C3F0420006FAFE /* People */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BB615C3F0420006FAFE /* DoubanEntryPeople.h */,\n\t\t\t\tD87D4BB715C3F0420006FAFE /* DoubanEntryPeople.m */,\n\t\t\t\tD87D4BB815C3F0420006FAFE /* DoubanFeedPeople.h */,\n\t\t\t\tD87D4BB915C3F0420006FAFE /* DoubanFeedPeople.m */,\n\t\t\t);\n\t\t\tpath = People;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4BBA15C3F0420006FAFE /* Photo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BBB15C3F0420006FAFE /* DoubanEntryAlbum.h */,\n\t\t\t\tD87D4BBC15C3F0420006FAFE /* DoubanEntryAlbum.m */,\n\t\t\t\tD87D4BBD15C3F0420006FAFE /* DoubanEntryPhoto.h */,\n\t\t\t\tD87D4BBE15C3F0420006FAFE /* DoubanEntryPhoto.m */,\n\t\t\t\tD87D4BBF15C3F0420006FAFE /* DoubanFeedAlbum.h */,\n\t\t\t\tD87D4BC015C3F0420006FAFE /* DoubanFeedAlbum.m */,\n\t\t\t\tD87D4BC115C3F0420006FAFE /* DoubanFeedPhoto.h */,\n\t\t\t\tD87D4BC215C3F0420006FAFE /* DoubanFeedPhoto.m */,\n\t\t\t);\n\t\t\tpath = Photo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4BC315C3F0420006FAFE /* Recommendation */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BC415C3F0420006FAFE /* DoubanEntryRecommendation.h */,\n\t\t\t\tD87D4BC515C3F0420006FAFE /* DoubanEntryRecommendation.m */,\n\t\t\t\tD87D4BC615C3F0430006FAFE /* DoubanFeedRecommendation.h */,\n\t\t\t\tD87D4BC715C3F0430006FAFE /* DoubanFeedRecommendation.m */,\n\t\t\t);\n\t\t\tpath = Recommendation;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4BC815C3F0430006FAFE /* Review */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BC915C3F0430006FAFE /* DoubanEntryReview.h */,\n\t\t\t\tD87D4BCA15C3F0430006FAFE /* DoubanEntryReview.m */,\n\t\t\t\tD87D4BCB15C3F0430006FAFE /* DoubanFeedReview.h */,\n\t\t\t\tD87D4BCC15C3F0430006FAFE /* DoubanFeedReview.m */,\n\t\t\t);\n\t\t\tpath = Review;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4BCD15C3F0430006FAFE /* Subject */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BCE15C3F0430006FAFE /* DoubanEntrySubject.h */,\n\t\t\t\tD87D4BCF15C3F0430006FAFE /* DoubanEntrySubject.m */,\n\t\t\t\tD87D4BD015C3F0430006FAFE /* DoubanFeedSubject.h */,\n\t\t\t\tD87D4BD115C3F0430006FAFE /* DoubanFeedSubject.m */,\n\t\t\t);\n\t\t\tpath = Subject;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4BD415C3F0430006FAFE /* Elements */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4BD515C3F0430006FAFE /* DoubanAttribute.h */,\n\t\t\t\tD87D4BD615C3F0430006FAFE /* DoubanAttribute.m */,\n\t\t\t\tD87D4BD715C3F0430006FAFE /* DoubanLocation.h */,\n\t\t\t\tD87D4BD815C3F0430006FAFE /* DoubanLocation.m */,\n\t\t\t\tD87D4BD915C3F0430006FAFE /* DoubanSignature.h */,\n\t\t\t\tD87D4BDA15C3F0430006FAFE /* DoubanSignature.m */,\n\t\t\t\tD87D4BDB15C3F0430006FAFE /* DoubanTag.h */,\n\t\t\t\tD87D4BDC15C3F0430006FAFE /* DoubanTag.m */,\n\t\t\t\tD87D4BDD15C3F0430006FAFE /* DoubanUID.h */,\n\t\t\t\tD87D4BDE15C3F0430006FAFE /* DoubanUID.m */,\n\t\t\t\tD87D4BDF15C3F0430006FAFE /* GeorssPoint.h */,\n\t\t\t\tD87D4BE015C3F0430006FAFE /* GeorssPoint.m */,\n\t\t\t);\n\t\t\tpath = Elements;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4C8315C3F2700006FAFE /* Model */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4C8515C3F2A70006FAFE /* DoubanCityTests.m */,\n\t\t\t\tD87D4C8615C3F2A70006FAFE /* DoubanCommentTests.m */,\n\t\t\t\tD87D4C8715C3F2A70006FAFE /* DoubanEventCategoryTests.m */,\n\t\t\t\tD87D4C8815C3F2A70006FAFE /* DoubanEventTests.m */,\n\t\t\t\tD87D4C8915C3F2A70006FAFE /* DoubanMiniblogTests.m */,\n\t\t\t\tD87D4C8A15C3F2A70006FAFE /* DoubanPeopleTests.m */,\n\t\t\t\tD87D4C8B15C3F2A70006FAFE /* DoubanPhotoTests.m */,\n\t\t\t\tD87D4C8C15C3F2A70006FAFE /* DoubanSubjectTests.m */,\n\t\t\t);\n\t\t\tpath = Model;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4C8415C3F2760006FAFE /* Model2 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1A3451EA167889140097FEF5 /* DOUMusicTests.m */,\n\t\t\t\t1A3451EB167889140097FEF5 /* DOUBookTests.m */,\n\t\t\t\tD88800D3166F65A200DAFFC4 /* DOUMovieTests.m */,\n\t\t\t\tD88800CB166F609300DAFFC4 /* DOUNoteTests.m */,\n\t\t\t\tD87D4CC315C3F56D0006FAFE /* DOUCommentTests.m */,\n\t\t\t\tD87D4CC415C3F56D0006FAFE /* DOUOnlineTests.m */,\n\t\t\t\tD87D4CC515C3F56D0006FAFE /* DOUPhotoTests.m */,\n\t\t\t);\n\t\t\tname = Model2;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4C9515C3F4550006FAFE /* Model */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4C9715C3F4850006FAFE /* DoubanEntryCity.xml */,\n\t\t\t\tD87D4C9815C3F4850006FAFE /* DoubanEntryEvent.xml */,\n\t\t\t\tD87D4C9915C3F4850006FAFE /* DoubanEntryMiniblog.xml */,\n\t\t\t\tD87D4C9A15C3F4850006FAFE /* DoubanEntryPeople.xml */,\n\t\t\t\tD87D4C9B15C3F4850006FAFE /* DoubanEntryPhoto.xml */,\n\t\t\t\tD87D4C9C15C3F4850006FAFE /* DoubanEntryRecommendation.xml */,\n\t\t\t\tD87D4C9D15C3F4850006FAFE /* DoubanEntrySubject.xml */,\n\t\t\t\tD87D4C9E15C3F4850006FAFE /* DoubanFeedCity.xml */,\n\t\t\t\tD87D4C9F15C3F4850006FAFE /* DoubanFeedComment.xml */,\n\t\t\t\tD87D4CA015C3F4850006FAFE /* DoubanFeedEvent.xml */,\n\t\t\t\tD87D4CA115C3F4850006FAFE /* DoubanFeedEventCategory.xml */,\n\t\t\t\tD87D4CA215C3F4850006FAFE /* DoubanFeedMiniblog.xml */,\n\t\t\t\tD87D4CA315C3F4850006FAFE /* DoubanFeedPeople.xml */,\n\t\t\t\tD87D4CA415C3F4850006FAFE /* DoubanFeedPhoto.xml */,\n\t\t\t\tD87D4CA515C3F4850006FAFE /* DoubanFeedRecommendation.xml */,\n\t\t\t\tD87D4CA615C3F4850006FAFE /* DoubanFeedSubject.xml */,\n\t\t\t);\n\t\t\tpath = Model;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD87D4C9615C3F4620006FAFE /* Model2 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1A3451E6167889060097FEF5 /* MusicArray.json */,\n\t\t\t\t1A3451E7167889060097FEF5 /* BookArray.json */,\n\t\t\t\tD88800D1166F654100DAFFC4 /* MovieArray.json */,\n\t\t\t\tD88800C9166F603F00DAFFC4 /* Note.json */,\n\t\t\t\tD87D4CB715C3F5580006FAFE /* Album.json */,\n\t\t\t\tD89A2A5515ECA3360027C0B0 /* Event.json */,\n\t\t\t\tD87D4CB815C3F5580006FAFE /* CommentArray.json */,\n\t\t\t\tD87D4CB915C3F5580006FAFE /* Online.json */,\n\t\t\t\tD87D4CBA15C3F5580006FAFE /* OnlineArray.json */,\n\t\t\t\tD87D4CBB15C3F5580006FAFE /* Photo.json */,\n\t\t\t\tD87D4CBC15C3F5580006FAFE /* PhotoArray.json */,\n\t\t\t);\n\t\t\tpath = Model2;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD882161615889DDE004B4AD4 /* Testing */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD882161715889DDE004B4AD4 /* DOUTestResponseLoader.h */,\n\t\t\t\tD882161815889DDE004B4AD4 /* DOUTestResponseLoader.m */,\n\t\t\t);\n\t\t\tpath = Testing;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD88800C0166F5C3000DAFFC4 /* Book */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1A3451D9167887E90097FEF5 /* DOUBook.h */,\n\t\t\t\t1A3451D8167887E90097FEF5 /* DOUBook.m */,\n\t\t\t\t1A3451D7167887E90097FEF5 /* DOUBookArray.h */,\n\t\t\t\t1A3451D6167887E90097FEF5 /* DOUBookArray.m */,\n\t\t\t);\n\t\t\tpath = Book;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD88800C1166F5C3700DAFFC4 /* Movie */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD88800D5166F65CA00DAFFC4 /* DOUMovie.h */,\n\t\t\t\tD88800D6166F65CA00DAFFC4 /* DOUMovie.m */,\n\t\t\t\tD88800D9166F65E400DAFFC4 /* DOUMovieArray.h */,\n\t\t\t\tD88800DA166F65E400DAFFC4 /* DOUMovieArray.m */,\n\t\t\t);\n\t\t\tpath = Movie;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD88800C2166F5C4300DAFFC4 /* Music */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1A3451E1167887F80097FEF5 /* DOUMusic.h */,\n\t\t\t\t1A3451E0167887F80097FEF5 /* DOUMusic.m */,\n\t\t\t\t1A3451DF167887F80097FEF5 /* DOUMusicArray.h */,\n\t\t\t\t1A3451DE167887F80097FEF5 /* DOUMusicArray.m */,\n\t\t\t);\n\t\t\tpath = Music;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD88EAF3514692D9400A4DE43 /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4C9615C3F4620006FAFE /* Model2 */,\n\t\t\t\tD87D4C9515C3F4550006FAFE /* Model */,\n\t\t\t);\n\t\t\tpath = Resources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD89A6A98162D384100954BC4 /* Event */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD89A6A99162D384100954BC4 /* DOUEvent.h */,\n\t\t\t\tD89A6A9A162D384100954BC4 /* DOUEvent.m */,\n\t\t\t\tD89A6A9B162D384100954BC4 /* DOUEventArray.h */,\n\t\t\t\tD89A6A9C162D384100954BC4 /* DOUEventArray.m */,\n\t\t\t\tD89A6A9D162D384100954BC4 /* DOULoc.h */,\n\t\t\t\tD89A6A9E162D384100954BC4 /* DOULoc.m */,\n\t\t\t\tD89A6A9F162D384100954BC4 /* DOULocArray.h */,\n\t\t\t\tD89A6AA0162D384100954BC4 /* DOULocArray.m */,\n\t\t\t);\n\t\t\tpath = Event;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8CFD43C151C742700CCC311 /* Base64 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD87D4C7315C3F11C0006FAFE /* NSData+Base64.h */,\n\t\t\t\tD87D4C7415C3F11C0006FAFE /* NSData+Base64.m */,\n\t\t\t);\n\t\t\tname = Base64;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\tD800D536146907B2009F64FD /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD800D56D146908AF009F64FD /* DOUAPIEngine.h in Headers */,\n\t\t\t\tD800D56E146908AF009F64FD /* DOUHttpRequest.h in Headers */,\n\t\t\t\tD800D570146908AF009F64FD /* DOUOAuth2.h in Headers */,\n\t\t\t\tD800D5C9146908FD009F64FD /* ASIAuthenticationDialog.h in Headers */,\n\t\t\t\tD800D5CB146908FD009F64FD /* ASICacheDelegate.h in Headers */,\n\t\t\t\tD800D5CC146908FD009F64FD /* ASIDataCompressor.h in Headers */,\n\t\t\t\tD800D5CE146908FD009F64FD /* ASIDataDecompressor.h in Headers */,\n\t\t\t\tD800D5D0146908FD009F64FD /* ASIDownloadCache.h in Headers */,\n\t\t\t\tD800D5D2146908FD009F64FD /* ASIFormDataRequest.h in Headers */,\n\t\t\t\tD800D5D4146908FD009F64FD /* ASIHTTPRequest.h in Headers */,\n\t\t\t\tD800D5D6146908FD009F64FD /* ASIHTTPRequestConfig.h in Headers */,\n\t\t\t\tD800D5D7146908FD009F64FD /* ASIHTTPRequestDelegate.h in Headers */,\n\t\t\t\tD800D5D8146908FD009F64FD /* ASIInputStream.h in Headers */,\n\t\t\t\tD800D5DA146908FD009F64FD /* ASINetworkQueue.h in Headers */,\n\t\t\t\tD800D5DC146908FD009F64FD /* ASIProgressDelegate.h in Headers */,\n\t\t\t\tD800D5DD146908FD009F64FD /* ASIWebPageRequest.h in Headers */,\n\t\t\t\tD800D5DF146908FD009F64FD /* ASICloudFilesCDNRequest.h in Headers */,\n\t\t\t\tD800D5E1146908FD009F64FD /* ASICloudFilesContainer.h in Headers */,\n\t\t\t\tD800D5E3146908FD009F64FD /* ASICloudFilesContainerRequest.h in Headers */,\n\t\t\t\tD800D5E5146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.h in Headers */,\n\t\t\t\tD800D5E7146908FD009F64FD /* ASICloudFilesObject.h in Headers */,\n\t\t\t\tD800D5E9146908FD009F64FD /* ASICloudFilesObjectRequest.h in Headers */,\n\t\t\t\tD800D5EB146908FD009F64FD /* ASICloudFilesRequest.h in Headers */,\n\t\t\t\tD800D5ED146908FD009F64FD /* ASINSXMLParserCompat.h in Headers */,\n\t\t\t\tD800D5EE146908FD009F64FD /* ASIS3Bucket.h in Headers */,\n\t\t\t\tD800D5F0146908FD009F64FD /* ASIS3BucketObject.h in Headers */,\n\t\t\t\tD800D5F2146908FD009F64FD /* ASIS3BucketRequest.h in Headers */,\n\t\t\t\tD800D5F4146908FD009F64FD /* ASIS3ObjectRequest.h in Headers */,\n\t\t\t\tD800D5F6146908FD009F64FD /* ASIS3Request.h in Headers */,\n\t\t\t\tD800D5F8146908FD009F64FD /* ASIS3ServiceRequest.h in Headers */,\n\t\t\t\tD800D5FA146908FD009F64FD /* NSObject+SBJson.h in Headers */,\n\t\t\t\tD800D5FC146908FD009F64FD /* SBJson.h in Headers */,\n\t\t\t\tD800D5FD146908FD009F64FD /* SBJsonParser.h in Headers */,\n\t\t\t\tD800D5FF146908FD009F64FD /* SBJsonStreamParser.h in Headers */,\n\t\t\t\tD800D601146908FD009F64FD /* SBJsonStreamParserAccumulator.h in Headers */,\n\t\t\t\tD800D603146908FD009F64FD /* SBJsonStreamParserAdapter.h in Headers */,\n\t\t\t\tD800D605146908FD009F64FD /* SBJsonStreamParserState.h in Headers */,\n\t\t\t\tD800D607146908FD009F64FD /* SBJsonStreamWriter.h in Headers */,\n\t\t\t\tD800D609146908FD009F64FD /* SBJsonStreamWriterAccumulator.h in Headers */,\n\t\t\t\tD800D60B146908FD009F64FD /* SBJsonStreamWriterState.h in Headers */,\n\t\t\t\tD800D60D146908FD009F64FD /* SBJsonTokeniser.h in Headers */,\n\t\t\t\tD800D60F146908FD009F64FD /* SBJsonUTF8Stream.h in Headers */,\n\t\t\t\tD800D611146908FD009F64FD /* SBJsonWriter.h in Headers */,\n\t\t\t\tD800D613146908FD009F64FD /* Reachability.h in Headers */,\n\t\t\t\tD800D626146909C2009F64FD /* DOUAPIConfig.h in Headers */,\n\t\t\t\tD858E04614C3AC0D00335280 /* DOUQuery.h in Headers */,\n\t\t\t\tD858E04E14C3DA9100335280 /* DOUService.h in Headers */,\n\t\t\t\tD882161015889C5F004B4AD4 /* DOUOAuthService.h in Headers */,\n\t\t\t\tD882161215889C5F004B4AD4 /* DOUOAuthStore.h in Headers */,\n\t\t\t\tD87D4B2315C3EF600006FAFE /* DOUObject.h in Headers */,\n\t\t\t\tD87D4B2515C3EF600006FAFE /* DOUObject+Utils.h in Headers */,\n\t\t\t\tD87D4B2715C3EF600006FAFE /* DOUObjectArray.h in Headers */,\n\t\t\t\tD87D4B2E15C3EFE70006FAFE /* DOUOnline.h in Headers */,\n\t\t\t\tD87D4B3015C3EFE70006FAFE /* DOUOnlineArray.h in Headers */,\n\t\t\t\tD87D4B3915C3F0230006FAFE /* DOUAlbum.h in Headers */,\n\t\t\t\tD87D4B3B15C3F0230006FAFE /* DOUPhoto.h in Headers */,\n\t\t\t\tD87D4B3D15C3F0230006FAFE /* DOUPhotoArray.h in Headers */,\n\t\t\t\tD87D4BE115C3F0430006FAFE /* GDataEntryBase.h in Headers */,\n\t\t\t\tD87D4BE315C3F0430006FAFE /* GDataFeedBase.h in Headers */,\n\t\t\t\tD87D4BE515C3F0430006FAFE /* GDataObject.h in Headers */,\n\t\t\t\tD87D4BE715C3F0430006FAFE /* GDataAtomPubControl.h in Headers */,\n\t\t\t\tD87D4BE915C3F0430006FAFE /* GDataBaseElements.h in Headers */,\n\t\t\t\tD87D4BEB15C3F0430006FAFE /* GDataBatchID.h in Headers */,\n\t\t\t\tD87D4BED15C3F0430006FAFE /* GDataBatchInterrupted.h in Headers */,\n\t\t\t\tD87D4BEF15C3F0430006FAFE /* GDataBatchOperation.h in Headers */,\n\t\t\t\tD87D4BF115C3F0430006FAFE /* GDataBatchStatus.h in Headers */,\n\t\t\t\tD87D4BF315C3F0430006FAFE /* GDataCategory.h in Headers */,\n\t\t\t\tD87D4BF515C3F0430006FAFE /* GDataComment.h in Headers */,\n\t\t\t\tD87D4BF715C3F0430006FAFE /* GDataCustomProperty.h in Headers */,\n\t\t\t\tD87D4BF915C3F0430006FAFE /* GDataDateTime.h in Headers */,\n\t\t\t\tD87D4BFB15C3F0430006FAFE /* GDataDeleted.h in Headers */,\n\t\t\t\tD87D4BFD15C3F0430006FAFE /* GDataElements.h in Headers */,\n\t\t\t\tD87D4BFE15C3F0430006FAFE /* GDataEmail.h in Headers */,\n\t\t\t\tD87D4C0015C3F0430006FAFE /* GDataEntryContent.h in Headers */,\n\t\t\t\tD87D4C0215C3F0430006FAFE /* GDataEntryLink.h in Headers */,\n\t\t\t\tD87D4C0415C3F0430006FAFE /* GDataExtendedProperty.h in Headers */,\n\t\t\t\tD87D4C0615C3F0430006FAFE /* GDataFeedLink.h in Headers */,\n\t\t\t\tD87D4C0815C3F0430006FAFE /* GDataGenerator.h in Headers */,\n\t\t\t\tD87D4C0A15C3F0430006FAFE /* GDataGeoPt.h in Headers */,\n\t\t\t\tD87D4C0C15C3F0430006FAFE /* GDataIM.h in Headers */,\n\t\t\t\tD87D4C0E15C3F0430006FAFE /* GDataLink.h in Headers */,\n\t\t\t\tD87D4C1015C3F0430006FAFE /* GDataMoney.h in Headers */,\n\t\t\t\tD87D4C1215C3F0430006FAFE /* GDataName.h in Headers */,\n\t\t\t\tD87D4C1415C3F0430006FAFE /* GDataOrganization.h in Headers */,\n\t\t\t\tD87D4C1615C3F0430006FAFE /* GDataOrganizationName.h in Headers */,\n\t\t\t\tD87D4C1815C3F0430006FAFE /* GDataPerson.h in Headers */,\n\t\t\t\tD87D4C1A15C3F0430006FAFE /* GDataPhoneNumber.h in Headers */,\n\t\t\t\tD87D4C1C15C3F0430006FAFE /* GDataPostalAddress.h in Headers */,\n\t\t\t\tD87D4C1E15C3F0430006FAFE /* GDataRating.h in Headers */,\n\t\t\t\tD87D4C2015C3F0430006FAFE /* GDataStructuredPostalAddress.h in Headers */,\n\t\t\t\tD87D4C2215C3F0430006FAFE /* GDataTextConstruct.h in Headers */,\n\t\t\t\tD87D4C2415C3F0430006FAFE /* GDataValueConstruct.h in Headers */,\n\t\t\t\tD87D4C2615C3F0430006FAFE /* GDataWhen.h in Headers */,\n\t\t\t\tD87D4C2815C3F0430006FAFE /* GDataWhere.h in Headers */,\n\t\t\t\tD87D4C2A15C3F0430006FAFE /* GDataWho.h in Headers */,\n\t\t\t\tD87D4C2C15C3F0430006FAFE /* GDataDefines.h in Headers */,\n\t\t\t\tD87D4C2D15C3F0430006FAFE /* GDataUtilities.h in Headers */,\n\t\t\t\tD87D4C2F15C3F0430006FAFE /* GTMGatherInputStream.h in Headers */,\n\t\t\t\tD87D4C3115C3F0430006FAFE /* GTMMIMEDocument.h in Headers */,\n\t\t\t\tD87D4C3315C3F0430006FAFE /* GDataXMLNode.h in Headers */,\n\t\t\t\tD87D4C3515C3F0430006FAFE /* DoubanEntryComment.h in Headers */,\n\t\t\t\tD87D4C3715C3F0430006FAFE /* DoubanFeedComment.h in Headers */,\n\t\t\t\tD87D4C3915C3F0430006FAFE /* DoubanEntryCity.h in Headers */,\n\t\t\t\tD87D4C3B15C3F0430006FAFE /* DoubanEntryEvent.h in Headers */,\n\t\t\t\tD87D4C3D15C3F0430006FAFE /* DoubanEntryEventCategory.h in Headers */,\n\t\t\t\tD87D4C3F15C3F0430006FAFE /* DoubanFeedCity.h in Headers */,\n\t\t\t\tD87D4C4115C3F0430006FAFE /* DoubanFeedEvent.h in Headers */,\n\t\t\t\tD87D4C4315C3F0430006FAFE /* DoubanFeedEventCategory.h in Headers */,\n\t\t\t\tD87D4C4515C3F0430006FAFE /* GDataAtomAuthor+Extension.h in Headers */,\n\t\t\t\tD87D4C4715C3F0430006FAFE /* GDataEntryBase+Extension.h in Headers */,\n\t\t\t\tD87D4C4915C3F0430006FAFE /* DoubanEntryMiniblog.h in Headers */,\n\t\t\t\tD87D4C4B15C3F0430006FAFE /* DoubanFeedMiniblog.h in Headers */,\n\t\t\t\tD87D4C4D15C3F0430006FAFE /* DoubanEntryPeople.h in Headers */,\n\t\t\t\tD87D4C4F15C3F0430006FAFE /* DoubanFeedPeople.h in Headers */,\n\t\t\t\tD87D4C5115C3F0430006FAFE /* DoubanEntryAlbum.h in Headers */,\n\t\t\t\tD87D4C5315C3F0430006FAFE /* DoubanEntryPhoto.h in Headers */,\n\t\t\t\tD87D4C5515C3F0430006FAFE /* DoubanFeedAlbum.h in Headers */,\n\t\t\t\tD87D4C5715C3F0430006FAFE /* DoubanFeedPhoto.h in Headers */,\n\t\t\t\tD87D4C5915C3F0430006FAFE /* DoubanEntryRecommendation.h in Headers */,\n\t\t\t\tD87D4C5B15C3F0430006FAFE /* DoubanFeedRecommendation.h in Headers */,\n\t\t\t\tD87D4C5D15C3F0430006FAFE /* DoubanEntryReview.h in Headers */,\n\t\t\t\tD87D4C5F15C3F0430006FAFE /* DoubanFeedReview.h in Headers */,\n\t\t\t\tD87D4C6115C3F0430006FAFE /* DoubanEntrySubject.h in Headers */,\n\t\t\t\tD87D4C6315C3F0430006FAFE /* DoubanFeedSubject.h in Headers */,\n\t\t\t\tD87D4C6515C3F0430006FAFE /* DoubanDefines.h in Headers */,\n\t\t\t\tD87D4C6715C3F0430006FAFE /* DoubanAttribute.h in Headers */,\n\t\t\t\tD87D4C6915C3F0430006FAFE /* DoubanLocation.h in Headers */,\n\t\t\t\tD87D4C6B15C3F0430006FAFE /* DoubanSignature.h in Headers */,\n\t\t\t\tD87D4C6D15C3F0430006FAFE /* DoubanTag.h in Headers */,\n\t\t\t\tD87D4C6F15C3F0430006FAFE /* DoubanUID.h in Headers */,\n\t\t\t\tD87D4C7115C3F0430006FAFE /* GeorssPoint.h in Headers */,\n\t\t\t\tD87D4C7515C3F11C0006FAFE /* NSData+Base64.h in Headers */,\n\t\t\t\tD87D4C7D15C3F14E0006FAFE /* DOUComment.h in Headers */,\n\t\t\t\tD87D4C7F15C3F14E0006FAFE /* DOUCommentArray.h in Headers */,\n\t\t\t\tD89A6A96162D37EE00954BC4 /* DOUUser.h in Headers */,\n\t\t\t\tD89A6AA1162D384100954BC4 /* DOUEvent.h in Headers */,\n\t\t\t\tD89A6AA3162D384100954BC4 /* DOUEventArray.h in Headers */,\n\t\t\t\tD89A6AA5162D384100954BC4 /* DOULoc.h in Headers */,\n\t\t\t\tD89A6AA7162D384100954BC4 /* DOULocArray.h in Headers */,\n\t\t\t\tD88800BD166F5BF600DAFFC4 /* DOUAlbumArray.h in Headers */,\n\t\t\t\tD88800C7166F5D4F00DAFFC4 /* DOUNote.h in Headers */,\n\t\t\t\tD88800CF166F63B600DAFFC4 /* DOUNoteArray.h in Headers */,\n\t\t\t\tD88800D7166F65CA00DAFFC4 /* DOUMovie.h in Headers */,\n\t\t\t\tD88800DB166F65E400DAFFC4 /* DOUMovieArray.h in Headers */,\n\t\t\t\t1A3451DB167887E90097FEF5 /* DOUBookArray.h in Headers */,\n\t\t\t\t1A3451DD167887E90097FEF5 /* DOUBook.h in Headers */,\n\t\t\t\t1A3451E3167887F80097FEF5 /* DOUMusicArray.h in Headers */,\n\t\t\t\t1A3451E5167887F80097FEF5 /* DOUMusic.h in Headers */,\n\t\t\t\tD8695E8F167AD59000EFFF41 /* DOUNotification.h in Headers */,\n\t\t\t\tD8695E91167AD59000EFFF41 /* DOUNotificationArray.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\tD800D537146907B2009F64FD /* DoubanAPIEngine */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = D800D55C146907B2009F64FD /* Build configuration list for PBXNativeTarget \"DoubanAPIEngine\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tD800D534146907B2009F64FD /* Sources */,\n\t\t\t\tD800D535146907B2009F64FD /* Frameworks */,\n\t\t\t\tD800D536146907B2009F64FD /* Headers */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = DoubanAPIEngine;\n\t\t\tproductName = DoubanAPIEngine;\n\t\t\tproductReference = D800D538146907B2009F64FD /* libDoubanAPIEngine.a */;\n\t\t\tproductType = \"com.apple.product-type.library.static\";\n\t\t};\n\t\tD800D547146907B2009F64FD /* DoubanAPIEngineTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = D800D55F146907B2009F64FD /* Build configuration list for PBXNativeTarget \"DoubanAPIEngineTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tD800D543146907B2009F64FD /* Sources */,\n\t\t\t\tD800D544146907B2009F64FD /* Frameworks */,\n\t\t\t\tD800D545146907B2009F64FD /* Resources */,\n\t\t\t\tD800D546146907B2009F64FD /* ShellScript */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tD800D54F146907B2009F64FD /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = DoubanAPIEngineTests;\n\t\t\tproductName = DoubanAPIEngineTests;\n\t\t\tproductReference = D800D548146907B2009F64FD /* DoubanAPIEngineTests.octest */;\n\t\t\tproductType = \"com.apple.product-type.bundle\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tD800D52F146907B2009F64FD /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0430;\n\t\t\t\tORGANIZATIONNAME = \"Douban Inc\";\n\t\t\t};\n\t\t\tbuildConfigurationList = D800D532146907B2009F64FD /* Build configuration list for PBXProject \"DoubanAPIEngine\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = D800D52D146907B2009F64FD;\n\t\t\tproductRefGroup = D800D539146907B2009F64FD /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tD800D537146907B2009F64FD /* DoubanAPIEngine */,\n\t\t\t\tD800D547146907B2009F64FD /* DoubanAPIEngineTests */,\n\t\t\t\tD820CFA7166E03FC0067C5A5 /* libDoubanApiEngine */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tD800D545146907B2009F64FD /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD800D556146907B2009F64FD /* InfoPlist.strings in Resources */,\n\t\t\t\tD87D4CA715C3F4850006FAFE /* DoubanEntryCity.xml in Resources */,\n\t\t\t\tD87D4CA815C3F4850006FAFE /* DoubanEntryEvent.xml in Resources */,\n\t\t\t\tD87D4CA915C3F4850006FAFE /* DoubanEntryMiniblog.xml in Resources */,\n\t\t\t\tD87D4CAA15C3F4850006FAFE /* DoubanEntryPeople.xml in Resources */,\n\t\t\t\tD87D4CAB15C3F4850006FAFE /* DoubanEntryPhoto.xml in Resources */,\n\t\t\t\tD87D4CAC15C3F4850006FAFE /* DoubanEntryRecommendation.xml in Resources */,\n\t\t\t\tD87D4CAD15C3F4850006FAFE /* DoubanEntrySubject.xml in Resources */,\n\t\t\t\tD87D4CAE15C3F4850006FAFE /* DoubanFeedCity.xml in Resources */,\n\t\t\t\tD87D4CAF15C3F4850006FAFE /* DoubanFeedComment.xml in Resources */,\n\t\t\t\tD87D4CB015C3F4850006FAFE /* DoubanFeedEvent.xml in Resources */,\n\t\t\t\tD87D4CB115C3F4850006FAFE /* DoubanFeedEventCategory.xml in Resources */,\n\t\t\t\tD87D4CB215C3F4850006FAFE /* DoubanFeedMiniblog.xml in Resources */,\n\t\t\t\tD87D4CB315C3F4850006FAFE /* DoubanFeedPeople.xml in Resources */,\n\t\t\t\tD87D4CB415C3F4850006FAFE /* DoubanFeedPhoto.xml in Resources */,\n\t\t\t\tD87D4CB515C3F4850006FAFE /* DoubanFeedRecommendation.xml in Resources */,\n\t\t\t\tD87D4CB615C3F4850006FAFE /* DoubanFeedSubject.xml in Resources */,\n\t\t\t\tD87D4CBD15C3F5580006FAFE /* Album.json in Resources */,\n\t\t\t\tD87D4CBE15C3F5580006FAFE /* CommentArray.json in Resources */,\n\t\t\t\tD87D4CBF15C3F5580006FAFE /* Online.json in Resources */,\n\t\t\t\tD87D4CC015C3F5580006FAFE /* OnlineArray.json in Resources */,\n\t\t\t\tD87D4CC115C3F5580006FAFE /* Photo.json in Resources */,\n\t\t\t\tD87D4CC215C3F5580006FAFE /* PhotoArray.json in Resources */,\n\t\t\t\tD89A2A5615ECA3360027C0B0 /* Event.json in Resources */,\n\t\t\t\tD88800CA166F603F00DAFFC4 /* Note.json in Resources */,\n\t\t\t\tD88800D2166F654100DAFFC4 /* MovieArray.json in Resources */,\n\t\t\t\t1A3451E8167889060097FEF5 /* MusicArray.json in Resources */,\n\t\t\t\t1A3451E9167889060097FEF5 /* BookArray.json in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\tD800D546146907B2009F64FD /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"# Run the unit tests in this test bundle.\\n\\\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\\\"\\n\";\n\t\t};\n\t\tD820CFAE166E04230067C5A5 /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"xcodebuild -project ${PROJECT_NAME}.xcodeproj -sdk iphonesimulator -target ${PROJECT_NAME} -configuration ${CONFIGURATION} clean build\\n\\nxcodebuild -project ${PROJECT_NAME}.xcodeproj -sdk iphoneos -target ${PROJECT_NAME} -configuration ${CONFIGURATION} clean build\\n\";\n\t\t};\n\t\tD820CFAF166E044C0067C5A5 /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"SIMULATOR_LIBRARY_PATH=\\\"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a\\\" &&\\nDEVICE_LIBRARY_PATH=\\\"${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a\\\" &&\\nUNIVERSAL_LIBRARY_DIR=\\\"${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal\\\" &&\\nUNIVERSAL_LIBRARY_PATH=\\\"${UNIVERSAL_LIBRARY_DIR}/${PRODUCT_NAME}\\\" &&\\nFRAMEWORK=\\\"${UNIVERSAL_LIBRARY_DIR}/${PRODUCT_NAME}.framework\\\" &&\\n\\n\\n# Create framework directory structure.\\nrm -rf \\\"${FRAMEWORK}\\\" &&\\nmkdir -p \\\"${UNIVERSAL_LIBRARY_DIR}\\\" &&\\nmkdir -p \\\"${FRAMEWORK}/Versions/A/Headers\\\" &&\\nmkdir -p \\\"${FRAMEWORK}/Versions/A/Resources\\\" &&\\n\\n\\n# Generate universal binary for the device and simulator.\\nlipo \\\"${SIMULATOR_LIBRARY_PATH}\\\" \\\"${DEVICE_LIBRARY_PATH}\\\" -create -output \\\"${UNIVERSAL_LIBRARY_PATH}\\\" &&\\n\\n\\n# Move files to appropriate locations in framework paths.\\ncp \\\"${UNIVERSAL_LIBRARY_PATH}\\\" \\\"${FRAMEWORK}/Versions/A\\\" &&\\nln -s \\\"A\\\" \\\"${FRAMEWORK}/Versions/Current\\\" &&\\nln -s \\\"Versions/Current/Headers\\\" \\\"${FRAMEWORK}/Headers\\\" &&\\nln -s \\\"Versions/Current/Resources\\\" \\\"${FRAMEWORK}/Resources\\\" &&\\nln -s \\\"Versions/Current/${PRODUCT_NAME}\\\" \\\"${FRAMEWORK}/${PRODUCT_NAME}\\\"\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tD800D534146907B2009F64FD /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD800D56F146908AF009F64FD /* DOUHttpRequest.m in Sources */,\n\t\t\t\tD800D5CA146908FD009F64FD /* ASIAuthenticationDialog.m in Sources */,\n\t\t\t\tD800D5CD146908FD009F64FD /* ASIDataCompressor.m in Sources */,\n\t\t\t\tD800D5CF146908FD009F64FD /* ASIDataDecompressor.m in Sources */,\n\t\t\t\tD800D5D1146908FD009F64FD /* ASIDownloadCache.m in Sources */,\n\t\t\t\tD800D5D3146908FD009F64FD /* ASIFormDataRequest.m in Sources */,\n\t\t\t\tD800D5D5146908FD009F64FD /* ASIHTTPRequest.m in Sources */,\n\t\t\t\tD800D5D9146908FD009F64FD /* ASIInputStream.m in Sources */,\n\t\t\t\tD800D5DB146908FD009F64FD /* ASINetworkQueue.m in Sources */,\n\t\t\t\tD800D5DE146908FD009F64FD /* ASIWebPageRequest.m in Sources */,\n\t\t\t\tD800D5E0146908FD009F64FD /* ASICloudFilesCDNRequest.m in Sources */,\n\t\t\t\tD800D5E2146908FD009F64FD /* ASICloudFilesContainer.m in Sources */,\n\t\t\t\tD800D5E4146908FD009F64FD /* ASICloudFilesContainerRequest.m in Sources */,\n\t\t\t\tD800D5E6146908FD009F64FD /* ASICloudFilesContainerXMLParserDelegate.m in Sources */,\n\t\t\t\tD800D5E8146908FD009F64FD /* ASICloudFilesObject.m in Sources */,\n\t\t\t\tD800D5EA146908FD009F64FD /* ASICloudFilesObjectRequest.m in Sources */,\n\t\t\t\tD800D5EC146908FD009F64FD /* ASICloudFilesRequest.m in Sources */,\n\t\t\t\tD800D5EF146908FD009F64FD /* ASIS3Bucket.m in Sources */,\n\t\t\t\tD800D5F1146908FD009F64FD /* ASIS3BucketObject.m in Sources */,\n\t\t\t\tD800D5F3146908FD009F64FD /* ASIS3BucketRequest.m in Sources */,\n\t\t\t\tD800D5F5146908FD009F64FD /* ASIS3ObjectRequest.m in Sources */,\n\t\t\t\tD800D5F7146908FD009F64FD /* ASIS3Request.m in Sources */,\n\t\t\t\tD800D5F9146908FD009F64FD /* ASIS3ServiceRequest.m in Sources */,\n\t\t\t\tD800D5FB146908FD009F64FD /* NSObject+SBJson.m in Sources */,\n\t\t\t\tD800D5FE146908FD009F64FD /* SBJsonParser.m in Sources */,\n\t\t\t\tD800D600146908FD009F64FD /* SBJsonStreamParser.m in Sources */,\n\t\t\t\tD800D602146908FD009F64FD /* SBJsonStreamParserAccumulator.m in Sources */,\n\t\t\t\tD800D604146908FD009F64FD /* SBJsonStreamParserAdapter.m in Sources */,\n\t\t\t\tD800D606146908FD009F64FD /* SBJsonStreamParserState.m in Sources */,\n\t\t\t\tD800D608146908FD009F64FD /* SBJsonStreamWriter.m in Sources */,\n\t\t\t\tD800D60A146908FD009F64FD /* SBJsonStreamWriterAccumulator.m in Sources */,\n\t\t\t\tD800D60C146908FD009F64FD /* SBJsonStreamWriterState.m in Sources */,\n\t\t\t\tD800D60E146908FD009F64FD /* SBJsonTokeniser.m in Sources */,\n\t\t\t\tD800D610146908FD009F64FD /* SBJsonUTF8Stream.m in Sources */,\n\t\t\t\tD800D612146908FD009F64FD /* SBJsonWriter.m in Sources */,\n\t\t\t\tD800D614146908FD009F64FD /* Reachability.m in Sources */,\n\t\t\t\tD800D627146909C2009F64FD /* DOUAPIConfig.m in Sources */,\n\t\t\t\tD858E04714C3AC0D00335280 /* DOUQuery.m in Sources */,\n\t\t\t\tD858E04F14C3DA9100335280 /* DOUService.m in Sources */,\n\t\t\t\tD882161115889C5F004B4AD4 /* DOUOAuthService.m in Sources */,\n\t\t\t\tD882161315889C5F004B4AD4 /* DOUOAuthStore.m in Sources */,\n\t\t\t\tD87D4B2415C3EF600006FAFE /* DOUObject.m in Sources */,\n\t\t\t\tD87D4B2615C3EF600006FAFE /* DOUObject+Utils.m in Sources */,\n\t\t\t\tD87D4B2815C3EF600006FAFE /* DOUObjectArray.m in Sources */,\n\t\t\t\tD87D4B2F15C3EFE70006FAFE /* DOUOnline.m in Sources */,\n\t\t\t\tD87D4B3115C3EFE70006FAFE /* DOUOnlineArray.m in Sources */,\n\t\t\t\tD87D4B3A15C3F0230006FAFE /* DOUAlbum.m in Sources */,\n\t\t\t\tD87D4B3C15C3F0230006FAFE /* DOUPhoto.m in Sources */,\n\t\t\t\tD87D4B3E15C3F0230006FAFE /* DOUPhotoArray.m in Sources */,\n\t\t\t\tD87D4BE215C3F0430006FAFE /* GDataEntryBase.m in Sources */,\n\t\t\t\tD87D4BE415C3F0430006FAFE /* GDataFeedBase.m in Sources */,\n\t\t\t\tD87D4BE615C3F0430006FAFE /* GDataObject.m in Sources */,\n\t\t\t\tD87D4BE815C3F0430006FAFE /* GDataAtomPubControl.m in Sources */,\n\t\t\t\tD87D4BEA15C3F0430006FAFE /* GDataBaseElements.m in Sources */,\n\t\t\t\tD87D4BEC15C3F0430006FAFE /* GDataBatchID.m in Sources */,\n\t\t\t\tD87D4BEE15C3F0430006FAFE /* GDataBatchInterrupted.m in Sources */,\n\t\t\t\tD87D4BF015C3F0430006FAFE /* GDataBatchOperation.m in Sources */,\n\t\t\t\tD87D4BF215C3F0430006FAFE /* GDataBatchStatus.m in Sources */,\n\t\t\t\tD87D4BF415C3F0430006FAFE /* GDataCategory.m in Sources */,\n\t\t\t\tD87D4BF615C3F0430006FAFE /* GDataComment.m in Sources */,\n\t\t\t\tD87D4BF815C3F0430006FAFE /* GDataCustomProperty.m in Sources */,\n\t\t\t\tD87D4BFA15C3F0430006FAFE /* GDataDateTime.m in Sources */,\n\t\t\t\tD87D4BFC15C3F0430006FAFE /* GDataDeleted.m in Sources */,\n\t\t\t\tD87D4BFF15C3F0430006FAFE /* GDataEmail.m in Sources */,\n\t\t\t\tD87D4C0115C3F0430006FAFE /* GDataEntryContent.m in Sources */,\n\t\t\t\tD87D4C0315C3F0430006FAFE /* GDataEntryLink.m in Sources */,\n\t\t\t\tD87D4C0515C3F0430006FAFE /* GDataExtendedProperty.m in Sources */,\n\t\t\t\tD87D4C0715C3F0430006FAFE /* GDataFeedLink.m in Sources */,\n\t\t\t\tD87D4C0915C3F0430006FAFE /* GDataGenerator.m in Sources */,\n\t\t\t\tD87D4C0B15C3F0430006FAFE /* GDataGeoPt.m in Sources */,\n\t\t\t\tD87D4C0D15C3F0430006FAFE /* GDataIM.m in Sources */,\n\t\t\t\tD87D4C0F15C3F0430006FAFE /* GDataLink.m in Sources */,\n\t\t\t\tD87D4C1115C3F0430006FAFE /* GDataMoney.m in Sources */,\n\t\t\t\tD87D4C1315C3F0430006FAFE /* GDataName.m in Sources */,\n\t\t\t\tD87D4C1515C3F0430006FAFE /* GDataOrganization.m in Sources */,\n\t\t\t\tD87D4C1715C3F0430006FAFE /* GDataOrganizationName.m in Sources */,\n\t\t\t\tD87D4C1915C3F0430006FAFE /* GDataPerson.m in Sources */,\n\t\t\t\tD87D4C1B15C3F0430006FAFE /* GDataPhoneNumber.m in Sources */,\n\t\t\t\tD87D4C1D15C3F0430006FAFE /* GDataPostalAddress.m in Sources */,\n\t\t\t\tD87D4C1F15C3F0430006FAFE /* GDataRating.m in Sources */,\n\t\t\t\tD87D4C2115C3F0430006FAFE /* GDataStructuredPostalAddress.m in Sources */,\n\t\t\t\tD87D4C2315C3F0430006FAFE /* GDataTextConstruct.m in Sources */,\n\t\t\t\tD87D4C2515C3F0430006FAFE /* GDataValueConstruct.m in Sources */,\n\t\t\t\tD87D4C2715C3F0430006FAFE /* GDataWhen.m in Sources */,\n\t\t\t\tD87D4C2915C3F0430006FAFE /* GDataWhere.m in Sources */,\n\t\t\t\tD87D4C2B15C3F0430006FAFE /* GDataWho.m in Sources */,\n\t\t\t\tD87D4C2E15C3F0430006FAFE /* GDataUtilities.m in Sources */,\n\t\t\t\tD87D4C3015C3F0430006FAFE /* GTMGatherInputStream.m in Sources */,\n\t\t\t\tD87D4C3215C3F0430006FAFE /* GTMMIMEDocument.m in Sources */,\n\t\t\t\tD87D4C3415C3F0430006FAFE /* GDataXMLNode.m in Sources */,\n\t\t\t\tD87D4C3615C3F0430006FAFE /* DoubanEntryComment.m in Sources */,\n\t\t\t\tD87D4C3815C3F0430006FAFE /* DoubanFeedComment.m in Sources */,\n\t\t\t\tD87D4C3A15C3F0430006FAFE /* DoubanEntryCity.m in Sources */,\n\t\t\t\tD87D4C3C15C3F0430006FAFE /* DoubanEntryEvent.m in Sources */,\n\t\t\t\tD87D4C3E15C3F0430006FAFE /* DoubanEntryEventCategory.m in Sources */,\n\t\t\t\tD87D4C4015C3F0430006FAFE /* DoubanFeedCity.m in Sources */,\n\t\t\t\tD87D4C4215C3F0430006FAFE /* DoubanFeedEvent.m in Sources */,\n\t\t\t\tD87D4C4415C3F0430006FAFE /* DoubanFeedEventCategory.m in Sources */,\n\t\t\t\tD87D4C4615C3F0430006FAFE /* GDataAtomAuthor+Extension.m in Sources */,\n\t\t\t\tD87D4C4815C3F0430006FAFE /* GDataEntryBase+Extension.m in Sources */,\n\t\t\t\tD87D4C4A15C3F0430006FAFE /* DoubanEntryMiniblog.m in Sources */,\n\t\t\t\tD87D4C4C15C3F0430006FAFE /* DoubanFeedMiniblog.m in Sources */,\n\t\t\t\tD87D4C4E15C3F0430006FAFE /* DoubanEntryPeople.m in Sources */,\n\t\t\t\tD87D4C5015C3F0430006FAFE /* DoubanFeedPeople.m in Sources */,\n\t\t\t\tD87D4C5215C3F0430006FAFE /* DoubanEntryAlbum.m in Sources */,\n\t\t\t\tD87D4C5415C3F0430006FAFE /* DoubanEntryPhoto.m in Sources */,\n\t\t\t\tD87D4C5615C3F0430006FAFE /* DoubanFeedAlbum.m in Sources */,\n\t\t\t\tD87D4C5815C3F0430006FAFE /* DoubanFeedPhoto.m in Sources */,\n\t\t\t\tD87D4C5A15C3F0430006FAFE /* DoubanEntryRecommendation.m in Sources */,\n\t\t\t\tD87D4C5C15C3F0430006FAFE /* DoubanFeedRecommendation.m in Sources */,\n\t\t\t\tD87D4C5E15C3F0430006FAFE /* DoubanEntryReview.m in Sources */,\n\t\t\t\tD87D4C6015C3F0430006FAFE /* DoubanFeedReview.m in Sources */,\n\t\t\t\tD87D4C6215C3F0430006FAFE /* DoubanEntrySubject.m in Sources */,\n\t\t\t\tD87D4C6415C3F0430006FAFE /* DoubanFeedSubject.m in Sources */,\n\t\t\t\tD87D4C6615C3F0430006FAFE /* DoubanDefines.m in Sources */,\n\t\t\t\tD87D4C6815C3F0430006FAFE /* DoubanAttribute.m in Sources */,\n\t\t\t\tD87D4C6A15C3F0430006FAFE /* DoubanLocation.m in Sources */,\n\t\t\t\tD87D4C6C15C3F0430006FAFE /* DoubanSignature.m in Sources */,\n\t\t\t\tD87D4C6E15C3F0430006FAFE /* DoubanTag.m in Sources */,\n\t\t\t\tD87D4C7015C3F0430006FAFE /* DoubanUID.m in Sources */,\n\t\t\t\tD87D4C7215C3F0430006FAFE /* GeorssPoint.m in Sources */,\n\t\t\t\tD87D4C7615C3F11C0006FAFE /* NSData+Base64.m in Sources */,\n\t\t\t\tD87D4C7E15C3F14E0006FAFE /* DOUComment.m in Sources */,\n\t\t\t\tD87D4C8015C3F14E0006FAFE /* DOUCommentArray.m in Sources */,\n\t\t\t\tD89A6A97162D37EE00954BC4 /* DOUUser.m in Sources */,\n\t\t\t\tD89A6AA2162D384100954BC4 /* DOUEvent.m in Sources */,\n\t\t\t\tD89A6AA4162D384100954BC4 /* DOUEventArray.m in Sources */,\n\t\t\t\tD89A6AA6162D384100954BC4 /* DOULoc.m in Sources */,\n\t\t\t\tD89A6AA8162D384100954BC4 /* DOULocArray.m in Sources */,\n\t\t\t\tD88800BE166F5BF600DAFFC4 /* DOUAlbumArray.m in Sources */,\n\t\t\t\tD88800C8166F5D4F00DAFFC4 /* DOUNote.m in Sources */,\n\t\t\t\tD88800D0166F63B600DAFFC4 /* DOUNoteArray.m in Sources */,\n\t\t\t\tD88800D8166F65CA00DAFFC4 /* DOUMovie.m in Sources */,\n\t\t\t\tD88800DC166F65E400DAFFC4 /* DOUMovieArray.m in Sources */,\n\t\t\t\t1A3451DA167887E90097FEF5 /* DOUBookArray.m in Sources */,\n\t\t\t\t1A3451DC167887E90097FEF5 /* DOUBook.m in Sources */,\n\t\t\t\t1A3451E2167887F80097FEF5 /* DOUMusicArray.m in Sources */,\n\t\t\t\t1A3451E4167887F80097FEF5 /* DOUMusic.m in Sources */,\n\t\t\t\tD8695E90167AD59000EFFF41 /* DOUNotification.m in Sources */,\n\t\t\t\tD8695E92167AD59000EFFF41 /* DOUNotificationArray.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tD800D543146907B2009F64FD /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD800D559146907B2009F64FD /* DoubanAPIEngineTests.m in Sources */,\n\t\t\t\tD882161915889DDE004B4AD4 /* DOUOAuthServiceTests.m in Sources */,\n\t\t\t\tD882161B15889DDE004B4AD4 /* DOUTestResponseLoader.m in Sources */,\n\t\t\t\tD87D4C8D15C3F2A70006FAFE /* DoubanCityTests.m in Sources */,\n\t\t\t\tD87D4C8E15C3F2A70006FAFE /* DoubanCommentTests.m in Sources */,\n\t\t\t\tD87D4C8F15C3F2A70006FAFE /* DoubanEventCategoryTests.m in Sources */,\n\t\t\t\tD87D4C9015C3F2A70006FAFE /* DoubanEventTests.m in Sources */,\n\t\t\t\tD87D4C9115C3F2A70006FAFE /* DoubanMiniblogTests.m in Sources */,\n\t\t\t\tD87D4C9215C3F2A70006FAFE /* DoubanPeopleTests.m in Sources */,\n\t\t\t\tD87D4C9315C3F2A70006FAFE /* DoubanPhotoTests.m in Sources */,\n\t\t\t\tD87D4C9415C3F2A70006FAFE /* DoubanSubjectTests.m in Sources */,\n\t\t\t\tD87D4CC615C3F56D0006FAFE /* DOUCommentTests.m in Sources */,\n\t\t\t\tD87D4CC715C3F56D0006FAFE /* DOUOnlineTests.m in Sources */,\n\t\t\t\tD87D4CC815C3F56D0006FAFE /* DOUPhotoTests.m in Sources */,\n\t\t\t\tD88800CC166F609300DAFFC4 /* DOUNoteTests.m in Sources */,\n\t\t\t\tD88800D4166F65A200DAFFC4 /* DOUMovieTests.m in Sources */,\n\t\t\t\t1A3451EC167889140097FEF5 /* DOUMusicTests.m in Sources */,\n\t\t\t\t1A3451ED167889140097FEF5 /* DOUBookTests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tD800D54F146907B2009F64FD /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = D800D537146907B2009F64FD /* DoubanAPIEngine */;\n\t\t\ttargetProxy = D800D54E146907B2009F64FD /* PBXContainerItemProxy */;\n\t\t};\n\t\tD820CFAD166E04170067C5A5 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = D800D537146907B2009F64FD /* DoubanAPIEngine */;\n\t\t\ttargetProxy = D820CFAC166E04170067C5A5 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\tD800D554146907B2009F64FD /* InfoPlist.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tD800D555146907B2009F64FD /* en */,\n\t\t\t);\n\t\t\tname = InfoPlist.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\tD800D55A146907B2009F64FD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = (\n\t\t\t\t\tarmv6,\n\t\t\t\t\t\"$(ARCHS_STANDARD_32_BIT)\",\n\t\t\t\t);\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_THUMB_SUPPORT = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 4.0;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tD800D55B146907B2009F64FD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = (\n\t\t\t\t\tarmv6,\n\t\t\t\t\t\"$(ARCHS_STANDARD_32_BIT)\",\n\t\t\t\t);\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_THUMB_SUPPORT = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 4.0;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tD800D55D146907B2009F64FD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = (\n\t\t\t\t\tarmv6,\n\t\t\t\t\t\"$(ARCHS_STANDARD_32_BIT)\",\n\t\t\t\t);\n\t\t\t\tDSTROOT = /tmp/DoubanAPIEngine.dst;\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"DoubanAPIEngine/DoubanAPIEngine-Prefix.pch\";\n\t\t\t\tGCC_THUMB_SUPPORT = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = \"${SDK_DIR}/usr/include/libxml2\";\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tD800D55E146907B2009F64FD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = (\n\t\t\t\t\tarmv6,\n\t\t\t\t\t\"$(ARCHS_STANDARD_32_BIT)\",\n\t\t\t\t);\n\t\t\t\tDSTROOT = /tmp/DoubanAPIEngine.dst;\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"DoubanAPIEngine/DoubanAPIEngine-Prefix.pch\";\n\t\t\t\tGCC_THUMB_SUPPORT = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tHEADER_SEARCH_PATHS = \"${SDK_DIR}/usr/include/libxml2\";\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tD800D560146907B2009F64FD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\",\n\t\t\t\t);\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"DoubanAPIEngine/DoubanAPIEngine-Prefix.pch\";\n\t\t\t\tGCC_THUMB_SUPPORT = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = \"${SDK_DIR}/usr/include/libxml2\";\n\t\t\t\tINFOPLIST_FILE = \"DoubanAPIEngineTests/DoubanAPIEngineTests-Info.plist\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-all_load\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tVALID_ARCHS = \"armv6 armv7\";\n\t\t\t\tWRAPPER_EXTENSION = octest;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tD800D561146907B2009F64FD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\",\n\t\t\t\t);\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"DoubanAPIEngine/DoubanAPIEngine-Prefix.pch\";\n\t\t\t\tGCC_THUMB_SUPPORT = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = \"${SDK_DIR}/usr/include/libxml2\";\n\t\t\t\tINFOPLIST_FILE = \"DoubanAPIEngineTests/DoubanAPIEngineTests-Info.plist\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-all_load\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tVALID_ARCHS = \"armv6 armv7\";\n\t\t\t\tWRAPPER_EXTENSION = octest;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tD820CFA8166E03FC0067C5A5 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tD820CFA9166E03FC0067C5A5 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tD800D532146907B2009F64FD /* Build configuration list for PBXProject \"DoubanAPIEngine\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tD800D55A146907B2009F64FD /* Debug */,\n\t\t\t\tD800D55B146907B2009F64FD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tD800D55C146907B2009F64FD /* Build configuration list for PBXNativeTarget \"DoubanAPIEngine\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tD800D55D146907B2009F64FD /* Debug */,\n\t\t\t\tD800D55E146907B2009F64FD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tD800D55F146907B2009F64FD /* Build configuration list for PBXNativeTarget \"DoubanAPIEngineTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tD800D560146907B2009F64FD /* Debug */,\n\t\t\t\tD800D561146907B2009F64FD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tD820CFAA166E03FC0067C5A5 /* Build configuration list for PBXAggregateTarget \"libDoubanApiEngine\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tD820CFA8166E03FC0067C5A5 /* Debug */,\n\t\t\t\tD820CFA9166E03FC0067C5A5 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = D800D52F146907B2009F64FD /* Project object */;\n}\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/DOUOAuthServiceTests.m",
    "content": "//\n//  DOUOAuthServiceTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/20/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUAPIEngine.h\"\n#import \"DOUTestResponseLoader.h\"\n\n\n\n\n\nstatic NSString * const kAPIKey = @\"0339b495d888705009ad1dc1899950f0\";\nstatic NSString * const kPrivateKey = @\"69f50280e68a742a\";\nstatic NSString * const kRedirectUrl = @\"http://www.douban.com/location/mobile\";\n\n\n@interface DOUOAuthServiceTests : SenTestCase\n\n@end\n\n\n\n\n@implementation DOUOAuthServiceTests\n\n\n//- (void)testOAuthServiceByAuthorizationCode {\n//  DOUTestResponseLoader *loader = [DOUTestResponseLoader responseLoader];\n//  [loader setTimeout:10];\n//  DOUOAuthService* service = [DOUOAuthService clientWithClientID:@\"appID\" secret:@\"appSecret\"];\n//  \n//  service.delegate = loader;\n//  service.authorizationURL = kTokenUrl;\n//  service.authorizationCode = @\"someInvalidAuthorizationCode\";\n//  service.callbackURL = kRedirectUrl;\n//  [service validateAuthorizationCode];\n//  [loader waitForResponse];\n//}\n\n\n- (void)testOAuthServiceByUsernameAndPassword {\n  DOUTestResponseLoader *loader = [DOUTestResponseLoader responseLoader];\n  [loader setTimeout:10];\n  \n  DOUOAuthService* service = [DOUOAuthService sharedInstance];\n  service.clientId = kAPIKey;\n  service.clientSecret = kPrivateKey;\n  \n  service.delegate = loader;\n  service.authorizationURL = @\"https://www.douban.com/service/auth2/token\";\n  service.callbackURL = kRedirectUrl;\n  \n  [service validateUsername:@\"ruhan@douban.com\" password:@\"ruhan\"];\n  [loader waitForResponse];\n  STAssertTrue(loader.wasSuccessful == YES, @\"\");\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/DoubanAPIEngineTests-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${EXECUTABLE_NAME}</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.douban.${PRODUCT_NAME:rfc1034identifier}</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/DoubanAPIEngineTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUTestResponseLoader.h\"\n#import \"DOUAPIConfig.h\"\n#import \"DOUHttpRequest.h\"\n#import \"DOUService.h\"\n#import \"DOUQuery.h\"\n#import \"DoubanEntrySubject.h\"\n#import \"DOUAPIEngine.h\"\n\n\n@interface DoubanAPIEngineTests : SenTestCase \n\n- (void)testPostEvent;\n\n@end\n\n\n@implementation DoubanAPIEngineTests\n\nstatic NSString * const kUsernameStr = @\"yourUsername@\";\nstatic NSString * const kPasswordStr = @\"yourpassword\";\n\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n+ (DOUQuery *)queryCurrentUser {\n  NSString *subPath = @\"/shuo/users/@me\";\n  DOUQuery *query = [[DOUQuery alloc] initWithSubPath:subPath parameters:nil];\n  return [query autorelease];\n}\n\n+ (DOUQuery *)queryUserWithId:(NSUInteger)userId {\n  NSString *subPath = [NSString stringWithFormat:@\"/shuo/users/%d\", userId];\n  DOUQuery *query = [[DOUQuery alloc] initWithSubPath:subPath parameters:nil];\n  return [query autorelease];\n}\n\n\n+ (DOUQuery *)queryEventWithId:(NSUInteger)eventId {\n  NSString *subPath = [NSString stringWithFormat:@\"/event/%d\", eventId];\n  NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:@\"xml\", @\"alt\", nil];\n  DOUQuery *query = [[DOUQuery alloc] initWithSubPath:subPath parameters:params];\n  return [query autorelease];\n}\n\n\n+ (DOUQuery *)queryCreateEvent {\n  NSString *subPath = @\"/v2/event/create\";\n  DOUQuery *query = [[DOUQuery alloc] initWithSubPath:subPath parameters:nil];\n  return [query autorelease];\n}\n\n\n+ (DOUQuery *)queryBookWithId:(int)bookId {\n  NSString *subPath = [NSString stringWithFormat:@\"/book/subject/%d\", bookId];\n  NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:@\"xml\", @\"alt\", nil];\n  DOUQuery *query = [[DOUQuery alloc] initWithSubPath:subPath parameters:params];\n  return [query autorelease];\n}\n\n- (void)testPostEvent {\n// todo\n}\n\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanCityTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DoubanEntryCity.h\"\n#import \"DoubanFeedCity.h\"\n\n@interface DoubanCityTests : SenTestCase \n\n- (void)testDoubanEntryCity;\n\n- (void)testDoubanFeedCity;\n\n@end\n\n\n@implementation DoubanCityTests\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanEntryCity {\n\n  NSString *filePath = \n            [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanEntryCity\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"filePath fail!\");\n    \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n    \n  DoubanEntryCity *city = [[DoubanEntryCity alloc] initWithData:data]; \n  STAssertTrue([[[city title] stringValue] isEqualToString:@\"上海\"] , @\"path fail\");\n  STAssertTrue([[city name] isEqualToString:@\"上海\"] , @\"path fail\");\n  STAssertTrue([city isHabitable] , @\"isHabitable\");\n  \n}\n\n\n- (void)testDoubanFeedCity {\n  \n  NSString *filePath = \n          [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanFeedCity\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n  DoubanFeedCity *feed = [[DoubanFeedCity alloc] initWithData:data];\n  STAssertTrue([[[feed title] stringValue] isEqualToString:@\"活动热门城市\"], @\"feed title\");\n  for (DoubanEntryCity * city in feed) {\n    \n    if ([[[city title] stringValue] isEqualToString:@\"北京\"]) {\n      STAssertTrue([[[city title] stringValue] isEqualToString:@\"北京\"] , @\"path fail\");\n      STAssertTrue([[city name] isEqualToString:@\"北京\"] , @\"path fail\");\n      STAssertTrue([city isHabitable] , @\"isHabitable\");\n    }\n  }\n  \n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanCommentTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"GDataBaseElements.h\"\n#import \"DOUAPIEngine.h\"\n#import \"DoubanEntryComment.h\"\n#import \"DoubanFeedComment.h\"\n#import \"GDataEntryBase+Extension.h\"\n\n@interface DoubanCommentTests : SenTestCase \n\n\n- (void)testDoubanFeedComment;\n\n@end\n\n\n@implementation DoubanCommentTests\n\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanFeedComment {\n  \n  NSString *filePath = \n          [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanFeedComment\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n  DoubanFeedComment *feed = [[DoubanFeedComment alloc] initWithData:data];\n  STAssertNotNil(feed, @\"\" );\n  \n  for (GDataAtomAuthor *author in [feed authors]){\n    STAssertTrue([[author name] isEqualToString:@\"lincode\"], @\"author\");\n  }\n  \n  \n  STAssertTrue([[[feed title] stringValue] isEqualToString:@\"照片 的回应\"], @\"Feed title\");\n\n  for (DoubanEntryComment *comment in feed) {\n    NSLog(@\"id:%@\", [comment identifier]);\n    if ([[comment identifier] isEqualToString:@\"http://api.douban.com/recommendation/1474552938/comment/99611691\"]) {\n      STAssertTrue([[[comment content] stringValue] length] >= 1 , @\"content\");\n      STAssertTrue([[[comment publishedDate] stringValue] isEqualToString:@\"2012-03-22T21:23:43+08:00\"], @\"published\");    \n\n      GDataAtomAuthor *author = [comment theFirstAuthor];\n      STAssertTrue([[author name] isEqualToString:@\"放开那个西红柿\"], @\"author\");\n    }\n    \n    if ([[comment identifier] isEqualToString:@\"http://api.douban.com/recommendation/1474552938/comment/99612528\"]) {\n      STAssertTrue([[[comment content] stringValue] isEqualToString:@\"大众点评啦\"] , @\"content\");\n\n      STAssertTrue([[[comment publishedDate] stringValue] isEqualToString:@\"2012-03-22T21:29:27+08:00\"], @\"published\");\n      \n      GDataAtomAuthor *author = [comment theFirstAuthor];\n      STAssertTrue([[author name] isEqualToString:@\"lincode\"], @\"author\");\n    }\n\n    if ([[comment identifier] isEqualToString:@\"http://api.douban.com/recommendation/1474552938/comment/99624829\"]) {\n      STAssertTrue([[[comment content] stringValue] isEqualToString:@\"不知道大叔的新店如何？\"] , @\"content\");\n      STAssertTrue([[[comment publishedDate] stringValue] isEqualToString:@\"2012-03-22T22:51:50+08:00\"], @\"published\");    \n      \n      GDataAtomAuthor *author = [comment theFirstAuthor];\n      STAssertTrue([[author URI] isEqualToString:@\"http://api.douban.com/people/1354395\"], @\"author uri\");\n      STAssertTrue([[author name] isEqualToString:@\"Kirsten\"], @\"author name\");\n    }\n    \n  }\n  \n  \n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanEventCategoryTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DoubanEntryEventCategory.h\"\n#import \"DoubanFeedEventCategory.h\"\n\n\n@interface DoubanEventCategoryTests : SenTestCase \n\n- (void)testDoubanFeedEventCategory;\n\n@end\n\n\n@implementation DoubanEventCategoryTests\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanFeedEventCategory {\n  \n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanFeedEventCategory\" \n                                                                        ofType:@\"xml\"];  \n  if (filePath) {\n    NSData *data = [NSData dataWithContentsOfFile:filePath];\n    DoubanFeedEventCategory *feed = [[DoubanFeedEventCategory alloc] initWithData:data];\n    NSLog(@\"feed title: %@\", [[feed title] stringValue]);\n    STAssertTrue([[[feed title] stringValue] isEqualToString:@\"北京的活动数目\"], @\"title\");\n    \n    NSArray *categories = [feed entries];\n    STAssertTrue([categories count] == 11, @\"category count\");\n    \n    for (DoubanEntryEventCategory *category in categories) {\n      if ([[[category title] stringValue] isEqualToString:@\"all\"]) {\n        STAssertTrue([category eventsCount] == 781, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"所有类型\"] , @\"eventCateogryName\");\n      }\n      \n      if ([[[category title] stringValue] isEqualToString:@\"drama\"]) {\n        STAssertTrue([category eventsCount] == 51, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"戏剧/曲艺\"] , @\"eventCateogryName\");\n       }\n      \n      if ([[[category title] stringValue] isEqualToString:@\"music\"]) {\n        STAssertTrue([category eventsCount] == 105, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"音乐/演出\"] , @\"eventCateogryName\");\n      }\n\n      if ([[[category title] stringValue] isEqualToString:@\"exhibition\"]) {\n        STAssertTrue([category eventsCount] == 100, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"展览\"] , @\"eventCateogryName\");\n      }\n\n      if ([[[category title] stringValue] isEqualToString:@\"sports\"]) {\n        STAssertTrue([category eventsCount] == 46, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"体育\"] , @\"eventCateogryName\");\n      }\n\n      if ([[[category title] stringValue] isEqualToString:@\"party\"]) {\n        STAssertTrue([category eventsCount] == 156, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"生活/聚会\"] , @\"eventCateogryName\");\n      }\n\n      if ([[[category title] stringValue] isEqualToString:@\"commonweal\"]) {\n        STAssertTrue([category eventsCount] == 56, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"公益\"] , @\"eventCateogryName\");\n      }\n      \n      if ([[[category title] stringValue] isEqualToString:@\"travel\"]) {\n        STAssertTrue([category eventsCount] == 28, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"旅行\"] , @\"eventCateogryName\");\n      }\n      \n      \n      if ([[[category title] stringValue] isEqualToString:@\"film\"]) {\n        STAssertTrue([category eventsCount] == 37, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"电影\"] , @\"eventCateogryName\");\n      }\n\n      if ([[[category title] stringValue] isEqualToString:@\"salon\"]) {\n        STAssertTrue([category eventsCount] == 132, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"讲座/沙龙\"] , @\"eventCateogryName\");\n      }\n      \n      if ([[[category title] stringValue] isEqualToString:@\"others\"]) {\n        STAssertTrue([category eventsCount] == 70, @\"eventsCount\");\n        STAssertTrue([[category name] isEqualToString:@\"其他\"] , @\"eventCateogryName\");\n      }\n      \n    }\n  }\n\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanEventTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUAPIEngine.h\"\n#import \"DoubanEntryEvent.h\"\n#import \"DoubanFeedEvent.h\"\n#import \"DoubanLocation.h\"\n#import \"DoubanAttribute.h\"\n#import \"GDataWhen.h\"\n#import \"GDataWhere.h\"\n\n@interface DoubanEventTests : SenTestCase \n\n- (void)testDoubanEntryEvent;\n\n- (void)testDoubanFeedEvent;\n\n@end\n\n\n@implementation DoubanEventTests\n\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanEntryEvent {\n\n  NSString *filePath = \n    [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanEntryEvent\" ofType:@\"xml\"];\n\n  if (filePath) {\n    \n    NSData *data = [NSData dataWithContentsOfFile:filePath];\n    \n    DoubanEntryEvent *event = [[DoubanEntryEvent alloc] initWithData:data]; \n    \n    NSArray *authors = [event authors];\n    STAssertNotNil(authors, @\"authors\");\n    STAssertTrue([[[authors objectAtIndex:0] name] isEqualToString:@\"小娟山谷里的居民\"], @\"\");\n    \n    STAssertTrue([[event identifier] isEqualToString:@\"http://api.douban.com/event/14792861\"], @\"latitude\");\n    STAssertTrue([[[event title] stringValue] isEqualToString:@\"山谷里，我的家/小娟山谷里的居民2011北京演唱会\"], @\"title\");\n    \n    STAssertTrue([[[[event when] startTime] stringValue] isEqualToString:@\"2011-12-18T19:30:00+08:00\"], @\"startTime\");\n    STAssertTrue([[[[event when] endTime] stringValue] isEqualToString:@\"2011-12-18T21:30:00+08:00\"], @\"endTime\");\n    STAssertTrue([[[event where] stringValue] isEqualToString:@\"北京 西城区 西直门/动物园 北京展览馆剧场\"], @\"where\");\n    STAssertTrue([event albumId] == 58416320, @\"album\");\n\n    STAssertTrue([event participantsCount] == 342, @\"participantsCount\");\n    STAssertTrue([event wishersCount] == 1118, @\"wishersCount\");\n    STAssertTrue([[[event location] identity] isEqualToString:@\"beijing\"], @\"location\");\n    STAssertTrue(fabs([event geoLatitude] - 39.904213 )< 0.000001, @\"latitude\");\n    STAssertTrue(fabs([event geoLongitude] - 116.40741) < 0.000001, @\"longitude\");  \n    \n\n    \n    GDataEntryBase *empty = [GDataEntryBase entry];\n    [empty addExtensionDeclarations];\n    [empty addExtensionDeclarationForParentClass:[empty class]\n                                   childClasses:[DoubanAttribute class],nil];\n    \n    \n    DoubanAttribute *attribute = [[[DoubanAttribute alloc] init] autorelease];\n    [attribute setName:@\"participate_date\"];\n    [attribute setContent:@\"2011-01-01\"];\n    \n    [empty addObject:attribute forExtensionClass: [DoubanAttribute class]];  \n    \n    NSData *theData = [[empty XMLDocument] XMLData];\n    NSString *string = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];\n    NSLog(@\"result: %@\", string);\n  }\n}\n\n\n- (void)testDoubanFeedEvent {\n  \n  NSString *filePath = \n          [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanFeedEvent\" ofType:@\"xml\"];  \n  if (filePath) {\n    NSData *data = [NSData dataWithContentsOfFile:filePath];\n    DoubanFeedEvent *feed = [[DoubanFeedEvent alloc] initWithData:data];\n    STAssertTrue([[[feed title] stringValue] isEqualToString:@\"胖胖的大头鱼的活动\"], @\"title\");\n    \n    NSArray *events = [feed entries];\n    STAssertTrue([events count] == 1, @\"events count\");\n    \n    DoubanEntryEvent *event = [events objectAtIndex:0];\n    STAssertTrue([[event identifier] isEqualToString:@\"http://api.douban.com/event/10297336\"], @\"latitude\");\n    STAssertTrue([[[event title] stringValue] isEqualToString:@\"Open Source Camp 北京 2008技术交流盛会\"], @\"title\");\n    \n    STAssertTrue([[[[event when] startTime] stringValue] isEqualToString:@\"2008-10-25T13:00:00+08:00\"], @\"startTime\");\n    STAssertTrue([[[[event when] endTime] stringValue] isEqualToString:@\"2008-10-25T19:00:00+08:00\"], @\"endTime\");\n    STAssertTrue([[[event where] stringValue] isEqualToString:@\"北京 海淀区蓝旗营路北 工商银行旁 Study 英语学 习吧（三角地）\"], @\"where\");\n    STAssertTrue([event albumId] == 0, @\"album\");\n    \n    \n    STAssertTrue([event participantsCount] == 13, @\"participantsCount\");\n    STAssertTrue([event wishersCount] == 22, @\"wishersCount\");\n    STAssertTrue([[[event location] identity] isEqualToString:@\"beijing\"], @\"location\");\n    STAssertTrue([event geoLatitude] == 0 , @\"latitude\");\n    STAssertTrue([event geoLongitude] == 0 , @\"longitude\");\n        \n    NSMutableArray *mutableEvents = [[NSMutableArray alloc] initWithArray:events];\n    [mutableEvents removeObject:event];\n    [feed setEntries:mutableEvents];\n    STAssertTrue([[feed entries] count] == 0 , @\"after remove\");\n  }\n  \n  \n  \n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanMiniblogTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"GDataBaseElements.h\"\n#import \"DoubanAttribute.h\"\n#import \"DOUAPIEngine.h\"\n#import \"DoubanEntryMiniblog.h\"\n#import \"DoubanFeedMiniblog.h\"\n#import \"DoubanDefines.h\"\n\n#import \"GDataAtomAuthor+Extension.h\"\n#import \"GDataLink.h\"\n#import \"GDataEntryBase.h\"\n#import \"GDataEntryBase+Extension.h\"\n\n\n@interface DoubanMiniblogTests : SenTestCase \n\n- (void)testDoubanEntryMiniblog;\n\n- (void)testDoubanFeedMiniblog;\n\n@end\n\n\n@implementation DoubanMiniblogTests\n\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanEntryMiniblog {\n\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanEntryMiniblog\" \n                                                                        ofType:@\"xml\"];  \n\n  if (!filePath)\n    STAssertTrue(FALSE, @\"filePath fail!\");\n    \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n\n  DoubanEntryMiniblog *miniblog= [[[DoubanEntryMiniblog alloc] initWithData:data] autorelease];\n  \n  GDataAtomAuthor *author = [miniblog theFirstAuthor];\n\n  STAssertTrue([[author name] isEqualToString:@\"挑灯看剑\"], @\"author name\");\n  \n  GDataLink *link = [author linkWithRelAttributeValue:@\"icon\"];\n  \n  NSURL *url = [link URL];\n  STAssertTrue([[url absoluteString] isEqualToString:@\"http://t.douban.com/icon/u1079441-7.jpg\"], @\"author icon\");\n  \n  STAssertTrue([[[miniblog title] stringValue] isEqualToString:@\"上传了一张照片到临时存放\"]  , @\"title\");\n  STAssertTrue([[miniblog identifier] isEqualToString:@\"http://api.douban.com/miniblog/12974354\"], @\"identifier\");\n  STAssertTrue([[[miniblog content] stringValue] length] >= 1 , @\"content\");\n  STAssertTrue([[[miniblog publishedDate] stringValue] isEqualToString:@\"2008-07-29T15:10:29+08:00\"], @\"published\");\n}\n\n\n- (void)testDoubanFeedMiniblog {\n  \n  NSString *filePath = \n          [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanFeedMiniblog\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n  DoubanFeedMiniblog *feed = [[DoubanFeedMiniblog alloc] initWithData:data];\n  STAssertNotNil(feed, @\"\" );\n  \n  for (GDataAtomAuthor *author in [feed authors]){\n    STAssertTrue([[author name] isEqualToString:@\"胖胖的大头鱼\"], @\"author\");\n  }\n  \n  \n  STAssertTrue([[[feed title] stringValue] isEqualToString:@\"胖胖的大头鱼 的友邻广播\"], @\"Feed title\");\n\n  for (DoubanEntryMiniblog *miniblog in feed) {\n    \n    if ([[miniblog identifier] isEqualToString:@\"http://api.douban.com/miniblog/12974400\"]) {\n      STAssertTrue([miniblog miniblogCategory] == MINIBLOG_BLOG_CATEGORY, @\"\");\n      STAssertTrue([[[miniblog title] stringValue] isEqualToString:@\"写了新blog文章第一批北京志愿者的工作情况\"]  , @\"title\");\n      STAssertTrue([[[miniblog content] stringValue] length] >= 1 , @\"content\");\n      STAssertTrue([[[miniblog publishedDate] stringValue] isEqualToString:@\"2008-07-31T11:57:47+08:00\"], @\"published\");    \n      \n      for (GDataAtomAuthor *author in [miniblog authors]){\n        STAssertTrue([[author name] isEqualToString:@\"Davies\"], @\"author\");\n      }\n    }\n    \n    if ([[miniblog identifier] isEqualToString:@\"http://api.douban.com/miniblog/12974395\"]) {\n      STAssertTrue([miniblog miniblogCategory] == MINIBLOG_GROUP_CATEGORY, @\"\");\n      STAssertTrue([[[miniblog title] stringValue] isEqualToString:@\"加入了岩井俊二小组\"]  , @\"title\");\n      STAssertTrue([[[miniblog content] stringValue] length] >= 1 , @\"content\");\n      STAssertTrue([[[miniblog publishedDate] stringValue] isEqualToString:@\"2008-07-30T21:45:35+08:00\"], @\"published\");    \n       \n\n      for (GDataAtomAuthor *author in [miniblog authors]){\n        STAssertTrue([[author name] isEqualToString:@\"挑灯看剑\"], @\"author\");\n      }\n    }\n  }\n  \n  \n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanPeopleTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n\n#import \"DoubanEntryPeople.h\"\n#import \"DoubanFeedPeople.h\"\n#import \"GDataBaseElements.h\"\n#import \"DoubanUID.h\"\n#import \"DoubanSignature.h\"\n#import \"DoubanLocation.h\"\n\n\n@interface DoubanPeopleTests : SenTestCase \n\n- (void)testDoubanEntryPeople;\n\n- (void)testDoubanFeedPeople;\n\n@end\n\n\n@implementation DoubanPeopleTests\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanEntryPeople {\n\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanEntryPeople\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"filePath fail!\");\n    \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n    \n  DoubanEntryPeople *people = [[DoubanEntryPeople alloc] initWithData:data]; \n\n  STAssertTrue([[people.location identity] isEqualToString:@\"beijing\"], @\"location\"); \n    \n  STAssertTrue([[people.location content] isEqualToString:@\"北京\"], @\"location\"); \n  STAssertTrue([[people.uid content] isEqualToString:@\"ahbei\"], @\"ahbei\");\n  \n  STAssertTrue([[people.signature content] isEqualToString:@\"风骚为人\"], @\"signature\");\n  \n  STAssertTrue([people.identifier isEqualToString:@\"http://api.douban.com/people/ahbei\"], @\"identifier\");\n  STAssertTrue([[people.title stringValue] isEqualToString:@\"阿北\"], @\"title\");\n  STAssertTrue([[people.content stringValue] length] > 0, @\"content\");\n  \n  NSString * imageUrlStr = [[people.iconLink URL] absoluteString]; \n  STAssertTrue([imageUrlStr isEqualToString:@\"http://www.douban.com/icon/u1000001.jpg\"], @\"imageLink\");   \n  NSString *homePageUrlStr = [[people.homePage URL] absoluteString];\n  STAssertTrue([homePageUrlStr isEqualToString:@\"http://ahbei.com/\"], @\"homePage\"); \n}\n\n\n- (void)testDoubanFeedPeople {\n  \n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanFeedPeople\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n  DoubanFeedPeople *feed = [[DoubanFeedPeople alloc] initWithData:data];\n    \n  STAssertTrue([[feed.title stringValue] isEqualToString:@\"搜索 douban 的结果\"], @\"feed title\");\n\n  for (DoubanEntryPeople *people in [feed entries]) {\n\n    if ([people.identifier isEqualToString:@\"http://api.douban.com/people/1000000\"]) {\n      STAssertTrue([[people.title stringValue] isEqualToString:@\"六零\"], @\"title\");\n      STAssertTrue([[people.uid content] isEqualToString:@\"douban\"] , @\"douban\");\n      STAssertTrue([people.identifier isEqualToString:@\"http://api.douban.com/people/1000000\"], @\"identifier\");  \n    }\n    \n    if ([people.identifier isEqualToString:@\"http://api.douban.com/people/1428797\"]) {\n      STAssertTrue([[people.title stringValue] isEqualToString:@\"yangjiani\"], @\"title\");\n      STAssertTrue([[people.uid content] isEqualToString:@\"www.douban.amy.\"] , @\"uid\");\n      STAssertTrue([people.identifier isEqualToString:@\"http://api.douban.com/people/1428797\"], @\"identifier\");  \n      STAssertTrue([[people.content stringValue] length] > 0, @\"content\");\n      \n      NSString * imageUrlStr = [[people.iconLink URL] absoluteString]; \n      STAssertTrue([imageUrlStr isEqualToString:@\"http://t.douban.com/icon/u1428797-1.jpg\"], @\"imageLink\");   \n      NSString *homePageUrlStr = [[people.homePage URL] absoluteString];\n      STAssertTrue([homePageUrlStr isEqualToString:@\"http://http://blog.sina.com.cn/yangjianiamy\"], @\"homePage\"); \n      \n    }\n\n    if ([people.identifier isEqualToString:@\"http://api.douban.com/people/1405403\"]) {\n      STAssertTrue([[people.title stringValue] isEqualToString:@\"douban\"], @\"title\");\n      STAssertTrue([[people.uid content] isEqualToString:@\"perfectlie\"] , @\"uid\");\n      STAssertTrue([people.identifier isEqualToString:@\"http://api.douban.com/people/1405403\"], @\"identifier\");  \n\n    }\n    \n  }\n\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanPhotoTests.m",
    "content": "//\n//  DoubanPhotoTests.m\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"GDataBaseElements.h\"\n\n#import \"DoubanEntryPhoto.h\"\n#import \"DoubanFeedPhoto.h\"\n\n\n@interface DoubanPhotoTests : SenTestCase \n\n- (void)testDoubanEntryPhoto;\n\n- (void)testDoubanFeedPhoto;\n\n@end\n\n\n@implementation DoubanPhotoTests\n\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanEntryPhoto {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanEntryPhoto\" \n                                                                        ofType:@\"xml\"];  \n  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"filePath fail!\");\n  \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n  DoubanEntryPhoto *photo =  [[DoubanEntryPhoto alloc] initWithData:data];\n  STAssertTrue([[photo.title stringValue] isEqualToString:@\"照片\"]  , @\"title\");\n  STAssertTrue([photo.identifier isEqualToString:@\"http://api.douban.com/photo/1259201045\"], @\"identifier\");\n  STAssertTrue([[photo.publishedDate stringValue] isEqualToString:@\"2011-10-17T11:55:31+08:00\"], @\"published\");\n  STAssertTrue([photo.author.name isEqualToString:@\"公路\"], @\"author\");\n\n  STAssertTrue(photo.commentsCount == 12, @\"comment count\");\n  STAssertTrue(photo.recsCount == 1, @\"recs count\");\n  STAssertTrue(photo.position == 20, @\"position\");\n\n  STAssertTrue(photo.nextPhotoId == 1259196350, @\"nextPhotoId\");  \n  STAssertTrue(photo.prevPhotoId == 1259193512, @\"prevPhotoId\");\n  STAssertTrue(photo.albumId == 58416320, @\"albumId\");\n  STAssertTrue([photo.albumTitle isEqualToString:@\"活动照片\"], @\"album Title\");  \n\n}\n\n\n- (void)testDoubanFeedPhoto {\n  \n}\n\n\n@end"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model/DoubanSubjectTests.m",
    "content": "//\n//  DOUAPIEngineTests.m\n//  DOUAPIEngineTests\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DoubanEntrySubject.h\"\n#import \"DoubanFeedSubject.h\"\n#import \"GDataBaseElements.h\"\n#import \"GDataRating.h\"\n#import \"DoubanAttribute.h\"\n#import \"DoubanTag.h\"\n\n\n@interface DoubanSubjectTests : SenTestCase \n\n- (void)testDoubanEntrySubject;\n\n- (void)testDoubanFeedSubject;\n\n@end\n\n\n@implementation DoubanSubjectTests\n\n\n- (void)setUp {\n  [super setUp];\n}\n\n\n- (void)tearDown {\n  [super tearDown];\n}\n\n\n- (void)testDoubanEntrySubject {\n\n  NSString *filePath = \n            [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanEntrySubject\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"filePath fail!\");\n    \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n    \n  DoubanEntrySubject *subject = [[DoubanEntrySubject alloc] initWithData:data]; \n  \n  STAssertTrue([[subject tags] count] == 5, @\"tags \");\n  \n  for (id tagObject in [subject tags]) {\n\n    DoubanTag *tag = (DoubanTag*)tagObject;\n    if ([[tag name] isEqualToString:@\"片山恭一\"])\n       STAssertTrue([[tag count] integerValue] == 15, @\"name\");\n\n    if ([[tag name] isEqualToString:@\"小说\"])\n      STAssertTrue([[tag count] integerValue]== 6, @\"name\");  \n    \n    if ([[tag name] isEqualToString:@\"日本小说\"])\n      STAssertTrue([[tag count] integerValue]== 5, @\"name\");  \n    \n    if ([[tag name] isEqualToString:@\"日本文学\"])\n      STAssertTrue([[tag count] integerValue]== 2, @\"name\");  \n\n    if ([[tag name] isEqualToString:@\"日本\"])\n      STAssertTrue([[tag count] integerValue]== 2, @\"name\"); \n  }\n  \n  STAssertTrue([[subject identifier] isEqualToString:@\"http://api.douban.com/book/subject/2023013\"], @\"identifier\");\n  STAssertTrue([[[subject title] stringValue] isEqualToString:@\"倘若我在彼岸-日本畅销爱情小说\"], @\"title\");\n  STAssertTrue([[[subject summary] stringValue] length] > 0, @\"summary\");\n\n  STAssertTrue([[subject authors] count] == 1, @\"authors\");\n  for (GDataAtomAuthor *author in [subject authors]){\n    STAssertTrue([[author name] isEqualToString:@\"片山恭一\"], @\"author\");\n  }\n    \n  for (DoubanAttribute* attribute in [subject attributes]) {\n    if ([[attribute name] isEqualToString:@\"isbn10\"]) {\n      STAssertTrue([[attribute content] isEqualToString:@\"7543639130\"], @\"attribute\");\n    }\n    if ([[attribute name] isEqualToString:@\"isbn13\"]) {\n      STAssertTrue([[attribute content] isEqualToString:@\"9787543639133\"], @\"attribute\");\n    }\n    if ([[attribute name] isEqualToString:@\"pages\"]) {\n      STAssertTrue([[attribute content] isEqualToString:@\"193\"], @\"attribute\");\n    }\n    if ([[attribute name] isEqualToString:@\"tranlator\"]) {\n      STAssertTrue([[attribute content] isEqualToString:@\"张兴\"], @\"attribute\");\n    }\n    if ([[attribute name] isEqualToString:@\"price\"]) {\n      STAssertTrue([[attribute content] isEqualToString:@\"14\"], @\"attribute\");\n    }\n    if ([[attribute name] isEqualToString:@\"author\"]) {\n      STAssertTrue([[attribute content] isEqualToString:@\"片山恭一\"], @\"attribute\");\n    }\n    if ([[attribute name] isEqualToString:@\"publisher\"]) {\n      STAssertTrue([[attribute content] isEqualToString:@\"青岛出版社\"], @\"attribute\");\n    }\n    if ([[attribute name] isEqualToString:@\"author-intro\"]) {\n      STAssertTrue([[attribute content] length] > 0, @\"authors-intro\");      \n    }\n  }\n\n  STAssertTrue([[subject.rating average] floatValue]== 4.00, @\"rating average\");\n  STAssertTrue([[subject.rating max] integerValue] == 5, @\"rating average\");\n  STAssertTrue([[subject.rating min] integerValue] == 1, @\"rating average\");\n  STAssertTrue([[subject.rating numberOfRaters] integerValue] == 12, @\"rating average\");\n}\n\n\n\n- (void)testDoubanFeedSubject {\n  \n  NSString *filePath = \n          [[NSBundle bundleForClass:[self class]] pathForResource:@\"DoubanFeedSubject\" ofType:@\"xml\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSData *data = [NSData dataWithContentsOfFile:filePath];\n  DoubanFeedSubject *feed = [[DoubanFeedSubject alloc] initWithData:data];\n    \n  STAssertTrue([[[feed title] stringValue] isEqualToString:@\"带有标签 cowboy 的条目\"], @\"feed title\");\n    \n  for (DoubanFeedSubject *subject in [feed entries]) {\n\n    \n    \n    if ([[subject identifier] isEqualToString:@\"http://api.douban.com/subject/subject/1424406\"]) {\n      STAssertTrue([[[subject title] stringValue] isEqualToString:@\"Cowboy Bebop\"], @\"title\");\n      \n      STAssertTrue([[subject authors] count] == 1, @\"authors\");\n      for (GDataAtomAuthor *author in [subject authors]){\n        STAssertTrue([[author name] isEqualToString:@\"渡边信一郎\"], @\"author\");\n      }\n      \n      for (DoubanAttribute* attribute in [subject attributes]) {\n        if ([[attribute name] isEqualToString:@\"site\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"http://www.cowboybebop.org/\"], @\"site\");\n        }\n        if ([[attribute name] isEqualToString:@\"year\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"1998\"], @\"year\");\n        }\n        if ([[attribute name] isEqualToString:@\"language\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"日语\"], @\"language\");\n        }\n        if ([[attribute name] isEqualToString:@\"imdb\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"http://www.imdb.com/title/tt0213338/\"], @\"imdb\");\n        }\n        if ([[attribute name] isEqualToString:@\"country\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"Japan\"], @\"imdb\");\n        }\n        \n      }\n    }\n    \n    \n    if ([[subject identifier] isEqualToString:@\"http://api.douban.com/subject/subject/1307031\"]) {\n      STAssertTrue([[[subject title] stringValue] isEqualToString:@\"Cowboy Bebop: Knockin' on Heaven's Door\"], @\"title\");\n      \n      STAssertTrue([[subject authors] count] == 1, @\"authors\");\n      for (GDataAtomAuthor *author in [subject authors]){\n        STAssertTrue([[author name] isEqualToString:@\"渡边信一郎 (Shinichirô Watanabe)\"], @\"author\");\n      }\n      \n      for (DoubanAttribute* attribute in [subject attributes]) {\n        if ([[attribute name] isEqualToString:@\"site\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"http://www.sonypictures.com/cthe/cowboybebop/\"], @\"site\");\n        }\n        if ([[attribute name] isEqualToString:@\"year\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"2001\"], @\"year\");\n        }\n        if ([[attribute name] isEqualToString:@\"language\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"Japanese\"], @\"language\");\n        }\n        if ([[attribute name] isEqualToString:@\"imdb\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"http://www.imdb.com/title/tt0275277/\"], @\"imdb\");\n        }\n        if ([[attribute name] isEqualToString:@\"country\"]) {\n          STAssertTrue([[attribute content] isEqualToString:@\"Japan\"], @\"imdb\");\n        }\n        \n      }\n    }\n\n  }\n\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model2/DOUBookTests.m",
    "content": "//\n//  DOUCommentTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUBook.h\"\n#import \"DOUBookArray.h\"\n#import \"DOUObject+Utils.h\"\n\n@interface DOUBookTests : SenTestCase\n\n@end\n\n\n@implementation DOUBookTests\n\n- (void)testBookArray {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"BookArray\" ofType:@\"json\"];\n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUBookArray *books = [[DOUBookArray alloc] initWithString:string];\n  \n  STAssertTrue(books.count == 20, @\"count\");\n  STAssertTrue(books.start == 0, @\"start\");\n  STAssertTrue(books.total  == 3, @\"total\");\n  STAssertTrue([books.objectArray count]  == 3, @\"objectArray\");\n  \n  for (DOUBook *book in books.objectArray) {\n    \n    if ([book.identifier isEqualToString:@\"10757942\"]) {\n      STAssertTrue([book.title isEqualToString:@\"怨女\"], @\"title\");\n      STAssertTrue([book.subTitle isEqualToString:@\"张爱玲全集03——小说\"], @\"subtitle\");\n      STAssertTrue([book.ISBN10 isEqualToString:@\"7530211188\"], @\"isbn10\");\n      STAssertTrue([book.ISBN13 isEqualToString:@\"9787530211182\"], @\"isbn13\");\n      STAssertTrue([book.publishDateStr isEqualToString:@\"2012-6\"], @\"publishdata\");\n      STAssertTrue([book.publishDate isEqualToDate: [[book class] dateOfString:@\"2012-6\" dateFormat:@\"yyyy-MM\"]], @\"pubdate\");\n    }\n  }\n  \n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model2/DOUCommentTests.m",
    "content": "//\n//  DOUCommentTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUComment.h\"\n#import \"DOUCommentArray.h\"\n\n\n@interface DOUCommentTests : SenTestCase\n\n@end\n\n\n@implementation DOUCommentTests\n\n- (void)testCommentArray {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"CommentArray\" ofType:@\"json\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUCommentArray *comments = [[DOUCommentArray alloc] initWithString:string];\n  \n  STAssertTrue(comments.count == 20, @\"count\");\n  STAssertTrue(comments.start == 0, @\"start\");\n  STAssertTrue(comments.total  == 2, @\"total\");\n  STAssertTrue([comments.objectArray count]  == 2, @\"objectArray\");\n  \n  for (DOUComment *comment in comments.objectArray) {\n    if ([comment.identifier isEqualToString:@\"104802214\"]) {\n      STAssertTrue([comment.content isEqualToString:@\"童年呀\"], @\"content\"); \n    }\n    \n    if ([comment.identifier isEqualToString:@\"104802291\"]) {\n      STAssertTrue([comment.content isEqualToString:@\"停产了 我最爱的蜜汁猪排\"], @\"content\"); \n    }\n\n  }\n  \n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model2/DOUMovieTests.m",
    "content": "//\n//  DOUCommentTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUMovie.h\"\n#import \"DOUMovieArray.h\"\n#import \"DOUObject+Utils.h\"\n\n@interface DOUMovieTests : SenTestCase\n\n@end\n\n\n@implementation DOUMovieTests\n\n- (void)testMovieArray {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"MovieArray\" ofType:@\"json\"];\n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUMovieArray *movies = [[DOUMovieArray alloc] initWithString:string];\n  \n  STAssertTrue(movies.count == 20, @\"count\");\n  STAssertTrue(movies.start == 0, @\"start\");\n  STAssertTrue(movies.total  == 1, @\"total\");\n  STAssertTrue([movies.objectArray count]  == 1, @\"objectArray\");\n  \n  for (DOUMovie *movie in movies.objectArray) {\n    if ([movie.identifier isEqualToString:@\"20280228\"]) {\n      STAssertTrue([movie.title isEqualToString:@\"我们可以结婚吗\"], @\"title\");\n      STAssertTrue([movie.originalTitle isEqualToString:@\"우리가 결혼할 수 있을까\"], @\"title\");\n      STAssertTrue([movie.rating isEqualToString:@\"8.4\"], @\"rating\");\n      STAssertTrue([movie.stars isEqualToString:@\"45\"], @\"stars\");\n      STAssertTrue([movie.publishTimeStr isEqualToString:@\"2012-10-29\"], @\"publishdata\");\n      NSLog(@\"*****%@\", movie.publishTime);\n      STAssertTrue([movie.publishTime isEqualToDate: [[movie class] dateOfString:@\"2012-10-29\" dateFormat:@\"yyyy-MM-dd\"]], @\"publishdata\");\n      STAssertTrue(movie.wishCount == 400, @\"wish\");\n      STAssertTrue(movie.collectionCount == 117, @\"collection\");\n    }\n  }\n  \n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model2/DOUMusicTests.m",
    "content": "//\n//  DOUCommentTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUMusic.h\"\n#import \"DOUMusicArray.h\"\n#import \"DOUObject+Utils.h\"\n\n@interface DOUMusicTests : SenTestCase\n\n@end\n\n\n@implementation DOUMusicTests\n\n- (void)testMusicArray {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"MusicArray\" ofType:@\"json\"];\n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUMusicArray *musics = [[DOUMusicArray alloc] initWithString:string];\n  STAssertTrue(musics.count == 1, @\"count\");\n  STAssertTrue(musics.start == 0, @\"start\");\n  STAssertTrue(musics.total  == 1, @\"total\");\n  STAssertTrue([musics.objectArray count]  == 1, @\"objectArray\");\n  \n  for (DOUMusic *music in musics.objectArray) {\n    if ([music.identifier isEqualToString:@\"20275660\"]) {\n      STAssertTrue([music.title isEqualToString:@\"花又開好了 (生命的美好平裝發行版)\"], @\"title\");\n      STAssertTrue([music.rating isEqualToString:@\"7.4\"], @\"rating\");\n      STAssertTrue([music.publisher isEqualToString:@\"華研唱片\"], @\"publisher\");\n      STAssertTrue([music.publishDateStr isEqualToString:@\"2012-11-16\"], @\"pubdata\");\n      STAssertTrue([music.publishDate isEqualToDate: [[music class] dateOfString:@\"2012-11-16\" dateFormat:@\"yyyy-MM-dd\"]], @\"pubdata\");\n\n    }\n  }\n  \n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model2/DOUNoteTests.m",
    "content": "//\n//  DOUCommentTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUNote.h\"\n\n\n@interface DOUNoteTests : SenTestCase\n\n@end\n\n\n@implementation DOUNoteTests\n\n- (void)testNote {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"Note\"\n                                                                        ofType:@\"json\"];\n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath\n                                               encoding:NSUTF8StringEncoding error:nil];\n  DOUNote *note = [[DOUNote alloc] initWithString:string];\n  STAssertTrue(note.recsCount == 10, @\"resCount\");\n  STAssertTrue(note.commentsCount == 3, @\"commentsCount\");\n  STAssertTrue(note.likedCount  == 17, @\"likeCound\");\n  STAssertTrue([note.privacy isEqualToString:@\"public\"], @\"privacy\");\n  STAssertTrue([note.title isEqualToString:@\"冯象译经源流考（停止更新）\"], @\"title\");\n  STAssertTrue([note.identifier isEqualToString:@\"244600047\"], @\"identifier\");\n  STAssertTrue([note.alt isEqualToString:@\"http://www.douban.com/note/244600047/\"], @\"alt\");\n  STAssertTrue([note.summary isEqualToString:@\"目前豆瓣已经有了关于冯译的相关小站，站长在把《源流考》的旧文搬进去。加之近来...\"], @\"summary\");\n\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model2/DOUOnlineTests.m",
    "content": "//\n//  DOUOnlineTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUOnline.h\"\n#import \"DOUOnlineArray.h\"\n#import \"DOUUser.h\"\n\n\n@interface DOUOnlineTests : SenTestCase\n\n@end\n\n\n@implementation DOUOnlineTests\n\n- (void)testOnline {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"Online\" ofType:@\"json\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUOnline *online = [[DOUOnline alloc] initWithString:string];\n  STAssertTrue([online.identifier isEqualToString:@\"11038343\"], @\"identifier\");\n  STAssertTrue([online.alt isEqualToString:@\"http://www.douban.com/online/11038343/\"], @\"alt\");\n  STAssertNotNil(online.desc, @\"desc\");\n  STAssertTrue([online.title isEqualToString:@\"新的截图猜电影，来！\"], @\"title\");\n  STAssertTrue([online.createTimeStr isEqualToString:@\"2012-02-24 11:49:32\"], @\"createTime\");\n  STAssertTrue([online.beginTimeStr isEqualToString:@\"2012-02-24 11:00:00\"], @\"beginTime\");\n  STAssertTrue([online.endTimeStr isEqualToString:@\"2012-05-23 11:00:00\"], @\"endTime\");\n\n  STAssertTrue([online.relatedUrl isEqualToString:@\"http://www.douban.com/online/10999361/\"], @\"relatedUrl\");\n  STAssertTrue([online.topic isEqualToString:@\"新的截图猜电影，来！\"], @\"topic\");\n  STAssertTrue(online.cascadeInvite, @\"cascadeInvite\");\n  STAssertTrue([online.groupId isEqualToString:@\"0\"], @\"groupId\");\n  STAssertTrue([online.albumId isEqualToString:@\"65606728\"], @\"albumId\");\n  \n  STAssertTrue(online.participantCount == 13939, @\"participantCount\");\n  STAssertTrue(online.photoCount == 63562, @\"photoCount\");\n  STAssertTrue(online.likedCount == 2134, @\"likedCount\");\n  STAssertTrue(online.recsCount == 417, @\"recsCount\");\n\n  STAssertTrue([online.icon isEqualToString:@\"http://img1.douban.com/bpic/o590273.jpg\"], @\"icon\");\n  STAssertTrue([online.thumb isEqualToString:@\"http://img1.douban.com/spic/o590273.jpg\"], @\"thumb\");\n  STAssertTrue([online.cover isEqualToString:@\"http://img1.douban.com/tpic/o590273.jpg\"], @\"cover\");\n  STAssertTrue([online.image isEqualToString:@\"http://img1.douban.com/lpic/o590273.jpg\"], @\"image\");\n\n  STAssertNotNil(online.owner, @\"owner\");\n  \n  STAssertTrue([online.owner.identifier isEqualToString:@\"3121692\"], @\"owner identifier\");\n  STAssertTrue([online.owner.avatar isEqualToString:@\"http://img3.douban.com/icon/u3121692-33.jpg\"], @\"owner avatar\");\n  STAssertTrue([online.owner.alt isEqualToString:@\"http://www.douban.com/people/linghowl/\"], @\"owner alt\");\n  STAssertTrue([online.owner.name isEqualToString:@\"浩叔出没东莫村\"], @\"owner name\");\n  STAssertTrue([online.owner.uid isEqualToString:@\"linghowl\"], @\"owner uid\");\n\n  STAssertTrue(online.participated == FALSE, @\"joined\");\n  STAssertTrue(online.liked == FALSE, @\"liked\");\n}\n\n\n- (void)testOnlineArray {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"OnlineArray\" ofType:@\"json\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUOnlineArray *onlines = [[DOUOnlineArray alloc] initWithString:string];\n\n  STAssertTrue(onlines.count == 3, @\"count\");\n  STAssertTrue(onlines.start == 0, @\"start\");\n  STAssertTrue(onlines.total  == 270, @\"total\");\n  STAssertTrue([onlines.objectArray count]  == 3, @\"objectArray\");\n\n  for (DOUOnline *online in onlines.objectArray) {\n    if ([online.identifier isEqualToString:@\"11038343\"]) {\n      STAssertTrue([online.alt isEqualToString:@\"http://www.douban.com/online/11038343/\"], @\"alt\"); \n    }\n    \n    if ([online.identifier isEqualToString:@\"11063385\"]) {\n      STAssertTrue([online.alt isEqualToString:@\"http://www.douban.com/online/11063385/\"], @\"alt\"); \n    }\n\n    if ([online.identifier isEqualToString:@\"11063653\"]) {\n      STAssertTrue([online.alt isEqualToString:@\"http://www.douban.com/online/11063653/\"], @\"alt\"); \n    }\n  }\n  \n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Model2/DOUPhotoTests.m",
    "content": "//\n//  DOUPhotoTests.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <SenTestingKit/SenTestingKit.h>\n#import \"DOUPhoto.h\"\n#import \"DOUPhotoArray.h\"\n#import \"DOUAlbum.h\"\n#import \"DOUUser.h\"\n\n\n@interface DOUPhotoTests : SenTestCase\n\n@end\n\n\n@implementation DOUPhotoTests\n\n- (void)testOnline {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"Photo\" ofType:@\"json\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUPhoto *photo = [[DOUPhoto alloc] initWithString:string];\n  STAssertTrue([photo.identifier isEqualToString:@\"1328238583\"], @\"identifier\");\n  STAssertTrue([photo.alt isEqualToString:@\"http://www.douban.com/photos/photo/1328238583/\"], @\"alt\");\n  STAssertNotNil(photo.desc, @\"desc\");\n\n  STAssertTrue([photo.albumId isEqualToString:@\"61434971\"], @\"albumId\");\n  \n  STAssertTrue(photo.likedCount == 120, @\"likedCount\");\n  STAssertTrue(photo.recsCount == 20, @\"recsCount\");\n  STAssertTrue(photo.commentsCount == 10, @\"commentsCount\");\n\n  \n  STAssertTrue([photo.icon isEqualToString:@\"http://img1.douban.com/view/photo/icon/public/p1328238583.jpg\"], @\"icon\");\n  STAssertTrue([photo.thumb isEqualToString:@\"http://img1.douban.com/view/photo/thumb/public/p1328238583.jpg\"], @\"thumb\");\n  STAssertTrue([photo.cover isEqualToString:@\"http://img1.douban.com/view/photo/cover/public/p1328238583.jpg\"], @\"cover\");\n  STAssertTrue([photo.image isEqualToString:@\"http://img1.douban.com/view/photo/image/public/p1328238583.jpg\"], @\"image\");\n  \n  STAssertNotNil(photo.author, @\"author\");\n  \n  STAssertTrue([photo.author.identifier isEqualToString:@\"1645921\"], @\"author identifier\");\n  STAssertTrue([photo.author.avatar isEqualToString:@\"http://img3.douban.com/icon/u1645921-14.jpg\"], @\"author avatar\");\n  STAssertTrue([photo.author.alt isEqualToString:@\"http://www.douban.com/people/bear/\"], @\"author alt\");\n  STAssertTrue([photo.author.name isEqualToString:@\"Bear\"], @\"author name\");\n  STAssertTrue([photo.author.uid isEqualToString:@\"bear\"], @\"author uid\");\n  \n  STAssertTrue(photo.liked == FALSE, @\"liked\");\n}\n\n\n- (void)testOnlineArray {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"PhotoArray\" ofType:@\"json\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUPhotoArray *photos = [[DOUPhotoArray alloc] initWithString:string];\n  \n  STAssertTrue(photos.count == 3, @\"count\");\n  STAssertTrue(photos.start == 0, @\"start\");\n  STAssertTrue(photos.total  == 17, @\"total\");\n  STAssertTrue([photos.sortBy isEqualToString:@\"time\"], @\"sortby\");\n  STAssertTrue([photos.order isEqualToString:@\"asc\"], @\"order\");\n\n  STAssertTrue([photos.objectArray count]  == 3, @\"objectArray\");\n  \n  for (DOUPhoto *photo in photos.objectArray) {\n    if ([photo.identifier isEqualToString:@\"1328238489\"]) {\n      STAssertTrue([photo.alt isEqualToString:@\"http://www.douban.com/photos/photo/1328238489/\"], @\"alt\"); \n    }\n    \n    if ([photo.identifier isEqualToString:@\"1328238583\"]) {\n      STAssertTrue([photo.alt isEqualToString:@\"http://www.douban.com/photos/photo/1328238583/\"], @\"alt\"); \n    }\n    \n    if ([photo.identifier isEqualToString:@\"1328238698\"]) {\n      STAssertTrue([photo.alt isEqualToString:@\"http://www.douban.com/photos/photo/1328238698/\"], @\"alt\"); \n    }\n  }\n  \n}\n\n\n- (void)testAlbum {\n  NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@\"Album\" ofType:@\"json\"];  \n  if (!filePath)\n    STAssertTrue(FALSE, @\"path fail\");\n  \n  NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n  DOUAlbum *album = [[DOUAlbum alloc] initWithString:string];\n  STAssertTrue([album.identifier isEqualToString:@\"61434971\"], @\"identifier\");\n  STAssertTrue([album.title isEqualToString:@\"罗马 - 古堡酒店\"], @\"title\");\n\n  STAssertTrue([album.alt isEqualToString:@\"http://www.douban.com/photos/album/61434971/\"], @\"alt\");\n  STAssertNotNil(album.desc, @\"desc\");\n    \n  STAssertTrue(album.likedCount == 120, @\"likedCount\");\n  STAssertTrue(album.recsCount == 20, @\"recsCount\");\n  STAssertTrue(album.size == 17, @\"size\");\n  \n  STAssertTrue([album.icon isEqualToString:@\"http://img3.douban.com/view/photo/icon/public/p1328238698.jpg\"], @\"icon\");\n  STAssertTrue([album.thumb isEqualToString:@\"http://img3.douban.com/view/photo/thumb/public/p1328238698.jpg\"], @\"thumb\");\n  STAssertTrue([album.cover isEqualToString:@\"http://img3.douban.com/view/photo/cover/public/p1328238698.jpg\"], @\"cover\");\n  STAssertTrue([album.image isEqualToString:@\"http://img3.douban.com/view/photo/image/public/p1328238698.jpg\"], @\"image\");\n  \n  STAssertNotNil(album.author, @\"author\");\n  \n  STAssertTrue([album.author.identifier isEqualToString:@\"1645921\"], @\"author identifier\");\n  STAssertTrue([album.author.avatar isEqualToString:@\"http://img3.douban.com/icon/u1645921-14.jpg\"], @\"author avatar\");\n  STAssertTrue([album.author.alt isEqualToString:@\"http://www.douban.com/people/bear/\"], @\"author alt\");\n  STAssertTrue([album.author.name isEqualToString:@\"Bear\"], @\"author name\");\n  STAssertTrue([album.author.uid isEqualToString:@\"bear\"], @\"author uid\");\n  \n  STAssertTrue(album.liked == FALSE, @\"liked\");\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanEntryCity.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <id>http://api.douban.com/location/shanghai</id>\n  <title>上海</title>\n  <link href=\"http://api.douban.com/location/shanghai\" rel=\"self\"/>\n  <link href=\"http://www.douban.com/location/shanghai\" rel=\"alternate\"/>\n  <db:attribute name=\"name\">上海</db:attribute>\n  <db:attribute name=\"name_cn\">上海</db:attribute>\n  <db:attribute name=\"habitable\">True</db:attribute>\n  <db:attribute name=\"parent\">china</db:attribute>\n  <db:uid>shanghai</db:uid>\n</entry>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanEntryEvent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <id>http://api.douban.com/event/14792861</id>\n  <title>山谷里，我的家/小娟山谷里的居民2011北京演唱会</title>\n    <category scheme=\"http://www.douban.com/2007#kind\" term=\"http://www.douban.com/2007#event.music\"/>\n    <author>\n    <link href=\"http://site.douban.com/greenflower\" rel=\"alternate\"/>\n    <link href=\"http://api.douban.com/site/greenflower\" rel=\"self\"/>\n    <link href=\"http://img3.douban.com/view/site/small/public/6e324998d0ccfbd.jpg\" rel=\"icon\"/>\n    <name>小娟山谷里的居民</name>\n    <uri>http://api.douban.com/site/greenflower</uri>\n    </author>\n    <link href=\"http://api.douban.com/event/14792861\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/event/14792861/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/mpic/e538089.jpg\" rel=\"image\"/>\n    <summary>\n    当城市的边界消失 还有 山谷 风 心中的歌 “山谷里，我的家”，「小娟山谷里的居民」乐队2011年度北京唯一的一场演唱会，12月18日，相约北展剧场，打开山谷里的家。 山谷是一种生活的态度，也是生活的感恩。当城市的边界消失，沧海桑田，山谷里的居民始终拥有自己的清澈，让歌唱成为简单快乐的自由。 围绕“山谷”和“家”，山谷里的...\n    </summary>\n    <content>\n    当城市的边界消失 还有 山谷 风 心中的歌 “山谷里，我的家”，「小娟山谷里的居民」乐队2011年度北京唯一的一场演唱会，12月18日，相约北展剧场，打开山谷里的家。 山谷是一种生活的态度，也是生活的感恩。当城市的边界消失，沧海桑田，山谷里的居民始终拥有自己的清澈，让歌唱成为简单快乐的自由。 围绕“山谷”和“家”，山谷里的居民为这场演唱会特别设计曲目和编曲，划分六个重要单元：山谷序曲、冬季的城市、秋日的童话、夏夜的晚风、春天的约会、家的恋曲。独立延续的段落，季节更迭变换，亲密无间的友爱和对音乐的执着相信从不会改变。再次携手“台北到淡水”巡回演唱会的特邀乐手，为好久不见的朋友带来更加精致、亲切的现场感，乐队即将出版的新专辑《C大调的城》部分曲目亦将首次现场呈现。 那些想做而没做到的事，那些想唱而没能唱的歌，那些渐行渐远的梦想，若仍可以在某一天开花结果，来山谷里的家，听我们的四季，唱自由的歌。 【演出名称】 山谷里，我的家 /小娟山谷里的居民2011北京演唱会 【演出场地】 北京展览馆剧场 【演出时间】 2011年12月18日19：30 【票 价】 180/280/380/580/680/VIP/1000套票（580×2） 【演出阵容】 小娟/主唱木吉他铃鼓、黎强/木吉他竹笛Mandolin、刘晓光/长笛口琴钢琴萨克斯、荒井壮一郞/打击乐架子鼓、大中（特邀乐手）/木贝司低音大提琴 【制 作】小娟山谷里的居民 【售票热线】400-899-8989 400-896-6868 【订票网站】票务中国www.piaocn.com 首都票务网www.piao88.com\n    </content>\n    <db:attribute name=\"invite_only\">no</db:attribute>\n    <db:attribute name=\"can_invite\">no</db:attribute>\n    <db:attribute name=\"participants\">342</db:attribute>\n    <db:attribute name=\"wishers\">1118</db:attribute>\n    <db:attribute name=\"album\">58416320</db:attribute>\n    <db:location id=\"beijing\">北京</db:location>\n    <gd:when endTime=\"2011-12-18T21:30:00+08:00\" startTime=\"2011-12-18T19:30:00+08:00\"/>\n    <gd:where valueString=\"北京 西城区 西直门/动物园 北京展览馆剧场\"/>\n    <georss:point>39.904213 116.40741</georss:point>\n    </entry>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanEntryMiniblog.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entry>\n  <id>http://api.douban.com/miniblog/12974354</id>\n  <title>上传了一张照片到临时存放</title>\n  <author>\n    <link href=\"http://api.douban.com/people/1079441\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/flycondor/\" rel=\"alternate\"/>\n    <link href=\"http://t.douban.com/icon/u1079441-7.jpg\" rel=\"icon\"/>\n    <name>挑灯看剑</name>\n    <uri>http://api.douban.com/people/1079441</uri>\n  </author>\n  <category scheme=\"http://www.douban.com/2007#kind\" term=\"http://www.douban.com/2007#miniblog.photo\"/>\n  <published>2008-07-29T15:10:29+08:00</published>\n  <content type=\"html\"><![CDATA[上传了一张<a href=\"http://www.douban.com/photos/photo/17300/\">照片</a>到<a href=\"http://www.douban.com/photos/album/10002472/\">临时存放</a>]]></content>\n</entry>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanEntryPeople.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entry xmlns=\"http://www.w3.org/2005/Atom\"\n  xmlns:gd=\"http://schemas.google.com/g/2005\"\n  xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\"\n  xmlns:db=\"http://www.douban.com/xmlns/\">\n  <db:location id=\"beijing\">北京</db:location>\n  <db:signature>风骚为人</db:signature>\n  <db:uid>ahbei</db:uid>\n  <title>阿北</title>\n  <content>\n    豆瓣的临时总管。现在多数时间在忙忙碌碌地为豆瓣添砖加瓦。坐在马桶上看书，算是一天中最放松的时间。\n    \n    \n    我不但喜欢读书、旅行和音乐电影，还曾经是一个乐此不疲的实践者，有一墙碟、两墙书、三大洲的车船票为记。现在自己游荡差不多够了，开始懂得分享和回馈。豆瓣是一个开始，希望它对你同样有用。\n  </content>\n  <link rel=\"self\" href=\"http://api.douban.com/people/ahbei\" />\n  <link rel=\"alternate\" href=\"http://www.douban.com/people/ahbei/\" />\n  <link rel=\"icon\" href=\"http://www.douban.com/icon/u1000001.jpg\" />\n  \n  <link rel=\"homepage\" href=\"http://ahbei.com/\" />\n  <id>http://api.douban.com/people/ahbei</id>\n</entry>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanEntryPhoto.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <id>http://api.douban.com/photo/1259201045</id>\n  <title>照片</title>\n  <author>\n    <link href=\"http://api.douban.com/people/3220815\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/highway61/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/icon/u3220815-2.jpg\" rel=\"icon\"/>\n    <name>公路</name>\n    <uri>http://api.douban.com/people/3220815</uri>\n  </author>\n  <published>2011-10-17T11:55:31+08:00</published>\n  <link href=\"http://api.douban.com/photo/1259201045\" rel=\"self\"/>\n  <link href=\"http://www.douban.com/event/photo/1259201045/\" rel=\"alternate\"/>\n  <link href=\"http://img3.douban.com/view/photo/icon/public/p1259201045.jpg\" rel=\"icon\"/>\n  <link href=\"http://img3.douban.com/view/photo/photo/public/p1259201045.jpg\" rel=\"image\"/>\n  <link href=\"http://img3.douban.com/view/photo/thumb/public/p1259201045.jpg\" rel=\"thumb\"/>\n  <link href=\"http://img3.douban.com/view/photo/albumcover/public/p1259201045.jpg\" rel=\"cover\"/>\n  <link href=\"http://m.douban.com/photos/photo/1259201045/\" rel=\"mobile\"/>\n  <content/>\n  <db:attribute name=\"comments_count\">12</db:attribute>\n  <db:attribute name=\"recs_count\">1</db:attribute>\n  <db:attribute name=\"position\">20</db:attribute>\n  <db:attribute name=\"next_photo\">1259196350</db:attribute>\n  <db:attribute name=\"prev_photo\">1259193512</db:attribute>\n  <db:attribute name=\"album\">58416320</db:attribute>\n  <db:attribute name=\"album_title\">活动照片</db:attribute>\n</entry>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanEntryRecommendation.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <id>http://api.douban.com/recommendation/3673470</id>\n  <title>推荐喵喵喵</title>\n  <published>2008-11-07T08:28:40+08:00</published>\n  <content type=\"html\"><![CDATA[推荐<a href=\"http://www.douban.com/photos/album/12573993/\">喵喵喵</a>]]></content>\n  <db:attribute name=\"category\">photo_album</db:attribute>\n  <db:attribute name=\"comment\">团子，我家团子，以前觉得她小时候很丑，现在觉得一 点也不丑啊～哇哈哈哈</db:attribute>\n  <db:attribute name=\"comments_count\">6</db:attribute>\n</entry>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanEntrySubject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entry xmlns=\"http://www.w3.org/2005/Atom\"\n  xmlns:gd=\"http://schemas.google.com/g/2005\"\n  xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\"\n  xmlns:db=\"http://www.douban.com/xmlns/\">\n  <category scheme=\"http://www.douban.com/2007#kind\"\n  term=\"http://www.douban.com/2007#book\" />\n  <db:tag count=\"15\" name=\"片山恭一\" />\n  <db:tag count=\"6\" name=\"小说\" />\n  <db:tag count=\"5\" name=\"日本小说\" />\n  <db:tag count=\"2\" name=\"日本文学\" />\n  <db:tag count=\"2\" name=\"日本\" />\n  <title>倘若我在彼岸-日本畅销爱情小说</title>\n  <author>\n    <name>片山恭一</name>\n  </author>\n  <summary>\n    本书由三个看似独立实则相通的凄美的爱情故事组成。主人公是老师，都喜欢某种运动，他们都曾亲身经历过或目睹过接近死神的一瞬间并从中感悟或懂得了生命中的某些东西。\n    这是作者在《在世界中心呼唤爱》后的首部爱情小说集。片山恭一，学生时代通读了包括夏目漱石和大江健三郎在内的日本近现代文学全集，同时读了从笛卡尔、莱布尼茨到结构主义的欧洲近现代哲学，也读了马克思。自二十二三岁开始创作小说，《气息》、《世界在你不知道的地方运转》、《别相信约翰·列侬》等均为他的代表作。\n  </summary>\n  <link rel=\"self\" href=\"http://api.douban.com/book/subject/2023013\" />\n  <link rel=\"collection\" href=\"http://api.douban.com/collection/1234567\" /><!-- API认证授权后才包含 -->\n  <link rel=\"alternate\" href=\"http://book.douban.com/subject/2023013/\" />\n  <link rel=\"image\" href=\"http://t.douban.com/spic/s2328836.jpg\" />\n  <db:attribute name=\"isbn10\">7543639130</db:attribute>\n  <db:attribute name=\"isbn13\">9787543639133</db:attribute>\n  <db:attribute name=\"pages\">193</db:attribute>\n  <db:attribute name=\"tranlator\">张兴</db:attribute>\n  <db:attribute name=\"price\">14</db:attribute>\n  <db:attribute name=\"author\">片山恭一</db:attribute>\n  <db:attribute name=\"publisher\">青岛出版社</db:attribute>\n  <db:attribute name=\"binding\">平装</db:attribute>\n  <db:attribute name=\"author-intro\">\n    片山恭一，1959年生于日本爱媛县，九州大学农学系农业经济学专业毕业。学生时代通读了包括夏目漱石和大江健三郎在内的日本近现代文学全集，同时读了从笛卡尔、莱布尼茨到结构主义的欧洲近现代哲学。也读了马克思。学士论文写的是马克思，硕士论文写的是恩格斯。二十二三岁开始创作小说。代表作有《在世界中心呼唤爱》、《世界在你不知道的地方运转》、《满月之夜白鲸现》、《空镜头》以及新作《倘若我在彼岸》《雨天的海豚们》、《最后盛开的花》等。\n  </db:attribute>\n  <id>http://api.douban.com/book/subject/2023013</id>\n  <gd:rating min=\"1\" numRaters=\"12\" average=\"4.00\" max=\"5\" />\n</entry>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedCity.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <title>活动热门城市</title>\n  <entry>\n    <id>http://api.douban.com/location/beijing</id>\n    <db:attribute name=\"name\">北京</db:attribute>\n    <db:uid>beijing</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/shanghai</id>\n    <db:attribute name=\"name\">上海</db:attribute>\n    <db:uid>shanghai</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/guangzhou</id>\n    <db:attribute name=\"name\">广州</db:attribute>\n    <db:uid>guangzhou</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/wuhan</id>\n    <db:attribute name=\"name\">武汉</db:attribute>\n    <db:uid>wuhan</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/chengdu</id>\n    <db:attribute name=\"name\">成都</db:attribute>\n    <db:uid>chengdu</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/shenzhen</id>\n    <db:attribute name=\"name\">深圳</db:attribute>\n    <db:uid>shenzhen</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/hangzhou</id>\n    <db:attribute name=\"name\">杭州</db:attribute>\n    <db:uid>hangzhou</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/xian</id>\n    <db:attribute name=\"name\">西安</db:attribute>\n    <db:uid>xian</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/nanjing</id>\n    <db:attribute name=\"name\">南京</db:attribute>\n    <db:uid>nanjing</db:uid>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/location/changsha</id>\n    <db:attribute name=\"name\">长沙</db:attribute>\n    <db:uid>changsha</db:uid>\n  </entry>\n  <openSearch:itemsPerPage>10</openSearch:itemsPerPage>\n  <openSearch:startIndex>1</openSearch:startIndex>\n  <openSearch:totalResults>853</openSearch:totalResults>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedComment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <title>照片 的回应</title>\n  <author>\n    <link href=\"http://api.douban.com/people/1080296\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/linguo/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/icon/u1080296-7.jpg\" rel=\"icon\"/>\n    <name>lincode</name>\n    <uri>http://api.douban.com/people/1080296</uri>\n  </author>\n  <entry>\n    <id>http://api.douban.com/recommendation/1474552938/comment/99611691</id>\n    <author>\n      <link href=\"http://api.douban.com/people/2449296\" rel=\"self\"/>\n      <link href=\"http://www.douban.com/people/JGuo/\" rel=\"alternate\"/>\n      <link href=\"http://img3.douban.com/icon/u2449296-34.jpg\" rel=\"icon\"/>\n      <name>放开那个西红柿</name>\n      <uri>http://api.douban.com/people/2449296</uri>\n    </author>\n    <published>2012-03-22T21:23:43+08:00</published>\n    <content>什么时候拍的？</content>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/recommendation/1474552938/comment/99612528</id>\n    <author>\n      <link href=\"http://api.douban.com/people/1080296\" rel=\"self\"/>\n      <link href=\"http://www.douban.com/people/linguo/\" rel=\"alternate\"/>\n      <link href=\"http://img3.douban.com/icon/u1080296-7.jpg\" rel=\"icon\"/>\n      <name>lincode</name>\n      <uri>http://api.douban.com/people/1080296</uri>\n    </author>\n    <published>2012-03-22T21:29:27+08:00</published>\n    <content>大众点评啦</content>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/recommendation/1474552938/comment/99624829</id>\n    <author>\n      <link href=\"http://api.douban.com/people/1354395\" rel=\"self\"/>\n      <link href=\"http://www.douban.com/people/p3865/\" rel=\"alternate\"/>\n      <link href=\"http://img3.douban.com/icon/u1354395-48.jpg\" rel=\"icon\"/>\n      <name>Kirsten</name>\n      <uri>http://api.douban.com/people/1354395</uri>\n    </author>\n    <published>2012-03-22T22:51:50+08:00</published>\n    <content>不知道大叔的新店如何？</content>\n  </entry>\n  <openSearch:itemsPerPage>10</openSearch:itemsPerPage>\n  <openSearch:startIndex>1</openSearch:startIndex>\n  <openSearch:totalResults>3</openSearch:totalResults>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedEvent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <title>胖胖的大头鱼的活动</title>\n  <author>\n    <link href=\"http://api.douban.com/people/1057620\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/aka/\" rel=\"alternate\"/>\n    <link href=\"http://t.douban.com/icon/u1057620-16.jpg\" rel=\"icon\"/>\n    <name>胖胖的大头鱼</name>\n    <uri>http://api.douban.com/people/1057620</uri>\n  </author>\n  <link href=\"http://www.douban.com/people/1057620/events\" rel=\"alternate\"/>\n  <opensearch:startIndex>3</opensearch:startIndex>\n  <opensearch:itemPerPage>1</opensearch:itemPerPage>\n  <opensearch:totalResults>46</opensearch:totalResults>\n  <entry>\n    <id>http://api.douban.com/event/10297336</id>\n    <title>Open Source Camp 北京 2008技术交流盛会</title>\n    <category scheme=\"http://www.douban.com/2007#kind\" term=\"http://www.douban.com/2007#event.salon\"/>\n    <author>\n      <link href=\"http://api.douban.com/people/1000062\" rel=\"self\"/>\n      <link href=\"http://www.douban.com/people/shizhao/\" rel=\"alternate\"/>\n      <link href=\"http://t.douban.com/icon/u1000062-1.jpg\" rel=\"icon\"/>\n      <name>shizhao</name>\n      <uri>http://api.douban.com/people/1000062</uri>\n    </author>\n    <link href=\"http://api.douban.com/event/10297336\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/event/10297336/\" rel=\"alternate\"/>\n    <link href=\"http://t.douban.com/mpic/e39902.jpg\" rel=\"image\"/>\n    <summary>更多信息，请访问：http://www.opensourcecamp.org/ , http://www.opensourcecamp.org.cn/\n      OSCAMP@Facebook：http://www.new.facebook.com/home.php#/group.php?gid=5626789741\n      \n      活动联系人\n      \n      Peter Cheng 138-1138-1302 opensourcecamp@gmail.com\n      如何报名参加\n      \n      如果你想参加OpenSourceCamp 北京活动，请填写在线的报名表格：https://sp...</summary>\n    <content>更多信息，请访问：http://www.opensourcecamp.org/ , http://www.opensourcecamp.org.cn/\n      OSCAMP@Facebook：http://www.new.facebook.com/home.php#/group.php?gid=5626789741\n      \n      活动联系人\n      \n      Peter Cheng 138-1138-1302 opensourcecamp@gmail.com\n      如何报名参加\n      \n      如果你想参加OpenSourceCamp 北京活动，请填写在线的报名表格：https://sp...</content>\n    <db:attribute name=\"invite_only\">no</db:attribute>\n    <db:attribute name=\"can_invite\">yes</db:attribute>\n    <db:attribute name=\"participants\">13</db:attribute>\n    <db:attribute name=\"wishers\">22</db:attribute>\n    <db:attribute name=\"status\">wish</db:attribute>\n    <db:location id=\"beijing\">北京</db:location>\n    <gd:when endTime=\"2008-10-25T19:00:00+08:00\" startTime=\"2008-10-25T13:00:00+08:00\"/>\n    <gd:where valueString=\"北京 海淀区蓝旗营路北 工商银行旁 Study 英语学 习吧（三角地）\"/>\n  </entry>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedEventCategory.xml",
    "content": "<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <title>北京的活动数目</title>\n  <entry>\n    <title>drama</title>\n    <db:attribute name=\"cname\">戏剧/曲艺</db:attribute>\n    <db:attribute name=\"event_count\">51</db:attribute>\n  </entry>\n  <entry>\n    <title>music</title>\n    <db:attribute name=\"cname\">音乐/演出</db:attribute>\n    <db:attribute name=\"event_count\">105</db:attribute>\n  </entry>\n  <entry>\n    <title>all</title>\n    <db:attribute name=\"cname\">所有类型</db:attribute>\n    <db:attribute name=\"event_count\">781</db:attribute>\n  </entry>\n  <entry>\n    <title>exhibition</title>\n    <db:attribute name=\"cname\">展览</db:attribute>\n    <db:attribute name=\"event_count\">100</db:attribute>\n  </entry>\n  <entry>\n    <title>sports</title>\n    <db:attribute name=\"cname\">体育</db:attribute>\n    <db:attribute name=\"event_count\">46</db:attribute>\n  </entry>\n  <entry>\n    <title>party</title>\n    <db:attribute name=\"cname\">生活/聚会</db:attribute>\n    <db:attribute name=\"event_count\">156</db:attribute>\n  </entry>\n  <entry>\n    <title>commonweal</title>\n    <db:attribute name=\"cname\">公益</db:attribute>\n    <db:attribute name=\"event_count\">56</db:attribute>\n  </entry>\n  <entry>\n    <title>travel</title>\n    <db:attribute name=\"cname\">旅行</db:attribute>\n    <db:attribute name=\"event_count\">28</db:attribute>\n  </entry>\n  <entry>\n    <title>film</title>\n    <db:attribute name=\"cname\">电影</db:attribute>\n    <db:attribute name=\"event_count\">37</db:attribute>\n  </entry>\n  <entry>\n    <title>salon</title>\n    <db:attribute name=\"cname\">讲座/沙龙</db:attribute>\n    <db:attribute name=\"event_count\">132</db:attribute>\n  </entry>\n  <entry>\n    <title>others</title>\n    <db:attribute name=\"cname\">其他</db:attribute>\n    <db:attribute name=\"event_count\">70</db:attribute>\n  </entry>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedMiniblog.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <title>胖胖的大头鱼 的友邻广播</title>\n  <author>\n    <link href=\"http://api.douban.com/people/1057620\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/aka/\" rel=\"alternate\"/>\n    <link href=\"http://t.douban.com/icon/u1057620-26.jpg\" rel=\"icon\"/>\n    <name>胖胖的大头鱼</name>\n    <uri>http://api.douban.com/people/1057620</uri>\n  </author>\n  <opensearch:startIndex>1</opensearch:startIndex>\n  <opensearch:itemsPerPage>2</opensearch:itemsPerPage>\n  <entry>\n    <id>http://api.douban.com/miniblog/12974400</id>\n    <title>写了新blog文章第一批北京志愿者的工作情况</title>\n    <category scheme=\"http://www.douban.com/2007#kind\" term=\"http://www.douban.com/2007#miniblog.blog\"/>\n    <author>\n      <link href=\"http://api.douban.com/people/1255282\" rel=\"self\"/>\n      <link href=\"http://www.douban.com/people/davies/\" rel=\"alternate\"/>\n      <link href=\"http://t.douban.com/icon/u1255282-2.jpg\" rel=\"icon\"/>\n      <name>Davies</name>\n      <uri>http://api.douban.com/people/1255282</uri>\n    </author>\n    <published>2008-07-31T11:57:47+08:00</published>\n    <content type=\"html\"><![CDATA[写了新blog文章<a href=\"http://9.douban.com/site/entry/52192091/\">第一批北京志愿者的工作情况</a>]]></content>\n  </entry>\n  <entry>\n    <id>http://api.douban.com/miniblog/12974395</id>\n    <title>加入了岩井俊二小组</title>\n    <category scheme=\"http://www.douban.com/2007#kind\" term=\"http://www.douban.com/2007#miniblog.group\"/>\n    <author>\n      <link href=\"http://api.douban.com/people/1079441\" rel=\"self\"/>\n      <link href=\"http://www.douban.com/people/flycondor/\" rel=\"alternate\"/>\n      <link href=\"http://t.douban.com/icon/u1079441-7.jpg\" rel=\"icon\"/>\n      <name>挑灯看剑</name>\n      <uri>http://api.douban.com/people/1079441</uri>\n    </author>\n    <published>2008-07-30T21:45:35+08:00</published>\n    <link href=\"/icon/g10355-1.jpg\" rel=\"image\"/>\n    <content type=\"html\"><![CDATA[加入了<a href=\"http://www.douban.com/group/10355/\">岩井俊二小组</a>]]></content>\n  </entry>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedPeople.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n\t<title>搜索 douban 的结果</title>\n\t<opensearch:startIndex>10</opensearch:startIndex>\n\t<opensearch:itemsPerPage>2</opensearch:itemsPerPage>\n\t<opensearch:totalResults>158</opensearch:totalResults>\n\t<entry>\n\t\t<id>http://api.douban.com/people/1000000</id>\n\t\t<title>六零</title>\n\t\t<link href=\"http://api.douban.com/people/1000000\" rel=\"self\"/>\n\t\t<link href=\"http://www.douban.com/people/douban/\" rel=\"alternate\"/>\n\t\t<content></content>\n\t\t<db:uid>douban</db:uid>\n\t</entry>\n\t<entry>\n\t\t<id>http://api.douban.com/people/1428797</id>\n\t\t<title>yangjiani</title>\n\t\t<link href=\"http://api.douban.com/people/1428797\" rel=\"self\"/>\n\t\t<link href=\"http://www.douban.com/people/www.douban.amy./\" rel=\"alternate\"/>\n\t\t<link href=\"http://t.douban.com/icon/u1428797-1.jpg\" rel=\"icon\"/>\n\t\t<link href=\"http://http://blog.sina.com.cn/yangjianiamy\" rel=\"homepage\"/>\n\t\t<content>日子过充实是真的很好\n      让你可以忘掉一切\n      一切的一切\n      再也没有了孤独~\n      也许他们这是偶尔躲我一下\n      但还是不错的样子\n      \n      生活少了些暧昧\n      多了些真实\n      越来越不认识\n      ~~~自己</content>\n\t\t<db:uid>www.douban.amy.</db:uid>\n\t</entry>\n\t<entry>\n\t\t<id>http://api.douban.com/people/1405403</id>\n\t\t<title>douban</title>\n\t\t<link href=\"http://api.douban.com/people/1405403\" rel=\"self\"/>\n\t\t<link href=\"http://www.douban.com/people/perfectlie/\" rel=\"alternate\"/>\n\t\t<link href=\"http://t.douban.com/icon/u1405403-1.jpg\" rel=\"icon\"/>\n\t\t<content></content>\n\t\t<db:uid>perfectlie</db:uid>\n\t</entry>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedPhoto.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <title>山谷里，我的家/小娟山谷里的居民2011北京演唱会 的照片</title>\n    <author>\n    <link href=\"http://www.douban.com/event/14792861/\" rel=\"alternate\"/>\n    <link href=\"http://api.douban.com/event/14792861\" rel=\"self\"/>\n    <link href=\"http://img3.douban.com/mpic/e538089.jpg\" rel=\"image\"/>\n    <name>山谷里，我的家/小娟山谷里的居民2011北京演唱会</name>\n    <uri>http://api.douban.com/event/14792861</uri>\n    </author>\n    <entry>\n    <id>http://api.douban.com/photo/1259201045</id>\n    <title>照片</title>\n    <author>\n    <link href=\"http://api.douban.com/people/3220815\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/highway61/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/icon/u3220815-2.jpg\" rel=\"icon\"/>\n    <name>公路</name>\n    <uri>http://api.douban.com/people/3220815</uri>\n    </author>\n    <published>2011-10-17T11:55:31+08:00</published>\n    <link href=\"http://api.douban.com/photo/1259201045\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/event/photo/1259201045/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/view/photo/icon/public/p1259201045.jpg\" rel=\"icon\"/>\n    <link href=\"http://img3.douban.com/view/photo/photo/public/p1259201045.jpg\" rel=\"image\"/>\n    <link href=\"http://img3.douban.com/view/photo/thumb/public/p1259201045.jpg\" rel=\"thumb\"/>\n    <link href=\"http://img3.douban.com/view/photo/albumcover/public/p1259201045.jpg\" rel=\"cover\"/>\n    <link href=\"http://m.douban.com/photos/photo/1259201045/\" rel=\"mobile\"/>\n    <content/>\n    <db:attribute name=\"comments_count\">0</db:attribute>\n    <db:attribute name=\"recs_count\">0</db:attribute>\n    <db:attribute name=\"position\">0</db:attribute>\n    <db:attribute name=\"next_photo\">1259196350</db:attribute>\n    <db:attribute name=\"prev_photo\">1259193512</db:attribute>\n    </entry>\n    <entry>\n    <id>http://api.douban.com/photo/1259196350</id>\n    <title>照片</title>\n    <author>\n    <link href=\"http://api.douban.com/people/3220815\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/highway61/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/icon/u3220815-2.jpg\" rel=\"icon\"/>\n    <name>公路</name>\n    <uri>http://api.douban.com/people/3220815</uri>\n    </author>\n    <published>2011-10-17T11:52:17+08:00</published>\n    <link href=\"http://api.douban.com/photo/1259196350\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/event/photo/1259196350/\" rel=\"alternate\"/>\n    <link href=\"http://img1.douban.com/view/photo/icon/public/p1259196350.jpg\" rel=\"icon\"/>\n    <link href=\"http://img1.douban.com/view/photo/photo/public/p1259196350.jpg\" rel=\"image\"/>\n    <link href=\"http://img1.douban.com/view/photo/thumb/public/p1259196350.jpg\" rel=\"thumb\"/>\n    <link href=\"http://img1.douban.com/view/photo/albumcover/public/p1259196350.jpg\" rel=\"cover\"/>\n    <link href=\"http://m.douban.com/photos/photo/1259196350/\" rel=\"mobile\"/>\n    <content/>\n    <db:attribute name=\"comments_count\">0</db:attribute>\n    <db:attribute name=\"recs_count\">0</db:attribute>\n    <db:attribute name=\"position\">1</db:attribute>\n    <db:attribute name=\"next_photo\">1259195668</db:attribute>\n    <db:attribute name=\"prev_photo\">1259201045</db:attribute>\n    </entry>\n    <entry>\n    <id>http://api.douban.com/photo/1259195668</id>\n    <title>照片</title>\n    <author>\n    <link href=\"http://api.douban.com/people/3220815\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/highway61/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/icon/u3220815-2.jpg\" rel=\"icon\"/>\n    <name>公路</name>\n    <uri>http://api.douban.com/people/3220815</uri>\n    </author>\n    <published>2011-10-17T11:51:45+08:00</published>\n    <link href=\"http://api.douban.com/photo/1259195668\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/event/photo/1259195668/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/view/photo/icon/public/p1259195668.jpg\" rel=\"icon\"/>\n    <link href=\"http://img3.douban.com/view/photo/photo/public/p1259195668.jpg\" rel=\"image\"/>\n    <link href=\"http://img3.douban.com/view/photo/thumb/public/p1259195668.jpg\" rel=\"thumb\"/>\n    <link href=\"http://img3.douban.com/view/photo/albumcover/public/p1259195668.jpg\" rel=\"cover\"/>\n    <link href=\"http://m.douban.com/photos/photo/1259195668/\" rel=\"mobile\"/>\n    <content/>\n    <db:attribute name=\"comments_count\">0</db:attribute>\n    <db:attribute name=\"recs_count\">0</db:attribute>\n    <db:attribute name=\"position\">2</db:attribute>\n    <db:attribute name=\"next_photo\">1259193512</db:attribute>\n    <db:attribute name=\"prev_photo\">1259196350</db:attribute>\n    </entry>\n    <entry>\n    <id>http://api.douban.com/photo/1259193512</id>\n    <title>照片</title>\n    <author>\n    <link href=\"http://api.douban.com/people/3220815\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/highway61/\" rel=\"alternate\"/>\n    <link href=\"http://img3.douban.com/icon/u3220815-2.jpg\" rel=\"icon\"/>\n    <name>公路</name>\n    <uri>http://api.douban.com/people/3220815</uri>\n    </author>\n    <published>2011-10-17T11:49:41+08:00</published>\n    <link href=\"http://api.douban.com/photo/1259193512\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/event/photo/1259193512/\" rel=\"alternate\"/>\n    <link href=\"http://img1.douban.com/view/photo/icon/public/p1259193512.jpg\" rel=\"icon\"/>\n    <link href=\"http://img1.douban.com/view/photo/photo/public/p1259193512.jpg\" rel=\"image\"/>\n    <link href=\"http://img1.douban.com/view/photo/thumb/public/p1259193512.jpg\" rel=\"thumb\"/>\n    <link href=\"http://img1.douban.com/view/photo/albumcover/public/p1259193512.jpg\" rel=\"cover\"/>\n    <link href=\"http://m.douban.com/photos/photo/1259193512/\" rel=\"mobile\"/>\n    <content/>\n    <db:attribute name=\"comments_count\">0</db:attribute>\n    <db:attribute name=\"recs_count\">0</db:attribute>\n    <db:attribute name=\"position\">3</db:attribute>\n    <db:attribute name=\"next_photo\">1259201045</db:attribute>\n    <db:attribute name=\"prev_photo\">1259195668</db:attribute>\n    </entry>\n    <openSearch:itemsPerPage>10</openSearch:itemsPerPage>\n    <openSearch:startIndex>1</openSearch:startIndex>\n    <openSearch:totalResults>4</openSearch:totalResults>\n    </feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedRecommendation.xml",
    "content": "<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\">\n  <title>胖胖的大头鱼 的推荐</title>\n  <author>\n    <link href=\"http://api.douban.com/people/1057620\" rel=\"self\"/>\n    <link href=\"http://www.douban.com/people/aka/\" rel=\"alternate\"/>\n    <link href=\"http://t.douban.com/icon/u1057620-16.jpg\" rel=\"icon\"/>\n    <name>胖胖的大头鱼</name>\n    <uri>http://api.douban.com/people/1057620</uri>\n  </author>\n  <opensearch:startIndex>1</opensearch:startIndex>\n  <entry>\n    <id>http://api.douban.com/recommendation/3677685</id>\n    <title>推荐麦凯恩的败选演说——2008美国大选之夜（上）</title>\n    <published>2008-11-07T13:36:05+08:00</published>\n    <content type=\"html\"><![CDATA[推荐<a href=\"http://9.douban.com/site/entry/74478867/\">麦凯恩的败选演说——2008美国大选之夜（上）</a>]]></content>\n    <db:attribute name=\"category\">entry</db:attribute>\n    <db:attribute name=\"comment\"></db:attribute>\n    <db:attribute name=\"comments_count\">0</db:attribute>\n  </entry>\n  <opensearch:itemsPerPage>1</opensearch:itemsPerPage>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model/DoubanFeedSubject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:gd=\"http://schemas.google.com/g/2005\" xmlns:opensearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:db=\"http://www.douban.com/xmlns/\">\n  <title>带有标签 cowboy 的条目</title>\n  <opensearch:totalResults>246</opensearch:totalResults>\n  <opensearch:startIndex>1</opensearch:startIndex>\n  <entry>\n    <category scheme=\"http://www.douban.com/2007#kind\" term=\"http://www.douban.com/2007#movie\"/>\n    <author>\n      <name>渡边信一郎</name>\n    </author>\n    <title>Cowboy Bebop</title>\n    <summary>友情、爱情、廉价道德观，这些都放在一边，享受着朝不保夕的自由人生，以自己的利益为绝对优先的——赏金猎人们，在剧中被称为COWBOY。\n      日本动画中一贯会以某 ...</summary>\n    <link rel=\"self\" href=\"http://api.douban.com/movie/subject/1424406\"/>\n    <link rel=\"alternate\" href=\"http://movie.douban.com/subject/1424406/\"/>\n    <link rel=\"image\" href=\"http://t.douban.com/spic/s2351152.jpg\"/>\n    <db:attribute name=\"year\">1998</db:attribute>\n    <db:attribute name=\"language\">日语</db:attribute>\n    <db:attribute name=\"site\">http://www.cowboybebop.org/</db:attribute>\n    <db:attribute name=\"imdb\">http://www.imdb.com/title/tt0213338/</db:attribute>\n    <db:attribute name=\"country\">Japan</db:attribute>\n    <db:attribute name=\"cast\">山寺宏一</db:attribute>\n    <db:attribute name=\"cast\">石塚运昇</db:attribute>\n    <db:attribute name=\"cast\">林原惠</db:attribute>\n    <id>http://api.douban.com/movie/subject/1424406</id>\n  </entry>\n  <entry>\n    <category scheme=\"http://www.douban.com/2007#kind\" term=\"http://www.douban.com/2007#movie\"/>\n    <author>\n      <name>渡边信一郎 (Shinichirô Watanabe)</name>\n    </author>\n    <title>Cowboy Bebop: Knockin' on Heaven's Door</title>\n    <summary>地点是火星，时间是２０７１年的万圣节前夕，一群歹徒在一号公路上炸毁一辆油罐车，并释出一种致命病毒。有关单位担心他们会发动一波更致命的生化战攻击，所以提出钜额奖金 ...</summary>\n    <link rel=\"self\" href=\"http://api.douban.com/movie/subject/1307031\"/>\n    <link rel=\"alternate\" href=\"http://movie.douban.com/subject/1307031/\"/>\n    <link rel=\"image\" href=\"http://t.douban.com/spic/s1318036.jpg\"/>\n    <db:attribute name=\"site\">http://www.sonypictures.com/cthe/cowboybebop/</db:attribute>\n    <db:attribute name=\"year\">2001</db:attribute>\n    <db:attribute name=\"language\">Japanese</db:attribute>\n    <db:attribute name=\"imdb\">http://www.imdb.com/title/tt0275277/</db:attribute>\n    <db:attribute name=\"country\">Japan</db:attribute>\n    <id>http://api.douban.com/movie/subject/1307031</id>\n  </entry>\n  <opensearch:itemsPerPage>2</opensearch:itemsPerPage>\n</feed>"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/Album.json",
    "content": "{\n  \"updated\": \"2011-12-05 20:07:05\",\n  \"author\": {\n    \"avatar\": \"http://img3.douban.com/icon/u1645921-14.jpg\",\n    \"alt\": \"http://www.douban.com/people/bear/\",\n    \"id\": \"1645921\",\n    \"name\": \"Bear\",\n    \"uid\": \"bear\"\n  },\n  \"icon\": \"http://img3.douban.com/view/photo/icon/public/p1328238698.jpg\",\n  \"image\": \"http://img3.douban.com/view/photo/image/public/p1328238698.jpg\",\n  \"liked\": false,\n  \"recs_count\": 20,\n  \"alt\": \"http://www.douban.com/photos/album/61434971/\",\n  \"id\": \"61434971\",\n  \"size\": 17,\n  \"thumb\": \"http://img3.douban.com/view/photo/thumb/public/p1328238698.jpg\",\n  \"privacy\": \"public\",\n  \"title\": \"罗马 - 古堡酒店\",\n  \"cover\": \"http://img3.douban.com/view/photo/cover/public/p1328238698.jpg\",\n  \"created\": \"2011-12-05 19:45:28\",\n  \"liked_count\": 120,\n  \"desc\": \"\"\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/BookArray.json",
    "content": "{\n    \"count\": 20,\n    \"start\": 0,\n    \"total\": 3,\n    \"books\": [\n              {\n              \"publisher\": \"北京十月文艺出版社\",\n              \"subtitle\": \"张爱玲全集03——小说\",\n              \"isbn10\": \"7530211188\",\n              \"isbn13\": \"9787530211182\",\n              \"title\": \"怨女\",\n              \"url\": \"http://api.douban.com/v2/book/10757942\",\n              \"origin_title\": \"\",\n              \"image\": \"http://img3.douban.com/mpic/s10199576.jpg\",\n              \"alt_title\": \"\",\n              \"binding\": \"平装\",\n              \"author_intro\": \"张爱玲，1920年9月30日出生於上海，原名张煐。1922年迁居天津。1928年由天津搬回上海，读《红楼梦》和《三国演义》。1930年改名张爱玲，1939年考进香港大学，1941年太平洋战争爆发，投入文学创作。两年後，发表《倾城之恋》和《金锁记》等作品，并结识周瘦鹃、柯灵、苏青和胡兰成。1944与胡兰成结婚，1945年自编《倾城之恋》在上海公演；同年，抗战胜利。1947年与胡兰成离婚，1952年移居香港，1955年离港赴美，并拜访胡适。1956年结识剧作家赖雅，同年八月，在纽约与赖雅结婚。1967年赖雅去世，1973年定居洛杉矶；两年后，完成英译清代长篇小说《海上花列传》。1995年九月逝於洛杉矶公寓，享年七十四岁。\",\n              \"summary\": \"她生于贫穷之家，因世俗虚荣的压力，嫁给一个半残废的富家少爷，虽有锦衣玉食，精神上确实茫然无依。\\n有目的的爱都不是真爱，女主角的愤懑与刻薄，被张爱玲描写的几近变态，却又凄凉无比。——根据《金锁记》改写的长篇小说，被誉为文坛最美的收获之一。\\n张爱玲也许不是时下“正确”定义里的女性主义者，但在《怨女》中，她从未停止对女性命运的严肃思考。——王德威\",\n              \"price\": \"29.60元\",\n              \"pages\": \"345\",\n              \"author\": [\n                         \"张爱玲\"\n                         ],\n              \"translator\": [],\n              \"images\": {\n              \"small\": \"http://img3.douban.com/spic/s10199576.jpg\",\n              \"large\": \"http://img3.douban.com/lpic/s10199576.jpg\",\n              \"medium\": \"http://img3.douban.com/mpic/s10199576.jpg\"\n              },\n              \"alt\": \"http://book.loc-zeta.douban.com/subject/10757942/\",\n              \"pubdate\": \"2012-6\",\n              \"id\": \"10757942\",\n              \"tags\": [\n                       {\n                       \"count\": 394,\n                       \"name\": \"张爱玲\"\n                       },\n                       {\n                       \"count\": 120,\n                       \"name\": \"怨女\"\n                       },\n                       {\n                       \"count\": 103,\n                       \"name\": \"小说\"\n                       },\n                       {\n                       \"count\": 43,\n                       \"name\": \"爱情\"\n                       },\n                       {\n                       \"count\": 40,\n                       \"name\": \"现当代文学\"\n                       },\n                       {\n                       \"count\": 33,\n                       \"name\": \"文学\"\n                       },\n                       {\n                       \"count\": 32,\n                       \"name\": \"怨女的名字很贴切\"\n                       },\n                       {\n                       \"count\": 32,\n                       \"name\": \"现代文学\"\n                       }\n                       ]\n              },\n              {\n              \"publisher\": \"北京联合出版公司\",\n              \"subtitle\": \"增订本\",\n              \"isbn10\": \"7550209782\",\n              \"isbn13\": \"9787550209787\",\n              \"title\": \"最好的女子\",\n              \"url\": \"http://api.douban.com/v2/book/20261734\",\n              \"origin_title\": \"\",\n              \"image\": \"http://img1.douban.com/mpic/s24227712.jpg\",\n              \"alt_title\": \"\",\n              \"binding\": \"平装\",\n              \"author_intro\": \"黄佟佟\\n当下专栏界写女子写得最好的女子，出版有散文随笔集《感情这东西》、《浮世爱情》、《最爱的男子》、《傲慢即偏见》，及长篇小说《女人是比男人更高级的动物》等，现居广州。\\n长期为《南方都市报》、《南方人物周刊》、《ELLE》、《VOGUE》、《GQ》等二十多家一线媒体、品牌杂志撰写采访与专栏，被誉为“最懂女人心的专栏作家”、其专栏亦获有“传世专栏”之誉。\",\n              \"summary\": \"《最好的女子》是黄佟佟迄今最畅销的传记散文集，书中所写女子皆是伴随70、80后成长的港台女明星、女作家、女艺术家，她们是这世上最美丽、最温婉、最聪慧的一群女子，看她们的人生起伏与悲欢离合、幸福哀伤与爱恨忧愁……就是看这时代女子的天性，也可得见这时代女子的天命。\\n本部《最好的女子》在2010版基础上增补6万余字，尤其是新增的“佟式小词典”，信息量大，别有韵味，是目前最让作者满意，也是最具阅读与收藏价值的一版。\",\n              \"price\": \"32.80元\",\n              \"pages\": \"320\",\n              \"author\": [\n                         \"黄佟佟\"\n                         ],\n              \"translator\": [],\n              \"images\": {\n              \"small\": \"http://img1.douban.com/spic/s24227712.jpg\",\n              \"large\": \"http://img1.douban.com/lpic/s24227712.jpg\",\n              \"medium\": \"http://img1.douban.com/mpic/s24227712.jpg\"\n              },\n              \"alt\": \"http://book.loc-zeta.douban.com/subject/20261734/\",\n              \"pubdate\": \"2012-11-15\",\n              \"id\": \"20261734\",\n              \"tags\": [\n                       {\n                       \"count\": 376,\n                       \"name\": \"最好的女子\"\n                       },\n                       {\n                       \"count\": 168,\n                       \"name\": \"女性\"\n                       },\n                       {\n                       \"count\": 142,\n                       \"name\": \"黄佟佟\"\n                       },\n                       {\n                       \"count\": 129,\n                       \"name\": \"散文\"\n                       },\n                       {\n                       \"count\": 100,\n                       \"name\": \"女子\"\n                       },\n                       {\n                       \"count\": 85,\n                       \"name\": \"散文传记\"\n                       },\n                       {\n                       \"count\": 71,\n                       \"name\": \"生活\"\n                       },\n                       {\n                       \"count\": 69,\n                       \"name\": \"女人必修课\"\n                       }\n                       ]\n              },\n              {\n              \"publisher\": \"\",\n              \"subtitle\": \"心慢下来，行动才能快起来\",\n              \"isbn10\": \"7504479306\",\n              \"isbn13\": \"9787504479303\",\n              \"title\": \"慢慢来，一切都来得及\",\n              \"url\": \"http://api.douban.com/v2/book/20389195\",\n              \"origin_title\": \"\",\n              \"image\": \"http://img3.douban.com/mpic/s24444729.jpg\",\n              \"alt_title\": \"\",\n              \"binding\": \"\",\n              \"author_intro\": \"meiya\\nhttp://www.douban.com/people/meiyang/\\n是豆瓣网上的一位大红人。她在上海的一家广告公司工作。\\n80后双子座女生，热爱写作、阅读、跑步、旅行和美食。\\n她独自在城市里孤独奋斗的同时，不忘享受生命。她把美好的生命体验记录下来，也把自己时常会有的压力、焦躁、急迫感和不安全感写下来，引起广大网友的强烈共鸣。\\n她会在早上边跑步边大声哭泣来缓解压力，也会对着镜子说“我爱你呀”来鼓励自己对抗拖延症，她通过写作和阅读来学习认识生活，她活得真实，努力，因此被誉为豆瓣网最温暖、最励志的女子。\\n网友们喜欢跟她倾诉心事，并从她的文字里获得正能量。\\n另外，她的文章被多家杂志收入专栏，并有广播美文在“静雅思听”播出。近期出版另一本小书《这辈子最渴望做的那些事》。\",\n              \"summary\": \"每个在城市中学习工作的人，都会被这本书深深的打动。\\n在奋斗的道路上，我们都想快起来，快一点成功，快一点过上自己想要的生活。\\n可是人就是这样的，越是着急，事情越是做不好。工作会拖延，情绪变糟糕，压力让人焦躁。\\n本书的作者meiya跟我们大家一样，“独自在城市中努力的奋斗着”。她把自己这些情况都写下来，涉及到“开始爱好者”，空有梦想，不付诸行动、拖延症、注意力涣散症、负面情绪、缺乏运动，身体亚健康等等，分享有效、有趣的解决方法。她和大家一起，练习“把心慢下来，让行动快起来”。\\n她还通过自己丰富的生命体验告诉大家：成功并不是最重要的，更重要的事情，是一个人心智的成熟和精神的自由。\\n这也是一本促人行动的书，“允许自己慢慢来，才能重新上路”。认真的过好每天，认真的对待生命。试读的读者说，看完书，就想明早去跑步，锻炼身体。或者耐心把一些基本的事做好，开始慢慢来；学习接纳生活中的痛苦，并记录下每一份微幸福。\",\n              \"price\": \"29.80元\",\n              \"pages\": \"256\",\n              \"author\": [\n                         \"meiya\"\n                         ],\n              \"translator\": [],\n              \"images\": {\n              \"small\": \"http://img3.douban.com/spic/s24444729.jpg\",\n              \"large\": \"http://img3.douban.com/lpic/s24444729.jpg\",\n              \"medium\": \"http://img3.douban.com/mpic/s24444729.jpg\"\n              },\n              \"alt\": \"http://book.loc-zeta.douban.com/subject/20389195/\",\n              \"pubdate\": \"2012-12\",\n              \"id\": \"20389195\",\n              \"tags\": [\n                       {\n                       \"count\": 1926,\n                       \"name\": \"正能量\"\n                       },\n                       {\n                       \"count\": 1102,\n                       \"name\": \"meiya\"\n                       },\n                       {\n                       \"count\": 818,\n                       \"name\": \"心灵成长\"\n                       },\n                       {\n                       \"count\": 604,\n                       \"name\": \"励志\"\n                       },\n                       {\n                       \"count\": 590,\n                       \"name\": \"成长\"\n                       },\n                       {\n                       \"count\": 344,\n                       \"name\": \"生活\"\n                       },\n                       {\n                       \"count\": 300,\n                       \"name\": \"心灵\"\n                       },\n                       {\n                       \"count\": 189,\n                       \"name\": \"豆瓣\"\n                       }\n                       ]\n              }\n              ]\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/CommentArray.json",
    "content": "{\n  \"count\": 20,\n  \"start\": 0,\n  \"total\": 2,\n  \"comments\": [\n               {\n               \"content\": \"童年呀\",\n               \"created\": \"2012-05-19 21:52:48\",\n               \"id\": \"104802214\",\n               \"author\": {\n               \"avatar\": \"http://img3.douban.com/icon/u55390020-2.jpg\",\n               \"alt\": \"http://www.douban.com/people/55390020/\",\n               \"id\": \"55390020\",\n               \"name\": \"加快小速度\",\n               \"uid\": \"55390020\"\n               }\n               },\n               {\n               \"content\": \"停产了 我最爱的蜜汁猪排\",\n               \"created\": \"2012-05-19 21:53:23\",\n               \"id\": \"104802291\",\n               \"author\": {\n               \"avatar\": \"http://img3.douban.com/icon/u54585237-10.jpg\",\n               \"alt\": \"http://www.douban.com/people/threemonths/\",\n               \"id\": \"54585237\",\n               \"name\": \"操起西瓜刀\",\n               \"uid\": \"threemonths\"\n               }\n               }\n               ]\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/Event.json",
    "content": "{\n  \"participant_count\": 1,\n  \"image\": \"http://lincode.dev.douban.com:9000/pics/event/median_event_dft.jpg\",\n  \"adapt_url\": \"http://lincode.dev.douban.com:9000/location/adapt/event/10000359/\",\n  \"begin_time\": \"2012-08-27 10:27:06\",\n  \"owner\": {\n    \"avatar\": \"http://lincode.dev.douban.com:9000/icon/user_normal.jpg\",\n    \"alt\": \"http://lincode.dev.douban.com:9000/people/sysadmin1/\",\n    \"id\": \"64050041\",\n    \"name\": \"sysadmin1\",\n    \"uid\": \"sysadmin1\"\n  },\n  \"alt\": \"http://lincode.dev.douban.com:9000/event/10000359/\",\n  \"geo\": \"0.0 0.0\",\n  \"id\": \"10000359\",\n  \"album\": \"10000354\",\n  \"title\": \"豆瓣活动创建\",\n  \"wisher_count\": 0,\n  \"content\": \"生活  Story 说Hello豆 evaomoad豆瓣阿吧    evaomoad测试阿豆瓣阿   evaomoad吧Hello啊生活豆汗豆瓣汗Hello 我们测试EmoTamla 啊豆中文evaomoad EmoTamla  说说 赞 Story 说  吧汗   豆瓣中文生活汗  赞 阿啊 Story 我们测试啊 说吧汗中文我们 豆生活evaomoad豆中文我们赞阿Story  EmoTamla 赞 HelloEmoTamla  中文测试EmoTamla 赞吧啊Story 生活豆瓣测试Hello 我们\",\n  \"image-hlarge\": \"http://lincode.dev.douban.com:9000/pics/event/hlarge_event_dft.jpg\",\n  \"end_time\": \"2012-09-17 10:27:07\",\n  \"image-lmobile\": \"http://lincode.dev.douban.com:9000/pics/event/lmobile_event_dft.jpg\",\n  \"can_invite\": \"no\",\n  \"address\": \"北京 海淀区 中关村\",\n  \"location\": \"beijing\"\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/MovieArray.json",
    "content": "{\n  \"count\": 20,\n  \"start\": 0,\n  \"total\": 1,\n  \"movies\": [\n             {\n             \"rating\": \"8.4\",\n             \"stars\": \"45\",\n             \"pubdate\": \"2012-10-29\",\n             \"title\": \"我们可以结婚吗\",\n             \"images\": {\n             \"large\": \"http://img3.douban.com/lpic/s23130731.jpg\",\n             \"small\": \"http://img3.douban.com/lpic/s23130731.jpg\",\n             \"medium\": \"http://img3.douban.com/mpic/s23130731.jpg\"\n             },\n             \"wish\": 400,\n             \"id\": \"20280228\",\n             \"orignal_title\": \"우리가 결혼할 수 있을까\",\n             \"collection\": 117\n             }\n             ]\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/MusicArray.json",
    "content": "{\n    \"count\": 1,\n    \"start\": 0,\n    \"total\": 1,\n    \"musics\": [\n               {\n               \"rating\": {\n               \"max\": 10,\n               \"average\": \"7.4\",\n               \"numRaters\": 3080,\n               \"min\": 0\n               },\n               \"author\": [\n                          {\n                          \"name\": \"S.H.E\"\n                          }\n                          ],\n               \"alt_title\": \"\",\n               \"image\": \"http://img3.douban.com/spic/s24231882.jpg\",\n               \"tags\": [\n                        {\n                        \"count\": 1480,\n                        \"name\": \"S.H.E\"\n                        },\n                        {\n                        \"count\": 542,\n                        \"name\": \"台湾\"\n                        },\n                        {\n                        \"count\": 374,\n                        \"name\": \"2012\"\n                        },\n                        {\n                        \"count\": 338,\n                        \"name\": \"华语\"\n                        },\n                        {\n                        \"count\": 227,\n                        \"name\": \"女声\"\n                        },\n                        {\n                        \"count\": 145,\n                        \"name\": \"Pop\"\n                        },\n                        {\n                        \"count\": 132,\n                        \"name\": \"HIM华研国际\"\n                        },\n                        {\n                        \"count\": 79,\n                        \"name\": \"流行\"\n                        }\n                        ],\n               \"mobile_link\": \"http://m.douban.com/music/subject/20275660/\",\n               \"attrs\": {\n               \"publisher\": [\n                             \"華研唱片\"\n                             ],\n               \"singer\": [\n                          \"S.H.E\"\n                          ],\n               \"version\": [\n                           \"专辑\"\n                           ],\n               \"pubdate\": [\n                           \"2012-11-16\"\n                           ],\n               \"title\": [\n                         \"花又開好了 (生命的美好平裝發行版)\"\n                         ],\n               \"media\": [\n                         \"CD+DVD\"\n                         ],\n               \"tracks\": [\n                          \"CD：\\n1. 迫不及待\\n2. 花又開好了\\n3. 不說再見\\n4. 心還是熱的\\n5. 親愛的樹洞\\n6. 還我\\n7. 明天的自己\\n8. 那時候的樹\\n9. 像女孩的女人\\n10. 後來後來\\nBonus DVD：SHERO MV全紀錄DVD 曲目\\n1. SHERO (2010臺北國際花卉博覽會指定主題曲)\\n2. 我愛雨夜花\\n3. 愛就對了\\n4. 你不會\\n5. 愛上你 (電視劇「就想賴著妳」片尾曲)\\n6. 兩個人的荒島 (時尚職場勵志劇「杜拉拉升職記」片尾曲)\"\n                          ],\n               \"discs\": [\n                         \"2\"\n                         ]\n               },\n               \"title\": \"花又開好了 (生命的美好平裝發行版)\",\n               \"alt\": \"http://music.douban.com/subject/20275660/\",\n               \"id\": \"20275660\"\n               }\n               ]\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/Note.json",
    "content": "{\n  \"update_time\": \"2012-11-12 08:30:24\",\n  \"publish_time\": \"2012-10-31 10:31:36\",\n  \"photos\": {\n    \n  },\n  \"recs_count\": 10,\n  \"alt\": \"http:\\/\\/www.douban.com\\/note\\/244600047\\/\",\n  \"id\": \"244600047\",\n  \"can_reply\": true,\n  \"title\": \"冯象译经源流考（停止更新）\",\n  \"privacy\": \"public\",\n  \"summary\": \"目前豆瓣已经有了关于冯译的相关小站，站长在把《源流考》的旧文搬进去。加之近来...\",\n  \"content\": \"目前豆瓣已经有了关于冯译的相关小站，站长在把《源流考》的旧文搬进去。加之近来翻墙不力，因之本日记停止更新。\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n转自http:\\/\\/fengtranslation.wordpress.com\\/。墙外网站，访问不力，姑且转发于此。拟随时关注，经常更新，以供参考。mondain 君及相关他人如不同意转载，请通知本人，即刻删除之。\\r\\n2012-10-31 10:45:41 mondain\\r\\n因为我会修订，所以最好注明一下以 wordpress 上为准\\r\\n2012-11-02 00:16:38 mondain \\r\\n加入九点 http:\\/\\/9.douban.com\\/subject\\/9549935\\/ \\r\\n墙内订阅地址: http:\\/\\/pipes.yahoo.com\\/pipes\\/pipe.run?_id=917ce843df0782578572cdca29ab8cdf&_render=rss\\r\\n\\r\\n\\r\\n2012年11月5日更新：\\r\\n\\r\\n約翰福音 1:21 John 1:21 \\r\\nPosted on November 4, 2012 by mondain \\r\\n約翰福音 1:21\\r\\n那麼, 你是以利亞了?\\r\\nJohn 1:21, New Jerusalem Bible\\r\\nThen are you Elijah?\\r\\n按: 原文(NA27)有相連的兩問 τί οὖν; σὺ Ἠλίας εἶ; 馮譯本與 NJB 都併作一問, 省略了第一問的“是誰”.\\r\\n| Tagged 譯文, Gospel of John-約翰福音, NJB, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n路加福音 4:1 Luke 4:1 \\r\\nPosted on November 3, 2012 by mondain \\r\\n路 4:1 馮象譯文:\\r\\n耶穌為聖靈所充盈, 離開約旦河\\r\\nLuke 4:1, New Jerusalem Bible\\r\\nFilled with the Holy Spirit, Jesus left the Jordan\\r\\n按: 原文 ὑπέστρεψεν ἀπὸ τοῦ Ἰορδάνου, 和合本譯作“從約旦河回來”, 英譯本多用“returned”翻譯, 法語 La Bible de Jérusalem « revint du Jourdain ». 馮象譯文用「離開」, NJB 用“left.”\\r\\n| Tagged 譯文, Gospel of Luke-路加福音, NJB, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n2012年11月2日更新：\\r\\n\\r\\n路加福音 2:24 Luke 2:24 \\r\\nPosted on November 2, 2012 by mondain \\r\\n路 2:24 馮譯:\\r\\n按主的律法的規定\\r\\nLuke 2:24, New Jerusalem Bible:\\r\\nin accordance with what is prescribed in the Law of the Lord\\r\\n按: 原文(NA27) τὸ εἰρημένον ἐν τῷ νόμῳ κυρίου 即「律法上所说」(和合本), « ce qui est dit dans la Loi du Seigneur » (La Bible de Jérusalem). 「規定」係 NJB 的措辭.\\r\\n  | Tagged 譯文, Gospel of Luke-路加福音, NJB, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n路加福音 1:48 Gospel of Luke 1:48 \\r\\nPosted on November 2, 2012 by mondain \\r\\n路 1:48 馮譯:\\r\\n是啊, 今後, 萬代要稱我有福!\\r\\nLuke 1:48, New Jerusalem Bible:\\r\\nYes, from now onwards all generations will call me blessed\\r\\nLa Bible de Jérusalem\\r\\nOui, désormais toutes les générations me diront bienheureuse\\r\\n按: 原文(NA27) ἰδοὺ γὰρ 通譯 ‘for behold,’ 和合本略, 未譯出. 馮象「是啊」與 NJB 及法文 La Bible de Jérusalem 同.\\r\\n  | Tagged 譯文, Gospel of Luke-路加福音, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n路加福音 1:28, 30 Luke 1:28, 30 \\r\\nPosted on November 1, 2012 by mondain \\r\\n路 1:28\\r\\n蒙聖恩的人，主與你同在\\r\\nLuke 1:28, New Jerusalem Bible\\r\\nyou who enjoy God’s favour! The Lord is with you.\\r\\n按: 原文無“聖”字, favour 前的 God’s 係 NJB 譯者所增, 馮象譯本從之.\\r\\n另見下文路 1:30:\\r\\n因為你得了上帝的恩寵\\r\\nLuke 1:30, New Jerusalem Bible\\r\\nyou have won God’s favour\\r\\n按: “得了上帝的恩寵”原文(NA27)作 παρὰ τῷ θεῷ, 英譯本多譯作“have found favor with God,” cf. 和合本“你在神面前已經蒙恩了”, La Bible de Jérusalem : « auprès de Dieu ». 獨有 NJB 將 παρά + dative 以屬格 God’s 譯出, 馮象亦然.\\r\\n  | Tagged 譯文, Gospel of Luke-路加福音, NJB, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n創世記 1:6 Genesis 1:6 \\r\\nPosted on October 31, 2012 by mondain \\r\\n創 1:6, 馮象譯本:\\r\\n上帝説：大水中間要有蒼穹，把水分開！水果然一分為二。\\r\\nGenesis 1:6, New Jerusalem Bible\\r\\nGod said, ‘Let there be a vault through the middle of the waters to divide the waters in two.’ And so it was.\\r\\n按: 馮譯本及 NJB 此節皆從希臘文七十士譯本, 故有「果然」 ‘so it was’ 之语. 但馮象此处未註明所採用的異文不同於其所聲明的希伯來文底本 BHS. 另原文本無「二」字, 諸譯本譯文皆作“把水分開”, 唯馮象譯作「一分為二」, 與 NJB ‘divide ［...］ into two’ 暗合.\\r\\ncjc:\\r\\n無論是MT， LXX或其他英譯本都是separate water(s) from water(s) ,或最多稍為意譯作separate the water above from the water below (CEV) 或 separate one body of water from the other。 後者的意思是把兩樣水分隔，跟前者把水一分為二（divide in two）的意思不盡相同。\\r\\n法語聖城本也只是sépare les eaux d’avec les eaux （separate the waters from the waters)。又一次看到馮象參考的不是法語版，而是NJB。\\r\\n參考討論\\r\\n•cjc, lengyowk, 〈創一6-8〉, 基督教人文學會, 21 Oct., 2012.\\r\\n  | Tagged cjc, 譯文, Genesis-創世記, NJB, Quellenforschung, 摩西五經 | Leave a comment \\r\\n\\r\\n2012年10月31日更新：\\r\\n\\r\\n使徒行傳 28:13 Acts of Apostles 28:12 \\r\\nPosted on October 30, 2012 by mondain \\r\\n徒 28:13\\r\\n然後沿岸上行，至雷玖\\r\\nActs 28:13, New Jerusalem Bible\\r\\nfrom there we followed the coast up to Rhegium\\r\\n張達民,〈文學氣象與學術假象: 評馮象譯注的《新約》〉(之一),《時代論壇》第一二○四期(26 Sept., 2010):\\r\\n馮象在前言和書目都聲稱他根據的希臘文底本是NA27，但NA27的正文卻是「從那裡拔（錨）出發，至雷玖……」，馮象翻譯的只是一個異文，也沒有插注交代，一反他在別處連芝麻綠豆的異文也作交代的常態。相信讀者可以猜想得到，無獨有偶，NJB採用了同樣的異文，也同樣沒有加注交代。不同的是，這異文在NJB所根據的希臘文底本其實是正文，所以無須交代，但馮象卻不知底蘊，囫圇吞棗便露出馬腳。不單如此，這個異文的字面意思是「從那裡繞行至雷玖……」（參《和合本》），但NJB卻相當寬鬆地把這句譯成「from there we followed the coast (沿岸) up to Rhegium…」。其他所有根據同樣異文的英語譯本，都採用了類似《和合本》「繞行」的字句，未有如NJB這樣翻譯的。馮象卻把NJB這意譯直譯為中文。順帶一提，過了3節，NJB有交代徒廿八16的抄本異文，馮象也恰巧在該節作同樣交代。\\r\\n延伸閱讀 Further readings\\r\\n張達民, 〈文學氣象與學術假象: 評馮象譯注的《新約》〉(之一),《時代論壇》第一二○四期, 26 Sept., 2010. \\r\\n倉海君, 〈好事者言——旁觀馮象與張達民之辯〉, 12 Oct., 2010. \\r\\nmondain, 〈关于張達民所举冯象译本三处新约经文〉, 13 Oct., 2010. \\r\\n張達民, 〈簡答批評文章〉(回應倉海君), 14 Oct., 2010. \\r\\n冯象, 〈和合本该不该修订〉, 《东方早报 上海书评》, 17 Oct., 2010. \\r\\n張達民, 〈回應馮象《和合本該不該修訂》〉,《時代論壇 時代講場》, 28 Oct., 2010. \\r\\n| Tagged Acts of Apostles-使徒行傳, Alex T. Cheung-張達民, 譯文, NJB, Quellenforschung, 新約 | \\r\\nLeave a comment \\r\\n\\r\\n希伯來書 1:7 Hebrews 1:7 \\r\\nPosted on October 30, 2012 by mondain \\r\\n來 1:7\\r\\n四方的風，當他的使者，烈焰是他的僕從 引七十士本《詩篇》104:4\\r\\nHebrews 1:7, New Jerusalem Bible\\r\\nTo the angels, he says: appointing the winds his messengers and flames of fire his servants\\r\\n張達民,〈文學氣象與學術假象: 評馮象譯注的《新約》〉(之一),《時代論壇》第一二○四期(26 Sept., 2010):\\r\\n其實七十士譯本詩篇的章節與希伯來文聖經不同，應是一○三4，不過這是小事。最嚴重的是，來一7和它所引用的七十士譯本經文根本不是這個意思，而是「使他 的天使為風（或靈），他的僕役為火焰」。《和合本》可能受希伯來文舊約的詩篇引文影響，也與馮象一樣錯譯（近期的中譯如《新漢語》、《新譯本》和《中文標 準譯本》已改正了），但既然馮象煞有介事地注明是引自七十士譯本，是沒有理由搞錯的。無獨有偶，NJB也是眾多歐美譯本裡唯一同樣錯譯的（法語版《耶路撒冷聖經》則是對的）。\\r\\n延伸閱讀 Further readings\\r\\n張達民, 〈文學氣象與學術假象: 評馮象譯注的《新約》〉(之一),《時代論壇》第一二○四期, 26 Sept., 2010. \\r\\nmondain, 〈关于張達民所举冯象译本三处新约经文〉, 13 Oct., 2010. \\r\\n冯象, 〈和合本该不该修订〉, 《东方早报 上海书评》, 17 Oct., 2010. \\r\\n張達民, 〈回應馮象《和合本該不該修訂》〉,《時代論壇 時代講場》, 28 Oct., 2010. \\r\\n| Tagged Alex T. Cheung-張達民, 譯文, Hebrews-希伯來書, NJB, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n馬太福音 4:6 Matthew 4:6 \\r\\nPosted on October 30, 2012 by mondain \\r\\n太4:6\\r\\n以免石子絆你的腳\\r\\nMatthew 4:6, New Jerusalem Bible\\r\\nin case you trip over a stone.\\r\\n張達民,〈文學氣象與學術假象: 評馮象譯注的《新約》〉(之一),《時代論壇》第一二○四期(26 Sept., 2010):\\r\\n馮象翻譯作「絆」的動詞，其他所有中文譯本都正確地翻譯作「碰」或「撞」（這動詞在不及物的情況下可以翻作「失足」，但這裡不適用）。無獨有偶，NJB也是同樣錯譯（「trip over」），而且是筆者對照過的二十多本主流的英、德、法語譯本中唯一這樣錯譯的（一九九八年法語版《耶路撒冷聖經》則是對的）。\\r\\n延伸閱讀 Further readings\\r\\n張達民, 〈文學氣象與學術假象: 評馮象譯注的《新約》〉(之一),《時代論壇》第一二○四期, 26 Sept., 2010. \\r\\n倉海君, 〈好事者言——旁觀馮象與張達民之辯〉, 12 Oct., 2010. \\r\\nmondain, 〈关于張達民所举冯象译本三处新约经文〉, 13 Oct., 2010. \\r\\n張達民, 〈簡答批評文章〉(回應倉海君), 14 Oct., 2010. \\r\\n倉海君, 〈第二回合：由旁觀到企跳〉, 14 Oct., 2010. \\r\\n倉海君, 〈撒旦的語言遊戲——評張達民對聖經某節的闡釋〉, 17 Oct., 2010. \\r\\n冯象, 〈和合本该不该修订〉, 《东方早报 上海书评》, 17 Oct., 2010. \\r\\n張達民, 〈回應馮象《和合本該不該修訂》〉,《時代論壇 時代講場》, 28 Oct., 2010. \\r\\n| Tagged Alex T. Cheung-張達民, 譯文, Gospel of Matthew-馬太福音, NJB, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n傳道書 9:18 Ecclesiastes 9:18 \\r\\nPosted on October 29, 2012 by mondain \\r\\n傳9:18 馮象譯文\\r\\n但觸一次罪，毀掉多少善功\\r\\nEcclesiastes 9:18, New Jerusalem Bible\\r\\nWisdom is worth more than weapons of war, but a single sin undoes a deal of good.\\r\\n按：馮象不用原文“一个罪人”也是 NJB 獨一無二的處理， cf. La Bible de Jérusalem : « un seul pécheur ».\\r\\n| Tagged Ecclesiastes-傳道書, 譯文, NJB, Quellenforschung, 智慧書 | Leave a comment \\r\\n\\r\\n馬太福音 12:46 Matthew 12:46 \\r\\nPosted on October 29, 2012 by mondain \\r\\n太12:46 馮象譯本\\r\\n正在向眾人講論，忽然他母亲带着弟弟們來了\\r\\nMatthew 12:46, New Jerusalem Bible\\r\\nHe was still speaking to the crowds when suddenly his mother and his brothers were standing outside\\r\\n按：希臘文原文及諸譯本(含法文圣城本)皆无「忽然」\\/suddenly，唯独馮譯本与 NJB 特有。\\r\\n| Tagged 譯文, Gospel of Matthew-馬太福音, NJB, Quellenforschung, 新約 | Leave a comment \\r\\n\\r\\n詩篇53 Psalm 53 \\r\\nPosted on October 29, 2012 by mondain \\r\\n詩 53\\r\\n大衛訓誨詩，交與樂官，調寄“病中吟”\\r\\nPsalm 53, New Jerusalem Bible\\r\\nFor the choirmaster In sickness Poem Of David\\r\\n按：诗 53 调用 Mahalath, 馮象譯本「病中吟」, 唯 NJB 译作“［i］n sickness”, cf. La Bible de Jérusalem : « pour la maladie ».\\r\\n| Tagged 譯文, NJB, Psalms-詩篇, Quellenforschung, 智慧書 | Leave a comment \",\n  \"comments_count\": 3,\n  \"liked_count\": 17\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/Online.json",
    "content": "{\n  \"liked\": false,\n  \"album_id\": \"65606728\",\n  \"image\": \"http://img1.douban.com/lpic/o590273.jpg\",\n  \"create_time\": \"2012-02-24 11:49:32\",\n  \"recs_count\": 417,\n  \"owner\": {\n    \"avatar\": \"http://img3.douban.com/icon/u3121692-33.jpg\",\n    \"alt\": \"http://www.douban.com/people/linghowl/\",\n    \"id\": \"3121692\",\n    \"name\": \"浩叔出没东莫村\",\n    \"uid\": \"linghowl\"\n  },\n  \"alt\": \"http://www.douban.com/online/11038343/\",\n  \"id\": \"11038343\",\n  \"thumb\": \"http://img1.douban.com/spic/o590273.jpg\",\n  \"title\": \"新的截图猜电影，来！\",\n  \"tags\": [\n           \"截图\",\n           \"电影\",\n           \"交友\",\n           \"猜图\"\n           ],\n  \"related_url\": \"http://www.douban.com/online/10999361/\",\n  \"liked_count\": 2134,\n  \"cascade_invite\": true,\n  \"desc\": \"截图猜电影\\r\\n猜中后描述改为：\\r\\n《电影名》 by （猜中者名字）\\r\\n请遵守规则！\\r\\n\\r\\n附注：相关网址是，听配乐猜电影友情活动，尽请参加！\",\n  \"photo_count\": 63562,\n  \"participant_count\": 13939,\n  \"shuo_topic\": \"新的截图猜电影，来！\",\n  \"begin_time\": \"2012-02-24 11:00:00\",\n  \"icon\": \"http://img1.douban.com/bpic/o590273.jpg\",\n  \"cover\": \"http://img1.douban.com/tpic/o590273.jpg\",\n  \"joined\":false,\n  \"end_time\": \"2012-05-23 11:00:00\",\n  \"group_id\": \"0\"\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/OnlineArray.json",
    "content": "{\n  \"count\": 3,\n  \"start\": 0,\n  \"total\": 270,\n  \"onlines\": [\n             {\n             \"liked\": false,\n             \"album_id\": \"65606728\",\n             \"image\": \"http://img1.douban.com/lpic/o590273.jpg\",\n             \"create_time\": \"2012-02-24 11:49:32\",\n             \"recs_count\": 417,\n             \"owner\": {\n             \"avatar\": \"http://img3.douban.com/icon/u3121692-33.jpg\",\n             \"alt\": \"http://www.douban.com/people/linghowl/\",\n             \"id\": \"3121692\",\n             \"name\": \"浩叔出没东莫村\",\n             \"uid\": \"linghowl\"\n             },\n             \"alt\": \"http://www.douban.com/online/11038343/\",\n             \"id\": \"11038343\",\n             \"thumb\": \"http://img1.douban.com/spic/o590273.jpg\",\n             \"title\": \"新的截图猜电影，来！\",\n             \"tags\": [\n                      \"截图\",\n                      \"电影\",\n                      \"交友\",\n                      \"猜图\"\n                      ],\n             \"related_url\": \"http://www.douban.com/online/10999361/\",\n             \"liked_count\": 2137,\n             \"cascade_invite\": true,\n             \"desc\": \"截图猜电影\\r\\n猜中后描述改为：\\r\\n《电影名》 by （猜中者名字）\\r\\n请遵守规则！\\r\\n\\r\\n附注：相关网址是，听配乐猜电影友情活动，尽请参加！\",\n             \"photo_count\": 63656,\n             \"participant_count\": 13945,\n             \"shuo_topic\": \"新的截图猜电影，来！\",\n             \"begin_time\": \"2012-02-24 11:00:00\",\n             \"icon\": \"http://img1.douban.com/bpic/o590273.jpg\",\n             \"cover\": \"http://img1.douban.com/tpic/o590273.jpg\",\n             \"end_time\": \"2012-05-23 11:00:00\",\n             \"group_id\": \"0\"\n             },\n             {\n             \"liked\": false,\n             \"album_id\": \"67085447\",\n             \"image\": \"http://img1.douban.com/lpic/o592460.jpg\",\n             \"create_time\": \"2012-03-22 11:03:26\",\n             \"recs_count\": 3,\n             \"owner\": {\n             \"avatar\": \"http://img3.douban.com/icon/u17674101-29.jpg\",\n             \"alt\": \"http://www.douban.com/people/jgf/\",\n             \"id\": \"17674101\",\n             \"name\": \"峯\",\n             \"uid\": \"jgf\"\n             },\n             \"alt\": \"http://www.douban.com/online/11063385/\",\n             \"id\": \"11063385\",\n             \"thumb\": \"http://img1.douban.com/spic/o592460.jpg\",\n             \"title\": \"告诉我你曾经用过的手机。。。\",\n             \"tags\": [\n                      \"手机\",\n                      \"怀旧\"\n                      ],\n             \"related_url\": \"\",\n             \"liked_count\": 7,\n             \"cascade_invite\": true,\n             \"desc\": \"告诉我你曾经用过的手机。。。不管国产，井口，山寨。。。一起来怀旧吧。。。\",\n             \"photo_count\": 353,\n             \"participant_count\": 383,\n             \"shuo_topic\": \"告诉我你曾经用过的手机。。。\",\n             \"begin_time\": \"2012-03-22 11:00:00\",\n             \"icon\": \"http://img1.douban.com/bpic/o592460.jpg\",\n             \"cover\": \"http://img1.douban.com/tpic/o592460.jpg\",\n             \"end_time\": \"2012-06-21 11:00:00\",\n             \"group_id\": \"0\"\n             },\n             {\n             \"liked\": false,\n             \"album_id\": \"67101445\",\n             \"image\": \"http://img1.douban.com/lpic/o592492.jpg\",\n             \"create_time\": \"2012-03-22 15:32:40\",\n             \"recs_count\": 68,\n             \"owner\": {\n             \"avatar\": \"http://img3.douban.com/icon/u47781029-9.jpg\",\n             \"alt\": \"http://www.douban.com/people/vocc1/\",\n             \"id\": \"47781029\",\n             \"name\": \"Y樱子\",\n             \"uid\": \"vocc1\"\n             },\n             \"alt\": \"http://www.douban.com/online/11063653/\",\n             \"id\": \"11063653\",\n             \"thumb\": \"http://img1.douban.com/spic/o592492.jpg\",\n             \"title\": \"看看你学生时代班上或者学校里最美/帅的那个人\",\n             \"tags\": [\n                      \"帅哥\",\n                      \"美女\",\n                      \"青春\"\n                      ],\n             \"related_url\": \"http://exp.qq.com/details.html#pid=276\",\n             \"liked_count\": 65,\n             \"cascade_invite\": true,\n             \"desc\": \"其实我是看到QQ圈子那个帖子想到的。。快贴照片吧 哈哈\",\n             \"photo_count\": 731,\n             \"participant_count\": 960,\n             \"shuo_topic\": \"看看你学生时代班上或者学校里最美/帅的那个人\",\n             \"begin_time\": \"2012-03-22 15:30:00\",\n             \"icon\": \"http://img1.douban.com/bpic/o592492.jpg\",\n             \"cover\": \"http://img1.douban.com/tpic/o592492.jpg\",\n             \"end_time\": \"2012-05-31 15:30:00\",\n             \"group_id\": \"0\"\n             }\n             ]\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/Photo.json",
    "content": "{\n  \"liked\": false,\n  \"author\": {\n    \"avatar\": \"http://img3.douban.com/icon/u1645921-14.jpg\",\n    \"alt\": \"http://www.douban.com/people/bear/\",\n    \"id\": \"1645921\",\n    \"name\": \"Bear\",\n    \"uid\": \"bear\"\n  },\n  \"album_id\": \"61434971\",\n  \"image\": \"http://img1.douban.com/view/photo/image/public/p1328238583.jpg\",\n  \"recs_count\": 20,\n  \"alt\": \"http://www.douban.com/photos/photo/1328238583/\",\n  \"album_title\": \"罗马 - 古堡酒店\",\n  \"id\": \"1328238583\",\n  \"icon\": \"http://img1.douban.com/view/photo/icon/public/p1328238583.jpg\",\n  \"thumb\": \"http://img1.douban.com/view/photo/thumb/public/p1328238583.jpg\",\n  \"created\": \"2011-12-05 19:54:43\",\n  \"privacy\": \"public\",\n  \"cover\": \"http://img1.douban.com/view/photo/cover/public/p1328238583.jpg\",\n  \"liked_count\": 120,\n  \"comments_count\": 10,\n  \"desc\": \"这个就是在古城墙里的酒店，一共就3个房间，很有趣\"\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Resources/Model2/PhotoArray.json",
    "content": "{\n  \"count\": 3,\n  \"album\": {\n    \"updated\": \"2011-12-05 20:07:05\",\n    \"author\": {\n      \"avatar\": \"http://img3.douban.com/icon/u1645921-14.jpg\",\n      \"alt\": \"http://www.douban.com/people/bear/\",\n      \"id\": \"1645921\",\n      \"name\": \"Bear\",\n      \"uid\": \"bear\"\n    },\n    \"icon\": \"http://img3.douban.com/view/photo/icon/public/p1328238698.jpg\",\n    \"image\": \"http://img3.douban.com/view/photo/image/public/p1328238698.jpg\",\n    \"liked\": false,\n    \"recs_count\": 0,\n    \"alt\": \"http://www.douban.com/photos/album/61434971/\",\n    \"id\": \"61434971\",\n    \"size\": 17,\n    \"thumb\": \"http://img3.douban.com/view/photo/thumb/public/p1328238698.jpg\",\n    \"privacy\": \"public\",\n    \"title\": \"罗马 - 古堡酒店\",\n    \"cover\": \"http://img3.douban.com/view/photo/cover/public/p1328238698.jpg\",\n    \"created\": \"2011-12-05 19:45:28\",\n    \"liked_count\": 0,\n    \"desc\": \"\"\n  },\n  \"photos\": [\n             {\n             \"liked\": false,\n             \"author\": {\n             \"avatar\": \"http://img3.douban.com/icon/u1645921-14.jpg\",\n             \"alt\": \"http://www.douban.com/people/bear/\",\n             \"id\": \"1645921\",\n             \"name\": \"Bear\",\n             \"uid\": \"bear\"\n             },\n             \"album_id\": \"61434971\",\n             \"image\": \"http://img5.douban.com/view/photo/image/public/p1328238489.jpg\",\n             \"recs_count\": 0,\n             \"alt\": \"http://www.douban.com/photos/photo/1328238489/\",\n             \"album_title\": \"罗马 - 古堡酒店\",\n             \"id\": \"1328238489\",\n             \"icon\": \"http://img5.douban.com/view/photo/icon/public/p1328238489.jpg\",\n             \"position\": 0,\n             \"thumb\": \"http://img5.douban.com/view/photo/thumb/public/p1328238489.jpg\",\n             \"created\": \"2011-12-05 19:54:39\",\n             \"privacy\": \"public\",\n             \"cover\": \"http://img5.douban.com/view/photo/cover/public/p1328238489.jpg\",\n             \"prev_photo\": \"1328256466\",\n             \"liked_count\": 0,\n             \"comments_count\": 0,\n             \"desc\": \"这个是一段连结圣天使古堡和梵蒂冈的圣彼得大教堂的古城墙\",\n             \"next_photo\": \"1328238583\"\n             },\n             {\n             \"liked\": false,\n             \"author\": {\n             \"avatar\": \"http://img3.douban.com/icon/u1645921-14.jpg\",\n             \"alt\": \"http://www.douban.com/people/bear/\",\n             \"id\": \"1645921\",\n             \"name\": \"Bear\",\n             \"uid\": \"bear\"\n             },\n             \"album_id\": \"61434971\",\n             \"image\": \"http://img1.douban.com/view/photo/image/public/p1328238583.jpg\",\n             \"recs_count\": 0,\n             \"alt\": \"http://www.douban.com/photos/photo/1328238583/\",\n             \"album_title\": \"罗马 - 古堡酒店\",\n             \"id\": \"1328238583\",\n             \"icon\": \"http://img1.douban.com/view/photo/icon/public/p1328238583.jpg\",\n             \"position\": 1,\n             \"thumb\": \"http://img1.douban.com/view/photo/thumb/public/p1328238583.jpg\",\n             \"created\": \"2011-12-05 19:54:43\",\n             \"privacy\": \"public\",\n             \"cover\": \"http://img1.douban.com/view/photo/cover/public/p1328238583.jpg\",\n             \"prev_photo\": \"1328238489\",\n             \"liked_count\": 0,\n             \"comments_count\": 0,\n             \"desc\": \"这个就是在古城墙里的酒店，一共就3个房间，很有趣\",\n             \"next_photo\": \"1328238698\"\n             },\n             {\n             \"liked\": false,\n             \"author\": {\n             \"avatar\": \"http://img3.douban.com/icon/u1645921-14.jpg\",\n             \"alt\": \"http://www.douban.com/people/bear/\",\n             \"id\": \"1645921\",\n             \"name\": \"Bear\",\n             \"uid\": \"bear\"\n             },\n             \"album_id\": \"61434971\",\n             \"image\": \"http://img3.douban.com/view/photo/image/public/p1328238698.jpg\",\n             \"recs_count\": 0,\n             \"alt\": \"http://www.douban.com/photos/photo/1328238698/\",\n             \"album_title\": \"罗马 - 古堡酒店\",\n             \"id\": \"1328238698\",\n             \"icon\": \"http://img3.douban.com/view/photo/icon/public/p1328238698.jpg\",\n             \"position\": 2,\n             \"thumb\": \"http://img3.douban.com/view/photo/thumb/public/p1328238698.jpg\",\n             \"created\": \"2011-12-05 19:54:50\",\n             \"privacy\": \"public\",\n             \"cover\": \"http://img3.douban.com/view/photo/cover/public/p1328238698.jpg\",\n             \"prev_photo\": \"1328238583\",\n             \"liked_count\": 0,\n             \"comments_count\": 0,\n             \"desc\": \"\",\n             \"next_photo\": \"1328238792\"\n             }\n             ],\n  \"start\": 0,\n  \"sortby\": \"time\",\n  \"total\": 17,\n  \"order\": \"asc\"\n}"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Testing/DOUTestResponseLoader.h",
    "content": "//\n//  DOUTestResponseLoader.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/17/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"DOUHttpRequest.h\"\n#import \"DOUOAuthService.h\"\n\n\n/**\n 为 DOUHttpRequest 提供异步测试支持\n */\n@interface DOUTestResponseLoader : NSObject<DOUOAuthServiceDelegate>\n\n\n@property (nonatomic, readonly, getter = wasSuccessful) BOOL successful;\n\n@property (nonatomic, readonly, getter = wasCancelled) BOOL cancelled;\n\n@property (nonatomic, readonly, getter = loadedUnexpectedResponse) BOOL unexpectedResponse;\n\n@property (nonatomic, copy, readonly) NSError *error;\n\n@property (nonatomic, assign) NSTimeInterval timeout;\n\n+ (id)responseLoader;\n\n- (void)waitForResponse;\n\n- (NSString *)errorMessage;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/Testing/DOUTestResponseLoader.m",
    "content": "//\n//  DOUTestResponseLoader.m\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/17/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUTestResponseLoader.h\"\n\n\nNSString * const DOUTestResponseLoaderTimeoutException = @\"DOUTestResponseLoaderTimeoutException\";\n\n\n@interface DOUTestResponseLoader ()\n\n@property (nonatomic, assign, getter = isAwaitingResponse) BOOL awaitingResponse;\n//@property (nonatomic, retain, readwrite) DOUHttpResponse *response;\n@property (nonatomic, copy, readwrite) NSError *error;\n\n@end\n\n@implementation DOUTestResponseLoader\n\n//@synthesize response;\n@synthesize error;\n@synthesize successful;\n@synthesize timeout;\n@synthesize cancelled;\n@synthesize unexpectedResponse;\n@synthesize awaitingResponse;\n\n\n+ (DOUTestResponseLoader *)responseLoader {\n  return [[[[self class] alloc] init] autorelease];\n}\n\n\n- (id)init {\n  self = [super init];\n  if (self) {\n    timeout = 4;\n    awaitingResponse = NO;\n  }\n  return self;\n}\n\n\n- (void)dealloc {\n//  [response release]; response = nil;\n  [error release]; error = nil;\n  [super dealloc];\n}\n\n\n- (void)waitForResponse {\n\tawaitingResponse = YES;\n\tNSDate *startDate = [NSDate date];\n  \n\twhile (awaitingResponse) {\n\t\t[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n\t\tif ([[NSDate date] timeIntervalSinceDate:startDate] > self.timeout) {\n\t\t\t[NSException raise:DOUTestResponseLoaderTimeoutException \n                  format:@\"*** Operation timed out after %f seconds...\", self.timeout];\n\t\t\tawaitingResponse = NO;\n\t\t}\n\t}\n}\n\n\n- (void)loadError:(NSError *)theError {\n  awaitingResponse = NO;\n  successful = NO;\n  self.error = theError;\n}\n\n\n- (NSString *)errorMessage {\n  if (self.error) {\n    return [[self.error userInfo] valueForKey:NSLocalizedDescriptionKey];\n  }\n  return nil;\n}\n\n\n#pragma mark - DOUHttpRequestDelegate\n\n- (void)request:(DOUHttpRequest *)aRequest didFail:(NSError *)anError {\n  [self loadError:anError];\n}\n\n\n#pragma mark - DOUOAuthServiceDelegate\n\n- (void)OAuthClient:(DOUOAuthService *)client didAcquireSuccessDictionary:(NSDictionary *)dic {\n  awaitingResponse = NO;\n  successful = YES;\n}\n\n\n- (void)OAuthClient:(DOUOAuthService *)client didFailWithError:(NSError *)error {\n  awaitingResponse = NO;\n  successful = NO;\n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngine/DoubanAPIEngineTests/en.lproj/InfoPlist.strings",
    "content": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 1/16/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (retain, nonatomic) UIWindow *window;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 1/16/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"NavController.h\"\n#import \"DOUAPIEngine.h\"\n\n\n@implementation AppDelegate\n\n// 仅用于此 demo, level 较低，大量使用时会遇到访问限制。实际使用，请重新申请。\nstatic NSString * const kAPIKey = @\"04e0b2ab7ca02a8a0ea2180275e07f9e\";\nstatic NSString * const kPrivateKey = @\"4275ee2fa3689a2f\";\nstatic NSString * const kRedirectUrl = @\"http://www.douban.com/location/mobile\";\n\n@synthesize window = window_;\n\n\n- (void)dealloc {\n  [window_ release];\n  [super dealloc];\n}\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n  \n  DOUService *service = [DOUService sharedInstance];\n  service.clientId = kAPIKey;\n  service.clientSecret = kPrivateKey;\n  if ([service isValid]) {\n    service.apiBaseUrlString = kHttpsApiBaseUrl;\n  }\n  else {\n    service.apiBaseUrlString = kHttpApiBaseUrl;\n  }\n  \n  \n  self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];\n\n  NavController *navController = [[[NavController alloc] initWithNibName:@\"NavController\" \n                                                                  bundle:nil] autorelease];\n  \n  UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:navController] autorelease];\n  self.window.rootViewController = nav;\n  [self.window makeKeyAndVisible];\n  return YES;\n}\n\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n  /*\n   Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n   Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n   */\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n  /*\n   Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. \n   If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n   */\n}\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n  /*\n   Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n   */\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n  /*\n   Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n   */\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n  /*\n   Called when the application is about to terminate.\n   Save data if appropriate.\n   See also applicationDidEnterBackground:.\n   */\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/DoubanAPIEngineDemo-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>${PRODUCT_NAME}</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${EXECUTABLE_NAME}</string>\n\t<key>CFBundleIconFiles</key>\n\t<array/>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.douban.album</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>${PRODUCT_NAME}</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1.0</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/DoubanAPIEngineDemo-Prefix.pch",
    "content": "//\n// Prefix header for all source files of the 'DoubanAPIEngineDemo' target in the 'DoubanAPIEngineDemo' project\n//\n\n#import <Availability.h>\n\n#ifndef __IPHONE_4_0\n#warning \"This project uses features only available in iOS SDK 4.0 and later.\"\n#endif\n\n#ifdef __OBJC__\n  #import <UIKit/UIKit.h>\n  #import <Foundation/Foundation.h>\n#endif\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/DoubanQueryEvent.h",
    "content": "//\n//  DOUQueryEvent.h\n//  DoubanEvent\n//\n//  Created by Lin GUO on 11-11-8.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"DOUAPIEngine.h\"\n\n\n@interface DoubanQueryEvent : DOUQuery\n\n+ (id)queryForEventById:(int)eventId;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/DoubanQueryEvent.m",
    "content": "//\n//  DOUQueryEvent.m\n//  DoubanEvent\n//\n//  Created by Lin GUO on 11-11-8.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DoubanQueryEvent.h\"\n\n@implementation DoubanQueryEvent\n\n\n+ (id)queryForEventById:(int)eventId {\n  NSString *subPath = [NSString stringWithFormat:@\"/v2/event/%d\", eventId];\n  DOUQuery *query = [[DOUQuery alloc] initWithSubPath:subPath parameters:nil];\n  return [query autorelease];\n}\n\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/GetEventController.h",
    "content": "//\n//  GetEventController.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n\n@class DOUEvent;\n@interface GetEventController : UIViewController {\n @private\n  DOUEvent *event_;\n\n  IBOutlet UILabel *titleLabel_;\n  IBOutlet UILabel *timeLabel_;\n  IBOutlet UILabel *whereLabel_;\n  IBOutlet UILabel *contentLabel_;\n\n}\n\n@property (nonatomic, retain) DOUEvent *event;\n\n@property (nonatomic, retain) UILabel *titleLabel;\n@property (nonatomic, retain) UILabel *timeLabel;\n@property (nonatomic, retain) UILabel *whereLabel;\n@property (nonatomic, retain) UILabel *contentLabel;\n\n- (IBAction)showInfo:(id)sender;\n\n- (void)updateUI;\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/GetEventController.m",
    "content": "//\n//  MainViewController.m\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GetEventController.h\"\n\n#import \"DOUAPIEngine.h\"\n#import \"DOUEvent.h\"\n#import \"DoubanQueryEvent.h\"\n\n@implementation GetEventController\n\n@synthesize event = event_;\n@synthesize titleLabel = titleLabel_;\n@synthesize timeLabel  = timeLabel_;\n@synthesize whereLabel = whereLabel_;\n@synthesize contentLabel = contentLabel_;\n\n\n#pragma mark - View lifecycle\n\n- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {\n  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];\n  if (self) {\n    self.title = @\"Get 活动信息\";\n  }\n  return self;\n}\n\n\n- (void)dealloc {\n  [event_ release]; event_ = nil;\n  [timeLabel_ release]; timeLabel_ = nil;\n  [whereLabel_ release]; whereLabel_ = nil;\n  [contentLabel_ release]; contentLabel_ = nil;\n  [super dealloc];\n}\n\n\n- (void)viewDidUnload {\n  [super viewDidUnload];\n  self.event = nil;\n  self.titleLabel = nil;\n  self.timeLabel = nil;\n  self.whereLabel = nil;\n  self.contentLabel = nil;\n}\n\n\n- (void)updateUI {\n  titleLabel_.text = [self.event title];\n  timeLabel_.text = [self.event beginTimeStr];\n  whereLabel_.text = [self.event address];\n  contentLabel_.text = [self.event content];\n}\n\n\n- (IBAction)showInfo:(id)sender {\n  DOUService *service = [DOUService sharedInstance];\n  service.apiBaseUrlString = kHttpApiBaseUrl;\n  \n  DOUQuery *query = [DoubanQueryEvent queryForEventById:14910931];\n\n  DOUReqBlock completionBlock = ^(DOUHttpRequest *req){\n    NSLog(@\"str:%@\", [req responseString]);\n    NSError *error = [req doubanError];\n    if (!error) {\n      \n      DOUEvent *newEvent = [[DOUEvent alloc] initWithString:[req responseString]];\n      self.event = newEvent;\n      [newEvent release];\n      [self updateUI];\n    }    \n  };\n  \n  [service get:query callback:completionBlock];\n}\n\n\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/NavController.h",
    "content": "//\n//  NavController.h\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 3/26/12.\n//  Copyright (c) 2012 douban Inc. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface NavController : UIViewController<UITableViewDelegate, UITableViewDataSource, UINavigationControllerDelegate, UIImagePickerControllerDelegate> {\n @private\n  IBOutlet UITableView *tableView_;\n}\n\n@property (nonatomic, retain) UITableView *tableView;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/NavController.m",
    "content": "//\n//  NavController.m\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 3/26/12.\n//  Copyright (c) 2012 douban Inc. All rights reserved.\n//\n#import <MobileCoreServices/MobileCoreServices.h>\n#import \"NavController.h\"\n#import \"GetEventController.h\"\n#import \"StatusController.h\"\n#import \"WebViewController.h\"\n#import \"DOUAPIEngine.h\"\n\n\n@implementation NavController\n\n@synthesize tableView = tableView_;\n\n\n- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {\n  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];\n  if (self) {\n    self.title = @\"演示\";\n  }\n  return self;\n}\n\n\n#pragma mark - View lifecycle\n\n- (void)viewDidLoad {\n\n}\n\n\n- (void)viewDidUnload {\n  self.tableView = nil;\n  [super viewDidUnload];\n}\n\n\n- (void)dealloc {\n  [tableView_ release];\n  [super dealloc];\n}\n\n\n#pragma mark -\n#pragma mark UITableViewDataSource's methods\n\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{\n  return 1;\n}\n\n\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n  return 4;\n}\n\n\n- (UITableViewCell *)tableView:(UITableView *)tableView \n         cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n  \n  static NSString* cellIdentifier = @\"TableViewCell\";\n  \n  UITableViewCell* cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];\n  if (cell == nil) {\n    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault \n                                   reuseIdentifier:cellIdentifier] autorelease];\n  }\n  \n  NSUInteger row = [indexPath row];\n  if (row == 0) {\n    cell.textLabel.text = @\"登录\";\n  }\n  else if (row == 1) {\n    cell.textLabel.text = @\"条目信息 v2\";\n  }\n  else if (row == 2) {\n    cell.textLabel.text = @\"发广播 v2\";\n  }\n  else if (row == 3) {\n    cell.textLabel.text = @\"Post 照片 v2\";\n  }\n  \n  return cell;\n}\n\n\n#pragma mark -\n#pragma mark UITableViewDelegate's methods\n\nstatic NSString * const kAPIKey = @\"04e0b2ab7ca02a8a0ea2180275e07f9e\";\nstatic NSString * const kPrivateKey = @\"4275ee2fa3689a2f\";\nstatic NSString * const kRedirectUrl = @\"http://www.douban.com/location/mobile\";\n\n\n- (void)tableView:(UITableView *)tableView \n    didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\n  \n  if ([indexPath row] == 0) {\n    NSString *str = [NSString stringWithFormat:@\"https://www.douban.com/service/auth2/auth?client_id=%@&redirect_uri=%@&response_type=code\", kAPIKey, kRedirectUrl];\n    \n    NSString *urlStr = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];\n    NSURL *url = [NSURL URLWithString:urlStr];\n    UIViewController *webViewController = [[WebViewController alloc] initWithRequestURL:url];\n    [self.navigationController pushViewController:webViewController animated:YES];\n      [webViewController release];\n  }\n  else if ([indexPath row] == 1) {\n    UIViewController *getEventController = [[GetEventController alloc] initWithNibName:@\"GetEventController\" \n                                                                                bundle:nil];\n    [self.navigationController pushViewController:getEventController animated:YES];\n      [getEventController release];\n  }\n   else if ([indexPath row] == 2){\n    UIViewController *statusController = [[StatusController alloc] init];\n    [self.navigationController pushViewController:statusController animated:YES];\n       [statusController release];\n  }\n  else if ([indexPath row] == 3) {\n      UIImagePickerController *photoController = [[[UIImagePickerController alloc] init]autorelease];\n    photoController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;\n    [self.navigationController presentModalViewController:photoController animated:YES]; \n    photoController.delegate = self;\n  }\n\n  [tableView deselectRowAtIndexPath:indexPath animated:YES];\n}\n\n\n- (void)imagePickerController:(UIImagePickerController *)picker\n    didFinishPickingMediaWithInfo:(NSDictionary *)info {\n\n  NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];\n  \n  if ([mediaType isEqualToString:(NSString *)kUTTypeMovie] == YES){\n\n  }  \n  else if ([mediaType isEqualToString:(NSString *)kUTTypeImage] == YES){\n    UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];\n    \n    if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {\n      UIImageWriteToSavedPhotosAlbum(pickedImage, nil, nil , nil);\n    }\n        \n    NSData *imageData = UIImagePNGRepresentation(pickedImage);    \n    DOUService *service = [DOUService sharedInstance];\n    NSString *subPath = [NSString stringWithFormat:@\"/album/%@\", @\"43672487\"];\n    DOUQuery *query = [[[DOUQuery alloc] initWithSubPath:subPath parameters:nil]autorelease];\n    DOUReqBlock completionBlock = ^(DOUHttpRequest *req){\n    \n    };\n  \n    [service post2:query\n         photoData:imageData\n       description:@\"description\"\n          callback:completionBlock\nuploadProgressDelegate:nil];\n    \n  }\n    \n  \n  [picker dismissModalViewControllerAnimated:YES];\n  \n}\n\n\n- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{\n  [picker dismissModalViewControllerAnimated:YES];\n}\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/NavController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<archive type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"8.00\">\n\t<data>\n\t\t<int key=\"IBDocument.SystemTarget\">1536</int>\n\t\t<string key=\"IBDocument.SystemVersion\">12C60</string>\n\t\t<string key=\"IBDocument.InterfaceBuilderVersion\">2840</string>\n\t\t<string key=\"IBDocument.AppKitVersion\">1187.34</string>\n\t\t<string key=\"IBDocument.HIToolboxVersion\">625.00</string>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginVersions\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t<string key=\"NS.object.0\">1926</string>\n\t\t</object>\n\t\t<array key=\"IBDocument.IntegratedClassDependencies\">\n\t\t\t<string>IBProxyObject</string>\n\t\t\t<string>IBUITableView</string>\n\t\t\t<string>IBUIView</string>\n\t\t</array>\n\t\t<array key=\"IBDocument.PluginDependencies\">\n\t\t\t<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t</array>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.Metadata\">\n\t\t\t<string key=\"NS.key.0\">PluginDependencyRecalculationVersion</string>\n\t\t\t<integer value=\"1\" key=\"NS.object.0\"/>\n\t\t</object>\n\t\t<array class=\"NSMutableArray\" key=\"IBDocument.RootObjects\" id=\"1000\">\n\t\t\t<object class=\"IBProxyObject\" id=\"841351856\">\n\t\t\t\t<string key=\"IBProxiedObjectIdentifier\">IBFilesOwner</string>\n\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t</object>\n\t\t\t<object class=\"IBProxyObject\" id=\"371349661\">\n\t\t\t\t<string key=\"IBProxiedObjectIdentifier\">IBFirstResponder</string>\n\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t</object>\n\t\t\t<object class=\"IBUIView\" id=\"884324498\">\n\t\t\t\t<reference key=\"NSNextResponder\"/>\n\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t<array class=\"NSMutableArray\" key=\"NSSubviews\">\n\t\t\t\t\t<object class=\"IBUITableView\" id=\"261895632\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"884324498\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">274</int>\n\t\t\t\t\t\t<string key=\"NSFrameSize\">{320, 460}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"884324498\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:418</string>\n\t\t\t\t\t\t<object class=\"NSColor\" key=\"IBUIBackgroundColor\">\n\t\t\t\t\t\t\t<int key=\"NSColorSpace\">1</int>\n\t\t\t\t\t\t\t<bytes key=\"NSRGB\">MCAwIDAgMAA</bytes>\n\t\t\t\t\t\t\t<string key=\"IBUIColorCocoaTouchKeyPath\">groupTableViewBackgroundColor</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<bool key=\"IBUIAlwaysBounceVertical\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIStyle\">1</int>\n\t\t\t\t\t\t<int key=\"IBUISeparatorStyle\">2</int>\n\t\t\t\t\t\t<int key=\"IBUISectionIndexMinimumDisplayRowCount\">0</int>\n\t\t\t\t\t\t<bool key=\"IBUIShowsSelectionImmediatelyOnTouchBegin\">YES</bool>\n\t\t\t\t\t\t<float key=\"IBUIRowHeight\">44</float>\n\t\t\t\t\t\t<float key=\"IBUISectionHeaderHeight\">10</float>\n\t\t\t\t\t\t<float key=\"IBUISectionFooterHeight\">10</float>\n\t\t\t\t\t</object>\n\t\t\t\t</array>\n\t\t\t\t<string key=\"NSFrameSize\">{320, 460}</string>\n\t\t\t\t<reference key=\"NSSuperview\"/>\n\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"261895632\"/>\n\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:196</string>\n\t\t\t\t<object class=\"NSColor\" key=\"IBUIBackgroundColor\">\n\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t<bytes key=\"NSWhite\">MQA</bytes>\n\t\t\t\t\t<object class=\"NSColorSpace\" key=\"NSCustomColorSpace\">\n\t\t\t\t\t\t<int key=\"NSID\">2</int>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t</object>\n\t\t</array>\n\t\t<object class=\"IBObjectContainer\" key=\"IBDocument.Objects\">\n\t\t\t<array class=\"NSMutableArray\" key=\"connectionRecords\">\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">tableView_</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"841351856\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"261895632\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">4</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">view</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"841351856\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"884324498\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">5</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">dataSource</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"261895632\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"841351856\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">6</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">delegate</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"261895632\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"841351856\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">7</int>\n\t\t\t\t</object>\n\t\t\t</array>\n\t\t\t<object class=\"IBMutableOrderedSet\" key=\"objectRecords\">\n\t\t\t\t<array key=\"orderedObjects\">\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">0</int>\n\t\t\t\t\t\t<array key=\"object\" id=\"0\"/>\n\t\t\t\t\t\t<reference key=\"children\" ref=\"1000\"/>\n\t\t\t\t\t\t<nil key=\"parent\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-1</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"841351856\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">File's Owner</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-2</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"371349661\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">2</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"884324498\"/>\n\t\t\t\t\t\t<array class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<reference ref=\"261895632\"/>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">3</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"261895632\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"884324498\"/>\n\t\t\t\t\t</object>\n\t\t\t\t</array>\n\t\t\t</object>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"flattenedProperties\">\n\t\t\t\t<string key=\"-1.CustomClassName\">NavController</string>\n\t\t\t\t<string key=\"-1.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"-2.CustomClassName\">UIResponder</string>\n\t\t\t\t<string key=\"-2.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"2.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"3.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t</dictionary>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"unlocalizedProperties\"/>\n\t\t\t<nil key=\"activeLocalization\"/>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"localizations\"/>\n\t\t\t<nil key=\"sourceID\"/>\n\t\t\t<int key=\"maxID\">7</int>\n\t\t</object>\n\t\t<object class=\"IBClassDescriber\" key=\"IBDocument.Classes\">\n\t\t\t<array class=\"NSMutableArray\" key=\"referencedPartialClassDescriptions\">\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">NavController</string>\n\t\t\t\t\t<string key=\"superclassName\">UIViewController</string>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"outlets\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">tableView_</string>\n\t\t\t\t\t\t<string key=\"NS.object.0\">UITableView</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"toOneOutletInfosByName\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">tableView_</string>\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"NS.object.0\">\n\t\t\t\t\t\t\t<string key=\"name\">tableView_</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">UITableView</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBProjectSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">./Classes/NavController.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t</array>\n\t\t</object>\n\t\t<int key=\"IBDocument.localizationMode\">0</int>\n\t\t<string key=\"IBDocument.TargetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t<bool key=\"IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion\">YES</bool>\n\t\t<int key=\"IBDocument.defaultPropertyAccessControl\">3</int>\n\t\t<string key=\"IBCocoaTouchPluginVersion\">1926</string>\n\t</data>\n</archive>\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/PhotosController.h",
    "content": "//\n//  PhotosController.h\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 3/26/12.\n//  Copyright (c) 2012 douban Inc.  All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface PhotosController : UIViewController\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/PhotosController.m",
    "content": "//\n//  PhotosController.m\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 3/26/12.\n//  Copyright (c) 2012 douban Inc. All rights reserved.\n//\n\n#import \"PhotosController.h\"\n\n@implementation PhotosController\n\n- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {\n  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];\n  if (self) {\n        // Custom initialization\n  }\n  return self;\n}\n\n\n#pragma mark - View lifecycle\n\n\n\n/**\n * 需要 scope: community_advanced_photo\n */\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/StatusController.h",
    "content": "//\n//  StatusController.h\n//  DoubanAPIEngineDemo\n//\n//  Created by GUO Lin on 11/23/12.\n//\n//\n\n#import <UIKit/UIKit.h>\n\n@interface StatusController : UIViewController<UITextViewDelegate>\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/StatusController.m",
    "content": "//\n//  StatusController.m\n//  DoubanAPIEngineDemo\n//\n//  Created by GUO Lin on 11/23/12.\n//\n//\n\n#import \"StatusController.h\"\n#import \"DOUQuery.h\"\n#import \"DOUAPIEngine.h\"\n\n\n@interface DoubanQueryStatus : DOUQuery\n\n+ (id)queryForStatus;\n\n@end\n\n\n@implementation DoubanQueryStatus\n\n+ (id)queryForStatus {\n  NSString *subPath = @\"/shuo/v2/statuses/\";\n  \n  DOUQuery *query = [[DOUQuery alloc] initWithSubPath:subPath parameters:nil];\n  \n  return [query autorelease];\n}\n\n@end\n\n\n\n\n@interface StatusController ()\n\n@property (nonatomic, retain) UITextView       *contentField;\n\n@end\n\n\n@implementation StatusController\n\n@synthesize contentField = contentField_;\n\n- (void)viewDidLoad\n{\n  [super viewDidLoad];\n  self.title = @\"发广播 v2\";\n  self.view.backgroundColor = [UIColor whiteColor];\n  \n  UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone\n                                                                              target:self\n                                                                              action:@selector(post)];\n  self.navigationItem.rightBarButtonItem = buttonItem;\n  [buttonItem release];\n  \n  contentField_ = [[UITextView alloc] initWithFrame:CGRectMake(30, 10, 260, 140)];\n  contentField_.autocapitalizationType = UITextAutocapitalizationTypeNone;\n  contentField_.showsHorizontalScrollIndicator = YES;\n  contentField_.returnKeyType = UIReturnKeyDone;\n  contentField_.delegate = self;\n  contentField_.backgroundColor = [UIColor lightGrayColor];\n  [self.view addSubview:contentField_];\n  contentField_.text = @\"来一发\";\n  [contentField_ becomeFirstResponder];\n}\n\n\n- (void)dealloc {\n  [contentField_ release];\n  [super dealloc];\n}\n\n\n- (void)didReceiveMemoryWarning\n{\n    [super didReceiveMemoryWarning];\n    // Dispose of any resources that can be recreated.\n}\n\n\n/**\n * 需要 scope: shuo_basic_w\n */\n- (void)post {\n  \n  DOUQuery *query = [DoubanQueryStatus queryForStatus];\n  \n  DOUReqBlock completionBlock = ^(DOUHttpRequest * req) {\n    \n    NSLog(@\"code:%d, str:%@\", [req responseStatusCode], [req responseString]);\n    NSError *theError = [req doubanError];\n    if (!theError) {\n      NSLog(@\"发送成功\");\n    }\n    else {\n      NSLog(@\"%@\", theError);\n    }\n    \n  };\n  \n  NSString *text = contentField_.text;\n  if (!text || [text length] == 0) {\n    text = @\"来一发\";\n  }\n  NSMutableString *postBody = [NSMutableString stringWithFormat:@\"text=%@\", text];\n  DOUService *service = [DOUService sharedInstance];\n  NSLog(@\"postBody:%@\", postBody);\n  [service post:query postBody:postBody callback:completionBlock];\n  \n}\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/WebViewController.h",
    "content": "//\n//  WebViewController.h\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 3/26/12.\n//  Copyright (c) 2012 douban Inc. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"DOUOAuthService.h\"\n\n@interface WebViewController : UIViewController<UIWebViewDelegate, DOUOAuthServiceDelegate>\n\n- (id)initWithRequestURL:(NSURL *)aURL;\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/WebViewController.m",
    "content": "//\n//  WebViewController.m\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 3/26/12.\n//  Copyright (c) 2012 douban Inc. All rights reserved.\n//\n\n#import \"WebViewController.h\"\n#import \"DOUAPIEngine.h\"\n\n\nstatic NSString * const kAPIKey = @\"04e0b2ab7ca02a8a0ea2180275e07f9e\";\nstatic NSString * const kPrivateKey = @\"4275ee2fa3689a2f\";\nstatic NSString * const kRedirectUrl = @\"http://www.douban.com/location/mobile\";\n\n\n@interface NSString (ParseCategory)\n- (NSMutableDictionary *)explodeToDictionaryInnerGlue:(NSString *)innerGlue \n                                           outterGlue:(NSString *)outterGlue;\n@end\n\n@implementation NSString (ParseCategory)\n\n- (NSMutableDictionary *)explodeToDictionaryInnerGlue:(NSString *)innerGlue \n                                           outterGlue:(NSString *)outterGlue {\n  // Explode based on outter glue\n  NSArray *firstExplode = [self componentsSeparatedByString:outterGlue];\n  NSArray *secondExplode;\n  \n  // Explode based on inner glue\n  NSInteger count = [firstExplode count];\n  NSMutableDictionary* returnDictionary = [NSMutableDictionary dictionaryWithCapacity:count];\n  for (NSInteger i = 0; i < count; i++) {\n    secondExplode = \n    [(NSString*)[firstExplode objectAtIndex:i] componentsSeparatedByString:innerGlue];\n    if ([secondExplode count] == 2) {\n      [returnDictionary setObject:[secondExplode objectAtIndex:1] \n                           forKey:[secondExplode objectAtIndex:0]];\n    }\n  }\n  return returnDictionary;\n}\n\n@end\n\n\n@interface WebViewController ()\n\n@property (nonatomic, retain) UIWebView *webView;\n@property (nonatomic, retain) NSURL *requestURL;\n\n@end\n\n\n@implementation WebViewController\n\n@synthesize webView = webView_;\n@synthesize requestURL = requestURL_;\n\n\n#pragma mark - View lifecycle\n\n- (id)initWithRequestURL:(NSURL *)aURL {\n  self = [super init];\n  if (self) {\n    self.requestURL = aURL;\n  }\n  return self;\n}\n\n\n- (void)viewDidLoad {\n  [super viewDidLoad];\n  self.navigationItem.title = @\"登录\"; \n  webView_ = [[UIWebView alloc] initWithFrame:CGRectMake(0, \n                                                         0, \n                                                         self.view.bounds.size.width, \n                                                         self.view.bounds.size.height - 49)];\n  webView_.scalesPageToFit = YES;\n  webView_.delegate = self;\n  NSURLRequest *request = [NSURLRequest requestWithURL:requestURL_];\n  [webView_ loadRequest:request];\n  [self.view addSubview:webView_];    \n\n}\n\n\n- (void)viewDidUnload {\n  self.webView = nil;\n  self.requestURL = nil;\n  [super viewDidUnload];\n}\n\n\n- (void)dealloc {\n  [webView_ release];\n  [requestURL_ release];\n  [super dealloc];\n}\n\n\n#pragma mark - UIWebViewDelegate\n\n- (BOOL)webView:(UIWebView *)webView\nshouldStartLoadWithRequest:(NSURLRequest *)request\n navigationType:(UIWebViewNavigationType)navigationType {\n  \n  NSURL *urlObj =  [request URL];\n  NSString *url = [urlObj absoluteString];\n  \n   \n  if ([url hasPrefix:kRedirectUrl]) {\n    \n    NSString* query = [urlObj query];\n    NSMutableDictionary *parsedQuery = [query explodeToDictionaryInnerGlue:@\"=\" \n                                                                outterGlue:@\"&\"];\n\n    //access_denied\n    NSString *error = [parsedQuery objectForKey:@\"error\"];\n    if (error) {\n        return NO;\n    }\n      \n    //access_accept\n    NSString *code = [parsedQuery objectForKey:@\"code\"];\n    DOUOAuthService *service = [DOUOAuthService sharedInstance];\n    service.authorizationURL = kTokenUrl;\n    service.delegate = self;\n    service.clientId = kAPIKey;\n    service.clientSecret = kPrivateKey;\n    service.callbackURL = kRedirectUrl;\n    service.authorizationCode = code;\n\n    [service validateAuthorizationCode];\n    \n    return NO;\n  }\n  \n  return YES;\n}\n\n\n- (void)OAuthClient:(DOUOAuthService *)client didAcquireSuccessDictionary:(NSDictionary *)dic {\n  NSLog(@\"success!\");\n  [self.navigationController popViewControllerAnimated:YES];\n\n}\n\n- (void)OAuthClient:(DOUOAuthService *)client didFailWithError:(NSError *)error {\n  NSLog(@\"Fail!\");\n}\n\n\n\n@end\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/en.lproj/GetEventController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<archive type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"8.00\">\n\t<data>\n\t\t<int key=\"IBDocument.SystemTarget\">1280</int>\n\t\t<string key=\"IBDocument.SystemVersion\">11D50d</string>\n\t\t<string key=\"IBDocument.InterfaceBuilderVersion\">1938</string>\n\t\t<string key=\"IBDocument.AppKitVersion\">1138.32</string>\n\t\t<string key=\"IBDocument.HIToolboxVersion\">568.00</string>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginVersions\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t<string key=\"NS.object.0\">933</string>\n\t\t</object>\n\t\t<array key=\"IBDocument.IntegratedClassDependencies\">\n\t\t\t<string>IBUIButton</string>\n\t\t\t<string>IBUIView</string>\n\t\t\t<string>IBUILabel</string>\n\t\t\t<string>IBProxyObject</string>\n\t\t</array>\n\t\t<array key=\"IBDocument.PluginDependencies\">\n\t\t\t<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t</array>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.Metadata\">\n\t\t\t<string key=\"NS.key.0\">PluginDependencyRecalculationVersion</string>\n\t\t\t<integer value=\"1\" key=\"NS.object.0\"/>\n\t\t</object>\n\t\t<array class=\"NSMutableArray\" key=\"IBDocument.RootObjects\" id=\"1000\">\n\t\t\t<object class=\"IBProxyObject\" id=\"372490531\">\n\t\t\t\t<string key=\"IBProxiedObjectIdentifier\">IBFilesOwner</string>\n\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t</object>\n\t\t\t<object class=\"IBProxyObject\" id=\"815241450\">\n\t\t\t\t<string key=\"IBProxiedObjectIdentifier\">IBFirstResponder</string>\n\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t</object>\n\t\t\t<object class=\"IBUIView\" id=\"883825266\">\n\t\t\t\t<reference key=\"NSNextResponder\"/>\n\t\t\t\t<int key=\"NSvFlags\">274</int>\n\t\t\t\t<array class=\"NSMutableArray\" key=\"NSSubviews\">\n\t\t\t\t\t<object class=\"IBUIButton\" id=\"558454645\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">265</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{195, 369}, {100, 38}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClearsContextBeforeDrawing\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<int key=\"IBUIContentHorizontalAlignment\">0</int>\n\t\t\t\t\t\t<int key=\"IBUIContentVerticalAlignment\">0</int>\n\t\t\t\t\t\t<int key=\"IBUIButtonType\">1</int>\n\t\t\t\t\t\t<string key=\"IBUINormalTitle\">走一个</string>\n\t\t\t\t\t\t<object class=\"NSColor\" key=\"IBUIHighlightedTitleColor\" id=\"659679425\">\n\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MQA</bytes>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSColor\" key=\"IBUINormalTitleColor\">\n\t\t\t\t\t\t\t<int key=\"NSColorSpace\">1</int>\n\t\t\t\t\t\t\t<bytes key=\"NSRGB\">MC4xOTYwNzg0MzE0IDAuMzA5ODAzOTIxNiAwLjUyMTU2ODYyNzUAA</bytes>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSColor\" key=\"IBUINormalTitleShadowColor\">\n\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MC41AA</bytes>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"IBUIFontDescription\" key=\"IBUIFontDescription\">\n\t\t\t\t\t\t\t<int key=\"type\">2</int>\n\t\t\t\t\t\t\t<int key=\"size\">2</int>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSFont\" key=\"IBUIFont\">\n\t\t\t\t\t\t\t<string key=\"NSName\">Helvetica-Bold</string>\n\t\t\t\t\t\t\t<double key=\"NSSize\">18</double>\n\t\t\t\t\t\t\t<int key=\"NSfFlags\">16</int>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"865697934\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{15, 42}, {280, 28}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"809284510\"/>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\"/>\n\t\t\t\t\t\t<object class=\"NSColor\" key=\"IBUITextColor\" id=\"638622435\">\n\t\t\t\t\t\t\t<int key=\"NSColorSpace\">1</int>\n\t\t\t\t\t\t\t<bytes key=\"NSRGB\">MCAwIDAAA</bytes>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<object class=\"IBUIFontDescription\" key=\"IBUIFontDescription\" id=\"1072863636\">\n\t\t\t\t\t\t\t<int key=\"type\">1</int>\n\t\t\t\t\t\t\t<double key=\"pointSize\">17</double>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSFont\" key=\"IBUIFont\" id=\"443575077\">\n\t\t\t\t\t\t\t<string key=\"NSName\">Helvetica</string>\n\t\t\t\t\t\t\t<double key=\"NSSize\">17</double>\n\t\t\t\t\t\t\t<int key=\"NSfFlags\">16</int>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"948703008\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{15, 99}, {280, 23}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"25331779\"/>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\"/>\n\t\t\t\t\t\t<reference key=\"IBUITextColor\" ref=\"638622435\"/>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<reference key=\"IBUIFontDescription\" ref=\"1072863636\"/>\n\t\t\t\t\t\t<reference key=\"IBUIFont\" ref=\"443575077\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"384037290\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{15, 157}, {280, 40}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"658976563\"/>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\"/>\n\t\t\t\t\t\t<reference key=\"IBUITextColor\" ref=\"638622435\"/>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<int key=\"IBUINumberOfLines\">2</int>\n\t\t\t\t\t\t<reference key=\"IBUIFontDescription\" ref=\"1072863636\"/>\n\t\t\t\t\t\t<reference key=\"IBUIFont\" ref=\"443575077\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"966680524\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{15, 245}, {280, 103}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"558454645\"/>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\"/>\n\t\t\t\t\t\t<reference key=\"IBUITextColor\" ref=\"638622435\"/>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<int key=\"IBUINumberOfLines\">0</int>\n\t\t\t\t\t\t<reference key=\"IBUIFontDescription\" ref=\"1072863636\"/>\n\t\t\t\t\t\t<reference key=\"IBUIFont\" ref=\"443575077\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"344753243\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{7, 13}, {51, 21}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"865697934\"/>\n\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:328</string>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\">标题：</string>\n\t\t\t\t\t\t<reference key=\"IBUITextColor\" ref=\"638622435\"/>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<object class=\"IBUIFontDescription\" key=\"IBUIFontDescription\" id=\"12649251\">\n\t\t\t\t\t\t\t<int key=\"type\">2</int>\n\t\t\t\t\t\t\t<double key=\"pointSize\">17</double>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSFont\" key=\"IBUIFont\" id=\"531656890\">\n\t\t\t\t\t\t\t<string key=\"NSName\">Helvetica-Bold</string>\n\t\t\t\t\t\t\t<double key=\"NSSize\">17</double>\n\t\t\t\t\t\t\t<int key=\"NSfFlags\">16</int>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"809284510\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{7, 78}, {51, 21}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"948703008\"/>\n\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:328</string>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\">时间：</string>\n\t\t\t\t\t\t<reference key=\"IBUITextColor\" ref=\"638622435\"/>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<reference key=\"IBUIFontDescription\" ref=\"12649251\"/>\n\t\t\t\t\t\t<reference key=\"IBUIFont\" ref=\"531656890\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"25331779\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{7, 128}, {51, 21}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"384037290\"/>\n\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:328</string>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\">地址：</string>\n\t\t\t\t\t\t<reference key=\"IBUITextColor\" ref=\"638622435\"/>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<reference key=\"IBUIFontDescription\" ref=\"12649251\"/>\n\t\t\t\t\t\t<reference key=\"IBUIFont\" ref=\"531656890\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBUILabel\" id=\"658976563\">\n\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"883825266\"/>\n\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t<string key=\"NSFrame\">{{7, 219}, {51, 21}}</string>\n\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"883825266\"/>\n\t\t\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"966680524\"/>\n\t\t\t\t\t\t<string key=\"NSReuseIdentifierKey\">_NS:328</string>\n\t\t\t\t\t\t<bool key=\"IBUIOpaque\">NO</bool>\n\t\t\t\t\t\t<bool key=\"IBUIClipsSubviews\">YES</bool>\n\t\t\t\t\t\t<int key=\"IBUIContentMode\">7</int>\n\t\t\t\t\t\t<bool key=\"IBUIUserInteractionEnabled\">NO</bool>\n\t\t\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t\t\t\t<string key=\"IBUIText\">简介：</string>\n\t\t\t\t\t\t<reference key=\"IBUITextColor\" ref=\"638622435\"/>\n\t\t\t\t\t\t<nil key=\"IBUIHighlightedColor\"/>\n\t\t\t\t\t\t<int key=\"IBUIBaselineAdjustment\">1</int>\n\t\t\t\t\t\t<float key=\"IBUIMinimumFontSize\">10</float>\n\t\t\t\t\t\t<reference key=\"IBUIFontDescription\" ref=\"12649251\"/>\n\t\t\t\t\t\t<reference key=\"IBUIFont\" ref=\"531656890\"/>\n\t\t\t\t\t</object>\n\t\t\t\t</array>\n\t\t\t\t<string key=\"NSFrame\">{{0, 64}, {320, 416}}</string>\n\t\t\t\t<reference key=\"NSSuperview\"/>\n\t\t\t\t<reference key=\"NSWindow\"/>\n\t\t\t\t<reference key=\"NSNextKeyView\" ref=\"344753243\"/>\n\t\t\t\t<reference key=\"IBUIBackgroundColor\" ref=\"659679425\"/>\n\t\t\t\t<bool key=\"IBUIClearsContextBeforeDrawing\">NO</bool>\n\t\t\t\t<object class=\"IBUISimulatedStatusBarMetrics\" key=\"IBUISimulatedStatusBarMetrics\"/>\n\t\t\t\t<object class=\"IBUISimulatedNavigationBarMetrics\" key=\"IBUISimulatedTopBarMetrics\">\n\t\t\t\t\t<bool key=\"IBUIPrompted\">NO</bool>\n\t\t\t\t</object>\n\t\t\t\t<string key=\"targetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t\t</object>\n\t\t</array>\n\t\t<object class=\"IBObjectContainer\" key=\"IBDocument.Objects\">\n\t\t\t<array class=\"NSMutableArray\" key=\"connectionRecords\">\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">view</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"372490531\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"883825266\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">35</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">contentLabel_</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"372490531\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"966680524\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">44</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">whereLabel_</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"372490531\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"384037290\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">45</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">timeLabel_</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"372490531\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"948703008\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">46</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">titleLabel_</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"372490531\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"865697934\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">47</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBCocoaTouchEventConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">showInfo:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"558454645\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"372490531\"/>\n\t\t\t\t\t\t<int key=\"IBEventType\">7</int>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">38</int>\n\t\t\t\t</object>\n\t\t\t</array>\n\t\t\t<object class=\"IBMutableOrderedSet\" key=\"objectRecords\">\n\t\t\t\t<array key=\"orderedObjects\">\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">0</int>\n\t\t\t\t\t\t<array key=\"object\" id=\"0\"/>\n\t\t\t\t\t\t<reference key=\"children\" ref=\"1000\"/>\n\t\t\t\t\t\t<nil key=\"parent\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-1</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"372490531\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">File's Owner</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-2</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"815241450\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">34</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"883825266\"/>\n\t\t\t\t\t\t<array class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<reference ref=\"966680524\"/>\n\t\t\t\t\t\t\t<reference ref=\"344753243\"/>\n\t\t\t\t\t\t\t<reference ref=\"865697934\"/>\n\t\t\t\t\t\t\t<reference ref=\"948703008\"/>\n\t\t\t\t\t\t\t<reference ref=\"384037290\"/>\n\t\t\t\t\t\t\t<reference ref=\"658976563\"/>\n\t\t\t\t\t\t\t<reference ref=\"809284510\"/>\n\t\t\t\t\t\t\t<reference ref=\"25331779\"/>\n\t\t\t\t\t\t\t<reference ref=\"558454645\"/>\n\t\t\t\t\t\t</array>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">36</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"558454645\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">39</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"865697934\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t\t<string key=\"objectName\">Title</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">41</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"948703008\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t\t<string key=\"objectName\">Time</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">42</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"384037290\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t\t<string key=\"objectName\">Where</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">43</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"966680524\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t\t<string key=\"objectName\">Content</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">48</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"344753243\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">49</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"809284510\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">50</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"25331779\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">51</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"658976563\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"883825266\"/>\n\t\t\t\t\t</object>\n\t\t\t\t</array>\n\t\t\t</object>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"flattenedProperties\">\n\t\t\t\t<string key=\"-1.CustomClassName\">GetEventController</string>\n\t\t\t\t<string key=\"-1.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"-2.CustomClassName\">UIResponder</string>\n\t\t\t\t<string key=\"-2.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"34.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"36.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"39.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"41.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"42.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"43.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"48.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"49.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"50.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t\t<string key=\"51.IBPluginDependency\">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>\n\t\t\t</dictionary>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"unlocalizedProperties\"/>\n\t\t\t<nil key=\"activeLocalization\"/>\n\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"localizations\"/>\n\t\t\t<nil key=\"sourceID\"/>\n\t\t\t<int key=\"maxID\">51</int>\n\t\t</object>\n\t\t<object class=\"IBClassDescriber\" key=\"IBDocument.Classes\">\n\t\t\t<array class=\"NSMutableArray\" key=\"referencedPartialClassDescriptions\">\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">GetEventController</string>\n\t\t\t\t\t<string key=\"superclassName\">UIViewController</string>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"actions\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">showInfo:</string>\n\t\t\t\t\t\t<string key=\"NS.object.0\">id</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"actionInfosByName\">\n\t\t\t\t\t\t<string key=\"NS.key.0\">showInfo:</string>\n\t\t\t\t\t\t<object class=\"IBActionInfo\" key=\"NS.object.0\">\n\t\t\t\t\t\t\t<string key=\"name\">showInfo:</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">id</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"outlets\">\n\t\t\t\t\t\t<string key=\"contentLabel_\">UILabel</string>\n\t\t\t\t\t\t<string key=\"timeLabel_\">UILabel</string>\n\t\t\t\t\t\t<string key=\"titleLabel_\">UILabel</string>\n\t\t\t\t\t\t<string key=\"whereLabel_\">UILabel</string>\n\t\t\t\t\t</dictionary>\n\t\t\t\t\t<dictionary class=\"NSMutableDictionary\" key=\"toOneOutletInfosByName\">\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"contentLabel_\">\n\t\t\t\t\t\t\t<string key=\"name\">contentLabel_</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">UILabel</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"timeLabel_\">\n\t\t\t\t\t\t\t<string key=\"name\">timeLabel_</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">UILabel</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"titleLabel_\">\n\t\t\t\t\t\t\t<string key=\"name\">titleLabel_</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">UILabel</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"IBToOneOutletInfo\" key=\"whereLabel_\">\n\t\t\t\t\t\t\t<string key=\"name\">whereLabel_</string>\n\t\t\t\t\t\t\t<string key=\"candidateClassName\">UILabel</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</dictionary>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBProjectSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">./Classes/GetEventController.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t</array>\n\t\t</object>\n\t\t<int key=\"IBDocument.localizationMode\">0</int>\n\t\t<string key=\"IBDocument.TargetRuntimeIdentifier\">IBCocoaTouchFramework</string>\n\t\t<bool key=\"IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion\">YES</bool>\n\t\t<int key=\"IBDocument.defaultPropertyAccessControl\">3</int>\n\t\t<string key=\"IBCocoaTouchPluginVersion\">933</string>\n\t</data>\n</archive>\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/en.lproj/InfoPlist.strings",
    "content": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo/main.m",
    "content": "//\n//  main.m\n//  DoubanAPIEngineDemo\n//\n//  Created by Lin GUO on 1/16/12.\n//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n#import \"AppDelegate.h\"\n\nint main(int argc, char *argv[])\n{\n  @autoreleasepool {\n      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n  }\n}\n"
  },
  {
    "path": "DoubanAPIEngineDemo/DoubanAPIEngineDemo.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\tD8BB4008165F706E00732107 /* StatusController.m in Sources */ = {isa = PBXBuildFile; fileRef = D8BB4007165F706E00732107 /* StatusController.m */; };\n\t\tD8F14DAF152002B1008F1875 /* NavController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D8F14DAE152002B1008F1875 /* NavController.xib */; };\n\t\tD8F14DB215200AF9008F1875 /* NavController.m in Sources */ = {isa = PBXBuildFile; fileRef = D8F14DB115200AF9008F1875 /* NavController.m */; };\n\t\tD8F14DCE1520200E008F1875 /* PhotosController.m in Sources */ = {isa = PBXBuildFile; fileRef = D8F14DCD1520200E008F1875 /* PhotosController.m */; };\n\t\tD8F14DD615204FC5008F1875 /* WebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D8F14DD515204FC5008F1875 /* WebViewController.m */; };\n\t\tD8FC8C5D14C416BB003E5A03 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8C5C14C416BB003E5A03 /* UIKit.framework */; };\n\t\tD8FC8C5F14C416BB003E5A03 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8C5E14C416BB003E5A03 /* Foundation.framework */; };\n\t\tD8FC8C6114C416BB003E5A03 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8C6014C416BB003E5A03 /* CoreGraphics.framework */; };\n\t\tD8FC8C6714C416BB003E5A03 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D8FC8C6514C416BB003E5A03 /* InfoPlist.strings */; };\n\t\tD8FC8C6914C416BB003E5A03 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D8FC8C6814C416BB003E5A03 /* main.m */; };\n\t\tD8FC8C6D14C416BB003E5A03 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D8FC8C6C14C416BB003E5A03 /* AppDelegate.m */; };\n\t\tD8FC8CCF14C48FAC003E5A03 /* GetEventController.m in Sources */ = {isa = PBXBuildFile; fileRef = D8FC8CCE14C48FAC003E5A03 /* GetEventController.m */; };\n\t\tD8FC8CE014C494AC003E5A03 /* DoubanQueryEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = D8FC8CDF14C494AC003E5A03 /* DoubanQueryEvent.m */; };\n\t\tD8FC8CE114C4952D003E5A03 /* libDoubanAPIEngine.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8CB014C48D5E003E5A03 /* libDoubanAPIEngine.a */; };\n\t\tD8FC8CE314C49544003E5A03 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8CE214C49544003E5A03 /* libxml2.dylib */; };\n\t\tD8FC8CE514C4960D003E5A03 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8CE414C4960D003E5A03 /* libz.dylib */; };\n\t\tD8FC8CE714C49628003E5A03 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8CE614C49628003E5A03 /* CFNetwork.framework */; };\n\t\tD8FC8CE914C49633003E5A03 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8CE814C49633003E5A03 /* Security.framework */; };\n\t\tD8FC8CEB14C4963D003E5A03 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8CEA14C4963D003E5A03 /* SystemConfiguration.framework */; };\n\t\tD8FC8CF014C49675003E5A03 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8FC8CEC14C4964A003E5A03 /* MobileCoreServices.framework */; };\n\t\tD8FC8CF314C496EC003E5A03 /* GetEventController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D8FC8CF114C496EC003E5A03 /* GetEventController.xib */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tD8FC8CAF14C48D5E003E5A03 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = D8FC8CAA14C48D5E003E5A03 /* DoubanAPIEngine.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = D800D538146907B2009F64FD;\n\t\t\tremoteInfo = DoubanAPIEngine;\n\t\t};\n\t\tD8FC8CB114C48D5E003E5A03 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = D8FC8CAA14C48D5E003E5A03 /* DoubanAPIEngine.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = D800D548146907B2009F64FD;\n\t\t\tremoteInfo = DoubanAPIEngineTests;\n\t\t};\n\t\tD8FC8CDA14C493A2003E5A03 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = D8FC8CAA14C48D5E003E5A03 /* DoubanAPIEngine.xcodeproj */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = D800D537146907B2009F64FD;\n\t\t\tremoteInfo = DoubanAPIEngine;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\tD8BB4006165F706E00732107 /* StatusController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StatusController.h; sourceTree = \"<group>\"; };\n\t\tD8BB4007165F706E00732107 /* StatusController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StatusController.m; sourceTree = \"<group>\"; };\n\t\tD8F14DAE152002B1008F1875 /* NavController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NavController.xib; sourceTree = \"<group>\"; };\n\t\tD8F14DB015200AF9008F1875 /* NavController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavController.h; sourceTree = \"<group>\"; };\n\t\tD8F14DB115200AF9008F1875 /* NavController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NavController.m; sourceTree = \"<group>\"; };\n\t\tD8F14DCC1520200E008F1875 /* PhotosController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotosController.h; sourceTree = \"<group>\"; };\n\t\tD8F14DCD1520200E008F1875 /* PhotosController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotosController.m; sourceTree = \"<group>\"; };\n\t\tD8F14DD415204FC5008F1875 /* WebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewController.h; sourceTree = \"<group>\"; };\n\t\tD8F14DD515204FC5008F1875 /* WebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewController.m; sourceTree = \"<group>\"; };\n\t\tD8FC8C5814C416BB003E5A03 /* DoubanAPIEngineDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DoubanAPIEngineDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tD8FC8C5C14C416BB003E5A03 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };\n\t\tD8FC8C5E14C416BB003E5A03 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };\n\t\tD8FC8C6014C416BB003E5A03 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };\n\t\tD8FC8C6414C416BB003E5A03 /* DoubanAPIEngineDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = \"DoubanAPIEngineDemo-Info.plist\"; sourceTree = \"<group>\"; };\n\t\tD8FC8C6614C416BB003E5A03 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n\t\tD8FC8C6814C416BB003E5A03 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tD8FC8C6A14C416BB003E5A03 /* DoubanAPIEngineDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"DoubanAPIEngineDemo-Prefix.pch\"; sourceTree = \"<group>\"; };\n\t\tD8FC8C6B14C416BB003E5A03 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\tD8FC8C6C14C416BB003E5A03 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\tD8FC8CAA14C48D5E003E5A03 /* DoubanAPIEngine.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = DoubanAPIEngine.xcodeproj; path = ../../DoubanAPIEngine/DoubanAPIEngine.xcodeproj; sourceTree = \"<group>\"; };\n\t\tD8FC8CCD14C48FAC003E5A03 /* GetEventController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetEventController.h; sourceTree = \"<group>\"; };\n\t\tD8FC8CCE14C48FAC003E5A03 /* GetEventController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GetEventController.m; sourceTree = \"<group>\"; };\n\t\tD8FC8CDE14C494AC003E5A03 /* DoubanQueryEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoubanQueryEvent.h; sourceTree = \"<group>\"; };\n\t\tD8FC8CDF14C494AC003E5A03 /* DoubanQueryEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoubanQueryEvent.m; sourceTree = \"<group>\"; };\n\t\tD8FC8CE214C49544003E5A03 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };\n\t\tD8FC8CE414C4960D003E5A03 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };\n\t\tD8FC8CE614C49628003E5A03 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };\n\t\tD8FC8CE814C49633003E5A03 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };\n\t\tD8FC8CEA14C4963D003E5A03 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };\n\t\tD8FC8CEC14C4964A003E5A03 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };\n\t\tD8FC8CF214C496EC003E5A03 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/GetEventController.xib; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tD8FC8C5514C416BB003E5A03 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD8FC8CF014C49675003E5A03 /* MobileCoreServices.framework in Frameworks */,\n\t\t\t\tD8FC8CEB14C4963D003E5A03 /* SystemConfiguration.framework in Frameworks */,\n\t\t\t\tD8FC8CE914C49633003E5A03 /* Security.framework in Frameworks */,\n\t\t\t\tD8FC8CE714C49628003E5A03 /* CFNetwork.framework in Frameworks */,\n\t\t\t\tD8FC8C6114C416BB003E5A03 /* CoreGraphics.framework in Frameworks */,\n\t\t\t\tD8FC8CE514C4960D003E5A03 /* libz.dylib in Frameworks */,\n\t\t\t\tD8FC8CE314C49544003E5A03 /* libxml2.dylib in Frameworks */,\n\t\t\t\tD8FC8CE114C4952D003E5A03 /* libDoubanAPIEngine.a in Frameworks */,\n\t\t\t\tD8FC8C5D14C416BB003E5A03 /* UIKit.framework in Frameworks */,\n\t\t\t\tD8FC8C5F14C416BB003E5A03 /* Foundation.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\tD8FC8C4D14C416BB003E5A03 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8C6214C416BB003E5A03 /* DoubanAPIEngineDemo */,\n\t\t\t\tD8FC8C5B14C416BB003E5A03 /* Frameworks */,\n\t\t\t\tD8FC8C5914C416BB003E5A03 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8FC8C5914C416BB003E5A03 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8C5814C416BB003E5A03 /* DoubanAPIEngineDemo.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8FC8C5B14C416BB003E5A03 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8CEC14C4964A003E5A03 /* MobileCoreServices.framework */,\n\t\t\t\tD8FC8CEA14C4963D003E5A03 /* SystemConfiguration.framework */,\n\t\t\t\tD8FC8CE814C49633003E5A03 /* Security.framework */,\n\t\t\t\tD8FC8CE614C49628003E5A03 /* CFNetwork.framework */,\n\t\t\t\tD8FC8CE414C4960D003E5A03 /* libz.dylib */,\n\t\t\t\tD8FC8CE214C49544003E5A03 /* libxml2.dylib */,\n\t\t\t\tD8FC8C5C14C416BB003E5A03 /* UIKit.framework */,\n\t\t\t\tD8FC8C5E14C416BB003E5A03 /* Foundation.framework */,\n\t\t\t\tD8FC8C6014C416BB003E5A03 /* CoreGraphics.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8FC8C6214C416BB003E5A03 /* DoubanAPIEngineDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8C6B14C416BB003E5A03 /* AppDelegate.h */,\n\t\t\t\tD8FC8C6C14C416BB003E5A03 /* AppDelegate.m */,\n\t\t\t\tD8FC8CDE14C494AC003E5A03 /* DoubanQueryEvent.h */,\n\t\t\t\tD8FC8CDF14C494AC003E5A03 /* DoubanQueryEvent.m */,\n\t\t\t\tD8F14DB015200AF9008F1875 /* NavController.h */,\n\t\t\t\tD8F14DB115200AF9008F1875 /* NavController.m */,\n\t\t\t\tD8F14DAE152002B1008F1875 /* NavController.xib */,\n\t\t\t\tD8FC8CCD14C48FAC003E5A03 /* GetEventController.h */,\n\t\t\t\tD8FC8CCE14C48FAC003E5A03 /* GetEventController.m */,\n\t\t\t\tD8FC8CF114C496EC003E5A03 /* GetEventController.xib */,\n\t\t\t\tD8BB4006165F706E00732107 /* StatusController.h */,\n\t\t\t\tD8BB4007165F706E00732107 /* StatusController.m */,\n\t\t\t\tD8F14DCC1520200E008F1875 /* PhotosController.h */,\n\t\t\t\tD8F14DCD1520200E008F1875 /* PhotosController.m */,\n\t\t\t\tD8F14DD415204FC5008F1875 /* WebViewController.h */,\n\t\t\t\tD8F14DD515204FC5008F1875 /* WebViewController.m */,\n\t\t\t\tD8FC8C9314C479DD003E5A03 /* Dependency */,\n\t\t\t\tD8FC8C6314C416BB003E5A03 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = DoubanAPIEngineDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8FC8C6314C416BB003E5A03 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8C6414C416BB003E5A03 /* DoubanAPIEngineDemo-Info.plist */,\n\t\t\t\tD8FC8C6514C416BB003E5A03 /* InfoPlist.strings */,\n\t\t\t\tD8FC8C6814C416BB003E5A03 /* main.m */,\n\t\t\t\tD8FC8C6A14C416BB003E5A03 /* DoubanAPIEngineDemo-Prefix.pch */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8FC8C9314C479DD003E5A03 /* Dependency */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8CAA14C48D5E003E5A03 /* DoubanAPIEngine.xcodeproj */,\n\t\t\t);\n\t\t\tname = Dependency;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8FC8CAB14C48D5E003E5A03 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8CB014C48D5E003E5A03 /* libDoubanAPIEngine.a */,\n\t\t\t\tD8FC8CB214C48D5E003E5A03 /* DoubanAPIEngineTests.octest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\tD8FC8C5714C416BB003E5A03 /* DoubanAPIEngineDemo */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = D8FC8C8214C416BB003E5A03 /* Build configuration list for PBXNativeTarget \"DoubanAPIEngineDemo\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tD8FC8C5414C416BB003E5A03 /* Sources */,\n\t\t\t\tD8FC8C5514C416BB003E5A03 /* Frameworks */,\n\t\t\t\tD8FC8C5614C416BB003E5A03 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tD8FC8CDB14C493A2003E5A03 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = DoubanAPIEngineDemo;\n\t\t\tproductName = DoubanAPIEngineDemo;\n\t\t\tproductReference = D8FC8C5814C416BB003E5A03 /* DoubanAPIEngineDemo.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tD8FC8C4F14C416BB003E5A03 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0420;\n\t\t\t};\n\t\t\tbuildConfigurationList = D8FC8C5214C416BB003E5A03 /* Build configuration list for PBXProject \"DoubanAPIEngineDemo\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = D8FC8C4D14C416BB003E5A03;\n\t\t\tproductRefGroup = D8FC8C5914C416BB003E5A03 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectReferences = (\n\t\t\t\t{\n\t\t\t\t\tProductGroup = D8FC8CAB14C48D5E003E5A03 /* Products */;\n\t\t\t\t\tProjectRef = D8FC8CAA14C48D5E003E5A03 /* DoubanAPIEngine.xcodeproj */;\n\t\t\t\t},\n\t\t\t);\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tD8FC8C5714C416BB003E5A03 /* DoubanAPIEngineDemo */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXReferenceProxy section */\n\t\tD8FC8CB014C48D5E003E5A03 /* libDoubanAPIEngine.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libDoubanAPIEngine.a;\n\t\t\tremoteRef = D8FC8CAF14C48D5E003E5A03 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\tD8FC8CB214C48D5E003E5A03 /* DoubanAPIEngineTests.octest */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.cfbundle;\n\t\t\tpath = DoubanAPIEngineTests.octest;\n\t\t\tremoteRef = D8FC8CB114C48D5E003E5A03 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n/* End PBXReferenceProxy section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tD8FC8C5614C416BB003E5A03 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD8FC8C6714C416BB003E5A03 /* InfoPlist.strings in Resources */,\n\t\t\t\tD8FC8CF314C496EC003E5A03 /* GetEventController.xib in Resources */,\n\t\t\t\tD8F14DAF152002B1008F1875 /* NavController.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tD8FC8C5414C416BB003E5A03 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tD8FC8C6914C416BB003E5A03 /* main.m in Sources */,\n\t\t\t\tD8FC8C6D14C416BB003E5A03 /* AppDelegate.m in Sources */,\n\t\t\t\tD8FC8CCF14C48FAC003E5A03 /* GetEventController.m in Sources */,\n\t\t\t\tD8FC8CE014C494AC003E5A03 /* DoubanQueryEvent.m in Sources */,\n\t\t\t\tD8F14DB215200AF9008F1875 /* NavController.m in Sources */,\n\t\t\t\tD8F14DCE1520200E008F1875 /* PhotosController.m in Sources */,\n\t\t\t\tD8F14DD615204FC5008F1875 /* WebViewController.m in Sources */,\n\t\t\t\tD8BB4008165F706E00732107 /* StatusController.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tD8FC8CDB14C493A2003E5A03 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\tname = DoubanAPIEngine;\n\t\t\ttargetProxy = D8FC8CDA14C493A2003E5A03 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\tD8FC8C6514C416BB003E5A03 /* InfoPlist.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8C6614C416BB003E5A03 /* en */,\n\t\t\t);\n\t\t\tname = InfoPlist.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD8FC8CF114C496EC003E5A03 /* GetEventController.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tD8FC8CF214C496EC003E5A03 /* en */,\n\t\t\t);\n\t\t\tname = GetEventController.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\tD8FC8C8014C416BB003E5A03 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_BIT)\";\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 5.0;\n\t\t\t\tOTHER_LDFLAGS = \"-all_load\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tD8FC8C8114C416BB003E5A03 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_BIT)\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_VERSION = com.apple.compilers.llvm.clang.1_0;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 5.0;\n\t\t\t\tOTHER_CFLAGS = \"-DNS_BLOCK_ASSERTIONS=1\";\n\t\t\t\tOTHER_LDFLAGS = \"-all_load\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tD8FC8C8314C416BB003E5A03 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=*]\" = \"\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(DEVELOPER_FRAMEWORKS_DIR)\\\"\",\n\t\t\t\t);\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"DoubanAPIEngineDemo/DoubanAPIEngineDemo-Prefix.pch\";\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"../DoubanAPIEngine/DoubanAPIEngine/OtherSources/**\",\n\t\t\t\t\t\"../DoubanAPIEngine/DoubanAPIEngine/Sources/**\",\n\t\t\t\t\t\"${SDK_DIR}/usr/include/libxml2/**\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"DoubanAPIEngineDemo/DoubanAPIEngineDemo-Info.plist\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 4.0;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tD8FC8C8414C416BB003E5A03 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(DEVELOPER_FRAMEWORKS_DIR)\\\"\",\n\t\t\t\t);\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = \"DoubanAPIEngineDemo/DoubanAPIEngineDemo-Prefix.pch\";\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"../DoubanAPIEngine/DoubanAPIEngine/OtherSources/**\",\n\t\t\t\t\t\"../DoubanAPIEngine/DoubanAPIEngine/Sources/**\",\n\t\t\t\t\t\"${SDK_DIR}/usr/include/libxml2/**\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"DoubanAPIEngineDemo/DoubanAPIEngineDemo-Info.plist\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 4.0;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tWRAPPER_EXTENSION = app;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tD8FC8C5214C416BB003E5A03 /* Build configuration list for PBXProject \"DoubanAPIEngineDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tD8FC8C8014C416BB003E5A03 /* Debug */,\n\t\t\t\tD8FC8C8114C416BB003E5A03 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tD8FC8C8214C416BB003E5A03 /* Build configuration list for PBXNativeTarget \"DoubanAPIEngineDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tD8FC8C8314C416BB003E5A03 /* Debug */,\n\t\t\t\tD8FC8C8414C416BB003E5A03 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = D8FC8C4F14C416BB003E5A03 /* Project object */;\n}\n"
  },
  {
    "path": "README.markdown",
    "content": "\n[豆瓣 API]: http://developers.douban.com/\n\n# douban-objc-client 介绍\n\n**该项目已经废弃**\n\n**douban-objc-client** 是一个 Objective C 实现的 豆瓣 API 客户端。现在仅支持 iOS。\n\n更多信息请查询 **[豆瓣 API]**\n\n\n# 如何配置?\n\n## 方法一：项目依赖\n#### *适用于开发过程中可能会修改 douban-objc-client 的源代码的项目\n\n### 1.DoubanAPIEngine\n\n将`DoubanAPIEngine.xcodeproj`图标拖拽到你的项目文件目录中。\n\n### 2.设置项目 Building Settings\n\n点击 `项目` -> `(TARGETS)` 图标，在 `Build Settings` 里找到 `Other Linker Flags`, 设置为 `-all_load`, 和 `-ObjC`\n\n### 3.设置目标 Building Settings\n\n同上，找到 Header Search Paths，添加\n\n* ../DoubanAPIEngine/DoubanAPIEngine/OtherSources\n* ../DoubanAPIEngine/DoubanAPIEngine/Sources\n* ${SDK_DIR}/usr/include/libxml2\n\n##### TIPS :\n以上的两个**DoubanAPIEngine**的目录可以是相对目录也可以是绝对目录，需要自行配置。这里将DoubanAPIEngine目录直接拷贝到了项目目录下。建议如此使用，有助于移植。\n\n\n### 4.添加依赖\n\n点击目标(TARGETS)图标，选择 `Building Phases`，找到 `Target Dependencies`，添加 `DoubanAPIEngine`。\n\n\n### 5.添加所需的 Frameworks\n\n点击目标(TARGETS)图标，选择 `Building Phases`，在 `Link Binary with Libaries` 中，加入下列库：\n\n  * libDoubanAPIEngine.a\n  * libxml2.dylib\n  * libz.dylib\n  * CoreGraphics.framework\n  * CFNetwork.framework\n  * Security.framework\n  * SystemConfiguration.framework\n  * MobileCoreServices.framework\n  * UIKit.framework\n  * Foundation.framework\n  * SenTestingkit.framework\n\n#### Tips : 此方法 import 头文件应该使用以下方式:\n\n\t#import \"DOUService.h\"\n\n## 方法二：添加 framework\n#### *适用于不会修改源代码的项目\n\n### 1.添加 libDoubanAPIEngine.framework\n点击目标(TARGETS)图标，选择Building Phases，在Link Binary with Libaries中，加入 libDoubanAPIEngine.framework\n\n### 2.设置项目 Building Settings\n点击 `项目` -> `(TARGETS)` 图标，在 `Build Settings` 里找到 `Other Linker Flags`, 设置为 `-all_load`, 和 `-ObjC`\n\n### 3.添加其他库\n点击目标(TARGETS)图标，选择Building Phases，在Link Binary with Libaries中，加入\n\n  * libxml2.dylib\n  * libz.dylib\n  * CoreGraphics.framework\n  * CFNetwork.framework\n  * Security.framework\n  * SystemConfiguration.framework\n  * MobileCoreServices.framework\n  * UIKit.framework\n  * Foundation.framework\n\n#### Tips : 此方法 import 头文件应该使用以下方式:\n\n\t#import <libDoubanAPIEngine/DOUService.h>\n\n\n# 如何使用?\n\n\n### 1.提供 OAuth2 所需参数\n\n \tDOUService *service = [DOUService sharedInstance];\n \tservice.clientId = kAPIKey;\n \tservice.clientSecret = kPrivateKey;\n\n### 2.发起一个异步请求\n\n\tNSString *subPath = [NSString stringWithFormat:@\"/book/subject/%d\", bookId];\n\tDOUQuery *query = [[[DOUQuery alloc] initWithSubPath:subPath parameters:nil] autorelease];\n  \n\tquery.apiBaseUrlString = service.apiBaseUrlString;\n\tDOUHttpRequest *req = [DOUHttpRequest requestWithQuery:query target:self];\n\n\tDOUService *service = [DOUService sharedInstance];\n\t[service addRequest:req];\n\n\n若使用 delegate 方式处理回调，要注意一个问题，某些情况下，request 的 delegate 被 dealloc 后，request 才得到了返回。这时就是一个 已释放的 delegate 来处理回调。\n这会造成程序崩溃。处理方法为，在 request 的 delegate (例如某个 UIViewController) 的 dealloc 方法中对 request 发送 clearDelegatesAndCancel 消息，再 release request。\n\n另外一个更为优雅的方法是使用“闭包” (block)，DOUHttpRequest 提供了一个方法，可以用闭包来处理回调。由于 request 会自动 retain 闭包。所以，这就避免了使用 delegate 处理回调时可能出现的上述问题。\n\n但， Objective－C 的闭包在 iOS 4.0 及其以上版本才得到支持。\n\nDOUHttpRequest 的闭包处理回调的方法：\n\n\t+ (DOUHttpRequest *)requestWithQuery:(DOUQuery *)query \n    \t                 completionBlock:(DOUBasicBlock)completionHandler;\n\n### 3.异步请求的回调\n\n\t- (void)requestFinished:(DOUHttpRequest *)req {\n  \t\tNSError *error = [req error];\n  \t\tif (!error) {\n    \t\tDoubanFeedEvent *feed = [[DoubanFeedEvent alloc] initWithData:[req responseData]];\n  \t\t}\n\t}\n\n\t- (void)requestFailed:(DOUHttpRequest *)req {\n  \t\tNSLog(@\"error\");\n\t}\n\n\n# 待办列表\n  * 提供更多数据类型的支持，如: 豆邮，日记，收藏\n  * 支持 Mac OSX\n  * 改进 token 过期时，refresh token 的方式，使其不依赖于本机时间\n  * ARC, no-ARC 双模支持\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/ASICacheDelegate.h",
    "content": "//\n//  ASICacheDelegate.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 01/05/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n@class ASIHTTPRequest;\n\n// Cache policies control the behaviour of a cache and how requests use the cache\n// When setting a cache policy, you can use a combination of these values as a bitmask\n// For example: [request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy|ASIDoNotWriteToCacheCachePolicy];\n// Note that some of the behaviours below are mutally exclusive - you cannot combine ASIAskServerIfModifiedWhenStaleCachePolicy and ASIAskServerIfModifiedCachePolicy, for example.\ntypedef enum _ASICachePolicy {\n\n\t// The default cache policy. When you set a request to use this, it will use the cache's defaultCachePolicy\n\t// ASIDownloadCache's default cache policy is 'ASIAskServerIfModifiedWhenStaleCachePolicy'\n\tASIUseDefaultCachePolicy = 0,\n\n\t// Tell the request not to read from the cache\n\tASIDoNotReadFromCacheCachePolicy = 1,\n\n\t// The the request not to write to the cache\n\tASIDoNotWriteToCacheCachePolicy = 2,\n\n\t// Ask the server if there is an updated version of this resource (using a conditional GET) ONLY when the cached data is stale\n\tASIAskServerIfModifiedWhenStaleCachePolicy = 4,\n\n\t// Always ask the server if there is an updated version of this resource (using a conditional GET)\n\tASIAskServerIfModifiedCachePolicy = 8,\n\n\t// If cached data exists, use it even if it is stale. This means requests will not talk to the server unless the resource they are requesting is not in the cache\n\tASIOnlyLoadIfNotCachedCachePolicy = 16,\n\n\t// If cached data exists, use it even if it is stale. If cached data does not exist, stop (will not set an error on the request)\n\tASIDontLoadCachePolicy = 32,\n\n\t// Specifies that cached data may be used if the request fails. If cached data is used, the request will succeed without error. Usually used in combination with other options above.\n\tASIFallbackToCacheIfLoadFailsCachePolicy = 64\n} ASICachePolicy;\n\n// Cache storage policies control whether cached data persists between application launches (ASICachePermanentlyCacheStoragePolicy) or not (ASICacheForSessionDurationCacheStoragePolicy)\n// Calling [ASIHTTPRequest clearSession] will remove any data stored using ASICacheForSessionDurationCacheStoragePolicy\ntypedef enum _ASICacheStoragePolicy {\n\tASICacheForSessionDurationCacheStoragePolicy = 0,\n\tASICachePermanentlyCacheStoragePolicy = 1\n} ASICacheStoragePolicy;\n\n\n@protocol ASICacheDelegate <NSObject>\n\n@required\n\n// Should return the cache policy that will be used when requests have their cache policy set to ASIUseDefaultCachePolicy\n- (ASICachePolicy)defaultCachePolicy;\n\n// Returns the date a cached response should expire on. Pass a non-zero max age to specify a custom date.\n- (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Updates cached response headers with a new expiry date. Pass a non-zero max age to specify a custom date.\n- (void)updateExpiryForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Looks at the request's cache policy and any cached headers to determine if the cache data is still valid\n- (BOOL)canUseCachedDataForRequest:(ASIHTTPRequest *)request;\n\n// Removes cached data for a particular request\n- (void)removeCachedDataForRequest:(ASIHTTPRequest *)request;\n\n// Should return YES if the cache considers its cached response current for the request\n// Should return NO is the data is not cached, or (for example) if the cached headers state the request should have expired\n- (BOOL)isCachedDataCurrentForRequest:(ASIHTTPRequest *)request;\n\n// Should store the response for the passed request in the cache\n// When a non-zero maxAge is passed, it should be used as the expiry time for the cached response\n- (void)storeResponseForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Removes cached data for a particular url\n- (void)removeCachedDataForURL:(NSURL *)url;\n\n// Should return an NSDictionary of cached headers for the passed URL, if it is stored in the cache\n- (NSDictionary *)cachedResponseHeadersForURL:(NSURL *)url;\n\n// Should return the cached body of a response for the passed URL, if it is stored in the cache\n- (NSData *)cachedResponseDataForURL:(NSURL *)url;\n\n// Returns a path to the cached response data, if it exists\n- (NSString *)pathToCachedResponseDataForURL:(NSURL *)url;\n\n// Returns a path to the cached response headers, if they url\n- (NSString *)pathToCachedResponseHeadersForURL:(NSURL *)url;\n\n// Returns the location to use to store cached response headers for a particular request\n- (NSString *)pathToStoreCachedResponseHeadersForRequest:(ASIHTTPRequest *)request;\n\n// Returns the location to use to store a cached response body for a particular request\n- (NSString *)pathToStoreCachedResponseDataForRequest:(ASIHTTPRequest *)request;\n\n// Clear cached data stored for the passed storage policy\n- (void)clearCachedResponsesForStoragePolicy:(ASICacheStoragePolicy)cachePolicy;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/ASIHTTPRequest.h",
    "content": "//\n//  ASIHTTPRequest.h\n//\n//  Created by Ben Copsey on 04/10/2007.\n//  Copyright 2007-2011 All-Seeing Interactive. All rights reserved.\n//\n//  A guide to the main features is available at:\n//  http://allseeing-i.com/ASIHTTPRequest\n//\n//  Portions are based on the ImageClient example from Apple:\n//  See: http://developer.apple.com/samplecode/ImageClient/listing37.html\n\n#import <Foundation/Foundation.h>\n#if TARGET_OS_IPHONE\n\t#import <CFNetwork/CFNetwork.h>\n\t#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n\t#import <UIKit/UIKit.h> // Necessary for background task support\n\t#endif\n#endif\n\n#import <stdio.h>\n#import \"ASIHTTPRequestConfig.h\"\n#import \"ASIHTTPRequestDelegate.h\"\n#import \"ASIProgressDelegate.h\"\n#import \"ASICacheDelegate.h\"\n\n@class ASIDataDecompressor;\n\nextern NSString *ASIHTTPRequestVersion;\n\n// Make targeting different platforms more reliable\n// See: http://www.blumtnwerx.com/blog/2009/06/cross-sdk-code-hygiene-in-xcode/\n#ifndef __IPHONE_3_2\n\t#define __IPHONE_3_2 30200\n#endif\n#ifndef __IPHONE_4_0\n\t#define __IPHONE_4_0 40000\n#endif\n#ifndef __MAC_10_5\n\t#define __MAC_10_5 1050\n#endif\n#ifndef __MAC_10_6\n\t#define __MAC_10_6 1060\n#endif\n\ntypedef enum _ASIAuthenticationState {\n\tASINoAuthenticationNeededYet = 0,\n\tASIHTTPAuthenticationNeeded = 1,\n\tASIProxyAuthenticationNeeded = 2\n} ASIAuthenticationState;\n\ntypedef enum _ASINetworkErrorType {\n  ASIConnectionFailureErrorType = 1,\n  ASIRequestTimedOutErrorType = 2,\n  ASIAuthenticationErrorType = 3,\n  ASIRequestCancelledErrorType = 4,\n  ASIUnableToCreateRequestErrorType = 5,\n  ASIInternalErrorWhileBuildingRequestType  = 6,\n  ASIInternalErrorWhileApplyingCredentialsType  = 7,\n\tASIFileManagementError = 8,\n\tASITooMuchRedirectionErrorType = 9,\n\tASIUnhandledExceptionError = 10,\n\tASICompressionError = 11\n\t\n} ASINetworkErrorType;\n\n\n// The error domain that all errors generated by ASIHTTPRequest use\nextern NSString* const NetworkRequestErrorDomain;\n\n// You can use this number to throttle upload and download bandwidth in iPhone OS apps send or receive a large amount of data\n// This may help apps that might otherwise be rejected for inclusion into the app store for using excessive bandwidth\n// This number is not official, as far as I know there is no officially documented bandwidth limit\nextern unsigned long const ASIWWANBandwidthThrottleAmount;\n\n#if NS_BLOCKS_AVAILABLE\ntypedef void (^ASIBasicBlock)(void);\ntypedef void (^ASIHeadersBlock)(NSDictionary *responseHeaders);\ntypedef void (^ASISizeBlock)(long long size);\ntypedef void (^ASIProgressBlock)(unsigned long long size, unsigned long long total);\ntypedef void (^ASIDataBlock)(NSData *data);\n#endif\n\n@interface ASIHTTPRequest : NSOperation <NSCopying> {\n\t\n\t// The url for this operation, should include GET params in the query string where appropriate\n\tNSURL *url; \n\t\n\t// Will always contain the original url used for making the request (the value of url can change when a request is redirected)\n\tNSURL *originalURL;\n\t\n\t// Temporarily stores the url we are about to redirect to. Will be nil again when we do redirect\n\tNSURL *redirectURL;\n\n\t// The delegate - will be notified of various changes in state via the ASIHTTPRequestDelegate protocol\n\tid <ASIHTTPRequestDelegate> delegate;\n\t\n\t// Another delegate that is also notified of request status changes and progress updates\n\t// Generally, you won't use this directly, but ASINetworkQueue sets itself as the queue so it can proxy updates to its own delegates\n\t// NOTE: WILL BE RETAINED BY THE REQUEST\n\tid <ASIHTTPRequestDelegate, ASIProgressDelegate> queue;\n\t\n\t// HTTP method to use (eg: GET / POST / PUT / DELETE / HEAD etc). Defaults to GET\n\tNSString *requestMethod;\n\t\n\t// Request body - only used when the whole body is stored in memory (shouldStreamPostDataFromDisk is false)\n\tNSMutableData *postBody;\n\t\n\t// gzipped request body used when shouldCompressRequestBody is YES\n\tNSData *compressedPostBody;\n\t\n\t// When true, post body will be streamed from a file on disk, rather than loaded into memory at once (useful for large uploads)\n\t// Automatically set to true in ASIFormDataRequests when using setFile:forKey:\n\tBOOL shouldStreamPostDataFromDisk;\n\t\n\t// Path to file used to store post body (when shouldStreamPostDataFromDisk is true)\n\t// You can set this yourself - useful if you want to PUT a file from local disk \n\tNSString *postBodyFilePath;\n\t\n\t// Path to a temporary file used to store a deflated post body (when shouldCompressPostBody is YES)\n\tNSString *compressedPostBodyFilePath;\n\t\n\t// Set to true when ASIHTTPRequest automatically created a temporary file containing the request body (when true, the file at postBodyFilePath will be deleted at the end of the request)\n\tBOOL didCreateTemporaryPostDataFile;\n\t\n\t// Used when writing to the post body when shouldStreamPostDataFromDisk is true (via appendPostData: or appendPostDataFromFile:)\n\tNSOutputStream *postBodyWriteStream;\n\t\n\t// Used for reading from the post body when sending the request\n\tNSInputStream *postBodyReadStream;\n\t\n\t// Dictionary for custom HTTP request headers\n\tNSMutableDictionary *requestHeaders;\n\t\n\t// Set to YES when the request header dictionary has been populated, used to prevent this happening more than once\n\tBOOL haveBuiltRequestHeaders;\n\t\n\t// Will be populated with HTTP response headers from the server\n\tNSDictionary *responseHeaders;\n\t\n\t// Can be used to manually insert cookie headers to a request, but it's more likely that sessionCookies will do this for you\n\tNSMutableArray *requestCookies;\n\t\n\t// Will be populated with cookies\n\tNSArray *responseCookies;\n\t\n\t// If use useCookiePersistence is true, network requests will present valid cookies from previous requests\n\tBOOL useCookiePersistence;\n\t\n\t// If useKeychainPersistence is true, network requests will attempt to read credentials from the keychain, and will save them in the keychain when they are successfully presented\n\tBOOL useKeychainPersistence;\n\t\n\t// If useSessionPersistence is true, network requests will save credentials and reuse for the duration of the session (until clearSession is called)\n\tBOOL useSessionPersistence;\n\t\n\t// If allowCompressedResponse is true, requests will inform the server they can accept compressed data, and will automatically decompress gzipped responses. Default is true.\n\tBOOL allowCompressedResponse;\n\t\n\t// If shouldCompressRequestBody is true, the request body will be gzipped. Default is false.\n\t// You will probably need to enable this feature on your webserver to make this work. Tested with apache only.\n\tBOOL shouldCompressRequestBody;\n\t\n\t// When downloadDestinationPath is set, the result of this request will be downloaded to the file at this location\n\t// If downloadDestinationPath is not set, download data will be stored in memory\n\tNSString *downloadDestinationPath;\n\t\n\t// The location that files will be downloaded to. Once a download is complete, files will be decompressed (if necessary) and moved to downloadDestinationPath\n\tNSString *temporaryFileDownloadPath;\n\t\n\t// If the response is gzipped and shouldWaitToInflateCompressedResponses is NO, a file will be created at this path containing the inflated response as it comes in\n\tNSString *temporaryUncompressedDataDownloadPath;\n\t\n\t// Used for writing data to a file when downloadDestinationPath is set\n\tNSOutputStream *fileDownloadOutputStream;\n\t\n\tNSOutputStream *inflatedFileDownloadOutputStream;\n\t\n\t// When the request fails or completes successfully, complete will be true\n\tBOOL complete;\n\t\n  // external \"finished\" indicator, subject of KVO notifications; updates after 'complete'\n  BOOL finished;\n    \n  // True if our 'cancel' selector has been called\n  BOOL cancelled;\n    \n\t// If an error occurs, error will contain an NSError\n\t// If error code is = ASIConnectionFailureErrorType (1, Connection failure occurred) - inspect [[error userInfo] objectForKey:NSUnderlyingErrorKey] for more information\n\tNSError *error;\n\t\n\t// Username and password used for authentication\n\tNSString *username;\n\tNSString *password;\n\t\n\t// User-Agent for this request\n\tNSString *userAgent;\n\t\n\t// Domain used for NTLM authentication\n\tNSString *domain;\n\t\n\t// Username and password used for proxy authentication\n\tNSString *proxyUsername;\n\tNSString *proxyPassword;\n\t\n\t// Domain used for NTLM proxy authentication\n\tNSString *proxyDomain;\n\t\n\t// Delegate for displaying upload progress (usually an NSProgressIndicator, but you can supply a different object and handle this yourself)\n\tid <ASIProgressDelegate> uploadProgressDelegate;\n\t\n\t// Delegate for displaying download progress (usually an NSProgressIndicator, but you can supply a different object and handle this yourself)\n\tid <ASIProgressDelegate> downloadProgressDelegate;\n\t\n\t// Whether we've seen the headers of the response yet\n    BOOL haveExaminedHeaders;\n\t\n\t// Data we receive will be stored here. Data may be compressed unless allowCompressedResponse is false - you should use [request responseData] instead in most cases\n\tNSMutableData *rawResponseData;\n\t\n\t// Used for sending and receiving data\n    CFHTTPMessageRef request;\t\n\tNSInputStream *readStream;\n\t\n\t// Used for authentication\n    CFHTTPAuthenticationRef requestAuthentication; \n\tNSDictionary *requestCredentials;\n\t\n\t// Used during NTLM authentication\n\tint authenticationRetryCount;\n\t\n\t// Authentication scheme (Basic, Digest, NTLM)\n\t// If you are using Basic authentication and want to force ASIHTTPRequest to send an authorization header without waiting for a 401, you must set this to (NSString *)kCFHTTPAuthenticationSchemeBasic\n\tNSString *authenticationScheme;\n\t\n\t// Realm for authentication when credentials are required\n\tNSString *authenticationRealm;\n\t\n\t// When YES, ASIHTTPRequest will present a dialog allowing users to enter credentials when no-matching credentials were found for a server that requires authentication\n\t// The dialog will not be shown if your delegate responds to authenticationNeededForRequest:\n\t// Default is NO.\n\tBOOL shouldPresentAuthenticationDialog;\n\t\n\t// When YES, ASIHTTPRequest will present a dialog allowing users to enter credentials when no-matching credentials were found for a proxy server that requires authentication\n\t// The dialog will not be shown if your delegate responds to proxyAuthenticationNeededForRequest:\n\t// Default is YES (basically, because most people won't want the hassle of adding support for authenticating proxies to their apps)\n\tBOOL shouldPresentProxyAuthenticationDialog;\t\n\t\n\t// Used for proxy authentication\n    CFHTTPAuthenticationRef proxyAuthentication; \n\tNSDictionary *proxyCredentials;\n\t\n\t// Used during authentication with an NTLM proxy\n\tint proxyAuthenticationRetryCount;\n\t\n\t// Authentication scheme for the proxy (Basic, Digest, NTLM)\n\tNSString *proxyAuthenticationScheme;\t\n\t\n\t// Realm for proxy authentication when credentials are required\n\tNSString *proxyAuthenticationRealm;\n\t\n\t// HTTP status code, eg: 200 = OK, 404 = Not found etc\n\tint responseStatusCode;\n\t\n\t// Description of the HTTP status code\n\tNSString *responseStatusMessage;\n\t\n\t// Size of the response\n\tunsigned long long contentLength;\n\t\n\t// Size of the partially downloaded content\n\tunsigned long long partialDownloadSize;\n\t\n\t// Size of the POST payload\n\tunsigned long long postLength;\t\n\t\n\t// The total amount of downloaded data\n\tunsigned long long totalBytesRead;\n\t\n\t// The total amount of uploaded data\n\tunsigned long long totalBytesSent;\n\t\n\t// Last amount of data read (used for incrementing progress)\n\tunsigned long long lastBytesRead;\n\t\n\t// Last amount of data sent (used for incrementing progress)\n\tunsigned long long lastBytesSent;\n\t\n\t// This lock prevents the operation from being cancelled at an inopportune moment\n\tNSRecursiveLock *cancelledLock;\n\t\n\t// Called on the delegate (if implemented) when the request starts. Default is requestStarted:\n\tSEL didStartSelector;\n\t\n\t// Called on the delegate (if implemented) when the request receives response headers. Default is request:didReceiveResponseHeaders:\n\tSEL didReceiveResponseHeadersSelector;\n\n\t// Called on the delegate (if implemented) when the request receives a Location header and shouldRedirect is YES\n\t// The delegate can then change the url if needed, and can restart the request by calling [request redirectToURL:], or simply cancel it\n\tSEL willRedirectSelector;\n\n\t// Called on the delegate (if implemented) when the request completes successfully. Default is requestFinished:\n\tSEL didFinishSelector;\n\t\n\t// Called on the delegate (if implemented) when the request fails. Default is requestFailed:\n\tSEL didFailSelector;\n\t\n\t// Called on the delegate (if implemented) when the request receives data. Default is request:didReceiveData:\n\t// If you set this and implement the method in your delegate, you must handle the data yourself - ASIHTTPRequest will not populate responseData or write the data to downloadDestinationPath\n\tSEL didReceiveDataSelector;\n\t\n\t// Used for recording when something last happened during the request, we will compare this value with the current date to time out requests when appropriate\n\tNSDate *lastActivityTime;\n\t\n\t// Number of seconds to wait before timing out - default is 10\n\tNSTimeInterval timeOutSeconds;\n\t\n\t// Will be YES when a HEAD request will handle the content-length before this request starts\n\tBOOL shouldResetUploadProgress;\n\tBOOL shouldResetDownloadProgress;\n\t\n\t// Used by HEAD requests when showAccurateProgress is YES to preset the content-length for this request\n\tASIHTTPRequest *mainRequest;\n\t\n\t// When NO, this request will only update the progress indicator when it completes\n\t// When YES, this request will update the progress indicator according to how much data it has received so far\n\t// The default for requests is YES\n\t// Also see the comments in ASINetworkQueue.h\n\tBOOL showAccurateProgress;\n\t\n\t// Used to ensure the progress indicator is only incremented once when showAccurateProgress = NO\n\tBOOL updatedProgress;\n\t\n\t// Prevents the body of the post being built more than once (largely for subclasses)\n\tBOOL haveBuiltPostBody;\n\t\n\t// Used internally, may reflect the size of the internal buffer used by CFNetwork\n\t// POST / PUT operations with body sizes greater than uploadBufferSize will not timeout unless more than uploadBufferSize bytes have been sent\n\t// Likely to be 32KB on iPhone 3.0, 128KB on Mac OS X Leopard and iPhone 2.2.x\n\tunsigned long long uploadBufferSize;\n\t\n\t// Text encoding for responses that do not send a Content-Type with a charset value. Defaults to NSISOLatin1StringEncoding\n\tNSStringEncoding defaultResponseEncoding;\n\t\n\t// The text encoding of the response, will be defaultResponseEncoding if the server didn't specify. Can't be set.\n\tNSStringEncoding responseEncoding;\n\t\n\t// Tells ASIHTTPRequest not to delete partial downloads, and allows it to use an existing file to resume a download. Defaults to NO.\n\tBOOL allowResumeForFileDownloads;\n\t\n\t// Custom user information associated with the request (not sent to the server)\n\tNSDictionary *userInfo;\n\tNSInteger tag;\n\t\n\t// Use HTTP 1.0 rather than 1.1 (defaults to false)\n\tBOOL useHTTPVersionOne;\n\t\n\t// When YES, requests will automatically redirect when they get a HTTP 30x header (defaults to YES)\n\tBOOL shouldRedirect;\n\t\n\t// Used internally to tell the main loop we need to stop and retry with a new url\n\tBOOL needsRedirect;\n\t\n\t// Incremented every time this request redirects. When it reaches 5, we give up\n\tint redirectCount;\n\t\n\t// When NO, requests will not check the secure certificate is valid (use for self-signed certificates during development, DO NOT USE IN PRODUCTION) Default is YES\n\tBOOL validatesSecureCertificate;\n    \n    // If not nil and the URL scheme is https, CFNetwork configured to supply a client certificate\n    SecIdentityRef clientCertificateIdentity;\n\tNSArray *clientCertificates;\n\t\n\t// Details on the proxy to use - you could set these yourself, but it's probably best to let ASIHTTPRequest detect the system proxy settings\n\tNSString *proxyHost;\n\tint proxyPort;\n\t\n\t// ASIHTTPRequest will assume kCFProxyTypeHTTP if the proxy type could not be automatically determined\n\t// Set to kCFProxyTypeSOCKS if you are manually configuring a SOCKS proxy\n\tNSString *proxyType;\n\n\t// URL for a PAC (Proxy Auto Configuration) file. If you want to set this yourself, it's probably best if you use a local file\n\tNSURL *PACurl;\n\t\n\t// See ASIAuthenticationState values above. 0 == default == No authentication needed yet\n\tASIAuthenticationState authenticationNeeded;\n\t\n\t// When YES, ASIHTTPRequests will present credentials from the session store for requests to the same server before being asked for them\n\t// This avoids an extra round trip for requests after authentication has succeeded, which is much for efficient for authenticated requests with large bodies, or on slower connections\n\t// Set to NO to only present credentials when explicitly asked for them\n\t// This only affects credentials stored in the session cache when useSessionPersistence is YES. Credentials from the keychain are never presented unless the server asks for them\n\t// Default is YES\n\t// For requests using Basic authentication, set authenticationScheme to (NSString *)kCFHTTPAuthenticationSchemeBasic, and credentials can be sent on the very first request when shouldPresentCredentialsBeforeChallenge is YES\n\tBOOL shouldPresentCredentialsBeforeChallenge;\n\t\n\t// YES when the request hasn't finished yet. Will still be YES even if the request isn't doing anything (eg it's waiting for delegate authentication). READ-ONLY\n\tBOOL inProgress;\n\t\n\t// Used internally to track whether the stream is scheduled on the run loop or not\n\t// Bandwidth throttling can unschedule the stream to slow things down while a request is in progress\n\tBOOL readStreamIsScheduled;\n\t\n\t// Set to allow a request to automatically retry itself on timeout\n\t// Default is zero - timeout will stop the request\n\tint numberOfTimesToRetryOnTimeout;\n\n\t// The number of times this request has retried (when numberOfTimesToRetryOnTimeout > 0)\n\tint retryCount;\n\n\t// Temporarily set to YES when a closed connection forces a retry (internally, this stops ASIHTTPRequest cleaning up a temporary post body)\n\tBOOL willRetryRequest;\n\n\t// When YES, requests will keep the connection to the server alive for a while to allow subsequent requests to re-use it for a substantial speed-boost\n\t// Persistent connections will not be used if the server explicitly closes the connection\n\t// Default is YES\n\tBOOL shouldAttemptPersistentConnection;\n\n\t// Number of seconds to keep an inactive persistent connection open on the client side\n\t// Default is 60\n\t// If we get a keep-alive header, this is this value is replaced with how long the server told us to keep the connection around\n\t// A future date is created from this and used for expiring the connection, this is stored in connectionInfo's expires value\n\tNSTimeInterval persistentConnectionTimeoutSeconds;\n\t\n\t// Set to yes when an appropriate keep-alive header is found\n\tBOOL connectionCanBeReused;\n\t\n\t// Stores information about the persistent connection that is currently in use.\n\t// It may contain:\n\t// * The id we set for a particular connection, incremented every time we want to specify that we need a new connection\n\t// * The date that connection should expire\n\t// * A host, port and scheme for the connection. These are used to determine whether that connection can be reused by a subsequent request (all must match the new request)\n\t// * An id for the request that is currently using the connection. This is used for determining if a connection is available or not (we store a number rather than a reference to the request so we don't need to hang onto a request until the connection expires)\n\t// * A reference to the stream that is currently using the connection. This is necessary because we need to keep the old stream open until we've opened a new one.\n\t//   The stream will be closed + released either when another request comes to use the connection, or when the timer fires to tell the connection to expire\n\tNSMutableDictionary *connectionInfo;\n\t\n\t// When set to YES, 301 and 302 automatic redirects will use the original method and and body, according to the HTTP 1.1 standard\n\t// Default is NO (to follow the behaviour of most browsers)\n\tBOOL shouldUseRFC2616RedirectBehaviour;\n\t\n\t// Used internally to record when a request has finished downloading data\n\tBOOL downloadComplete;\n\t\n\t// An ID that uniquely identifies this request - primarily used for debugging persistent connections\n\tNSNumber *requestID;\n\t\n\t// Will be ASIHTTPRequestRunLoopMode for synchronous requests, NSDefaultRunLoopMode for all other requests\n\tNSString *runLoopMode;\n\t\n\t// This timer checks up on the request every 0.25 seconds, and updates progress\n\tNSTimer *statusTimer;\n\t\n\t// The download cache that will be used for this request (use [ASIHTTPRequest setDefaultCache:cache] to configure a default cache\n\tid <ASICacheDelegate> downloadCache;\n\t\n\t// The cache policy that will be used for this request - See ASICacheDelegate.h for possible values\n\tASICachePolicy cachePolicy;\n\t\n\t// The cache storage policy that will be used for this request - See ASICacheDelegate.h for possible values\n\tASICacheStoragePolicy cacheStoragePolicy;\n\t\n\t// Will be true when the response was pulled from the cache rather than downloaded\n\tBOOL didUseCachedResponse;\n\n\t// Set secondsToCache to use a custom time interval for expiring the response when it is stored in a cache\n\tNSTimeInterval secondsToCache;\n\n\t#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n\tBOOL shouldContinueWhenAppEntersBackground;\n\tUIBackgroundTaskIdentifier backgroundTask;\n\t#endif\n\t\n\t// When downloading a gzipped response, the request will use this helper object to inflate the response\n\tASIDataDecompressor *dataDecompressor;\n\t\n\t// Controls how responses with a gzipped encoding are inflated (decompressed)\n\t// When set to YES (This is the default):\n\t// * gzipped responses for requests without a downloadDestinationPath will be inflated only when [request responseData] / [request responseString] is called\n\t// * gzipped responses for requests with a downloadDestinationPath set will be inflated only when the request completes\n\t//\n\t// When set to NO\n\t// All requests will inflate the response as it comes in\n\t// * If the request has no downloadDestinationPath set, the raw (compressed) response is discarded and rawResponseData will contain the decompressed response\n\t// * If the request has a downloadDestinationPath, the raw response will be stored in temporaryFileDownloadPath as normal, the inflated response will be stored in temporaryUncompressedDataDownloadPath\n\t//   Once the request completes successfully, the contents of temporaryUncompressedDataDownloadPath are moved into downloadDestinationPath\n\t//\n\t// Setting this to NO may be especially useful for users using ASIHTTPRequest in conjunction with a streaming parser, as it will allow partial gzipped responses to be inflated and passed on to the parser while the request is still running\n\tBOOL shouldWaitToInflateCompressedResponses;\n\n\t// Will be YES if this is a request created behind the scenes to download a PAC file - these requests do not attempt to configure their own proxies\n\tBOOL isPACFileRequest;\n\n\t// Used for downloading PAC files from http / https webservers\n\tASIHTTPRequest *PACFileRequest;\n\n\t// Used for asynchronously reading PAC files from file:// URLs\n\tNSInputStream *PACFileReadStream;\n\n\t// Used for storing PAC data from file URLs as it is downloaded\n\tNSMutableData *PACFileData;\n\n\t// Set to YES in startSynchronous. Currently used by proxy detection to download PAC files synchronously when appropriate\n\tBOOL isSynchronous;\n\n\t#if NS_BLOCKS_AVAILABLE\n\t//block to execute when request starts\n\tASIBasicBlock startedBlock;\n\n\t//block to execute when headers are received\n\tASIHeadersBlock headersReceivedBlock;\n\n\t//block to execute when request completes successfully\n\tASIBasicBlock completionBlock;\n\n\t//block to execute when request fails\n\tASIBasicBlock failureBlock;\n\n\t//block for when bytes are received\n\tASIProgressBlock bytesReceivedBlock;\n\n\t//block for when bytes are sent\n\tASIProgressBlock bytesSentBlock;\n\n\t//block for when download size is incremented\n\tASISizeBlock downloadSizeIncrementedBlock;\n\n\t//block for when upload size is incremented\n\tASISizeBlock uploadSizeIncrementedBlock;\n\n\t//block for handling raw bytes received\n\tASIDataBlock dataReceivedBlock;\n\n\t//block for handling authentication\n\tASIBasicBlock authenticationNeededBlock;\n\n\t//block for handling proxy authentication\n\tASIBasicBlock proxyAuthenticationNeededBlock;\n\t\n    //block for handling redirections, if you want to\n    ASIBasicBlock requestRedirectedBlock;\n\t#endif\n}\n\n#pragma mark init / dealloc\n\n// Should be an HTTP or HTTPS url, may include username and password if appropriate\n- (id)initWithURL:(NSURL *)newURL;\n\n// Convenience constructor\n+ (id)requestWithURL:(NSURL *)newURL;\n\n+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache;\n+ (id)requestWithURL:(NSURL *)newURL usingCache:(id <ASICacheDelegate>)cache andCachePolicy:(ASICachePolicy)policy;\n\n#if NS_BLOCKS_AVAILABLE\n- (void)setStartedBlock:(ASIBasicBlock)aStartedBlock;\n- (void)setHeadersReceivedBlock:(ASIHeadersBlock)aReceivedBlock;\n- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock;\n- (void)setFailedBlock:(ASIBasicBlock)aFailedBlock;\n- (void)setBytesReceivedBlock:(ASIProgressBlock)aBytesReceivedBlock;\n- (void)setBytesSentBlock:(ASIProgressBlock)aBytesSentBlock;\n- (void)setDownloadSizeIncrementedBlock:(ASISizeBlock) aDownloadSizeIncrementedBlock;\n- (void)setUploadSizeIncrementedBlock:(ASISizeBlock) anUploadSizeIncrementedBlock;\n- (void)setDataReceivedBlock:(ASIDataBlock)aReceivedBlock;\n- (void)setAuthenticationNeededBlock:(ASIBasicBlock)anAuthenticationBlock;\n- (void)setProxyAuthenticationNeededBlock:(ASIBasicBlock)aProxyAuthenticationBlock;\n- (void)setRequestRedirectedBlock:(ASIBasicBlock)aRedirectBlock;\n#endif\n\n#pragma mark setup request\n\n// Add a custom header to the request\n- (void)addRequestHeader:(NSString *)header value:(NSString *)value;\n\n// Called during buildRequestHeaders and after a redirect to create a cookie header from request cookies and the global store\n- (void)applyCookieHeader;\n\n// Populate the request headers dictionary. Called before a request is started, or by a HEAD request that needs to borrow them\n- (void)buildRequestHeaders;\n\n// Used to apply authorization header to a request before it is sent (when shouldPresentCredentialsBeforeChallenge is YES)\n- (void)applyAuthorizationHeader;\n\n\n// Create the post body\n- (void)buildPostBody;\n\n// Called to add data to the post body. Will append to postBody when shouldStreamPostDataFromDisk is false, or write to postBodyWriteStream when true\n- (void)appendPostData:(NSData *)data;\n- (void)appendPostDataFromFile:(NSString *)file;\n\n#pragma mark get information about this request\n\n// Returns the contents of the result as an NSString (not appropriate for binary data - used responseData instead)\n- (NSString *)responseString;\n\n// Response data, automatically uncompressed where appropriate\n- (NSData *)responseData;\n\n// Returns true if the response was gzip compressed\n- (BOOL)isResponseCompressed;\n\n#pragma mark running a request\n\n\n// Run a request synchronously, and return control when the request completes or fails\n- (void)startSynchronous;\n\n// Run request in the background\n- (void)startAsynchronous;\n\n// Clears all delegates and blocks, then cancels the request\n- (void)clearDelegatesAndCancel;\n\n#pragma mark HEAD request\n\n// Used by ASINetworkQueue to create a HEAD request appropriate for this request with the same headers (though you can use it yourself)\n- (ASIHTTPRequest *)HEADRequest;\n\n#pragma mark upload/download progress\n\n// Called approximately every 0.25 seconds to update the progress delegates\n- (void)updateProgressIndicators;\n\n// Updates upload progress (notifies the queue and/or uploadProgressDelegate of this request)\n- (void)updateUploadProgress;\n\n// Updates download progress (notifies the queue and/or uploadProgressDelegate of this request)\n- (void)updateDownloadProgress;\n\n// Called when authorisation is needed, as we only find out we don't have permission to something when the upload is complete\n- (void)removeUploadProgressSoFar;\n\n// Called when we get a content-length header and shouldResetDownloadProgress is true\n- (void)incrementDownloadSizeBy:(long long)length;\n\n// Called when a request starts and shouldResetUploadProgress is true\n// Also called (with a negative length) to remove the size of the underlying buffer used for uploading\n- (void)incrementUploadSizeBy:(long long)length;\n\n// Helper method for interacting with progress indicators to abstract the details of different APIS (NSProgressIndicator and UIProgressView)\n+ (void)updateProgressIndicator:(id *)indicator withProgress:(unsigned long long)progress ofTotal:(unsigned long long)total;\n\n// Helper method used for performing invocations on the main thread (used for progress)\n+ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount callerToRetain:(id)caller;\n\n#pragma mark talking to delegates\n\n// Called when a request starts, lets the delegate know via didStartSelector\n- (void)requestStarted;\n\n// Called when a request receives response headers, lets the delegate know via didReceiveResponseHeadersSelector\n- (void)requestReceivedResponseHeaders:(NSDictionary *)newHeaders;\n\n// Called when a request completes successfully, lets the delegate know via didFinishSelector\n- (void)requestFinished;\n\n// Called when a request fails, and lets the delegate know via didFailSelector\n- (void)failWithError:(NSError *)theError;\n\n// Called to retry our request when our persistent connection is closed\n// Returns YES if we haven't already retried, and connection will be restarted\n// Otherwise, returns NO, and nothing will happen\n- (BOOL)retryUsingNewConnection;\n\n// Can be called by delegates from inside their willRedirectSelector implementations to restart the request with a new url\n- (void)redirectToURL:(NSURL *)newURL;\n\n#pragma mark parsing HTTP response headers\n\n// Reads the response headers to find the content length, encoding, cookies for the session \n// Also initiates request redirection when shouldRedirect is true\n// And works out if HTTP auth is required\n- (void)readResponseHeaders;\n\n// Attempts to set the correct encoding by looking at the Content-Type header, if this is one\n- (void)parseStringEncodingFromHeaders;\n\n+ (void)parseMimeType:(NSString **)mimeType andResponseEncoding:(NSStringEncoding *)stringEncoding fromContentType:(NSString *)contentType;\n\n#pragma mark http authentication stuff\n\n// Apply credentials to this request\n- (BOOL)applyCredentials:(NSDictionary *)newCredentials;\n- (BOOL)applyProxyCredentials:(NSDictionary *)newCredentials;\n\n// Attempt to obtain credentials for this request from the URL, username and password or keychain\n- (NSMutableDictionary *)findCredentials;\n- (NSMutableDictionary *)findProxyCredentials;\n\n// Unlock (unpause) the request thread so it can resume the request\n// Should be called by delegates when they have populated the authentication information after an authentication challenge\n- (void)retryUsingSuppliedCredentials;\n\n// Should be called by delegates when they wish to cancel authentication and stop\n- (void)cancelAuthentication;\n\n// Apply authentication information and resume the request after an authentication challenge\n- (void)attemptToApplyCredentialsAndResume;\n- (void)attemptToApplyProxyCredentialsAndResume;\n\n// Attempt to show the built-in authentication dialog, returns YES if credentials were supplied, NO if user cancelled dialog / dialog is disabled / running on main thread\n// Currently only used on iPhone OS\n- (BOOL)showProxyAuthenticationDialog;\n- (BOOL)showAuthenticationDialog;\n\n// Construct a basic authentication header from the username and password supplied, and add it to the request headers\n// Used when shouldPresentCredentialsBeforeChallenge is YES\n- (void)addBasicAuthenticationHeaderWithUsername:(NSString *)theUsername andPassword:(NSString *)thePassword;\n\n#pragma mark stream status handlers\n\n// CFnetwork event handlers\n- (void)handleNetworkEvent:(CFStreamEventType)type;\n- (void)handleBytesAvailable;\n- (void)handleStreamComplete;\n- (void)handleStreamError;\n\n#pragma mark cleanup\n\n// Cleans up and lets the queue know this operation is finished.\n// Appears in this header for subclassing only, do not call this method from outside your request!\n- (void)markAsFinished;\n\n// Cleans up temporary files. There's normally no reason to call these yourself, they are called automatically when a request completes or fails\n\n// Clean up the temporary file used to store the downloaded data when it comes in (if downloadDestinationPath is set)\n- (BOOL)removeTemporaryDownloadFile;\n\n// Clean up the temporary file used to store data that is inflated (decompressed) as it comes in\n- (BOOL)removeTemporaryUncompressedDownloadFile;\n\n// Clean up the temporary file used to store the request body (when shouldStreamPostDataFromDisk is YES)\n- (BOOL)removeTemporaryUploadFile;\n\n// Clean up the temporary file used to store a deflated (compressed) request body when shouldStreamPostDataFromDisk is YES\n- (BOOL)removeTemporaryCompressedUploadFile;\n\n// Remove a file on disk, returning NO and populating the passed error pointer if it fails\n+ (BOOL)removeFileAtPath:(NSString *)path error:(NSError **)err;\n\n#pragma mark persistent connections\n\n// Get the ID of the connection this request used (only really useful in tests and debugging)\n- (NSNumber *)connectionID;\n\n// Called automatically when a request is started to clean up any persistent connections that have expired\n+ (void)expirePersistentConnections;\n\n#pragma mark default time out\n\n+ (NSTimeInterval)defaultTimeOutSeconds;\n+ (void)setDefaultTimeOutSeconds:(NSTimeInterval)newTimeOutSeconds;\n\n#pragma mark client certificate\n\n- (void)setClientCertificateIdentity:(SecIdentityRef)anIdentity;\n\n#pragma mark session credentials\n\n+ (NSMutableArray *)sessionProxyCredentialsStore;\n+ (NSMutableArray *)sessionCredentialsStore;\n\n+ (void)storeProxyAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials;\n+ (void)storeAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials;\n\n+ (void)removeProxyAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials;\n+ (void)removeAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials;\n\n- (NSDictionary *)findSessionProxyAuthenticationCredentials;\n- (NSDictionary *)findSessionAuthenticationCredentials;\n\n#pragma mark keychain storage\n\n// Save credentials for this request to the keychain\n- (void)saveCredentialsToKeychain:(NSDictionary *)newCredentials;\n\n// Save credentials to the keychain\n+ (void)saveCredentials:(NSURLCredential *)credentials forHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n+ (void)saveCredentials:(NSURLCredential *)credentials forProxy:(NSString *)host port:(int)port realm:(NSString *)realm;\n\n// Return credentials from the keychain\n+ (NSURLCredential *)savedCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n+ (NSURLCredential *)savedCredentialsForProxy:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n\n// Remove credentials from the keychain\n+ (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;\n+ (void)removeCredentialsForProxy:(NSString *)host port:(int)port realm:(NSString *)realm;\n\n// We keep track of any cookies we accept, so that we can remove them from the persistent store later\n+ (void)setSessionCookies:(NSMutableArray *)newSessionCookies;\n+ (NSMutableArray *)sessionCookies;\n\n// Adds a cookie to our list of cookies we've accepted, checking first for an old version of the same cookie and removing that\n+ (void)addSessionCookie:(NSHTTPCookie *)newCookie;\n\n// Dump all session data (authentication and cookies)\n+ (void)clearSession;\n\n#pragma mark get user agent\n\n// Will be used as a user agent if requests do not specify a custom user agent\n// Is only used when you have specified a Bundle Display Name (CFDisplayBundleName) or Bundle Name (CFBundleName) in your plist\n+ (NSString *)defaultUserAgentString;\n+ (void)setDefaultUserAgentString:(NSString *)agent;\n\n#pragma mark mime-type detection\n\n// Return the mime type for a file\n+ (NSString *)mimeTypeForFileAtPath:(NSString *)path;\n\n#pragma mark bandwidth measurement / throttling\n\n// The maximum number of bytes ALL requests can send / receive in a second\n// This is a rough figure. The actual amount used will be slightly more, this does not include HTTP headers\n+ (unsigned long)maxBandwidthPerSecond;\n+ (void)setMaxBandwidthPerSecond:(unsigned long)bytes;\n\n// Get a rough average (for the last 5 seconds) of how much bandwidth is being used, in bytes\n+ (unsigned long)averageBandwidthUsedPerSecond;\n\n- (void)performThrottling;\n\n// Will return YES is bandwidth throttling is currently in use\n+ (BOOL)isBandwidthThrottled;\n\n// Used internally to record bandwidth use, and by ASIInputStreams when uploading. It's probably best if you don't mess with this.\n+ (void)incrementBandwidthUsedInLastSecond:(unsigned long)bytes;\n\n// On iPhone, ASIHTTPRequest can automatically turn throttling on and off as the connection type changes between WWAN and WiFi\n\n#if TARGET_OS_IPHONE\n// Set to YES to automatically turn on throttling when WWAN is connected, and automatically turn it off when it isn't\n+ (void)setShouldThrottleBandwidthForWWAN:(BOOL)throttle;\n\n// Turns on throttling automatically when WWAN is connected using a custom limit, and turns it off automatically when it isn't\n+ (void)throttleBandwidthForWWANUsingLimit:(unsigned long)limit;\n\n#pragma mark reachability\n\n// Returns YES when an iPhone OS device is connected via WWAN, false when connected via WIFI or not connected\n+ (BOOL)isNetworkReachableViaWWAN;\n\n#endif\n\n#pragma mark queue\n\n// Returns the shared queue\n+ (NSOperationQueue *)sharedQueue;\n\n#pragma mark cache\n\n+ (void)setDefaultCache:(id <ASICacheDelegate>)cache;\n+ (id <ASICacheDelegate>)defaultCache;\n\n// Returns the maximum amount of data we can read as part of the current measurement period, and sleeps this thread if our allowance is used up\n+ (unsigned long)maxUploadReadLength;\n\n#pragma mark network activity\n\n+ (BOOL)isNetworkInUse;\n\n+ (void)setShouldUpdateNetworkActivityIndicator:(BOOL)shouldUpdate;\n\n// Shows the network activity spinner thing on iOS. You may wish to override this to do something else in Mac projects\n+ (void)showNetworkActivityIndicator;\n\n// Hides the network activity spinner thing on iOS\n+ (void)hideNetworkActivityIndicator;\n\n#pragma mark miscellany\n\n// Used for generating Authorization header when using basic authentication when shouldPresentCredentialsBeforeChallenge is true\n// And also by ASIS3Request\n+ (NSString *)base64forData:(NSData *)theData;\n\n// Returns the expiration date for the request.\n// Calculated from the Expires response header property, unless maxAge is non-zero or\n// there exists a non-zero max-age property in the Cache-Control response header.\n+ (NSDate *)expiryDateForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge;\n\n// Returns a date from a string in RFC1123 format\n+ (NSDate *)dateFromRFC1123String:(NSString *)string;\n\n\n// Used for detecting multitasking support at runtime (for backgrounding requests)\n#if TARGET_OS_IPHONE\n+ (BOOL)isMultitaskingSupported;\n#endif\n\n#pragma mark threading behaviour\n\n// In the default implementation, all requests run in a single background thread\n// Advanced users only: Override this method in a subclass for a different threading behaviour\n// Eg: return [NSThread mainThread] to run all requests in the main thread\n// Alternatively, you can create a thread on demand, or manage a pool of threads\n// Threads returned by this method will need to run the runloop in default mode (eg CFRunLoopRun())\n// Requests will stop the runloop when they complete\n// If you have multiple requests sharing the thread you'll need to restart the runloop when this happens\n+ (NSThread *)threadForRequest:(ASIHTTPRequest *)request;\n\n\n#pragma mark ===\n\n@property (retain) NSString *username;\n@property (retain) NSString *password;\n@property (retain) NSString *userAgent;\n@property (retain) NSString *domain;\n\n@property (retain) NSString *proxyUsername;\n@property (retain) NSString *proxyPassword;\n@property (retain) NSString *proxyDomain;\n\n@property (retain) NSString *proxyHost;\n@property (assign) int proxyPort;\n@property (retain) NSString *proxyType;\n\n@property (retain,setter=setURL:, nonatomic) NSURL *url;\n@property (retain) NSURL *originalURL;\n@property (assign, nonatomic) id delegate;\n@property (retain, nonatomic) id queue;\n@property (assign, nonatomic) id uploadProgressDelegate;\n@property (assign, nonatomic) id downloadProgressDelegate;\n@property (assign) BOOL useKeychainPersistence;\n@property (assign) BOOL useSessionPersistence;\n@property (retain) NSString *downloadDestinationPath;\n@property (retain) NSString *temporaryFileDownloadPath;\n@property (retain) NSString *temporaryUncompressedDataDownloadPath;\n@property (assign) SEL didStartSelector;\n@property (assign) SEL didReceiveResponseHeadersSelector;\n@property (assign) SEL willRedirectSelector;\n@property (assign) SEL didFinishSelector;\n@property (assign) SEL didFailSelector;\n@property (assign) SEL didReceiveDataSelector;\n@property (retain,readonly) NSString *authenticationRealm;\n@property (retain,readonly) NSString *proxyAuthenticationRealm;\n@property (retain) NSError *error;\n@property (assign,readonly) BOOL complete;\n@property (retain) NSDictionary *responseHeaders;\n@property (retain) NSMutableDictionary *requestHeaders;\n@property (retain) NSMutableArray *requestCookies;\n@property (retain,readonly) NSArray *responseCookies;\n@property (assign) BOOL useCookiePersistence;\n@property (retain) NSDictionary *requestCredentials;\n@property (retain) NSDictionary *proxyCredentials;\n@property (assign,readonly) int responseStatusCode;\n@property (retain,readonly) NSString *responseStatusMessage;\n@property (retain) NSMutableData *rawResponseData;\n@property (assign) NSTimeInterval timeOutSeconds;\n@property (retain, nonatomic) NSString *requestMethod;\n@property (retain) NSMutableData *postBody;\n@property (assign) unsigned long long contentLength;\n@property (assign) unsigned long long postLength;\n@property (assign) BOOL shouldResetDownloadProgress;\n@property (assign) BOOL shouldResetUploadProgress;\n@property (assign) ASIHTTPRequest *mainRequest;\n@property (assign) BOOL showAccurateProgress;\n@property (assign) unsigned long long totalBytesRead;\n@property (assign) unsigned long long totalBytesSent;\n@property (assign) NSStringEncoding defaultResponseEncoding;\n@property (assign) NSStringEncoding responseEncoding;\n@property (assign) BOOL allowCompressedResponse;\n@property (assign) BOOL allowResumeForFileDownloads;\n@property (retain) NSDictionary *userInfo;\n@property (assign) NSInteger tag;\n@property (retain) NSString *postBodyFilePath;\n@property (assign) BOOL shouldStreamPostDataFromDisk;\n@property (assign) BOOL didCreateTemporaryPostDataFile;\n@property (assign) BOOL useHTTPVersionOne;\n@property (assign, readonly) unsigned long long partialDownloadSize;\n@property (assign) BOOL shouldRedirect;\n@property (assign) BOOL validatesSecureCertificate;\n@property (assign) BOOL shouldCompressRequestBody;\n@property (retain) NSURL *PACurl;\n@property (retain) NSString *authenticationScheme;\n@property (retain) NSString *proxyAuthenticationScheme;\n@property (assign) BOOL shouldPresentAuthenticationDialog;\n@property (assign) BOOL shouldPresentProxyAuthenticationDialog;\n@property (assign, readonly) ASIAuthenticationState authenticationNeeded;\n@property (assign) BOOL shouldPresentCredentialsBeforeChallenge;\n@property (assign, readonly) int authenticationRetryCount;\n@property (assign, readonly) int proxyAuthenticationRetryCount;\n@property (assign) BOOL haveBuiltRequestHeaders;\n@property (assign, nonatomic) BOOL haveBuiltPostBody;\n@property (assign, readonly) BOOL inProgress;\n@property (assign) int numberOfTimesToRetryOnTimeout;\n@property (assign, readonly) int retryCount;\n@property (assign) BOOL shouldAttemptPersistentConnection;\n@property (assign) NSTimeInterval persistentConnectionTimeoutSeconds;\n@property (assign) BOOL shouldUseRFC2616RedirectBehaviour;\n@property (assign, readonly) BOOL connectionCanBeReused;\n@property (retain, readonly) NSNumber *requestID;\n@property (assign) id <ASICacheDelegate> downloadCache;\n@property (assign) ASICachePolicy cachePolicy;\n@property (assign) ASICacheStoragePolicy cacheStoragePolicy;\n@property (assign, readonly) BOOL didUseCachedResponse;\n@property (assign) NSTimeInterval secondsToCache;\n@property (retain) NSArray *clientCertificates;\n#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0\n@property (assign) BOOL shouldContinueWhenAppEntersBackground;\n#endif\n@property (retain) ASIDataDecompressor *dataDecompressor;\n@property (assign) BOOL shouldWaitToInflateCompressedResponses;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/ASIHTTPRequestConfig.h",
    "content": "//\n//  ASIHTTPRequestConfig.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 14/12/2009.\n//  Copyright 2009 All-Seeing Interactive. All rights reserved.\n//\n\n\n// ======\n// Debug output configuration options\n// ======\n\n// If defined will use the specified function for debug logging\n// Otherwise use NSLog\n#ifndef ASI_DEBUG_LOG\n    #define ASI_DEBUG_LOG NSLog\n#endif\n\n// When set to 1 ASIHTTPRequests will print information about what a request is doing\n#ifndef DEBUG_REQUEST_STATUS\n\t#define DEBUG_REQUEST_STATUS 0\n#endif\n\n// When set to 1, ASIFormDataRequests will print information about the request body to the console\n#ifndef DEBUG_FORM_DATA_REQUEST\n\t#define DEBUG_FORM_DATA_REQUEST 0\n#endif\n\n// When set to 1, ASIHTTPRequests will print information about bandwidth throttling to the console\n#ifndef DEBUG_THROTTLING\n\t#define DEBUG_THROTTLING 0\n#endif\n\n// When set to 1, ASIHTTPRequests will print information about persistent connections to the console\n#ifndef DEBUG_PERSISTENT_CONNECTIONS\n\t#define DEBUG_PERSISTENT_CONNECTIONS 0\n#endif\n\n// When set to 1, ASIHTTPRequests will print information about HTTP authentication (Basic, Digest or NTLM) to the console\n#ifndef DEBUG_HTTP_AUTHENTICATION\n    #define DEBUG_HTTP_AUTHENTICATION 0\n#endif\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/ASIHTTPRequestDelegate.h",
    "content": "//\n//  ASIHTTPRequestDelegate.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 13/04/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n@class ASIHTTPRequest;\n\n@protocol ASIHTTPRequestDelegate <NSObject>\n\n@optional\n\n// These are the default delegate methods for request status\n// You can use different ones by setting didStartSelector / didFinishSelector / didFailSelector\n- (void)requestStarted:(ASIHTTPRequest *)request;\n- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders;\n- (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL;\n- (void)requestFinished:(ASIHTTPRequest *)request;\n- (void)requestFailed:(ASIHTTPRequest *)request;\n- (void)requestRedirected:(ASIHTTPRequest *)request;\n\n// When a delegate implements this method, it is expected to process all incoming data itself\n// This means that responseData / responseString / downloadDestinationPath etc are ignored\n// You can have the request call a different method by setting didReceiveDataSelector\n- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;\n\n// If a delegate implements one of these, it will be asked to supply credentials when none are available\n// The delegate can then either restart the request ([request retryUsingSuppliedCredentials]) once credentials have been set\n// or cancel it ([request cancelAuthentication])\n- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;\n- (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/ASIProgressDelegate.h",
    "content": "//\n//  ASIProgressDelegate.h\n//  Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest\n//\n//  Created by Ben Copsey on 13/04/2010.\n//  Copyright 2010 All-Seeing Interactive. All rights reserved.\n//\n\n@class ASIHTTPRequest;\n\n@protocol ASIProgressDelegate <NSObject>\n\n@optional\n\n// These methods are used to update UIProgressViews (iPhone OS) or NSProgressIndicators (Mac OS X)\n// If you are using a custom progress delegate, you may find it easier to implement didReceiveBytes / didSendBytes instead\n#if TARGET_OS_IPHONE\n- (void)setProgress:(float)newProgress;\n#else\n- (void)setDoubleValue:(double)newProgress;\n- (void)setMaxValue:(double)newMax;\n#endif\n\n// Called when the request receives some data - bytes is the length of that data\n- (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes;\n\n// Called when the request sends some data\n// The first 32KB (128KB on older platforms) of data sent is not included in this amount because of limitations with the CFNetwork API\n// bytes may be less than zero if a request needs to remove upload progress (probably because the request needs to run again)\n- (void)request:(ASIHTTPRequest *)request didSendBytes:(long long)bytes;\n\n// Called when a request needs to change the length of the content to download\n- (void)request:(ASIHTTPRequest *)request incrementDownloadSizeBy:(long long)newLength;\n\n// Called when a request needs to change the length of the content to upload\n// newLength may be less than zero when a request needs to remove the size of the internal buffer from progress tracking\n- (void)request:(ASIHTTPRequest *)request incrementUploadSizeBy:(long long)newLength;\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUAPIConfig.h",
    "content": "//\n//  DOUAPIConfig.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\nextern NSString * const kHttpsApiBaseUrl;\nextern NSString * const kHttpApiBaseUrl;\n\nextern NSString * const kAuthUrl;\nextern NSString * const kTokenUrl;\n\n\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUAPIEngine.h",
    "content": "//\n//  DOUAPIEngine.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-2.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"DOUAPIConfig.h\"\n#import \"DOUQuery.h\"\n\n#import \"DOUService.h\"\n#import \"DOUOAuthService.h\"\n#import \"DOUOAuth2.h\"\n#import \"DOUOAuthStore.h\"\n#import \"DOUHttpRequest.h\"\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUAlbum.h",
    "content": "//\n//  DOUAlbum.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUAlbum : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *desc;\n@property (nonatomic, copy) NSString *privacy;\n\n@property (nonatomic, copy) NSString *createTimeStr;\n@property (nonatomic, retain) NSDate *createTime;\n@property (nonatomic, copy) NSString *updateTimeStr;\n@property (nonatomic, retain) NSDate *updateTime;\n\n@property (nonatomic, assign) NSInteger size;\n@property (nonatomic, assign) NSInteger recsCount;\n@property (nonatomic, assign) NSInteger likedCount;\n\n@property (nonatomic, assign) BOOL liked;\n\n@property (nonatomic, copy) NSString *icon;\n@property (nonatomic, copy) NSString *thumb;\n@property (nonatomic, copy) NSString *cover;\n@property (nonatomic, copy) NSString *image;\n\n@property (nonatomic, retain) DOUUser *author;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUAlbumArray.h",
    "content": "//\n//  DOUAlbumArray.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUAlbumArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUBook.h",
    "content": "//\n//  DOUBook.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUBook : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *subTitle;\n@property (nonatomic, copy) NSString *rating;\n@property (nonatomic, copy) NSString *ISBN10;\n@property (nonatomic, copy) NSString *ISBN13;\n\n@property (nonatomic, copy) NSString *publisher;\n@property (nonatomic, copy) NSString *publishDateStr;\n@property (nonatomic, retain) NSDate *publishDate;\n\n@property (nonatomic, copy) NSString *largeImage;\n@property (nonatomic, copy) NSString *smallImage;\n@property (nonatomic, copy) NSString *mediumImage;\n\n@property (nonatomic, copy) NSString *authorIntro;\n@property (nonatomic, copy) NSString *summary;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUBookArray.h",
    "content": "//\n//  DOUBookArray.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUBookArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUComment.h",
    "content": "//\n//  DOUComment.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUComment : DOUObject\n\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *content;\n\n@property (nonatomic, copy) NSString *createTimeStr; \n@property (nonatomic, retain) NSDate *createTime;\n\n@property (nonatomic, retain) DOUUser *author;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUCommentArray.h",
    "content": "//\n//  DOUCommentArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 5/19/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUCommentArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUEvent.h",
    "content": "//\n//  DOUEvent.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUEvent : DOUObject\n\nextern NSString * const kParticipatedStatus;\nextern NSString * const kWishedStatus;\nextern NSString * const kArrivedStatus;\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *content;\n\n@property (nonatomic, copy) NSString *beginTimeStr;\n@property (nonatomic, retain) NSDate *beginTime;\n@property (nonatomic, copy) NSString *endTimeStr;\n@property (nonatomic, retain) NSDate *endTime;\n@property (nonatomic, copy) NSString *category;\n@property (nonatomic, copy) NSString *categoryName;\n\n\n@property (nonatomic, copy) NSString *adaptUrl;\n@property (nonatomic, copy) NSString *locId;\n@property (nonatomic, copy) NSString *locName;\n@property (nonatomic, copy) NSString *address;\n\n@property (nonatomic, copy) NSString *albumId;\n\n@property (nonatomic, assign) NSInteger participantCount;\n@property (nonatomic, assign) NSInteger wisherCount;\n\n@property (nonatomic, copy) NSString *imageMobile;\n@property (nonatomic, copy) NSString *imageLarge;\n@property (nonatomic, copy) NSString *image;\n@property (nonatomic, copy) NSString *icon;\n\n@property (nonatomic, retain) DOUUser *owner;\n\n@property (nonatomic, copy) NSString    *participateDateStr;\n@property (nonatomic, retain) NSDate    *participateDate;\n@property (nonatomic, copy)   NSString  *status;\n\n@property (nonatomic, assign) float lat;\n@property (nonatomic, assign) float lng;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUEventArray.h",
    "content": "//\n//  DOUEventArray.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUEventArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUHttpRequest.h",
    "content": "//\n//  DOUHttpRequest.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"ASIHTTPRequest.h\"\n\n\nextern NSUInteger const kDefaultTimeoutSeconds;\n\nextern NSString * const DOUHTTPRequestErrorDomain;\n\nextern NSString * const DOUOAuthErrorDomain;\n\nextern NSString * const DOUErrorDomain;\n\n@class DOUHttpRequest;\n@class DOUQuery;\n@protocol DOUHttpRequestDelegate <NSObject>\n\n@required\n- (void)requestFinished:(DOUHttpRequest *)aRequest;\n- (void)requestFailed:(DOUHttpRequest *)aRequest;\n@end\n\n\ntypedef enum _DOUNetworkErrorType {\n  DOUConnectionFailureErrorType = 1,\n  DOURequestTimedOutErrorType = 2,\n  DOUAuthenticationErrorType = 3,\n  DOURequestCancelledErrorType = 4,\n  DOUUnableToCreateRequestErrorType = 5,\n  DOUInternalErrorWhileBuildingRequestType  = 6,\n  DOUInternalErrorWhileApplyingCredentialsType  = 7,\n\tDOUFileManagementError = 8,\n\tDOUTooMuchRedirectionErrorType = 9,\n\tDOUUnhandledExceptionError = 10,\n\tDOUCompressionError = 11\n} DOUNetworkErrorType;\n\n\n\n#if NS_BLOCKS_AVAILABLE\ntypedef void (^DOUBasicBlock)(void);\n\ntypedef void (^DOUReqBlock)(DOUHttpRequest *);\n\ntypedef void (^DOUSizeBlock)(long long size);\n#endif\n\n//\n// DOUHttpRequest is the wrapper of http request, now it's ASIHTTPRequest.\n//\n@interface DOUHttpRequest : ASIHTTPRequest\n\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL;\n\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL target:(id<DOUHttpRequestDelegate>)delegate;\n\n+ (DOUHttpRequest *)requestWithQuery:(DOUQuery *)query target:(id<DOUHttpRequestDelegate>)delegate;\n\n#if NS_BLOCKS_AVAILABLE\n+ (DOUHttpRequest *)requestWithURL:(NSURL *)URL \n                     completionBlock:(DOUBasicBlock)completionHandler;\n\n+ (DOUHttpRequest *)requestWithQuery:(DOUQuery *)query \n                     completionBlock:(DOUBasicBlock)completionHandler;\n#endif\n\n+ (NSError *)adapterError:(NSError *)asiError;\n\n- (NSError *)doubanError;\n\n- (void)appendPostString:(NSString *)string;\n\n@end\n\n\n\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOULoc.h",
    "content": "//\n//  DOULoc.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 9/7/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOULoc : DOUObject\n\n@property (nonatomic, copy) NSString  *identifier;\n@property (nonatomic, copy) NSString  *parent;\n@property (nonatomic, copy) NSString  *name;\n@property (nonatomic, copy) NSString  *uid;\n@property (nonatomic, assign) BOOL  isHabitable;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOULocArray.h",
    "content": "//\n//  DOULocArray.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 9/7/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOULocArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUMovie.h",
    "content": "//\n//  DOUMovie.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUMovie : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *originalTitle;\n@property (nonatomic, copy) NSString *rating;\n@property (nonatomic, copy) NSString *stars;\n\n@property (nonatomic, copy) NSString *publishTimeStr;\n@property (nonatomic, retain) NSDate *publishTime;\n\n@property (nonatomic, copy) NSString *largeImage;\n@property (nonatomic, copy) NSString *smallImage;\n@property (nonatomic, copy) NSString *mediumImage;\n\n@property (nonatomic, assign) NSInteger wishCount;\n@property (nonatomic, assign) NSInteger collectionCount;\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUMovieArray.h",
    "content": "//\n//  DOUMovieArray.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUMovieArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUMusic.h",
    "content": "//\n//  DOUMusic.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUMusic : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *altTitle;\n@property (nonatomic, copy) NSString *rating;\n\n@property (nonatomic, copy) NSString *publisher;\n\n@property (nonatomic, copy) NSString *publishDateStr;\n@property (nonatomic, retain) NSDate *publishDate;\n\n@property (nonatomic, copy) NSString *image;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUMusicArray.h",
    "content": "//\n//  DOUMusicArray.h\n//  DoubanAPIEngine\n//\n//  Created by Panglv on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUMusicArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUNote.h",
    "content": "//\n//  DOUNote.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUNote : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *summary;\n@property (nonatomic, retain) NSArray *content;\n@property (nonatomic, copy) NSString *privacy;\n\n@property (nonatomic, assign) BOOL    canReply;\n\n@property (nonatomic, copy) NSString *updateTimeStr;\n@property (nonatomic, retain) NSDate *updateTime;\n@property (nonatomic, copy) NSString *publishTimeStr;\n@property (nonatomic, retain) NSDate *publishTime;\n\n@property (nonatomic, assign) NSInteger recsCount;\n@property (nonatomic, assign) NSInteger likedCount;\n@property (nonatomic, assign) NSInteger commentsCount;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUNoteArray.h",
    "content": "//\n//  DOUNoteArray.h\n//  DoubanAPIEngine\n//\n//  Created by GUO Lin on 12/5/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUNoteArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUOAuth2.h",
    "content": "//\n//  DOUOAuth2Client.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 31/10/2011.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\nstatic NSString * const kOAuthErrorDomain = @\"kOAuthErrorDomain\";\n\nstatic NSInteger const kOAuthErrorInvalidRequestScheme       = 100;\nstatic NSInteger const kOAuthErrorInvalidRequestMethod       = 101;\nstatic NSInteger const kOAuthErrorAccessTokenIsMissing       = 102;\nstatic NSInteger const kOAuthErrorInvalidAccessToken         = 103;\nstatic NSInteger const kOAuthErrorInvalidAPIKey              = 104;\nstatic NSInteger const kOAuthErrorAPIKeyIsBlocked            = 105;\nstatic NSInteger const kOAuthErrorAccessTokenHasExpired      = 106;\nstatic NSInteger const kOAuthErrorInvalidRequestUri          = 107; \nstatic NSInteger const kOAuthErrorInvalidCredencial          = 108;\nstatic NSInteger const kOAuthErrorInvalidCredencial2         = 109;\nstatic NSInteger const kOAuthErrorNotTrialUser               = 110;\nstatic NSInteger const kOAuthErrorRateLimitExceeded          = 111;\nstatic NSInteger const kOAuthErrorRateLimitExceeded2         = 112;\nstatic NSInteger const kOAuthErrorRequiredParameterIsMissing = 113;\nstatic NSInteger const kOAuthErrorUnsupportedGrantType       = 114;\nstatic NSInteger const kOAuthErrorUnsupportedResponseType    = 115;\nstatic NSInteger const kOAuthErrorClientSecretMismatch       = 116;\nstatic NSInteger const kOAuthErrorRedirectUriMismatch        = 117;\nstatic NSInteger const kOAuthErrorInvalidAuthorizationCode   = 118;\nstatic NSInteger const kOAuthErrorInvalidRefreshToken        = 119;\nstatic NSInteger const kOAuthErrorUsernamePasswordMismatch   = 120;\nstatic NSInteger const kOAuthErrorInvalidUser                = 121;\nstatic NSInteger const kOAuthErrorUserHasBlocked             = 122;\nstatic NSInteger const kOAuthErrorAccessTokenHasExpiredSincePasswordChanged = 123;\nstatic NSInteger const kOAuthErrorAccessTokenHasNotExpired   = 124;\nstatic NSInteger const kOAuthErrorUnknown                    = 999;\n\n\nstatic NSString * const kClientIdKey = @\"client_id\";\nstatic NSString * const kClientSecretKey = @\"client_secret\";\nstatic NSString * const kRedirectURIKey = @\"redirect_uri\";\n\nstatic NSString * const kGrantTypeKey = @\"grant_type\";\nstatic NSString * const kAccessTokenKey = @\"access_token\";\nstatic NSString * const kRefreshTokenKey = @\"refresh_token\";\n\nstatic NSString * const kExpiresInKey = @\"expires_in\";\nstatic NSString * const kScopeKey = @\"scope\";\nstatic NSString * const kStateKey = @\"state\";\n\nstatic NSString * const kUserIdKey = @\"user_id\";\nstatic NSString * const kGrantTypeAuthorizationCode = @\"authorization_code\";\nstatic NSString * const kGrantTypeRefreshToken = @\"refresh_token\";\nstatic NSString * const kGrantTypePassword = @\"password\";\n\nstatic NSString * const kUsernameKey = @\"username\";\nstatic NSString * const kPasswordKey = @\"password\";\n\n\nstatic NSString * const kDoubanUserIdKey = @\"douban_user_id\";\n\nstatic NSString * const kOAuth2ResponseType = @\"response_type\";\nstatic NSString * const kOAuth2ResponseTypeCode = @\"code\";\nstatic NSString * const kOAuth2ResponseTypeToken = @\"refresh_token\";\n\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUOAuthService.h",
    "content": "//\n//  DOUOAuthService.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"DOUService.h\"\n\n\n@class DOUOAuthService;\n@protocol DOUOAuthServiceDelegate <NSObject>\n\n@required\n\n- (void)OAuthClient:(DOUOAuthService *)client didAcquireSuccessDictionary:(NSDictionary *)dic;\n\n- (void)OAuthClient:(DOUOAuthService *)client didFailWithError:(NSError *)error;\n\n@end\n\n\n\n@interface DOUOAuthService : NSObject {\n @private\n@private\n\tNSString *clientId_;\n  NSString *clientSecret_;\n\tNSString *authorizationCode_;\n  NSString *authorizationURL_;\n  NSString *callbackURL_;\n\n  \n  id<DOUOAuthServiceDelegate> delegate_;\n}\n\n@property (nonatomic, assign) id<DOUOAuthServiceDelegate> delegate;\n@property (nonatomic, retain) NSString *clientId;\n@property (nonatomic, retain) NSString *clientSecret;\n@property (nonatomic, retain) NSString *authorizationURL;\n@property (nonatomic, retain) NSString *callbackURL;\n@property (nonatomic, retain) NSString *authorizationCode;\n\n\n+ (id)sharedInstance;\n\n- (void)validateAuthorizationCode;\n\n- (void)validateUsername:(NSString *)username password:(NSString *)password;\n\n- (NSError *)validateRefresh;\n\n\n#if NS_BLOCKS_AVAILABLE\n\n- (void)validateUsername:(NSString *)username \n                password:(NSString *)password\n                callback:(DOUBasicBlock)block;\n\n- (void)validateAuthorizationCodeWithCallback:(DOUBasicBlock)block;\n\n#endif\n\n- (void)logout;\n\n@end\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUOAuthStore.h",
    "content": "//\n//  DOUOAuthStore.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-10-31.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface DOUOAuthStore : NSObject {\n @private  \n  NSString   *accessToken_;\n  NSString   *refreshToken_;\n  NSDate     *expiresIn_;\n  int        userId_;\n}\n\n\n@property (nonatomic, copy, readonly) NSString *accessToken;\n@property (nonatomic, copy, readonly) NSString *refreshToken;\n@property (nonatomic, copy, readonly) NSDate *expiresIn;\n\n@property (nonatomic, assign, readonly) int userId;\n\n+ (id)sharedInstance;\n\n\n- (void)updateWithSuccessDictionary:(NSDictionary *)dic;\n\n- (BOOL)hasExpired;\n\n// refresh token one day before token is expired.\n- (BOOL)shouldRefreshToken;\n\n- (void)save;\n\n- (void)clear;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUObject+Utils.h",
    "content": "//\n//  DOUObject+Utils.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUObject (Utils)\n\n+ (NSDate *)dateOfString:(NSString *)dateString;\n\n+ (NSDate *)dateOfString:(NSString *)dateString dateFormat:(NSString *)dateFormatString;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUObject.h",
    "content": "//\n//  DOUObject.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface DOUObject : NSObject\n\n@property (nonatomic, copy) NSString *string;\n@property (nonatomic, retain) NSMutableDictionary *dictionary;\n\n\n- (id)initWithString:(NSString *)theJsonStr;\n- (id)initWithDictionary:(NSDictionary *)theDictionary;\n\n+ (id)objectWithString:(NSString *)theJsonStr;\n+ (id)objectWithDictionary:(NSDictionary *)theDictionary;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUObjectArray.h",
    "content": "//\n//  DOUObjectArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUObjectArray : DOUObject\n\n@property (nonatomic, assign) NSInteger count;\n@property (nonatomic, assign) NSInteger start;\n@property (nonatomic, assign) NSInteger total;\n\n@property (nonatomic, retain, readonly) NSArray  *objectArray;\n\n+ (Class)objectClass;\n+ (NSString *)objectName;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUOnline.h",
    "content": "//\n//  DOUOnline.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUOnline : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *alt;\n\n@property (nonatomic, copy) NSString *title;\n@property (nonatomic, copy) NSString *desc;\n@property (nonatomic, retain) NSArray *tags;\n\n@property (nonatomic, copy) NSString *createTimeStr;\n@property (nonatomic, retain) NSDate *createTime;\n@property (nonatomic, copy) NSString *beginTimeStr;\n@property (nonatomic, retain) NSDate *beginTime;\n@property (nonatomic, copy) NSString *endTimeStr;\n@property (nonatomic, retain) NSDate *endTime;\n\n\n@property (nonatomic, copy) NSString *relatedUrl;\n@property (nonatomic, copy) NSString *topic;\n\n@property (nonatomic, assign) BOOL cascadeInvite;\n\n@property (nonatomic, copy) NSString *groupId;\n@property (nonatomic, copy) NSString *albumId;\n\n@property (nonatomic, assign) NSInteger participantCount;\n@property (nonatomic, assign) NSInteger photoCount;\n@property (nonatomic, assign) NSInteger likedCount;\n@property (nonatomic, assign) NSInteger recsCount;\n\n@property (nonatomic, copy) NSString *icon;\n@property (nonatomic, copy) NSString *thumb;\n@property (nonatomic, copy) NSString *cover;\n\n@property (nonatomic, copy) NSString *image;\n\n@property (nonatomic, retain) DOUUser *owner;\n\n@property (nonatomic, assign) BOOL liked;\n@property (nonatomic, assign) BOOL participated;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUOnlineArray.h",
    "content": "//\n//  DOUOnlineArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@interface DOUOnlineArray : DOUObjectArray\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUPhoto.h",
    "content": "//\n//  DOUPhoto.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n#import <UIKit/UIKit.h>\n#import \"DOUObject.h\"\n\n@class DOUUser;\n@interface DOUPhoto : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *desc;\n@property (nonatomic, copy) NSString *alt;\n@property (nonatomic, copy) NSString *privacy;\n\n@property (nonatomic, copy) NSString *createTimeStr;\n@property (nonatomic, retain) NSDate *createTime;\n\n@property (nonatomic, assign) NSInteger recsCount; \n@property (nonatomic, assign) NSInteger likedCount; \n@property (nonatomic, assign) NSInteger commentsCount; \n\n@property (nonatomic, copy) NSString *icon;\n@property (nonatomic, copy) NSString *thumb;\n@property (nonatomic, copy) NSString *cover;\n@property (nonatomic, copy) NSString *image;\n\n@property (nonatomic, assign) NSInteger position;\n@property (nonatomic, copy) NSString *prevPhoto;\n@property (nonatomic, copy) NSString *nextPhoto;\n\n@property (nonatomic, assign) BOOL liked;\n@property (nonatomic, retain) DOUUser *author;\n\n@property (nonatomic, assign) NSString *albumId;\n@property (nonatomic, assign) NSString *albumTitle;\n\n@property (nonatomic, assign) CGSize imageSize;\n@property (nonatomic, assign) CGSize coverSize;\n@property (nonatomic, assign) CGSize thumbSize;\n@property (nonatomic, assign) CGSize iconSize;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUPhotoArray.h",
    "content": "//\n//  DOUPhotoArray.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/26/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObjectArray.h\"\n\n@class DOUAlbum;\n@interface DOUPhotoArray : DOUObjectArray\n\n@property (nonatomic, copy) NSString *sortBy;\n@property (nonatomic, copy) NSString *order;\n@property (nonatomic, copy) DOUAlbum *album;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUQuery.h",
    "content": "//\n//  DOUQuery.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n//\n// DOUQuery the class by which we can define the API Request.\n//\n@interface DOUQuery : NSObject {\n @private\n  NSString     *subPath_;\n  NSDictionary *parameters_;\n  NSString     *apiBaseUrlString_;\n}\n\n@property (nonatomic, copy) NSString *subPath;\n@property (nonatomic, retain) NSDictionary *parameters;\n@property (nonatomic, copy) NSString *apiBaseUrlString;\n\n- (id)initWithSubPath:(NSString *)aSubPath parameters:(NSDictionary *)theParameters;\n\n- (NSString *)requestURLString;\n\n- (NSURL *)requestURL;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUService.h",
    "content": "//\n//  DOUService.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-1.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"DOUHttpRequest.h\"\n\n\n@class ASINetworkQueue;\n@interface DOUService : NSObject {\n @private\n  ASINetworkQueue   *queue_;  \n  NSString          *apiBaseUrlString_;  \n  NSString          *clientId_;\n  NSString          *clientSecret_;\n}\n\n@property (nonatomic, copy) NSString *apiBaseUrlString;\n@property (nonatomic, copy) NSString *clientId;\n@property (nonatomic, copy) NSString *clientSecret;\n\n\n+ (DOUService *)sharedInstance;\n\n- (BOOL)isValid;\n\n- (void)addRequest:(DOUHttpRequest *)request;\n\n\n#if NS_BLOCKS_AVAILABLE\n\n- (DOUHttpRequest *)get:(DOUQuery *)query callback:(DOUReqBlock)block;\n\n- (DOUHttpRequest *)post:(DOUQuery *)query \n                postBody:(NSString *)body \n                callback:(DOUReqBlock)block;\n\n- (DOUHttpRequest *)post:(DOUQuery *)query\n               photoData:(NSData *)photoData\n             description:(NSString *)description\n                callback:(DOUReqBlock)block\n  uploadProgressDelegate:(id<ASIProgressDelegate>)progressDelegate;\n\n// v2 api post image\n- (DOUHttpRequest *)post2:(DOUQuery *)query\n                photoData:(NSData *)photoData\n              description:(NSString *)description\n                 callback:(DOUReqBlock)block\n   uploadProgressDelegate:(id<ASIProgressDelegate>)progressDelegate;\n\n- (DOUHttpRequest *)delete:(DOUQuery *)query callback:(DOUReqBlock)block;\n\n#endif\n\n\n- (DOUHttpRequest *)get:(DOUQuery *)query delegate:(id<DOUHttpRequestDelegate>)delegate;\n\n- (DOUHttpRequest *)post:(DOUQuery *)query postBody:(NSString *)body delegate:(id<DOUHttpRequestDelegate>)delegate;\n\n- (DOUHttpRequest *)delete:(DOUQuery *)query delegate:(id<DOUHttpRequestDelegate>)delegate;\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DOUUser.h",
    "content": "//\n//  DOUUser.h\n//  DoubanApiClient\n//\n//  Created by Lin GUO on 4/25/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"DOUObject.h\"\n\n@interface DOUUser : DOUObject\n\n@property (nonatomic, copy) NSString *identifier;\n@property (nonatomic, copy) NSString *avatar;\n@property (nonatomic, copy) NSString *name;\n@property (nonatomic, copy) NSString *alt;\n@property (nonatomic, copy) NSString *uid;\n@property (nonatomic, copy) NSString *desc;\n\n@property (nonatomic, copy) NSString *locId;\n@property (nonatomic, copy) NSString *locName;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanAttribute.h",
    "content": "//\n//  DoubanAttribute.h\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Apple Inc. All rights reserved.\n//\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanAttribute : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanDefines.h",
    "content": "//\n//  DoubanDefines.h\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Apple Inc. All rights reserved.\n//\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBAN_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanCategorySubject  _INITIALIZE_AS(@\"http://www.douban.com/2007#subject\");\n_EXTERN NSString* const kDoubanCategoryMiniblog  _INITIALIZE_AS(@\"http://www.douban.com/2007#miniblog\");\n_EXTERN NSString* const kDoubanCategoryRecommendation  _INITIALIZE_AS(@\"http://www.douban.com/2007#recommendation\");\n\n_EXTERN NSString* const kDoubanCategoryComment  _INITIALIZE_AS(@\"http://www.douban.com/2007#comment\");\n\n_EXTERN NSString* const kDoubanCategoryReview  _INITIALIZE_AS(@\"http://www.douban.com/2007#review\");\n_EXTERN NSString* const kDoubanCategoryEvent  _INITIALIZE_AS(@\"http://www.douban.com/2007#event\");\n_EXTERN NSString* const kDoubanCategoryPeople  _INITIALIZE_AS(@\"http://www.douban.com/2007#people\");\n_EXTERN NSString* const kDoubanCategoryPhoto  _INITIALIZE_AS(@\"http://www.douban.com/2007#photo\");\n_EXTERN NSString* const kDoubanCategoryAlbum  _INITIALIZE_AS(@\"http://www.douban.com/2007#album\");\n\n_EXTERN NSString* const kDoubanCategoryEventCategory  _INITIALIZE_AS(@\"http://www.douban.com/2007#category\");\n_EXTERN NSString* const kDoubanCategoryCityCategory _INITIALIZE_AS(@\"http://www.douban.com/2007#city\");\n\n_EXTERN NSString* const kDoubanNamespace _INITIALIZE_AS(@\"http://www.douban.com/xmlns/\");\n_EXTERN NSString* const kDoubanNamespacePrefix _INITIALIZE_AS(@\"db\");\n\n_EXTERN NSString* const kAtomNamespace _INITIALIZE_AS(@\"http://www.w3.org/2005/Atom\");\n_EXTERN NSString* const kAtomNamespacePrefix _INITIALIZE_AS(@\"ns0\");\n\n_EXTERN NSString* const kGeorssNamespace _INITIALIZE_AS(@\"http://www.georss.org/georss\");\n_EXTERN NSString* const kGeorssNamespacePrefix _INITIALIZE_AS(@\"georess\");\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryAlbum.h",
    "content": "//\n//  DoubanEntryAlbum.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/31/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYALBUM_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanAlbumsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataAtomAuthor;\n@interface DoubanEntryAlbum : GDataEntryBase\n\n@property (nonatomic, readonly) GDataAtomAuthor *author;\n@property (nonatomic, readonly) GDataLink       *imageLink;\n@property (nonatomic, readonly) GDataLink       *thumbLink;\n@property (nonatomic, readonly) GDataLink       *albumCoverLink;\n\n@property (nonatomic, readonly) NSInteger       size;\n@property (nonatomic, readonly) NSString        *privacy;\n@property (nonatomic, readonly) NSInteger       recsCount;\n@property (nonatomic, readonly) NSInteger       likedCount;\n@property (nonatomic, readonly) NSInteger       albumId;\n@property (nonatomic, readonly) NSInteger       authorId;\n@property (nonatomic, readonly) BOOL            liked;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryCity.h",
    "content": "//\n//  DoubanEntryCity.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-27.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYCITY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanCityDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\n@class DoubanUID;\n@interface DoubanEntryCity : GDataEntryBase\n\n@property (nonatomic, copy) NSString  *name;\n@property (nonatomic, copy) NSString  *uid;\n@property (nonatomic, readonly) BOOL  isHabitable;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryComment.h",
    "content": "//\n//  DoubanEntryComment.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 3/23/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYCOMMENT_DEFINE_GLOBALS\n\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanCommentsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\n@interface DoubanEntryComment : GDataEntryBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryEvent.h",
    "content": "//\n//  DoubanEntryEvent.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYEVENT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanEventsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\nextern NSString * const kParticipatedStr;\nextern NSString * const kWishedStr;\nextern NSString * const kArrivedStr;\n\n\n@class DoubanEntryEventCategory;\n@class DoubanLocation;\n@class GDataWhere;\n@class GDataWhen;\n@interface DoubanEntryEvent : GDataEntryBase\n\n@property (nonatomic, readonly) NSInteger  eventId;\n@property (nonatomic, readonly) GDataWhere *where;\n@property (nonatomic, readonly) GDataWhen  *when;\n@property (nonatomic, readonly) DoubanLocation *location;\n@property (nonatomic, readonly) DoubanEntryEventCategory *eventCategory;\n@property (nonatomic, readonly) GDataLink   *imageLink;\n@property (nonatomic, readonly) GDataLink   *imageMobileLink;\n@property (nonatomic, readonly) GDataLink   *imageLargeLink;\n@property (nonatomic, readonly) GDataLink   *iconLink;\n@property (nonatomic, readonly) NSInteger   albumId;\n\n@property (nonatomic, readonly) NSInteger   participantsCount;\n@property (nonatomic, readonly) NSInteger   wishersCount;\n@property (nonatomic, retain)   NSDate      *participateDate;\n@property (nonatomic, copy)     NSString    *status;\n\n@property (nonatomic, readonly) float       geoLatitude;\n@property (nonatomic, readonly) float       geoLongitude;\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryEventCategory.h",
    "content": "//\n//  DoubanEntryEventCategory.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-26.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANEVENTCATEGORY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanEventCategoriesDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\n@interface DoubanEntryEventCategory : GDataEntryBase\n\nextern NSString * const kEventAllCategoryTitle;\nextern NSString * const kEventDramaCategoryTitle;\nextern NSString * const kEventMusicCategoryTitle;\nextern NSString * const kEventExhibitionCategoryTitle;\nextern NSString * const kEventSportsCategoryTitle;\nextern NSString * const kEventPartyCategoryTitle;\nextern NSString * const kEventCommonwealCategoryTitle;\nextern NSString * const kEventTravelCategoryTitle;\nextern NSString * const kEventFilmCategoryTitle;\nextern NSString * const kEventSalonCategoryTitle;\nextern NSString * const kEventOthersCategoryTitle;\n\n\n@property (nonatomic, readonly) NSInteger eventsCount;\n@property (nonatomic, copy)     NSString  *name;\n@property (nonatomic, readonly) GDataLink *coverLink;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryMiniblog.h",
    "content": "//\n//  DoubanEntryMiniblog.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-9.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYMINIBLOG_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanMiniblogsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n\ntypedef enum {\n  MINIBLOG_SAYING_CATEGORY,\n  MINIBLOG_BOOK_CATEGORY,\n  MINIBLOG_MAGAZINE_CATEGORY,\n  MINIBLOG_MOVIE_CATEGORY,\n  MINIBLOG_TV_CATEGORY,\n  MINIBLOG_MUSIC_CATEGORY,\n  \n  MINIBLOG_PLACE_CATEGORY,  \n  MINIBLOG_GROUP_CATEGORY,\n  MINIBLOG_EVENT_CATEGORY,\n  \n  MINIBLOG_SITE_CATEGORY,\n  MINIBLOG_RECOMMENDATION_CATEGORY,  \n  \n  MINIBLOG_NOTE_CATEGORY,  \n  MINIBLOG_BLOG_CATEGORY,  \n  MINIBLOG_PHOTO_CATEGORY,\n  MINIBLOG_CONTACT_CATEGORY,\n  \n  MINIBLOG_PLAZA_CATEGORY,\n  MINIBLOG_SIGNATURE_CATEGORY,\n\n} MiniblogCategory;\n\n@interface DoubanEntryMiniblog : GDataEntryBase\n\n@property (nonatomic, readonly) MiniblogCategory miniblogCategory;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryPeople.h",
    "content": "//\n//  DoubanEntryEvent.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYPEOPLE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanPeoplesDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class DoubanLocation;\n@class DoubanUID;\n@class DoubanSignature;\n@interface DoubanEntryPeople : GDataEntryBase\n\n@property (nonatomic, readonly) DoubanLocation  *location;\n@property (nonatomic, readonly) DoubanUID       *uid;\n@property (nonatomic, readonly) DoubanSignature *signature;\n@property (nonatomic, readonly) GDataLink       *iconLink;\n@property (nonatomic, readonly) GDataLink       *homePage;\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryPhoto.h",
    "content": "//\n//  DoubanEntryPhoto.h\n//  douban-objective-c\n//\n//  Created by py on 4/6/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYPHOTO_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanPhotosDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataAtomAuthor;\n@interface DoubanEntryPhoto : GDataEntryBase {\n\n}\n\n@property (nonatomic, readonly) GDataAtomAuthor *author;\n@property (nonatomic, readonly) GDataLink       *imageLink;\n@property (nonatomic, readonly) GDataLink       *thumbLink;\n@property (nonatomic, readonly) GDataLink       *albumCoverLink;\n@property (nonatomic, readonly) GDataLink       *iconLink;\n\n@property (nonatomic, readonly) NSInteger       commentsCount;\n@property (nonatomic, readonly) NSInteger       recsCount;\n@property (nonatomic, readonly) NSInteger       likedCount;\n@property (nonatomic, readonly) NSInteger       position;\n@property (nonatomic, readonly) NSInteger       photoId;\n@property (nonatomic, readonly) NSInteger       nextPhotoId;\n@property (nonatomic, readonly) NSInteger       prevPhotoId;\n@property (nonatomic, readonly) NSInteger       albumId;\n@property (nonatomic, readonly) NSString        *albumTitle;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryRecommendation.h",
    "content": "//\n//  DoubanEntryRecommendation.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n\n#ifdef DOUBANENTRYRECOMMENDATION_DEFINE_GLOBALS\n\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanRecommendationsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@interface DoubanEntryRecommendation : GDataEntryBase\n\n@property (nonatomic, readonly) NSString *category;\n@property (nonatomic, readonly) NSString *comment;\n@property (nonatomic, readonly) NSInteger commentsCount;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntryReview.h",
    "content": "//\n//  DoubanEntryReview.h\n//  douban-objective-c\n//\n//  Created by py on 3/26/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataEntryBase.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYREVIEW_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanReviewsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataRating;\n@interface DoubanEntryReview : GDataEntryBase\n\n@property (nonatomic, retain) GDataRating *rating;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanEntrySubject.h",
    "content": "//\n//  DoubanEntrySubject.h\n//  DOUAPIEngine\n//\n//  Created by Lin GUO on 11-11-4.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n\n#import \"GDataEntryBase.h\"\n\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef DOUBANENTRYSUBJECT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN extern\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kDoubanSubjectsDefaultServiceVersion _INITIALIZE_AS(@\"2.0\");\n\n@class GDataRating;\n@class GDataLink;\n@class DoubanTag;\n@interface DoubanEntrySubject : GDataEntryBase\n\n@property (nonatomic, retain) GDataRating  *rating;\n@property (nonatomic, retain) NSArray      *tags;\n\n@property (nonatomic, readonly) GDataLink  *imageLink;\n@property (nonatomic, readonly) NSString   *publisher; \n@property (nonatomic, readonly) NSString   *publishDate;\n@property (nonatomic, readonly) NSString   *isbn;\n@property (nonatomic, readonly) NSString   *price;\n@property (nonatomic, readonly) NSArray    *translators;\n\n- (void)addTag:(DoubanTag *)obj;\n\n@end\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedAlbum.h",
    "content": "//\n//  DoubanFeedAlbum.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 1/31/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedAlbum : GDataFeedBase\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedCity.h",
    "content": "//\n//  DoubanFeedCity.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-27.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedCity : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedComment.h",
    "content": "//\n//  DoubanFeedComment.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 3/23/12.\n//  Copyright (c) 2012 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n#import \"DoubanEntryComment.h\"\n\n@interface DoubanFeedComment : GDataFeedBase\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedEvent.h",
    "content": "//\n//  DoubanFeedEvent.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedEvent : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedEventCategory.h",
    "content": "//\n//  DoubanFeedEventCategory.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-26.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedEventCategory : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedMiniblog.h",
    "content": "//\n//  DoubanFeedMiniblog.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-9.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedMiniblog : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedPeople.h",
    "content": "//\n//  DoubanFeedPeople.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-15.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedPeople : GDataFeedBase\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedPhoto.h",
    "content": "//\n//  DoubanFeedPhoto.h\n//  douban-objective-c\n//\n//  Created by py on 4/6/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedPhoto : GDataFeedBase\n\n\n@end"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedRecommendation.h",
    "content": "//\n//  DoubanFeedRecommendation.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedRecommendation : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedReview.h",
    "content": "//\n//  DoubanFeedReview.h\n//  douban-objective-c\n//\n//  Created by py on 3/26/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedReview : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanFeedSubject.h",
    "content": "//\n//  DoubanFeedSubject.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-7.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataFeedBase.h\"\n\n@interface DoubanFeedSubject : GDataFeedBase\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanLocation.h",
    "content": "//\n//  DoubanLocation.h\n//  douban-objective-c\n//\n//  Created by py on 3/19/10.\n//  Copyright 2010 Douban.inc All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanLocation : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)identity;\n\n- (void)setIdentity:(NSString *)str;\n\n- (NSString *)uid;\n\n- (void)setUid:(NSString *)str;\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n@end\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanSignature.h",
    "content": "//\n//  DoubanSignature.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-11-15.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanSignature : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n- (void)setContent:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanTag.h",
    "content": "//\n//  DoubanTag.h\n//  douban-objective-c\n//\n//  Created by py on 3/18/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanTag : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)name;\n\n- (void)setName:(NSString *)str;\n\n- (NSNumber *)count;\n\n- (void)setCount:(NSNumber *)num;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/DoubanUID.h",
    "content": "//\n//  DoubanUID.h\n//  douban-objective-c\n//\n//  Created by py on 3/23/10.\n//  Copyright 2010 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface DoubanUID : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataAtomPubControl.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataAtomPubControl.h\n//\n\n#import \"GDataObject.h\"\n\n// For app:control, like:\n//   <app:control><app:draft>yes</app:draft></app:control>\n\n@interface GDataAtomPubControl : GDataObject <GDataExtension>\n+ (GDataAtomPubControl *)atomPubControl;\n+ (GDataAtomPubControl *)atomPubControlWithIsDraft:(BOOL)isDraft;\n\n- (BOOL)isDraft;\n- (void)setIsDraft:(BOOL)flag;\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataBaseElements.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataBaseElements.h\n//\n// Elements used by the GDataEntryBase and GDataFeedBase classes\n//\n\n#import \"GDataCategory.h\"\n#import \"GDataPerson.h\"\n#import \"GDataTextConstruct.h\"\n#import \"GDataValueConstruct.h\"\n#import \"GDataEntryContent.h\"\n\n// GData\n\n@interface GDataResourceID : GDataValueElementConstruct <GDataExtension>\n@end\n\n// Atom\n\n@interface GDataAtomID : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomPublishedDate : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomUpdatedDate : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomTitle : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomSubtitle : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomSummary : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomContent : GDataEntryContent <GDataExtension>\n@end\n\n@interface GDataAtomRights : GDataTextConstruct <GDataExtension>\n@end\n\n@interface GDataAtomAuthor : GDataPerson <GDataExtension>\n@end\n\n@interface GDataAtomContributor : GDataPerson <GDataExtension>\n@end\n\n@interface GDataAtomIcon : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataAtomLogo : GDataValueElementConstruct <GDataExtension>\n@end\n\n// AtomPub\n\n@interface GDataAtomPubEditedDate : GDataValueElementConstruct <GDataExtension>\n@end\n\n// OpenSearch 1.1, adopted for GData version 2\n\n@interface GDataOpenSearchTotalResults : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataOpenSearchStartIndex : GDataValueElementConstruct <GDataExtension>\n@end\n\n@interface GDataOpenSearchItemsPerPage : GDataValueElementConstruct <GDataExtension>\n@end\n\n// Attributes\n@interface GDataETagAttribute : GDataAttribute <GDataExtension>\n@end\n\n@interface GDataFieldsAttribute : GDataAttribute <GDataExtension>\n@end\n\n@interface GDataKindAttribute : GDataAttribute <GDataExtension>\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataBatchID.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchID.h\n//\n\n#import \"GDataObject.h\"\n\n// For batchID, like:\n//   <batch:id>item2</batch:id>\n\n@interface GDataBatchID : GDataObject <GDataExtension> {\n}\n\n+ (GDataBatchID *)batchIDWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n@end\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataBatchInterrupted.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchInterrupted.h\n//\n\n#import \"GDataObject.h\"\n\n\n// for batch Interrupteds, like\n//  <batch:interrupted reason=\"reason\" success=\"N\" failures=\"N\" parsed=\"N\" />\n\n@interface GDataBatchInterrupted : GDataObject <GDataExtension> {\n}\n\n+ (GDataBatchInterrupted *)batchInterrupted;\n\n- (NSString *)reason;\n- (void)setReason:(NSString *)str;\n\n- (NSNumber *)successCount;\n- (void)setSuccessCount:(NSNumber *)val;\n\n- (NSNumber *)errorCount;\n- (void)setErrorCount:(NSNumber *)val;\n\n- (NSNumber *)totalCount;\n- (void)setTotalCount:(NSNumber *)val;\n\n- (NSString *)contentType;\n- (void)setContentType:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataBatchOperation.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchOperation.h\n//\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATABATCH_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataBatchOperationInsert _INITIALIZE_AS(@\"insert\");\n_EXTERN NSString* const kGDataBatchOperationUpdate _INITIALIZE_AS(@\"update\");\n_EXTERN NSString* const kGDataBatchOperationDelete _INITIALIZE_AS(@\"delete\");\n_EXTERN NSString* const kGDataBatchOperationQuery  _INITIALIZE_AS(@\"query\");\n\n\n// for batch operations, like\n//  <batch:operation type=\"insert\"/>\n@interface GDataBatchOperation : GDataObject <GDataExtension>\n\n+ (GDataBatchOperation *)batchOperationWithType:(NSString *)type;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataBatchStatus.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataBatchStatus.h\n//\n\n#import \"GDataObject.h\"\n\n@class GDataFeedBase;\n\n// a batch response status\n//  <batch:status  code=\"404\"\n//    reason=\"Bad request\"\n//    content-type=\"application/xml\">\n//    <errors>\n//      <error type=\"request\" reason=\"Cannot find item\"/>\n//    </errors>\n//  </batch:status>\n\n@interface GDataBatchStatus : GDataObject <GDataExtension> {\n}\n\n+ (GDataBatchStatus *)batchStatusWithCode:(NSInteger)code\n                                   reason:(NSString *)reason;\n\n- (NSString *)reason;\n- (void)setReason:(NSString *)str;\n\n- (NSNumber *)code;\n- (void)setCode:(NSNumber *)val;\n\n- (NSString *)contentType;\n- (void)setContentType:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataCategory.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataCategory.h\n//\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATACATEGORY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataCategoryLabelScheme _INITIALIZE_AS(@\"http://schemas.google.com/g/2005/labels\");\n\n_EXTERN NSString* const kGDataCategoryLabelStarred          _INITIALIZE_AS(@\"starred\");\n_EXTERN NSString* const kGDataCategoryLabelTrashed          _INITIALIZE_AS(@\"trashed\");\n_EXTERN NSString* const kGDataCategoryLabelPublished        _INITIALIZE_AS(@\"published\");\n_EXTERN NSString* const kGDataCategoryLabelPrivate          _INITIALIZE_AS(@\"private\");\n_EXTERN NSString* const kGDataCategoryLabelMine             _INITIALIZE_AS(@\"mine\");\n_EXTERN NSString* const kGDataCategoryLabelSharedWithDomain _INITIALIZE_AS(@\"shared-with-domain\");\n_EXTERN NSString* const kGDataCategoryLabelHidden           _INITIALIZE_AS(@\"hidden\");\n_EXTERN NSString* const kGDataCategoryLabelViewed           _INITIALIZE_AS(@\"viewed\");\n\n// for categories, like\n//  <category scheme=\"http://schemas.google.com/g/2005#kind\"\n//        term=\"http://schemas.google.com/g/2005#event\"/>\n@interface GDataCategory : GDataObject <GDataExtension>\n\n+ (GDataCategory *)categoryWithScheme:(NSString *)scheme\n                                 term:(NSString *)term;\n\n+ (GDataCategory *)categoryWithLabel:(NSString *)label;\n\n- (NSString *)scheme;\n- (void)setScheme:(NSString *)str;\n- (NSString *)term;\n- (void)setTerm:(NSString *)str;\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n- (NSString *)labelLang;\n- (void)setLabelLang:(NSString *)str;\n\n#pragma mark -\n\n// utilities for extracting a subset of categories\n+ (NSArray *)categoriesWithScheme:(NSString *)scheme fromCategories:(NSArray *)array;\n+ (NSArray *)categoriesWithSchemePrefix:(NSString *)prefix fromCategories:(NSArray *)array;\n\n+ (NSArray *)categoryLabelsFromCategories:(NSArray *)array;\n+ (BOOL)categories:(NSArray *)array containsCategoryWithLabel:(NSString *)label;\n\n// this general search routine allows nil as \"don't care\" for scheme, term,\n// and label\n+ (BOOL)categories:(NSArray *)array\ncontainsCategoryWithScheme:(NSString *)scheme\n              term:(NSString *)term\n             label:(NSString *)label;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataComment.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataComment.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_BOOKS_SERVICE \\\n  || GDATA_INCLUDE_CALENDAR_SERVICE || GDATA_INCLUDE_YOUTUBE_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataFeedLink.h\"\n\n// a commments entry, as in\n// <gd:comments>\n//    <gd:feedLink href=\"http://www.google.com/calendar/feeds/t...\"/>\n// </gd:comments>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdComments\n\n@interface GDataComment : GDataObject <GDataExtension> {\n}\n\n+ (GDataComment *)commentWithFeedLink:(GDataFeedLink *)feedLink;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (GDataFeedLink *)feedLink;\n- (void)setFeedLink:(GDataFeedLink *)feedLink;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataCustomProperty.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataCustomProperty.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE\n\n#import \"GDataObject.h\"\n\n// custom property element, like\n//\n//   <gd:customProperty name=\"milk\" type=\"integer\" unit=\"gallons\">\n//     5\n//   </gd:customProperty>\n\n@interface GDataCustomProperty : GDataObject <GDataExtension>\n\n+ (GDataCustomProperty *)customPropertyWithName:(NSString *)name\n                                           type:(NSString *)type\n                                          value:(NSString *)value\n                                           unit:(NSString *)unit;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n- (NSString *)unit;\n- (void)setUnit:(NSString *)str;\n\n- (NSString *)value;\n- (void)setValue:(NSString *)str;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataDateTime.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataDateTime.h\n//\n\n#import <Foundation/Foundation.h>\n#import \"GDataDefines.h\"\n\n@interface GDataDateTime : NSObject <NSCopying> {\n  NSDateComponents *dateComponents_;\n  NSInteger offsetSeconds_; // may be NSUndefinedDateComponent\n  BOOL isUniversalTime_; // preserves \"Z\"\n  NSTimeZone *timeZone_; // specific time zone by name, if known\n}\n\n// Note: Nil can be passed for time zone arguments when the time zone is not\n//       known.\n\n+ (GDataDateTime *)dateTimeWithRFC3339String:(NSString *)str;\n+ (GDataDateTime *)dateTimeWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz;\n\n- (id)initWithRFC3339String:(NSString *)str;\n- (id)initWithDate:(NSDate *)date timeZone:(NSTimeZone *)tz;\n\n- (void)setFromDate:(NSDate *)date timeZone:(NSTimeZone *)tz;\n- (void)setFromRFC3339String:(NSString *)str;\n\n- (NSDate *)date;\n- (NSCalendar *)calendar;\n\n- (NSTimeZone *)timeZone;\n- (void)setTimeZone:(NSTimeZone *)timeZone;\n- (void)setTimeZone:(NSTimeZone *)timeZone withOffsetSeconds:(NSInteger)val;\n\n- (NSString *)RFC3339String;\n- (NSString *)stringValue; // same as RFC3339String\n\n- (BOOL)hasTime;\n- (void)setHasTime:(BOOL)shouldHaveTime;\n\n- (NSInteger)offsetSeconds;\n- (void)setOffsetSeconds:(NSInteger)val;\n\n- (BOOL)isUniversalTime;\n- (void)setIsUniversalTime:(BOOL)flag;\n\n- (NSDateComponents *)dateComponents;\n- (void)setDateComponents:(NSDateComponents *)dateComponents;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataDefines.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataDefines.h\n//\n\n// Ensure Apple's conditionals we depend on are defined.\n#import <TargetConditionals.h>\n#import <AvailabilityMacros.h>\n\n//\n// The developer may choose to define these in the project:\n//\n//   #define GDATA_TARGET_NAMESPACE Xxx  // preface all GData class names with Xxx (recommended for building plug-ins)\n//   #define GDATA_FOUNDATION_ONLY 1     // builds without AppKit or Carbon (default for iPhone builds)\n//   #define GDATA_SIMPLE_DESCRIPTIONS 1 // remove elaborate -description methods, reducing code size (default for iPhone release builds)\n//   #define STRIP_GDATA_FETCH_LOGGING 1 // omit http logging code (default for iPhone release builds)\n//\n// Mac developers may find GDATA_SIMPLE_DESCRIPTIONS and STRIP_GDATA_FETCH_LOGGING useful for\n// reducing code size.\n//\n\n// Define later OS versions when building on earlier versions\n#ifdef MAC_OS_X_VERSION_10_0\n  #ifndef MAC_OS_X_VERSION_10_6\n    #define MAC_OS_X_VERSION_10_6 1060\n  #endif\n#endif\n\n\n#ifdef GDATA_TARGET_NAMESPACE\n// prefix all GData class names with GDATA_TARGET_NAMESPACE for this target\n  #import \"GDataTargetNamespace.h\"\n#endif\n\n// Provide a common definition for externing constants/functions\n#if defined(__cplusplus)\n#define GDATA_EXTERN extern \"C\"\n#else\n#define GDATA_EXTERN extern\n#endif\n\n#if TARGET_OS_IPHONE // iPhone SDK\n\n  #define GDATA_IPHONE 1\n\n#endif\n\n#if GDATA_IPHONE\n\n  #define GDATA_FOUNDATION_ONLY 1\n\n  #define GDATA_USES_LIBXML 1\n\n  #import \"GDataXMLNode.h\"\n\n  #define NSXMLDocument                  GDataXMLDocument\n  #define NSXMLElement                   GDataXMLElement\n  #define NSXMLNode                      GDataXMLNode\n  #define NSXMLNodeKind                  GDataXMLNodeKind\n  #define NSXMLInvalidKind               GDataXMLInvalidKind\n  #define NSXMLDocumentKind              GDataXMLDocumentKind\n  #define NSXMLElementKind               GDataXMLElementKind\n  #define NSXMLAttributeKind             GDataXMLAttributeKind\n  #define NSXMLNamespaceKind             GDataXMLNamespaceKind\n  #define NSXMLProcessingInstructionKind GDataXMLDocumentKind\n  #define NSXMLCommentKind               GDataXMLCommentKind\n  #define NSXMLTextKind                  GDataXMLTextKind\n  #define NSXMLDTDKind                   GDataXMLDTDKind\n  #define NSXMLEntityDeclarationKind     GDataXMLEntityDeclarationKind\n  #define NSXMLAttributeDeclarationKind  GDataXMLAttributeDeclarationKind\n  #define NSXMLElementDeclarationKind    GDataXMLElementDeclarationKind\n  #define NSXMLNotationDeclarationKind   GDataXMLNotationDeclarationKind\n\n  // properties used for retaining the XML tree in the classes that use them\n  #define kGDataXMLDocumentPropertyKey @\"_XMLDocument\"\n  #define kGDataXMLElementPropertyKey  @\"_XMLElement\"\n#endif\n\n//\n// GDATA_ASSERT is like NSAssert, but takes a variable number of arguments:\n//\n//     GDATA_ASSERT(condition, @\"Problem in argument %@\", argStr);\n//\n// GDATA_DEBUG_ASSERT is similar, but compiles in only for debug builds\n//\n\n#ifndef GDATA_ASSERT\n  // we directly invoke the NSAssert handler so we can pass on the varargs\n  #if !defined(NS_BLOCK_ASSERTIONS)\n    #define GDATA_ASSERT(condition, ...)                                       \\\n      do {                                                                     \\\n        if (!(condition)) {                                                    \\\n          [[NSAssertionHandler currentHandler]                                 \\\n              handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \\\n                                 file:[NSString stringWithUTF8String:__FILE__] \\\n                           lineNumber:__LINE__                                 \\\n                          description:__VA_ARGS__];                            \\\n        }                                                                      \\\n      } while(0)\n  #else\n    #define GDATA_ASSERT(condition, ...) do { } while (0)\n  #endif // !defined(NS_BLOCK_ASSERTIONS)\n#endif // GDATA_ASSERT\n\n#ifndef GDATA_DEBUG_ASSERT\n  #if DEBUG\n    #define GDATA_DEBUG_ASSERT(condition, ...) GDATA_ASSERT(condition, __VA_ARGS__)\n  #else\n    #define GDATA_DEBUG_ASSERT(condition, ...) do { } while (0)\n  #endif\n#endif\n\n#ifndef GDATA_DEBUG_LOG\n  #if DEBUG\n    #define GDATA_DEBUG_LOG(...) NSLog(__VA_ARGS__)\n  #else\n    #define GDATA_DEBUG_LOG(...) do { } while (0)\n  #endif\n#endif\n\n\n//\n// To reduce code size on iPhone release builds, we compile out the helpful\n// description methods for GData objects\n//\n#ifndef GDATA_SIMPLE_DESCRIPTIONS\n  #if GDATA_IPHONE && !DEBUG\n    #define GDATA_SIMPLE_DESCRIPTIONS 1\n  #else\n    #define GDATA_SIMPLE_DESCRIPTIONS 0\n  #endif\n#endif\n\n#ifndef STRIP_GDATA_FETCH_LOGGING\n  #if GDATA_IPHONE && !DEBUG\n    #define STRIP_GDATA_FETCH_LOGGING 1\n  #else\n    #define STRIP_GDATA_FETCH_LOGGING 0\n  #endif\n#endif\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataDeleted.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataDeleted.h\n//\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n// marker for a deleted entry, as in\n// <gd:deleted/>\n\n@interface GDataDeleted : GDataImplicitValueConstruct <GDataExtension>\n\n+ (GDataDeleted *)deleted;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataElements.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n// GDataElements.h\n//\n// Common classes needed for any service\n//\n\n#import \"GDataFramework.h\"\n\n// utility classes\n#import \"GTMHTTPFetcher.h\"\n#import \"GTMHTTPFetcherLogging.h\"\n#import \"GTMHTTPUploadFetcher.h\"\n#import \"GTMGatherInputStream.h\"\n#import \"GTMMIMEDocument.h\"\n\n#import \"GDataDateTime.h\"\n#import \"GDataServerError.h\"\n\n// base classes\n#import \"GDataObject.h\"\n#import \"GDataEntryBase.h\"\n#import \"GDataFeedBase.h\"\n#import \"GDataServiceBase.h\"\n#import \"GDataServiceGoogle.h\"\n#import \"GDataQuery.h\"\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataEmail.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataEmail.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n\n// email element\n// <gd:email label=\"Personal\" address=\"fubar@gmail.com\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdEmail\n\n@interface GDataEmail : GDataObject <GDataExtension>\n\n+ (GDataEmail *)emailWithLabel:(NSString *)label\n                       address:(NSString *)address;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)address;\n- (void)setAddress:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataEntryBase.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n// GDataEntryBase.h\n//\n// This is the base class for all standard GData feed entries.\n//\n\n#import \"GDataDateTime.h\"\n#import \"GDataTextConstruct.h\"\n#import \"GDataEntryContent.h\"\n#import \"GDataPerson.h\"\n#import \"GDataCategory.h\"\n#import \"GDataDeleted.h\"\n#import \"GDataBatchOperation.h\"\n#import \"GDataBatchID.h\"\n#import \"GDataBatchStatus.h\"\n#import \"GDataBatchInterrupted.h\"\n#import \"GDataAtomPubControl.h\"\n#import \"GDataLink.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAENTRYBASE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataCategoryScheme _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#kind\");\n\n\n@interface GDataEntryBase : GDataObject <NSCopying> {\n  // either uploadData_ or uploadFileHandle_ may be set, but not both\n  NSData *uploadData_;\n  NSFileHandle *uploadFileHandle_;\n  NSURL *uploadLocationURL_; // requires uploadFileHandle be set\n  NSString *uploadMIMEType_;\n  NSString *uploadSlug_; // for http slug (filename) header when uploading\n  BOOL shouldUploadDataOnly_;\n}\n\n+ (NSDictionary *)baseGDataNamespaces;\n\n+ (id)entry;\n\n- (id)initWithData:(NSData *)data;\n\n- (id)initWithData:(NSData *)data\n    serviceVersion:(NSString *)serviceVersion\nshouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns;\n\n// basic entry fields\n- (NSString *)identifier;\n- (void)setIdentifier:(NSString *)theIdString;\n\n- (GDataDateTime *)publishedDate;\n- (void)setPublishedDate:(GDataDateTime *)thePublishedDate;\n\n- (GDataDateTime *)updatedDate;\n- (void)setUpdatedDate:(GDataDateTime *)theUpdatedDate;\n\n- (GDataDateTime *)editedDate;\n- (void)setEditedDate:(GDataDateTime *)theEditedDate;\n\n- (NSString *)ETag;\n- (void)setETag:(NSString *)str;\n\n- (NSString *)fieldSelection;\n- (void)setFieldSelection:(NSString *)str;\n\n- (NSString *)kind;\n- (void)setKind:(NSString *)str;\n\n- (NSString *)resourceID;\n- (void)setResourceID:(NSString *)str;\n\n- (GDataTextConstruct *)title;\n- (void)setTitle:(GDataTextConstruct *)theTitle;\n- (void)setTitleWithString:(NSString *)str;\n\n- (GDataTextConstruct *)summary;\n- (void)setSummary:(GDataTextConstruct *)theSummary;\n- (void)setSummaryWithString:(NSString *)str;\n\n- (GDataEntryContent *)content;\n- (void)setContent:(GDataEntryContent *)theContent;\n- (void)setContentWithString:(NSString *)str;\n\n- (GDataTextConstruct *)rightsString;\n- (void)setRightsString:(GDataTextConstruct *)theRightsString;\n- (void)setRightsStringWithString:(NSString *)str;\n\n- (NSArray *)links;\n- (void)setLinks:(NSArray *)links;\n- (void)addLink:(GDataLink *)link;\n\n- (NSArray *)authors;\n- (void)setAuthors:(NSArray *)authors;\n- (void)addAuthor:(GDataPerson *)authorElement;\n\n- (NSArray *)contributors;\n- (void)setContributors:(NSArray *)array;\n- (void)addContributor:(GDataPerson *)obj;\n\n- (NSArray *)categories;\n- (void)setCategories:(NSArray *)categories;\n- (void)addCategory:(GDataCategory *)category;\n- (void)removeCategory:(GDataCategory *)category;\n\n// File upload\n//\n// Either uploadData or uploadFileHandle should be set, but not both\n- (NSData *)uploadData;\n- (void)setUploadData:(NSData *)data;\n\n- (NSFileHandle *)uploadFileHandle;\n- (void)setUploadFileHandle:(NSFileHandle *)fileHandle;\n\n// The location URL is used to restart upload of a file handle\n- (NSURL *)uploadLocationURL;\n- (void)setUploadLocationURL:(NSURL *)url;\n\n- (NSString *)uploadMIMEType;\n- (void)setUploadMIMEType:(NSString *)str;\n\n// support for uploading media data without the XML from the GDataObject\n- (BOOL)shouldUploadDataOnly;\n- (void)setShouldUploadDataOnly:(BOOL)flag;\n\n// http slug (filename) header when uploading\n- (NSString *)uploadSlug;\n- (void)setUploadSlug:(NSString *)str;\n\n// extension for entries which may include deleted elements\n- (BOOL)isDeleted;\n- (void)setIsDeleted:(BOOL)isDeleted;\n\n// extensions for Atom publishing control\n- (GDataAtomPubControl *)atomPubControl;\n- (void)setAtomPubControl:(GDataAtomPubControl *)obj;\n\n// batch support\n+ (NSDictionary *)batchNamespaces;\n\n- (GDataBatchOperation *)batchOperation;\n- (void)setBatchOperation:(GDataBatchOperation *)obj;\n\n// the batch ID is an arbitrary string defined by clients, and present in the\n// batch response feed to let the client match each entry's response to\n// the entry\n- (GDataBatchID *)batchID;\n- (void)setBatchID:(GDataBatchID *)obj;\n- (void)setBatchIDWithString:(NSString *)str;\n\n- (GDataBatchStatus *)batchStatus;\n- (void)setBatchStatus:(GDataBatchStatus *)obj;\n\n- (GDataBatchInterrupted *)batchInterrupted;\n- (void)setBatchInterrupted:(GDataBatchInterrupted *)obj;\n\n// convenience accessors\n\n- (NSArray *)categoriesWithScheme:(NSString *)scheme;\n\n// most entries have a category element with scheme kGDataCategoryScheme\n// that indicates the kind of entry\n- (GDataCategory *)kindCategory;\n\n- (NSArray *)linksWithRelAttributeValue:(NSString *)relValue;\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)relValue;\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel\n                                    type:(NSString *)type;\n\n- (GDataLink *)feedLink;\n- (GDataLink *)editLink;\n- (GDataLink *)editMediaLink;\n- (GDataLink *)alternateLink;\n- (GDataLink *)relatedLink;\n- (GDataLink *)postLink;\n- (GDataLink *)selfLink;\n- (GDataLink *)HTMLLink;\n- (GDataLink *)uploadEditLink;\n\n- (BOOL)canEdit;\n\n///////////////////////////////////////////////////////////////////////////////\n//\n//  Protected methods\n//\n//  All remaining methods are intended for use only by subclasses\n//  of GDataEntryBase.\n//\n\n// subclasses call registerEntryClass to register their standardEntryKind\n+ (void)registerEntryClass;\n\n+ (Class)entryClassForCategoryWithScheme:(NSString *)scheme\n                                    term:(NSString *)term;\n+ (Class)entryClassForKindAttributeValue:(NSString *)kind;\n\n// temporary bridge method\n+ (void)registerEntryClass:(Class)theClass\n     forCategoryWithScheme:(NSString *)scheme\n                      term:(NSString *)term;\n\n\n// subclasses override standardEntryKind to provide the term string for the\n// kind attribute of their kind category element, if any\n+ (NSString *)standardEntryKind;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataEntryContent.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataEntryContent.h\n//\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAENTRYCONTENT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataContentTypeKML _INITIALIZE_AS(@\"application/vnd.google-earth.kml+xml\");\n\n\n// per http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.content\n//\n// For typed content, like <content type=\"text\">Here go the ferrets</content>\n//\n// or media content with a source URI specified,\n//  <content src=\"http://lh.google.com/image/Car.jpg\" type=\"image/jpeg\"/>\n//\n// or a child feed or entry, like\n//  <content type=\"application/atom+xml;feed\"> <feed>...</feed> </content>\n//\n// Text type can be text, text/plain, html, text/html, xhtml, text/xhtml\n\n@interface GDataEntryContent : GDataObject {\n  GDataObject *childObject_;\n}\n\n+ (id)contentWithString:(NSString *)str;\n\n+ (id)contentWithSourceURI:(NSString *)str type:(NSString *)type;\n\n+ (id)contentWithXMLValue:(NSXMLNode *)node type:(NSString *)type;\n\n+ (id)textConstructWithString:(NSString *)str; // deprecated\n\n- (NSString *)lang;\n- (void)setLang:(NSString *)str;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n- (NSString *)sourceURI;\n- (void)setSourceURI:(NSString *)str;\n- (NSURL *)sourceURL;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (GDataObject *)childObject;\n- (void)setChildObject:(GDataObject *)obj;\n\n- (NSArray *)XMLValues;\n- (void)setXMLValues:(NSArray *)arr;\n- (void)addXMLValue:(NSXMLNode *)node;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataEntryLink.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataEntryLink.h\n//\n\n#import \"GDataObject.h\"\n\n@class GDataEntryBase;\n\n// used inside GDataWhere, a link to an entry, like\n// <gd:entryLink href=\"http://gmail.com/jo/contacts/Jo\">\n@interface GDataEntryLink : GDataObject <GDataExtension> {\n  GDataEntryBase *entry_;\n}\n\n+ (GDataEntryLink *)entryLinkWithHref:(NSString *)href\n                           isReadOnly:(BOOL)isReadOnly;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent;\n\n- (NSXMLElement *)XMLElement;\n\n- (NSString *)href;\n- (void)setHref:(NSString *)str;\n\n- (BOOL)isReadOnly;\n- (void)setIsReadOnly:(BOOL)isReadOnly;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (GDataEntryBase *)entry;\n- (void)setEntry:(GDataEntryBase *)entry;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataExtendedProperty.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataExtendedProperty.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n   || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAEXTENDEDPROPERTY_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataExtendedPropertyRealmShared _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#shared\");\n\n\n// an element with a name=\"\" and a value=\"\" attribute, as in\n//  <gd:extendedProperty name='X-MOZ-ALARM-LAST-ACK' value='2006-10-03T19:01:14Z'/>\n//\n// or an arbitrary XML blob, as in\n//  <gd:extendedProperty name='com.myCompany.myProperties'> <myXMLBlob /> </gd:extendedProperty>\n//\n// Servers may impose additional restrictions on names or on the size\n// or composition of the values.\n\n@interface GDataExtendedProperty : GDataObject <GDataExtension>\n\n+ (id)propertyWithName:(NSString *)name\n                 value:(NSString *)value;\n\n- (NSString *)value;\n- (void)setValue:(NSString *)str;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)realm;\n- (void)setRealm:(NSString *)str;\n\n- (NSArray *)XMLValues;\n- (void)setXMLValues:(NSArray *)arr;\n- (void)addXMLValue:(NSXMLNode *)node;\n\n// Obj-C style interface to XML values storage\n//\n// keys are XMLValue node names, values are XMLValue node string values,\n// as in\n//   <key1>value1</key1>\n//   <key2>value2</key2>\n//\n// Behavior is undefined if child nodes are in some other format.\n\n- (void)setXMLValue:(NSString *)value forKey:(NSString *)key;\n- (NSString *)XMLValueForKey:(NSString *)key;\n\n- (NSDictionary *)XMLValuesDictionary;\n- (void)setXMLValuesDictionary:(NSDictionary *)dict;\n\n@end\n\n#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataFeedBase.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataFeedBase.h\n//\n\n#import \"GDataObject.h\"\n\n#import \"GDataGenerator.h\"\n#import \"GDataTextConstruct.h\"\n#import \"GDataLink.h\"\n#import \"GDataEntryBase.h\"\n#import \"GDataCategory.h\"\n#import \"GDataPerson.h\"\n#import \"GDataBatchOperation.h\"\n#import \"GDataAtomPubControl.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAFEEDBASE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// this constant, returned by a subclass implementation of -classForEntries,\n// specifies that a feed's entry class should be determined by inspecting\n// the XML for a \"kind\" category and looking at the registered entry classes\n// for an appropriate match\n_EXTERN Class const kUseRegisteredEntryClass _INITIALIZE_AS(nil);\n\n@interface GDataFeedBase : GDataObject <NSFastEnumeration> {\n\n  // generator is parsed manually to avoid comparison along with other\n  // extensions\n  GDataGenerator *generator_;\n\n  NSMutableArray *entries_;\n}\n\n+ (id)feedWithXMLData:(NSData *)data;\n- (id)initWithData:(NSData *)data;\n- (id)initWithData:(NSData *)data\n    serviceVersion:(NSString *)serviceVersion\nshouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns;\n\n// subclasses override initFeed to set up their ivars\n- (void)initFeedWithXMLElement:(NSXMLElement *)element;\n\n// subclass may override this to specify an entry class or\n// to return kUseRegisteredEntryClass\n- (Class)classForEntries;\n\n// subclasses may override this to specify a \"generic\" class for\n// the feed's entries, if not GDataEntryBase, mainly for when there\n// is no registered entry class found\n+ (Class)defaultClassForEntries;\n\n- (BOOL)canPost;\n\n// getters and setters\n- (GDataGenerator *)generator;\n- (void)setGenerator:(GDataGenerator *)gen;\n\n- (NSString *)identifier;\n- (void)setIdentifier:(NSString *)theString;\n\n- (GDataTextConstruct *)title;\n- (void)setTitle:(GDataTextConstruct *)theTitle;\n- (void)setTitleWithString:(NSString *)str;\n\n- (GDataTextConstruct *)subtitle;\n- (void)setSubtitle:(GDataTextConstruct *)theSubtitle;\n- (void)setSubtitleWithString:(NSString *)str;\n\n- (GDataTextConstruct *)rights;\n- (void)setRights:(GDataTextConstruct *)theRights;\n- (void)setRightsWithString:(NSString *)str;\n\n- (NSString *)icon;\n- (void)setIcon:(NSString *)theString;\n\n- (NSString *)logo;\n- (void)setLogo:(NSString *)theString;\n\n- (NSArray *)links;\n- (void)setLinks:(NSArray *)links;\n- (void)addLink:(GDataLink *)obj;\n- (void)removeLink:(GDataLink *)obj;\n\n- (NSArray *)authors;\n- (void)setAuthors:(NSArray *)authors;\n- (void)addAuthor:(GDataPerson *)obj;\n\n- (NSArray *)contributors;\n- (void)setContributors:(NSArray *)array;\n- (void)addContributor:(GDataPerson *)obj;\n\n- (NSArray *)categories;\n- (void)setCategories:(NSArray *)categories;\n- (void)addCategory:(GDataCategory *)category;\n- (void)removeCategory:(GDataCategory *)category;\n\n- (GDataDateTime *)updatedDate;\n- (void)setUpdatedDate:(GDataDateTime *)theDate;\n\n- (NSString *)ETag;\n- (void)setETag:(NSString *)str;\n\n- (NSString *)fieldSelection;\n- (void)setFieldSelection:(NSString *)str;\n\n- (NSString *)kind;\n- (void)setKind:(NSString *)str;\n\n- (NSString *)resourceID;\n- (void)setResourceID:(NSString *)str;\n\n- (NSArray *)entries;\n\n// setEntries: and addEntry: assert if the entries have other parents\n// already set; use setEntriesWithEntries: and addEntryWithEntry: to copy\n// entries that have other parents\n- (void)setEntries:(NSArray *)entries;\n- (void)addEntry:(GDataEntryBase *)obj;\n\n- (void)setEntriesWithEntries:(NSArray *)entries;\n- (void)addEntryWithEntry:(GDataEntryBase *)obj;\n\n- (NSNumber *)totalResults;\n- (void)setTotalResults:(NSNumber *)theString;\n\n- (NSNumber *)startIndex;\n- (void)setStartIndex:(NSNumber *)theString;\n\n- (NSNumber *)itemsPerPage;\n- (void)setItemsPerPage:(NSNumber *)theString;\n\n// Atom publishing control\n- (GDataAtomPubControl *)atomPubControl;\n- (void)setAtomPubControl:(GDataAtomPubControl *)obj;\n\n// Batch support\n- (GDataBatchOperation *)batchOperation;\n- (void)setBatchOperation:(GDataBatchOperation *)obj;\n\n// convenience routines\n\n- (GDataLink *)linkWithRelAttributeValue:(NSString *)rel;\n\n- (GDataLink *)feedLink;\n- (GDataLink *)alternateLink;\n- (GDataLink *)relatedLink;\n- (GDataLink *)postLink;\n- (GDataLink *)uploadLink; // \"resumable-create\" link\n- (GDataLink *)batchLink;\n- (GDataLink *)selfLink;\n- (GDataLink *)nextLink;\n- (GDataLink *)previousLink;\n\n// return the first entry, or nil if none\n- (id)firstEntry;\n\n// return the specified entry, or nil if index is out of bounds\n// (does not throw an exception if index exceeds the size of the entry array)\n- (id)entryAtIndex:(NSUInteger)index;\n\n// find the entry with the given identifier, or nil if none found\n- (id)entryForIdentifier:(NSString *)str;\n\n// find all entries with a kind category for the specified term\n//\n// this is useful for feeds which contain various kinds of entries with\n// distinct entry kind categories\n- (NSArray *)entriesWithCategoryKind:(NSString *)term;\n\n///////////////////////////////////////////////////////////////////////////////\n//\n//  Protected methods\n//\n//  All remaining methods are intended for use only by subclasses\n//  of GDataFeedBase.\n//\n\n// subclasses call registerEntryClass to register their standardFeedKind\n+ (void)registerFeedClass;\n\n+ (Class)feedClassForCategoryWithScheme:(NSString *)scheme\n                                   term:(NSString *)term;\n+ (Class)feedClassForKindAttributeValue:(NSString *)kind;\n\n// temporary bridge method\n+ (void)registerFeedClass:(Class)theClass\n    forCategoryWithScheme:(NSString *)scheme\n                     term:(NSString *)term;\n\n// subclasses override standardFeedKind to provide the term string for the\n// term attribute of their \"kind\" category element, if any\n+ (NSString *)standardFeedKind;\n\n// subclasses override standardKindAttributeValue to provide the string for the\n// kind attribute identifying their class (for core protocol v2.1 and later)\n+ (NSString *)standardKindAttributeValue;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataFeedLink.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataFeedLink.h\n//\n\n#import \"GDataObject.h\"\n\n@class GDataFeedBase;\n\n// a link to a feed, like\n// <gd:feedLink href=\"http://example.com/Jo/posts/MyFirstPost/comments\" countHint=\"10\">\n\n@interface GDataFeedLink : GDataObject <NSCopying, GDataExtension> {\n  GDataFeedBase *feed_;\n}\n\n+ (id)feedLinkWithHref:(NSString *)href\n            isReadOnly:(BOOL)isReadOnly;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent;\n\n- (NSXMLElement *)XMLElement;\n\n- (NSString *)href;\n- (void)setHref:(NSString *)str;\n\n- (BOOL)isReadOnly;\n- (void)setIsReadOnly:(BOOL)isReadOnly;\n\n- (NSNumber *)countHint;\n- (void)setCountHint:(NSNumber *)val;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (GDataFeedBase *)feed;\n- (void)setFeed:(GDataFeedBase *)feed;\n\n// convert the href string into an URL\n- (NSURL *)URL;\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataGenerator.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataGenerator.h\n//\n\n#import \"GDataObject.h\"\n\n// Feed generator element, as in\n//   <generator version='1.0' uri='http://www.google.com/calendar/'>CL2</generator>\n@interface GDataGenerator : GDataObject <GDataExtension> {\n}\n+ (GDataGenerator *)generatorWithName:(NSString *)name\n                              version:(NSString *)version\n                                  URI:(NSString *)uri;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)version;\n- (void)setVersion:(NSString *)str;\n\n- (NSString *)URI;\n- (void)setURI:(NSString *)str;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataGeoPt.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataGeoPt.h\n//\n//  NOTE: As of July 2007, GDataGeoPt is deprecated.  Use GDataGeo instead.\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n\n#import \"GDataObject.h\"\n\n@class GDataDateTime;\n\n// geoPt element, as in\n//   <gd:geoPt lat=\"27.98778\" lon=\"86.94444\" elev=\"8850.0\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdGeoPt\n\n\n@interface GDataGeoPt : GDataObject <NSCopying, GDataExtension> {\n  NSString *label_;\n  NSNumber *lat_;\n  NSNumber *lon_;\n  NSNumber *elev_;\n  GDataDateTime* time_;\n}\n+ (GDataGeoPt *)geoPtWithLabel:(NSString *)label\n                           lat:(NSNumber *)lat\n                           lon:(NSNumber *)lon\n                          elev:(NSNumber *)elev\n                          time:(GDataDateTime *)aTime;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent;\n- (NSXMLElement *)XMLElement;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n- (NSNumber *)lat;\n- (void)setLat:(NSNumber *)val;\n- (NSNumber *)lon;\n- (void)setLon:(NSNumber *)val;\n- (NSNumber *)elev;\n- (void)setElev:(NSNumber *)val;\n- (GDataDateTime *)time;\n- (void)setTime:(GDataDateTime *)cdate;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataIM.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataIM.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAIM_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataIMProtocolAIM        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#AIM\");\n_EXTERN NSString* const kGDataIMProtocolGoogleTalk _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#GOOGLE_TALK\");\n_EXTERN NSString* const kGDataIMProtocolICQ        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#ICQ\");\n_EXTERN NSString* const kGDataIMProtocolJabber     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#JABBER\");\n_EXTERN NSString* const kGDataIMProtocolMSN        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#MSN\");\n_EXTERN NSString* const kGDataIMProtocolNetMeeting _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#NETMEETING\");\n_EXTERN NSString* const kGDataIMProtocolQQ         _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#QQ\");\n_EXTERN NSString* const kGDataIMProtocolSkype      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#SKYPE\");\n_EXTERN NSString* const kGDataIMProtocolYahoo      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#YAHOO\");\n\n// IM element, as in\n//   <gd:im protocol=\"http://schemas.google.com/g/2005#MSN\"\n//      address=\"foo@bar.example.com\" label=\"Alternate\"\n//      rel=\"http://schemas.google.com/g/2005#other\" >\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdIm\n\n@interface GDataIM : GDataObject <GDataExtension> {\n}\n\n+ (GDataIM *)IMWithProtocol:(NSString *)protocol\n                        rel:(NSString *)rel\n                      label:(NSString *)label\n                    address:(NSString *)address;\n\n- (NSString *)address;\n- (void)setAddress:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)protocol;\n- (void)setProtocol:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataLink.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataLink.h\n//\n\n#import \"GDataObject.h\"\n\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATALINK_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataLinkRelFeed            _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#feed\");\n_EXTERN NSString* const kGDataLinkRelPost            _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#post\");\n_EXTERN NSString* const kGDataLinkRelBatch           _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#batch\");\n_EXTERN NSString* const kGDataLinkRelResumableCreate _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#resumable-create-media\");\n_EXTERN NSString* const kGDataLinkRelResumableEdit   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#resumable-edit-media\");\n\n_EXTERN NSString* const kGDataLinkTypeAtom _INITIALIZE_AS(@\"application/atom+xml\");\n_EXTERN NSString* const kGDataLinkTypeHTML _INITIALIZE_AS(@\"text/html\");\n\n// for links, like\n//\n//  <link rel=\"alternate\" type=\"text/html\"\n//        href=\"http://www.google.com/calendar/event?eid=b...\" title=\"alternate\">\n//     <content type=\"application/atom+xml;feed\"> <feed>...</feed> </content>\n//  </link>\n//\n\n@class GDataAtomContent;\n\n@interface GDataLink : GDataObject <GDataExtension>\n\n+ (GDataLink *)linkWithRel:(NSString *)rel\n                      type:(NSString *)type\n                      href:(NSString *)href;  // parameters may be nil\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n- (NSString *)href;\n- (void)setHref:(NSString *)str;\n\n- (NSString *)hrefLang;\n- (void)setHrefLang:(NSString *)str;\n\n- (NSString *)title;\n- (void)setTitle:(NSString *)str;\n\n- (NSString *)titleLang;\n- (void)setTitleLang:(NSString *)str;\n\n- (NSNumber *)resourceLength;\n- (void)setResourceLength:(NSNumber *)length;\n\n- (NSString *)ETag;\n- (void)setETag:(NSString *)str;\n\n- (GDataAtomContent *)content;\n- (void)setContent:(GDataAtomContent *)obj;\n\n// convenience method\n\n// convert the href string into an URL\n- (NSURL *)URL;\n\n// utility methods\n\n// get a list of short names for links in the array\n+ (NSArray *)linkNamesFromLinks:(NSArray *)links;\n\n// utilities for extracting a GDataLink from an array of links\n\n// to search by rel only, use nil type to match any type\n+ (GDataLink *)linkWithRel:(NSString *)relValue type:(NSString *)typeValue fromLinks:(NSArray *)array;\n\n+ (GDataLink *)linkWithRelAttributeSuffix:(NSString *)relSuffix fromLinks:(NSArray *)array;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataMoney.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataMoney.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_FINANCE_SERVICE || GDATA_INCLUDE_BOOKS_SERVICE\n\n#import \"GDataObject.h\"\n\n// money element, as in\n//  <gd:money amount=\"10\" currencycode=\"USD\"/>\n\n@interface GDataMoney : GDataObject <GDataExtension>\n\n+ (GDataMoney *)moneyWithAmount:(NSNumber *)amount\n                   currencyCode:(NSString *)currencyCode;\n\n- (NSDecimalNumber *)amount;\n- (void)setAmount:(NSNumber *)num;\n\n- (NSString *)currencyCode;\n- (void)setCurrencyCode:(NSString *)str;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_FINANCE_SERVICE || GDATA_INCLUDE_BOOKS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataName.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataName.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n@interface GDataNameElement : GDataObject\n\n+ (id)nameElementWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n// an optional yomi attribute for pronunciation\n- (void)setYomi:(NSString *)str;\n- (NSString *)yomi;\n@end\n\n@interface GDataName : GDataObject <GDataExtension>\n\n+ (GDataName *)name;\n+ (GDataName *)nameWithFullNameString:(NSString *)str;\n+ (GDataName *)nameWithPrefix:(NSString *)prefix\n                  givenString:(NSString *)first\n             additionalString:(NSString *)middle\n                 familyString:(NSString *)last\n                       suffix:(NSString *)suffix;\n\n- (GDataNameElement *)additionalName;\n- (void)setAdditionalName:(GDataNameElement *)obj;\n- (void)setAdditionalNameWithString:(NSString *)str;\n\n- (GDataNameElement *)familyName;\n- (void)setFamilyName:(GDataNameElement *)obj;\n- (void)setFamilyNameWithString:(NSString *)str;\n\n- (GDataNameElement *)fullName;\n- (void)setFullName:(GDataNameElement *)obj;\n- (void)setFullNameWithString:(NSString *)str;\n\n- (GDataNameElement *)givenName;\n- (void)setGivenName:(GDataNameElement *)obj;\n- (void)setGivenNameWithString:(NSString *)str;\n\n- (NSString *)namePrefix;\n- (void)setNamePrefix:(NSString *)str;\n\n- (NSString *)nameSuffix;\n- (void)setNameSuffix:(NSString *)str;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataObject.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataObject.h\n//\n\n// This is the base class for most objects in the Objective-C GData implementation.\n// Objects should derive from GDataObject in order to support XML parsing and\n// generation, and to support the extension model.\n\n// Subclasses will typically implement:\n//\n// - (void)addExtensionDeclarations;  -- declaring extensions\n// - (id)initWithXMLElement:(NSXMLElement *)element\n//                   parent:(GDataObject *)parent;  -- parsing\n// - (NSXMLElement *)XMLElement;  -- XML generation\n//\n// Subclasses should implement other typical NSObject methods, too:\n//\n// - (NSString *)description;\n// - (id)copyWithZone:(NSZone *)zone; (be sure to call superclass)\n// - (BOOL)isEqual:(GDataObject *)other; (be sure to call superclass)\n// - (void)dealloc;\n//\n// Subclasses which may be used as extensions should implement the\n// simple GDataExtension protocol.\n//\n\n//\n// Parsing and XML generation\n//\n// Parsing is done in the subclass's -initWithXMLElement:parent: method.\n//\n// For each parsed GData XML element, GDataObject maintains lists of\n// un-parsed attributes and children (unknownChildren_ and unknownAttributes_)\n// as raw NSXMLNodes.  Subclasses MUST use the methods in this class's\n// \"parsing helpers\" (below) to extract properties and elements during parsing;\n// this ensures that the lists of unknown properties and children are\n// accurate.  DO NOT parse using NSXMLElement methods.\n//\n// XML generation is done in the subclass's -XMLElement method.\n// That method will call XMLElementWithExtensionsAndDefaultName to get\n// a \"starter\" NSXMLElement, already decorated with extensions, to which\n// the subclass can add its unique children and attributes, if any.\n//\n//\n//\n// The extension model\n//\n// Extensions enable elements to contain children about which the element\n// may know no details.\n//\n// Typically, entries add extensions to themselves. For example, a Calendar\n// entry declares it may contain a color:\n//\n//  [self addExtensionDeclarationForParentClass:[GDataEntryCalendar class]\n//                                   childClass:[GDataColorProperty class]];\n//\n// This lets the base class handle much of the work of managing the child\n// element.  The Calendar entry can still provide accessor methods to get\n// to the extension by calling into the base class, as in\n//\n//  - (GDataColorProperty *)color {\n//    return (GDataColorProperty *)\n//               [self objectForExtensionClass:[GDataColorProperty class]];\n//  }\n//\n//  - (void)setColor:(GDataColorProperty *)val {\n//    [self setObject:val forExtensionClass:[GDataColorProperty class]];\n//  }\n//\n// The real purpose of extensions is to allow elements to contain children\n// they may not know about.  For example, a CalendarEventEntry declares\n// that GDataLinks contained within the calendar event entry may contain\n// GDataWebContent elements:\n//\n//  [self addExtensionDeclarationForParentClass:[GDataLink class]\n//                                   childClass:[GDataWebContent class]];\n//\n// The CalendarEvent has extended GDataLinks without GDataLinks knowing or\n// caring.  Because GDataLink derives from GDataObject, the GDataLink\n// object will automatically parse and maintain and copy and compare\n// the GDataWebContents contained within.\n//\n\n\n#import <Foundation/Foundation.h>\n\n#import \"GDataDefines.h\"\n#import \"GDataUtilities.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAOBJECT_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataNamespaceAtom          _INITIALIZE_AS(@\"http://www.w3.org/2005/Atom\");\n_EXTERN NSString* const kGDataNamespaceAtomPrefix    _INITIALIZE_AS(@\"atom\");\n\n_EXTERN NSString* const kGDataNamespaceAtomPub       _INITIALIZE_AS(@\"http://www.w3.org/2007/app\");\n_EXTERN NSString* const kGDataNamespaceAtomPubPrefix _INITIALIZE_AS(@\"app\");\n\n_EXTERN NSString* const kGDataNamespaceOpenSearch       _INITIALIZE_AS(@\"http://a9.com/-/spec/opensearch/1.1/\");\n_EXTERN NSString* const kGDataNamespaceOpenSearchPrefix _INITIALIZE_AS(@\"openSearch\");\n\n_EXTERN NSString* const kGDataNamespaceXHTML       _INITIALIZE_AS(@\"http://www.w3.org/1999/xhtml\");\n_EXTERN NSString* const kGDataNamespaceXHTMLPrefix _INITIALIZE_AS(@\"xh\");\n\n_EXTERN NSString* const kGDataNamespaceGData       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005\");\n_EXTERN NSString* const kGDataNamespaceGDataPrefix _INITIALIZE_AS(@\"gd\");\n\n_EXTERN NSString* const kGDataNamespaceBatch       _INITIALIZE_AS(@\"http://schemas.google.com/gdata/batch\");\n_EXTERN NSString* const kGDataNamespaceBatchPrefix _INITIALIZE_AS(@\"batch\");\n\n#define GDATA_DEBUG_ASSERT_MIN_SERVICE_VERSION(versionString) \\\n  GDATA_DEBUG_ASSERT([self isServiceVersionAtLeast:versionString], \\\n    @\"%@ requires newer version\", NSStringFromSelector(_cmd))\n\n#define GDATA_DEBUG_ASSERT_MAX_SERVICE_VERSION(versionString) \\\n  GDATA_DEBUG_ASSERT([self isServiceVersionAtMost:versionString], \\\n    @\"%@ deprecated under v%@\", NSStringFromSelector(_cmd), [self serviceVersion])\n\n#define GDATA_DEBUG_ASSERT_MIN_SERVICE_V2() \\\n  GDATA_DEBUG_ASSERT_MIN_SERVICE_VERSION(@\"2.0\")\n\n@class GDataDateTime;\n@class GDataCategory;\n\n@protocol GDataExtension\n+ (NSString *)extensionElementURI;\n+ (NSString *)extensionElementPrefix;\n+ (NSString *)extensionElementLocalName;\n@end\n\n// GDataAttribute is the base class for attribute extensions.\n// It is *not* used for local attributes, which are simply stored in\n// GDataObject' attributes_ dictionary.\n//\n// This returns nil for the attribute's URI and prefix qualifier;\n// subclasses must declare at least a local name.\n//\n// Functionally, this just stores a string value for the attribute.\n\n@interface GDataAttribute : NSObject {\n @private\n    NSString *value_;\n}\n+ (GDataAttribute *)attributeWithValue:(NSString *)str;\n- (id)initWithValue:(NSString *)value;\n\n- (void)setStringValue:(NSString *)str;\n- (NSString *)stringValue;\n@end\n\n// GDataDescriptionRecords are used for describing how the elements\n// and attributes of a GDataObject should be reported when -description\n// is called.\n\ntypedef enum GDataDescRecTypes {\n  kGDataDescValueLabeled = 1,\n  kGDataDescLabelIfNonNil,\n  kGDataDescArrayCount,\n  kGDataDescArrayDescs,\n  kGDataDescBooleanLabeled,\n  kGDataDescBooleanPresent,\n  kGDataDescNonZeroLength,\n  kGDataDescValueIsKeyPath\n} GDataDescRecTypes;\n\ntypedef struct GDataDescriptionRecord {\n  NSString *label;\n  NSString *keyPath;\n  GDataDescRecTypes reportType;\n} GDataDescriptionRecord;\n\n\n@interface GDataObject : NSObject <NSCopying> {\n\n  @private\n\n  // element name from original XML, used for later XML generation\n  NSString *elementName_;\n\n  __weak GDataObject *parent_;  // parent in tree of GData objects\n\n  // GDataObjects keep namespaces as {key:prefix value:URI} dictionary entries\n  NSMutableDictionary *namespaces_;\n\n  // extension declaration cache, retained by the topmost parent\n  //\n  // keys are classes that have declared their extensions\n  //\n  // the values are dictionaries mapping declared parent classes to\n  // GDataExtensionDeclarations objects\n  NSMutableDictionary *extensionDeclarationsCache_;\n\n  // list of attributes to be parsed for each class\n  NSMutableDictionary *attributeDeclarationsCache_;\n\n  // list of attributes to be parsed for this class (points strongly into the\n  // attribute declarations cache)\n  NSMutableArray *attributeDeclarations_;\n\n  // arrays of actual extension elements found for this element, keyed by extension class\n  NSMutableDictionary *extensions_;\n\n  // dictionary of attributes set for this element, keyed by attribute name\n  NSMutableDictionary *attributes_;\n\n  // string for element body, if declared as parseable\n  NSString *contentValue_;\n\n  // XMLElements saved from element body but not parsed, if declared by the subclass\n  NSMutableArray *childXMLElements_;\n\n  // arrays of XMLNodes of attributes and child elements not yet parsed\n  NSMutableArray *unknownChildren_;\n  NSMutableArray *unknownAttributes_;\n  BOOL shouldIgnoreUnknowns_;\n\n  // mapping of standard classes to user's surrogate subclasses, used when\n  // creating objects from XML\n  NSDictionary *surrogates_;\n\n  // service version, set for feeds and entries\n  NSString *serviceVersion_;\n\n  // core protocol version, set from the service version when\n  // -coreProtocolVersion is invoked\n  NSString *coreProtocolVersion_;\n\n  // anything defined by the client; retained but not used internally; not\n  // copied by copyWithZone:\n  id userData_;\n  NSMutableDictionary *userProperties_;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n//\n// Public methods\n//\n// These methods are intended for users of the library\n//\n\n+ (id)object;\n\n- (id)copyWithZone:(NSZone *)zone;\n\n- (id)initWithServiceVersion:(NSString *)serviceVersion;\n\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent; // subclasses must override\n- (NSXMLElement *)XMLElement; // subclasses must override\n\n- (NSXMLDocument *)XMLDocument; // returns this XMLElement wrapped in an NSXMLDocument\n\n// setters/getters\n\n// namespaces here are a dictionary mapping prefix to URI; they are not\n// NSXML namespace objects\n- (void)setNamespaces:(NSDictionary *)namespaces;\n- (void)addNamespaces:(NSDictionary *)namespaces;\n- (NSDictionary *)namespaces;\n\n// return a dictionary containing all namespaces\n// in this object and its parent objects\n- (NSDictionary *)completeNamespaces;\n\n// if a prefix is explicitly defined the same for a parent as it is locally,\n// remove it, since we can rely on the parent's definition\n- (void)pruneInheritedNamespaces;\n\n// name from original XML; this will be used during XML generation\n- (void)setElementName:(NSString *)elementName;\n- (NSString *)elementName;\n\n// parent in object tree (weak reference)\n- (void)setParent:(GDataObject *)obj;\n- (GDataObject *)parent;\n\n// surrogate lists for when alloc'ing classes from XML\n- (void)setSurrogates:(NSDictionary *)surrogates;\n- (NSDictionary *)surrogates;\n\n// service API version\n+ (NSString *)defaultServiceVersion;\n\n// a side-effect of setServiceVersion: is that the coreProtocolVersion is\n// reset\n- (void)setServiceVersion:(NSString *)str;\n- (NSString *)serviceVersion;\n\n- (BOOL)isServiceVersionAtLeast:(NSString *)otherVersion;\n- (BOOL)isServiceVersionAtMost:(NSString *)otherVersion;\n\n// calling -coreProtocolVersion sets the initial core protocol version based\n// on the service version\n- (NSString *)coreProtocolVersion;\n- (void)setCoreProtocolVersion:(NSString *)str;\n- (BOOL)isCoreProtocolVersion1;\n\n// userData is available for client use; retained by GDataObject, but not\n// copied by the copyWithZone\n- (void)setUserData:(id)obj;\n- (id)userData;\n\n// properties are supported for client convenience, but are not copied by\n// copyWithZone.  Properties keys beginning with _ are reserved by the library.\n- (void)setProperties:(NSDictionary *)dict;\n- (NSDictionary *)properties;\n\n- (void)setProperty:(id)obj forKey:(NSString *)key; // pass nil obj to remove property\n- (id)propertyForKey:(NSString *)key;\n\n// XMLNode children not parsed; primarily for internal use by the framework\n- (void)setUnknownChildren:(NSArray *)arr;\n- (NSArray *)unknownChildren;\n\n// XMLNode attributes not parsed; primarily for internal use by the framework\n- (void)setUnknownAttributes:(NSArray *)arr;\n- (NSArray *)unknownAttributes;\n\n// feeds and their elements may exclude tracking of unknown child elements\n// and unknown attributes; see GDataServiceBase for more information\n- (void)setShouldIgnoreUnknowns:(BOOL)flag;\n- (BOOL)shouldIgnoreUnknowns;\n\n///////////////////////////////////////////////////////////////////////////////\n//\n//  Protected methods\n//\n//  All remaining methods are intended for use only by subclasses\n//  of GDataObject.\n//\n\n// this init method should  be used only when creating the base of a tree\n// containing surrogates (the surrogate map is a dictionary of\n// standard GDataObject classes to replacement subclasses); this method\n// calls through to [self initWithXMLElement:parent:]\n- (id)initWithXMLElement:(NSXMLElement *)element\n                  parent:(GDataObject *)parent\n          serviceVersion:(NSString *)serviceVersion\n              surrogates:(NSDictionary *)surrogates\n    shouldIgnoreUnknowns:(BOOL)shouldIgnoreUnknowns;\n\n- (void)addExtensionDeclarations; // subclasses may override this to declare extensions\n\n- (void)addParseDeclarations; // subclasses may override this to declare local attributes and content value\n\n- (void)clearExtensionDeclarationsCache; // used by GDataServiceBase and by subclasses\n\n// content stream and upload data: these always return NO/nil for objects\n// other than entries\n\n- (BOOL)generateContentInputStream:(NSInputStream **)outInputStream\n                            length:(unsigned long long *)outLength\n                           headers:(NSDictionary **)outHeaders;\n\n- (NSString *)uploadMIMEType;\n- (NSData *)uploadData;\n- (NSFileHandle *)uploadFileHandle;\n- (NSURL *)uploadLocationURL;\n- (BOOL)shouldUploadDataOnly;\n\n//\n// Extensions\n//\n\n// declaring a potential extension; applies to this object and its children\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                   childClass:(Class)childClass;\n- (void)addExtensionDeclarationForParentClass:(Class)parentClass\n                                 childClasses:(Class)firstChildClass, ...;\n\n- (void)removeExtensionDeclarationForParentClass:(Class)parentClass\n                                      childClass:(Class)childClass;\n\n- (void)addAttributeExtensionDeclarationForParentClass:(Class)parentClass\n                                            childClass:(Class)childClass;\n- (void)removeAttributeExtensionDeclarationForParentClass:(Class)parentClass\n                                               childClass:(Class)childClass;\n\n// accessing actual extensions in this object\n- (NSArray *)objectsForExtensionClass:(Class)theClass;\n- (id)objectForExtensionClass:(Class)theClass;\n\n- (NSString *)attributeValueForExtensionClass:(Class)theClass;\n\n// replacing or adding actual extensions in this object\n- (void)setObjects:(NSArray *)objects forExtensionClass:(Class)theClass;\n- (void)setObject:(id)object forExtensionClass:(Class)theClass; // removes all previous objects for this class\n- (void)addObject:(id)object forExtensionClass:(Class)theClass;\n- (void)removeObject:(id)object forExtensionClass:(Class)theClass;\n\n- (void)setAttributeValue:(NSString *)str forExtensionClass:(Class)theClass;\n\n//\n// Local attributes\n//\n\n// derived classes may override parseAttributesForElement if they need to\n// inspect attributes prior to parsing of element content\n- (void)parseAttributesForElement:(NSXMLElement *)element;\n\n// derived classes should call -addLocalAttributeDeclarations in their\n// -addParseDeclarations method if they want element attributes to\n// automatically be parsed\n- (void)addLocalAttributeDeclarations:(NSArray *)attributeLocalNames;\n\n- (NSString *)stringValueForAttribute:(NSString *)name;\n- (NSNumber *)intNumberForAttribute:(NSString *)name;\n- (NSNumber *)doubleNumberForAttribute:(NSString *)name;\n- (NSNumber *)longLongNumberForAttribute:(NSString *)name;\n- (NSDecimalNumber *)decimalNumberForAttribute:(NSString *)name;\n- (GDataDateTime *)dateTimeForAttribute:(NSString *)name;\n- (BOOL)boolValueForAttribute:(NSString *)name defaultValue:(BOOL)defaultVal;\n\n// setting nil value for attribute removes it\n- (void)setStringValue:(NSString *)str forAttribute:(NSString *)name;\n- (void)setBoolValue:(BOOL)flag defaultValue:(BOOL)defaultVal forAttribute:(NSString *)name;\n- (void)setExplicitBoolValue:(BOOL)flag forAttribute:(NSString *)name;\n- (void)setDecimalNumberValue:(NSDecimalNumber *)num forAttribute:(NSString *)name;\n- (void)setDateTimeValue:(GDataDateTime *)cdate forAttribute:(NSString *)name;\n\n// dictionary of all local attributes actually found in the XML element\n- (void)setAttributes:(NSDictionary *)dict;\n- (NSDictionary *)attributes;\n\n\n//\n// Element Content Value\n//\n\n// derived classes should call -addContentValueDeclaration in their\n// -addParseDeclarations method if they want element content to\n// automatically be parsed as a string\n- (void)addContentValueDeclaration;\n- (BOOL)hasDeclaredContentValue;\n- (void)setContentStringValue:(NSString *)str;\n- (NSString *)contentStringValue;\n\n//\n// Unparsed XML child elements\n//\n\n// derived classes should call -addXMLValuesDeclaration in their\n// -addParseDeclarations method if they want all child elements to\n// be held as an array of NSXMLElements\n- (void)addChildXMLElementsDeclaration;\n- (BOOL)hasDeclaredChildXMLElements;\n- (NSArray *)childXMLElements;\n- (void)setChildXMLElements:(NSArray *)array;\n- (void)addChildXMLElement:(NSXMLNode *)node;\n\n\n//\n// Dynamic GDataObject generation\n//\n// Feeds and entries can register themselves in their + (void)load\n// methods.  When XML is being parsed, if a matching category\n// is found, the proper class is instantiated.\n//\n// The scheme or term in a category may be nil (during\n// registration and lookup) to match any values.\n\n// class registration method\n+ (void)registerClass:(Class)theClass\n                inMap:(NSMutableDictionary **)map\nforCategoryWithScheme:(NSString *)scheme\n                 term:(NSString *)term;\n\n+ (Class)classForCategoryWithScheme:(NSString *)scheme\n                               term:(NSString *)term\n                            fromMap:(NSDictionary *)map;\n\n// objectClassForXMLElement: returns a found registered feed\n// or entry class for the XML according to its contained category\n//\n// If no registered class is found with a matching category,\n// this returns GDataFeedBase for feed elements, GDataEntryBase\n// for entry elements.\n//\n// If the element is not a <feed> or <entry> then nil is returned\n+ (Class)objectClassForXMLElement:(NSXMLElement *)element;\n\n//\n// XML parsing helpers (used in initWithXMLElement:parent:)\n//\n// Use these parsing helpers, since they remove the parsed items from the\n// \"unknown children\" list for this object.\n//\n\n// this creates a single object of the specified class for the first XML child\n// element with the specified name. Returns nil if no child element is present.\n- (id)objectForChildOfElement:(NSXMLElement *)parentElement\n                qualifiedName:(NSString *)qualifiedName\n                 namespaceURI:(NSString *)namespaceURI\n                  objectClass:(Class)objectClass;\n\n// this creates an array of objects of the specified class for each XML child\n// element with the specified name\n- (id)objectOrArrayForChildrenOfElement:(NSXMLElement *)parentElement\n                          qualifiedName:(NSString *)qualifiedName\n                           namespaceURI:(NSString *)namespaceURI\n                            objectClass:(Class)objectClass;\n\n// childOfElement:withName returns the element with the name, or nil of there\n// are not exactly one of the element\n- (NSXMLElement *)childWithQualifiedName:(NSString *)localName\n                            namespaceURI:(NSString *)namespaceURI\n                             fromElement:(NSXMLElement *)parentElement;\n\n// searches up the parent tree to find a surrogate for the standard class;\n// if there is  no surrogate, returns the standard class itself\n- (Class)classOrSurrogateForClass:(Class)standardClass;\n\n// element parsing\n\n+ (NSDictionary *)dictionaryForElementNamespaces:(NSXMLElement *)element;\n\n// this method avoids the \"recursive descent\" behavior of NSXMLElement's\n// stringValue; the element parameter may be nil\n- (NSString *)stringValueFromElement:(NSXMLElement *)element;\n\n- (GDataDateTime *)dateTimeFromElement:(NSXMLElement *)element;\n\n- (NSNumber *)intNumberValueFromElement:(NSXMLElement *)element;\n\n- (NSNumber *)doubleNumberValueFromElement:(NSXMLElement *)element;\n\n// attribute parsing\n- (NSString *)stringForAttributeName:(NSString *)attributeName\n                         fromElement:(NSXMLElement *)element;\n\n- (NSString *)stringForAttributeLocalName:(NSString *)localName\n                                      URI:(NSString *)attributeURI\n                              fromElement:(NSXMLElement *)element;\n\n- (GDataDateTime *)dateTimeForAttributeName:(NSString *)attributeName\n                                fromElement:(NSXMLElement *)element;\n\n- (NSXMLNode *)attributeForName:(NSString *)attributeName\n                    fromElement:(NSXMLElement *)element;\n\n- (BOOL)boolForAttributeName:(NSString *)attributeName\n                 fromElement:(NSXMLElement *)element;\n\n- (NSNumber *)doubleNumberForAttributeName:(NSString *)attributeName\n                               fromElement:(NSXMLElement *)element;\n\n- (NSNumber *)intNumberForAttributeName:(NSString *)attributeName\n                            fromElement:(NSXMLElement *)element;\n\n\n//\n// XML generation helpers\n//\n\n// subclasses start their -XMLElement method by calling this\n- (NSXMLElement *)XMLElementWithExtensionsAndDefaultName:(NSString *)defaultName;\n\n// adding attributes\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n     attributeValueIfNonNil:(NSString *)val\n                   withName:(NSString *)name;\n\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n     attributeValueIfNonNil:(NSString *)val\n          withQualifiedName:(NSString *)qName\n                        URI:(NSString *)attributeURI;\n\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\n  attributeValueWithInteger:(NSInteger)val\n                   withName:(NSString *)name;\n\n// adding child elements\n- (NSXMLNode *)addToElement:(NSXMLElement *)element\nchildWithStringValueIfNonEmpty:(NSString *)str\n                   withName:(NSString *)name;\n\n- (void)addToElement:(NSXMLElement *)element\n XMLElementForObject:(id)object;\n\n- (void)addToElement:(NSXMLElement *)element\n XMLElementsForArray:(NSArray *)arrayOfGDataObjects;\n\n//\n// decription method helpers\n//\n\n// the final descRecord in the list should be { nil, nil, 0 }\n- (void)addDescriptionRecords:(GDataDescriptionRecord *)descRecordList\n                      toItems:(NSMutableArray *)items;\n\n- (void)addToArray:(NSMutableArray *)stringItems\nobjectDescriptionIfNonNil:(id)obj\n          withName:(NSString *)name;\n\n- (void)addAttributeDescriptionsToArray:(NSMutableArray *)stringItems;\n\n- (void)addContentDescriptionToArray:(NSMutableArray *)stringItems\n                            withName:(NSString *)name;\n\n// optional methods for overriding\n//\n// subclasses may implement -itemsForDescription and add to or\n// replace the superclass's array of items\n//\n// The base class itemsForDescription provides items for local attributes and\n// content, but not for any element extensions or attribute extensions\n- (NSMutableArray *)itemsForDescription;\n- (NSString *)descriptionWithItems:(NSArray *)items;\n- (NSString *)description;\n\n// coreProtocolVersionForServiceVersion maps the service version to the\n// underlying core protocol version.  The default implementation returns\n// the service version as the core protocol version.\n//\n// Entry and feed subclasses will need to implement this if their service\n// version numbers deviate from the core protocol version numbers.\n+ (NSString *)coreProtocolVersionForServiceVersion:(NSString *)str;\n\n@end\n\n@interface NSXMLElement (GDataObjectExtensions)\n\n// XML generation helpers\n\n// NSXMLNode's setStringValue: wipes out other children, so we'll use this\n// instead\n- (void)addStringValue:(NSString *)str;\n\n// creating objects from child elements\n+ (id)elementWithName:(NSString *)name attributeName:(NSString *)attrName attributeValue:(NSString *)attrValue;\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataOrganization.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataOrganization.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n@class GDataWhere;\n\n// organization, as in\n//\n// <gd:organization rel=\"http://schemas.google.com/g/2005#work\" label=\"Work\" primary=\"true\"/>\n//   <gd:orgName>Google</gd:orgName>\n//   <gd:orgTitle>Tech Writer</gd:orgTitle>\n//   <gd:orgJobDescription>Writes documentation</gd:orgJobDescription>\n//   <gd:orgDepartment>Software Development</gd:orgDepartment>\n//   <gd:orgSymbol>GOOG</gd:orgSymbol>\n// </gd:organization>\n\n@interface GDataOrganization : GDataObject <GDataExtension>\n\n+ (GDataOrganization *)organizationWithName:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n\n- (NSString *)orgName;\n- (void)setOrgName:(NSString *)str;\n\n- (NSString *)orgNameYomi;\n- (void)setOrgNameYomi:(NSString *)str;\n\n- (NSString *)orgTitle;\n- (void)setOrgTitle:(NSString *)str;\n\n- (NSString *)orgDepartment;\n- (void)setOrgDepartment:(NSString *)str;\n\n- (NSString *)orgJobDescription;\n- (void)setOrgJobDescription:(NSString *)str;\n\n- (NSString *)orgSymbol;\n- (void)setOrgSymbol:(NSString *)str;\n\n- (GDataWhere *)where;\n- (void)setWhere:(GDataWhere *)obj;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataOrganizationName.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataOrganizationName.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n// organization name\n//    <gd:orgName yomi=\"Ak Me\">Acme Corp</gd:orgName>\n\n@interface GDataOrganizationName : GDataObject <GDataExtension>\n\n+ (id)organizationNameWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSString *)yomi;\n- (void)setYomi:(NSString *)str;\n\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataPerson.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataPerson.h\n//\n\n#import \"GDataObject.h\"\n// a person, as in\n// <author>\n//   <name>Fred Flintstone</name>\n//   <email>test@domain.net</email>\n// </author>\n@interface GDataPerson : GDataObject <GDataExtension>\n\n+ (GDataPerson *)personWithName:(NSString *)name email:(NSString *)email;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)nameLang;\n- (void)setNameLang:(NSString *)str;\n\n- (NSString *)URI;\n- (void)setURI:(NSString *)str;\n\n- (NSString *)email;\n- (void)setEmail:(NSString *)str;\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataPhoneNumber.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataPhoneNumber.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAPHONENUMBER_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// Note: kGDataContactMobile, kGDataContactHome, and kGDataContactWork are\n// equivalent to kGDataPhoneNumberMobile, kGDataPhoneNumberHome, kGDataPhoneNumberWork\n\n_EXTERN NSString* const kGDataPhoneNumberAssistant   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#assistant\");\n_EXTERN NSString* const kGDataPhoneNumberCallback    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#callback\");\n_EXTERN NSString* const kGDataPhoneNumberCar         _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#car\");\n_EXTERN NSString* const kGDataPhoneNumberCompanyMain _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#company_main\");\n_EXTERN NSString* const kGDataPhoneNumberFax         _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#fax\");\n_EXTERN NSString* const kGDataPhoneNumberHome        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#home\");\n_EXTERN NSString* const kGDataPhoneNumberHomeFax     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#home_fax\");\n_EXTERN NSString* const kGDataPhoneNumberISDN        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#isdn\");\n_EXTERN NSString* const kGDataPhoneNumberMobile      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#mobile\");\n_EXTERN NSString* const kGDataPhoneNumberOther       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#other\");\n_EXTERN NSString* const kGDataPhoneNumberOtherFax    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#other_fax\");\n_EXTERN NSString* const kGDataPhoneNumberPager       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#pager\");\n_EXTERN NSString* const kGDataPhoneNumberRadio       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#radio\");\n_EXTERN NSString* const kGDataPhoneNumberTelex       _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#telex\");\n_EXTERN NSString* const kGDataPhoneNumberTTYTDD      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#tty_tdd\");\n_EXTERN NSString* const kGDataPhoneNumberWork        _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work\");\n_EXTERN NSString* const kGDataPhoneNumberWorkFax     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work_fax\");\n_EXTERN NSString* const kGDataPhoneNumberWorkMobile  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work_mobile\");\n_EXTERN NSString* const kGDataPhoneNumberWorkPager   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work_pager\");\n\n// phone number, as in\n//  <gd:phoneNumber rel=\"http://schemas.google.com/g/2005#work\" >\n//    (425) 555-8080 ext. 52585\n//  </gd:phoneNumber>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdPhoneNumber\n\n@interface GDataPhoneNumber : GDataObject <GDataExtension> {\n}\n\n+ (GDataPhoneNumber *)phoneNumberWithString:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)URI;\n- (void)setURI:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataPostalAddress.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataPostalAddress.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n// postal address, as in\n//  <gd:postalAddress>\n//    500 West 45th Street\n//    New York, NY 10036\n//  </gd:postalAddress>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdPostalAddress\n\n@interface GDataPostalAddress : GDataObject <GDataExtension> {\n}\n\n+ (GDataPostalAddress *)postalAddressWithString:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataRating.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataRating.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_BOOKS_SERVICE \\\n  || GDATA_INCLUDE_CALENDAR_SERVICE || GDATA_INCLUDE_YOUTUBE_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATARATING_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataRatingPrice   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#price\");\n_EXTERN NSString* const kGDataRatingQuality _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#quality\");\n\n// rating, as in\n//  <gd:rating rel=\"http://schemas.google.com/g/2005#price\" value=\"5\" min=\"1\" max=\"5\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdRating\n\n@interface GDataRating : GDataObject <GDataExtension>\n\n+ (GDataRating *)ratingWithValue:(NSInteger)value\n                             max:(NSInteger)max\n                             min:(NSInteger)min;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSNumber *)value; // int\n- (void)setValue:(NSNumber *)num;\n\n- (NSNumber *)max; // int\n- (void)setMax:(NSNumber *)num;\n\n- (NSNumber *)min; // int\n- (void)setMin:(NSNumber *)num;\n\n- (NSNumber *)average; // double\n- (void)setAverage:(NSNumber *)num;\n\n- (NSNumber *)numberOfRaters; // int\n- (void)setNumberOfRaters:(NSNumber *)num;\n@end\n\n#endif // #if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataStructuredPostalAddress.h",
    "content": "/* Copyright (c) 2009 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n//\n//  GDataStructuredPostalAddress.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CONTACTS_SERVICE \\\n  || GDATA_INCLUDE_MAPS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATASTRUCTUREDPOSTALADDRESS_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// rel values\n_EXTERN NSString* kGDataPostalAddressHome  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#home\");\n_EXTERN NSString* kGDataPostalAddressWork  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#work\");\n_EXTERN NSString* kGDataPostalAddressOther _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#other\");\n\n// mail class values\n_EXTERN NSString* kGDataPostalAddressLetters _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#letters\");\n_EXTERN NSString* kGDataPostalAddressParcels _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#parcels\");\n_EXTERN NSString* kGDataPostalAddressNeither _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#neither\");\n_EXTERN NSString* kGDataPostalAddressBoth    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#both\");\n\n// usage values\n_EXTERN NSString* kGDataPostalAddressGeneral  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#general\");\n_EXTERN NSString* kGDataPostalAddressLocal    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#local\");\n\n@interface GDataStructuredPostalAddress : GDataObject <GDataExtension>\n\n+ (id)structuredPostalAddress;\n\n// receiver of mail, or in care of (\"c/o\")\n- (NSString *)agent;\n- (void)setAgent:(NSString *)str;\n\n- (NSString *)city;\n- (void)setCity:(NSString *)str;\n\n// country name and code are in the same element, but we'll expose them\n// here as if they're independent to keep the interface simpler & KVC-compliant\n- (NSString *)countryName;\n- (void)setCountryName:(NSString *)str;\n\n// 3166-1 alpha-2 country codes\n// http://www.iso.org/iso/english_country_names_and_code_elements\n- (NSString *)countryCode;\n- (void)setCountryCode:(NSString *)str;\n\n// building name\n- (NSString *)houseName;\n- (void)setHouseName:(NSString *)str;\n\n- (NSString *)neighborhood;\n- (void)setNeighborhood:(NSString *)str;\n\n- (NSString *)POBox;\n- (void)setPOBox:(NSString *)str;\n\n- (NSString *)postCode;\n- (void)setPostCode:(NSString *)str;\n\n// region is a state, province, county (in Ireland), Land (in Germany),\n// departement (in France), or similar\n- (NSString *)region;\n- (void)setRegion:(NSString *)str;\n\n- (NSString *)street;\n- (void)setStreet:(NSString *)str;\n\n// subregion is not intended for delivery addresses\n- (NSString *)subregion;\n- (void)setSubregion:(NSString *)str;\n\n\n- (NSString *)formattedAddress;\n- (void)setFormattedAddress:(NSString *)str;\n\n// attributes\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)mailClass;\n- (void)setMailClass:(NSString *)str;\n\n- (BOOL)isPrimary;\n- (void)setIsPrimary:(BOOL)flag;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)usage;\n- (void)setUsage:(NSString *)str;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataTextConstruct.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataTextConstruct.h\n//\n\n#import \"GDataObject.h\"\n\n// For typed text, like: <title type=\"text\">Event title</title>\n//\n// type can be text, text/plain, html, text/html, xhtml, or other things\n@interface GDataTextConstruct : GDataObject {\n}\n\n+ (id)textConstructWithString:(NSString *)str;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n- (NSString *)lang;\n- (void)setLang:(NSString *)str;\n- (NSString *)type;\n- (void)setType:(NSString *)str;\n\n@end\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataUtilities.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#import <Foundation/Foundation.h>\n\n#ifndef SKIP_GDATA_DEFINES\n  #import \"GDataDefines.h\"\n#endif\n\n// helper functions for implementing isEqual:\nBOOL AreEqualOrBothNil(id obj1, id obj2);\nBOOL AreBoolsEqual(BOOL b1, BOOL b2);\n\n@interface GDataUtilities : NSObject\n\n// utility for removing non-whitespace control characters\n+ (NSString *)stringWithControlsFilteredForString:(NSString *)str;\n\n// utility for replacing whitespace and removing unsafe symbols for a\n// user-agent string\n+ (NSString *)userAgentStringForString:(NSString *)str;\n\n// utility for converting NSNumber to/from string, including inf/-inf\n//\n// an empty string returns a nil NSNumber\n+ (NSNumber *)doubleNumberOrInfForString:(NSString *)str;\n\n//\n// copy method helpers\n//\n\n// array with copies of the objects in the source array (1-deep)\n+ (NSArray *)arrayWithCopiesOfObjectsInArray:(NSArray *)source;\n+ (NSMutableArray *)mutableArrayWithCopiesOfObjectsInArray:(NSArray *)source;\n\n// dicionary with copies of the objects in the source dictionary (1-deep)\n+ (NSDictionary *)dictionaryWithCopiesOfObjectsInDictionary:(NSDictionary *)source;\n+ (NSMutableDictionary *)mutableDictionaryWithCopiesOfObjectsInDictionary:(NSDictionary *)source;\n\n// dictionary with 1-deep copies of the arrays which are the source dictionary's\n// values (2-deep)\n+ (NSDictionary *)dictionaryWithCopiesOfArraysInDictionary:(NSDictionary *)source;\n+ (NSMutableDictionary *)mutableDictionaryWithCopiesOfArraysInDictionary:(NSDictionary *)source;\n\n//\n// string encoding\n//\n\n// URL encoding, different for parts of URLs and parts of URL parameters\n//\n// +stringByURLEncodingString just makes a string legal for a URL\n//\n// +stringByURLEncodingForURI also encodes some characters that are legal in\n// URLs but should not be used in URIs,\n// per http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7\n//\n// +stringByURLEncodingStringParameter is like +stringByURLEncodingForURI but\n// replaces space characters with + characters rather than percent-escaping them\n//\n+ (NSString *)stringByURLEncodingString:(NSString *)str;\n+ (NSString *)stringByURLEncodingForURI:(NSString *)str;\n+ (NSString *)stringByURLEncodingStringParameter:(NSString *)str;\n\n// percent-encoded UTF-8\n+ (NSString *)stringByPercentEncodingUTF8ForString:(NSString *)str;\n\n//\n// key-value coding searches in an array\n//\n// utilities to get from an array objects having a known value (or nil)\n// at a keyPath\n\n+ (NSArray *)objectsFromArray:(NSArray *)sourceArray\n                    withValue:(id)desiredValue\n                   forKeyPath:(NSString *)keyPath;\n\n+ (id)firstObjectFromArray:(NSArray *)sourceArray\n                 withValue:(id)desiredValue\n                forKeyPath:(NSString *)keyPath;\n\n//\n// version helpers\n//\n\n+ (NSComparisonResult)compareVersion:(NSString *)ver1 toVersion:(NSString *)ver2;\n\n//\n// response string helpers\n//\n\n// convert responses of the form \"a=foo \\n b=bar\"   to a dictionary\n+ (NSDictionary *)dictionaryWithResponseString:(NSString *)str;\n+ (NSDictionary *)dictionaryWithResponseData:(NSData *)data;\n\n//\n// file type helpers\n//\n\n// utility routine to convert a file path to the file's MIME type using\n// Mac OS X's UTI database\n+ (NSString *)MIMETypeForFileAtPath:(NSString *)path\n                    defaultMIMEType:(NSString *)defaultType;\n\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataValueConstruct.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataValueConstruct.h\n//\n\n// GDataValueConstruct is meant to be subclassed for elements that\n// store just a single string either as an attribute or as the\n// element child text.\n//\n// See the examples with each subclass below.\n\n#import \"GDataObject.h\"\n#import \"GDataDateTime.h\"\n\n// an element with a value=\"\" attribute, as in\n// <gCal:timezone value=\"America/Los_Angeles\"/>\n// (subclasses may override the attribute name)\n@interface GDataValueConstruct : GDataObject\n\n// convenience functions: subclasses may call into these and\n// return the result, cast to the appropriate type\n//\n// if nil is passed in for pointer type args for these, nil is returned\n+ (id)valueWithString:(NSString *)str;\n+ (id)valueWithNumber:(NSNumber *)num;\n+ (id)valueWithInt:(int)val;\n+ (id)valueWithLongLong:(long long)val;\n+ (id)valueWithDouble:(double)val;\n+ (id)valueWithBool:(BOOL)flag;\n+ (id)valueWithDateTime:(GDataDateTime *)dateTime;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSString *)attributeName; // defaults to \"value\", subclasses can override\n\n// subclass value utilities\n- (NSNumber *)intNumberValue;\n- (int)intValue;\n- (void)setIntValue:(int)val;\n\n- (NSNumber *)longLongNumberValue;\n- (long long)longLongValue;\n- (void)setLongLongValue:(long long)val;\n\n- (NSNumber *)doubleNumberValue;\n- (double)doubleValue;\n- (void)setDoubleValue:(double)value;\n\n- (NSNumber *)boolNumberValue;\n- (BOOL)boolValue;\n- (void)setBoolValue:(BOOL)flag;\n\n- (GDataDateTime *)dateTimeValue;\n- (void)setDateTimeValue:(GDataDateTime *)dateTime;\n\n@end\n\n// GDataValueElementConstruct is for subclasses that keep the value\n// in the child text nodes, like <yt:books>Pride and Prejudice</yt:books>\n@interface GDataValueElementConstruct : GDataValueConstruct\n- (NSString *)attributeName; // returns nil\n@end\n\n// GDataImplicitValueConstruct is for subclasses that want a fixed value\n// because the element is merely present or absent, like <gd:deleted/>\n@interface GDataImplicitValueConstruct : GDataValueElementConstruct\n+ (id)implicitValue;\n- (NSString *)stringValue; // returns nil\n@end\n\n// an element with a value=true or false attribute, as in\n//   <gCal:sendEventNotifications value=\"true\"/>\n@interface GDataBoolValueConstruct : GDataValueConstruct\n+ (id)boolValueWithBool:(BOOL)flag;\n@end\n\n// GDataNameValueConstruct is for subclasses that have \"name\" and \"value\"\n// attributes\n@interface GDataNameValueConstruct : GDataValueConstruct\n+ (id)valueWithName:(NSString *)name stringValue:(NSString *)value;\n\n- (NSString *)name;\n- (void)setName:(NSString *)str;\n\n- (NSString *)nameAttributeName; // the default implementation returns @\"name\"\n@end\n\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataWhen.h",
    "content": "/* Copyright (c) 2007 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWhen.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n   || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#import \"GDataDateTime.h\"\n\n// when element, as in\n// <gd:when startTime=\"2005-06-06\" endTime=\"2005-06-07\" valueString=\"This weekend\"/>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWhen\n\n@interface GDataWhen : GDataObject <GDataExtension> {\n}\n\n+ (GDataWhen *)whenWithStartTime:(GDataDateTime *)startTime\n                         endTime:(GDataDateTime *)endTime;\n\n- (GDataDateTime *)startTime;\n- (void)setStartTime:(GDataDateTime *)cdate;\n\n- (GDataDateTime *)endTime;\n- (void)setEndTime:(GDataDateTime *)cdate;\n\n- (NSString *)value;\n- (void)setValue:(NSString *)str;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataWhere.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWhere.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE \\\n  || GDATA_INCLUDE_CONTACTS_SERVICE\n\n#import \"GDataObject.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAWHERE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n// rel values\n_EXTERN NSString* const kGDataEventWhereEventLocation _INITIALIZE_AS(nil); // use the enclosing event's location\n_EXTERN NSString* const kGDataEventWhereAlternate _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.alternate\");\n_EXTERN NSString* const kGDataEventWhereParking _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.parking\");\n\n@class GDataEntryLink;\n\n// where element, as in\n// <gd:where rel=\"http://schemas.google.com/g/2005#event\" valueString=\"Joe's Pub\">\n//    <gd:entryLink href=\"http://local.example.com/10018/JoesPub\">\n// </gd:where>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWhere\n\n@interface GDataWhere : GDataObject <GDataExtension>\n\n+ (GDataWhere *)whereWithString:(NSString *)str;\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)label;\n- (void)setLabel:(NSString *)str;\n\n- (NSString *)stringValue; // gets the \"valueString\" XML attribute\n- (void)setStringValue:(NSString *)str; // sets the \"valueString\" XML attribute\n\n- (GDataEntryLink *)entryLink;\n- (void)setEntryLink:(GDataEntryLink *)entryLink;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_*_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataWho.h",
    "content": "/* Copyright (c) 2007-2008 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n*     http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\n//\n//  GDataWho.h\n//\n\n#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n\n#import \"GDataObject.h\"\n#import \"GDataValueConstruct.h\"\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAWHO_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#define _EXTERN GDATA_EXTERN\n#define _INITIALIZE_AS(x)\n#endif\n\n_EXTERN NSString* const kGDataWhoEventAttendee  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.attendee\");\n_EXTERN NSString* const kGDataWhoEventOrganizer _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.organizer\");\n_EXTERN NSString* const kGDataWhoEventSpeaker   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.speaker\");\n_EXTERN NSString* const kGDataWhoEventPerformer _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.performer\");\n\n_EXTERN NSString* const kGDataWhoAttendeeTypeRequired     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.required\");\n_EXTERN NSString* const kGDataWhoAttendeeTypeOptional     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.optional\");\n\n_EXTERN NSString* const kGDataWhoAttendeeStatusInvited    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.invited\");\n_EXTERN NSString* const kGDataWhoAttendeeStatusAccepted   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.accepted\");\n_EXTERN NSString* const kGDataWhoAttendeeStatusTentative  _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.tentative\");\n_EXTERN NSString* const kGDataWhoAttendeeStatusDeclined   _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#event.declined\");\n\n_EXTERN NSString* const kGDataWhoTaskAssignedTo _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#task.assigned-to\");\n\n_EXTERN NSString* const kGDataWhoMessageFrom    _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.from\");\n_EXTERN NSString* const kGDataWhoMessageTo      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.to\");\n_EXTERN NSString* const kGDataWhoMessageCC      _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.cc\");\n_EXTERN NSString* const kGDataWhoMessageBCC     _INITIALIZE_AS(@\"http://schemas.google.com/g/2005#message.bcc\");\n\n@class GDataEntryLink;\n\n@interface GDataAttendeeStatus : GDataValueConstruct <GDataExtension>\n+ (NSString *)extensionElementURI;\n+ (NSString *)extensionElementPrefix;\n+ (NSString *)extensionElementLocalName;\n@end\n\n@interface GDataAttendeeType : GDataValueConstruct <GDataExtension>\n+ (NSString *)extensionElementURI;\n+ (NSString *)extensionElementPrefix;\n+ (NSString *)extensionElementLocalName;\n@end\n\n\n// a who entry, as in\n// <gd:who rel=\"http://schemas.google.com/g/2005#event.organizer\" valueString=\"Fred Flintstone\" email=\"fred@domain.com\">\n//   <gd:attendeeStatus value=\"http://schemas.google.com/g/2005#event.accepted\"/>\n// </gd:who>\n//\n// http://code.google.com/apis/gdata/common-elements.html#gdWho\n@interface GDataWho : GDataObject <GDataExtension> {\n}\n\n+ (GDataWho *)whoWithRel:(NSString *)rel\n                    name:(NSString *)valueString\n                   email:(NSString *)email; // name and email may be nil\n\n- (NSString *)rel;\n- (void)setRel:(NSString *)str;\n\n- (NSString *)email;\n- (void)setEmail:(NSString *)str;\n\n- (NSString *)stringValue; // gets the \"valueString\" XML attribute\n- (void)setStringValue:(NSString *)str; // sets the \"valueString\" XML attribute\n\n- (GDataAttendeeType *)attendeeType;\n- (void)setAttendeeType:(GDataAttendeeType *)val;\n\n- (GDataAttendeeStatus *)attendeeStatus;\n- (void)setAttendeeStatus:(GDataAttendeeStatus *)val;\n\n- (GDataEntryLink *)entryLink;\n- (void)setEntryLink:(GDataEntryLink *)entryLink;\n@end\n\n#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_CALENDAR_SERVICE\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GDataXMLNode.h",
    "content": "/* Copyright (c) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// These node, element, and document classes implement a subset of the methods\n// provided by NSXML.  While NSXML behavior is mimicked as much as possible,\n// there are important differences.\n//\n// The biggest difference is that, since this is based on libxml2, there\n// is no retain model for the underlying node data.  Rather than copy every\n// node obtained from a parse tree (which would have a substantial memory\n// impact), we rely on weak references, and it is up to the code that\n// created a document to retain it for as long as any\n// references rely on nodes inside that document tree.\n\n\n#import <Foundation/Foundation.h>\n\n// libxml includes require that the target Header Search Paths contain\n//\n//   /usr/include/libxml2\n//\n// and Other Linker Flags contain\n//\n//   -lxml2\n\n#import <libxml/tree.h>\n#import <libxml/parser.h>\n#import <libxml/xmlstring.h>\n#import <libxml/xpath.h>\n#import <libxml/xpathInternals.h>\n\n\n#ifdef GDATA_TARGET_NAMESPACE\n  // we're using target namespace macros\n  #import \"GDataDefines.h\"\n#endif\n\n#undef _EXTERN\n#undef _INITIALIZE_AS\n#ifdef GDATAXMLNODE_DEFINE_GLOBALS\n#define _EXTERN\n#define _INITIALIZE_AS(x) =x\n#else\n#if defined(__cplusplus)\n#define _EXTERN extern \"C\"\n#else\n#define _EXTERN extern\n#endif\n#define _INITIALIZE_AS(x)\n#endif\n\n// when no namespace dictionary is supplied for XPath, the default namespace\n// for the evaluated tree is registered with the prefix _def_ns\n_EXTERN const char* kGDataXMLXPathDefaultNamespacePrefix _INITIALIZE_AS(\"_def_ns\");\n\n// Nomenclature for method names:\n//\n// Node = GData node\n// XMLNode = xmlNodePtr\n//\n// So, for example:\n//  + (id)nodeConsumingXMLNode:(xmlNodePtr)theXMLNode;\n\n@class NSArray, NSDictionary, NSError, NSString, NSURL;\n@class GDataXMLElement, GDataXMLDocument;\n\nenum {\n  GDataXMLInvalidKind = 0,\n  GDataXMLDocumentKind,\n  GDataXMLElementKind,\n  GDataXMLAttributeKind,\n  GDataXMLNamespaceKind,\n  GDataXMLProcessingInstructionKind,\n  GDataXMLCommentKind,\n  GDataXMLTextKind,\n  GDataXMLDTDKind,\n  GDataXMLEntityDeclarationKind,\n  GDataXMLAttributeDeclarationKind,\n  GDataXMLElementDeclarationKind,\n  GDataXMLNotationDeclarationKind\n};\n\ntypedef NSUInteger GDataXMLNodeKind;\n\n@interface GDataXMLNode : NSObject <NSCopying> {\n@protected\n  // NSXMLNodes can have a namespace URI or prefix even if not part\n  // of a tree; xmlNodes cannot.  When we create nodes apart from\n  // a tree, we'll store the dangling prefix or URI in the xmlNode's name,\n  // like\n  //   \"prefix:name\"\n  // or\n  //   \"{http://uri}:name\"\n  //\n  // We will fix up the node's namespace and name (and those of any children)\n  // later when adding the node to a tree with addChild: or addAttribute:.\n  // See fixUpNamespacesForNode:.\n\n  xmlNodePtr xmlNode_; // may also be an xmlAttrPtr or xmlNsPtr\n  BOOL shouldFreeXMLNode_; // if yes, xmlNode_ will be free'd in dealloc\n\n  // cached values\n  NSString *cachedName_;\n  NSArray *cachedChildren_;\n  NSArray *cachedAttributes_;\n}\n\n+ (GDataXMLElement *)elementWithName:(NSString *)name;\n+ (GDataXMLElement *)elementWithName:(NSString *)name stringValue:(NSString *)value;\n+ (GDataXMLElement *)elementWithName:(NSString *)name URI:(NSString *)value;\n\n+ (id)attributeWithName:(NSString *)name stringValue:(NSString *)value;\n+ (id)attributeWithName:(NSString *)name URI:(NSString *)attributeURI stringValue:(NSString *)value;\n\n+ (id)namespaceWithName:(NSString *)name stringValue:(NSString *)value;\n\n+ (id)textWithStringValue:(NSString *)value;\n\n- (NSString *)stringValue;\n- (void)setStringValue:(NSString *)str;\n\n- (NSUInteger)childCount;\n- (NSArray *)children;\n- (GDataXMLNode *)childAtIndex:(unsigned)index;\n\n- (NSString *)localName;\n- (NSString *)name;\n- (NSString *)prefix;\n- (NSString *)URI;\n\n- (GDataXMLNodeKind)kind;\n\n- (NSString *)XMLString;\n\n+ (NSString *)localNameForName:(NSString *)name;\n+ (NSString *)prefixForName:(NSString *)name;\n\n// This is the preferred entry point for nodesForXPath.  This takes an explicit\n// namespace dictionary (keys are prefixes, values are URIs).\n- (NSArray *)nodesForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;\n\n// This implementation of nodesForXPath registers namespaces only from the\n// document's root node.  _def_ns may be used as a prefix for the default\n// namespace, though there's no guarantee that the default namespace will\n// be consistenly the same namespace in server responses.\n- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;\n\n// access to the underlying libxml node; be sure to release the cached values\n// if you change the underlying tree at all\n- (xmlNodePtr)XMLNode;\n- (void)releaseCachedValues;\n\n@end\n\n\n@interface GDataXMLElement : GDataXMLNode\n\n- (id)initWithXMLString:(NSString *)str error:(NSError **)error;\n\n- (NSArray *)namespaces;\n- (void)setNamespaces:(NSArray *)namespaces;\n- (void)addNamespace:(GDataXMLNode *)aNamespace;\n\n// addChild adds a copy of the child node to the element\n- (void)addChild:(GDataXMLNode *)child;\n- (void)removeChild:(GDataXMLNode *)child;\n\n- (NSArray *)elementsForName:(NSString *)name;\n- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI;\n\n- (NSArray *)attributes;\n- (GDataXMLNode *)attributeForName:(NSString *)name;\n- (GDataXMLNode *)attributeForLocalName:(NSString *)name URI:(NSString *)attributeURI;\n- (void)addAttribute:(GDataXMLNode *)attribute;\n\n- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI;\n\n@end\n\n@interface GDataXMLDocument : NSObject {\n@protected\n  xmlDoc* xmlDoc_; // strong; always free'd in dealloc\n}\n\n- (id)initWithXMLString:(NSString *)str options:(unsigned int)mask error:(NSError **)error;\n- (id)initWithData:(NSData *)data options:(unsigned int)mask error:(NSError **)error;\n\n// initWithRootElement uses a copy of the argument as the new document's root\n- (id)initWithRootElement:(GDataXMLElement *)element;\n\n- (GDataXMLElement *)rootElement;\n\n- (NSData *)XMLData;\n\n- (void)setVersion:(NSString *)version;\n- (void)setCharacterEncoding:(NSString *)encoding;\n\n// This is the preferred entry point for nodesForXPath.  This takes an explicit\n// namespace dictionary (keys are prefixes, values are URIs).\n- (NSArray *)nodesForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;\n\n// This implementation of nodesForXPath registers namespaces only from the\n// document's root node.  _def_ns may be used as a prefix for the default\n// namespace, though there's no guarantee that the default namespace will\n// be consistenly the same namespace in server responses.\n- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;\n\n- (NSString *)description;\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GTMGatherInputStream.h",
    "content": "/* Copyright (c) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n// The GTMGatherInput stream is an input stream implementation that is to be\n// instantiated with an NSArray of NSData objects.  It works in the traditional\n// scatter/gather vector I/O model.  Rather than allocating a big NSData object\n// to hold all of the data and performing a copy into that object, the\n// GTMGatherInputStream will maintain a reference to the NSArray and read from\n// each NSData in turn as the read method is called.  You should not alter the\n// underlying set of NSData objects until all read operations on this input\n// stream have completed.\n\n#import <Foundation/Foundation.h>\n\n#if defined(GTL_TARGET_NAMESPACE)\n  // we need NSInteger for the 10.4 SDK, or we're using target namespace macros\n  #import \"GTLDefines.h\"\n#elif defined(GDATA_TARGET_NAMESPACE)\n  #import \"GDataDefines.h\"\n#endif\n\n// Define <NSStreamDelegate> only for Mac OS X 10.6+ or iPhone OS 4.0+.\n#undef GTM_NSSTREAM_DELEGATE\n#if (TARGET_OS_MAC && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \\\n    (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 40000))\n #define GTM_NSSTREAM_DELEGATE <NSStreamDelegate>\n#else\n #define GTM_NSSTREAM_DELEGATE\n#endif\n\n@interface GTMGatherInputStream : NSInputStream GTM_NSSTREAM_DELEGATE {\n\n  NSArray* dataArray_;   // NSDatas that should be \"gathered\" and streamed.\n  NSUInteger arrayIndex_;       // Index in the array of the current NSData.\n  long long dataOffset_; // Offset in the current NSData we are processing.\n\n  __weak id delegate_;          // stream delegate, defaults to self\n\n  // Since various undocumented methods get called on a stream, we'll\n  // use a 1-byte dummy stream object to handle all unexpected messages.\n  // Actual reads from the stream we will perform using the data array, not\n  // from the dummy stream.\n  NSInputStream* dummyStream_;\n  NSData* dummyData_;\n}\n\n+ (NSInputStream *)streamWithArray:(NSArray *)dataArray;\n\n- (id)initWithArray:(NSArray *)dataArray;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GTMMIMEDocument.h",
    "content": "/* Copyright (c) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n// This is a simple class to create a MIME document.  To use, allocate\n// a new GTMMIMEDocument and start adding parts as necessary.  When you are\n// done adding parts, call generateInputStream to get an NSInputStream\n// containing the contents of your MIME document.\n//\n// A good reference for MIME is http://en.wikipedia.org/wiki/MIME\n\n#import <Foundation/Foundation.h>\n\n#if defined(GTL_TARGET_NAMESPACE)\n  // we're using target namespace macros\n  #import \"GTLDefines.h\"\n#elif defined(GDATA_TARGET_NAMESPACE)\n  #import \"GDataDefines.h\"\n#endif\n\n@interface GTMMIMEDocument : NSObject {\n  NSMutableArray* parts_;         // Contains an ordered set of MimeParts\n  unsigned long long length_;     // Length in bytes of the document.\n  u_int32_t randomSeed_;          // for testing\n}\n\n+ (GTMMIMEDocument *)MIMEDocument;\n\n// Adds a new part to this mime document with the given headers and body.  The\n// headers keys and values should be NSStrings\n- (void)addPartWithHeaders:(NSDictionary *)headers\n                      body:(NSData *)body;\n\n// An inputstream that can be used to efficiently read the contents of the\n// mime document.\n- (void)generateInputStream:(NSInputStream **)outStream\n                     length:(unsigned long long*)outLength\n                   boundary:(NSString **)outBoundary;\n\n// ------ UNIT TESTING ONLY BELOW ------\n\n// For unittesting only, seeds the random number generator\n- (void)seedRandomWith:(u_int32_t)seed;\n\n@end\n"
  },
  {
    "path": "libDoubanApiEngine.framework/Versions/A/Headers/GeorssPoint.h",
    "content": "//\n//  GeorssPoint.h\n//  DoubanAPIEngine\n//\n//  Created by Lin GUO on 11-12-19.\n//  Copyright (c) 2011年 Douban Inc. All rights reserved.\n//\n\n#import \"GDataExtendedProperty.h\"\n\n@interface GeorssPoint : GDataExtendedProperty <GDataExtension>\n\n- (NSString *)content;\n\n- (void)setContent:(NSString *)str;\n\n- (float) geoLatitude;\n\n- (float) geoLongitude;\n\n@end\n"
  }
]